⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kepler.cpp

📁 A C++ class library for scientific computing
💻 CPP
字号:
#include <blitz/vector.h>#include <blitz/tinyvec.h>BZ_USING_NAMESPACE(blitz)/* * Test a 12th order symmetric multistep method for solving the equations * of motion of a single planet circling the Sun.  The Sun is fixed in * space. * * Original F77 version written by John K. Prentice, Quetzal Computational * Associates, 21 Decmber 1992 *  * Blitz++ version by Todd Veldhuizen, 17 August 1997 * The C++ version is a faithful translation of the Fortran 90 version, * so apologies for the "C++Tran" style. */inline double relativeError(double a, double b){    if (b != 0.0)        return (a - b) / b;    else        return a;}int main(){    Vector<double> x_position_numerical(13), y_position_numerical(13),        alpha(13), beta(13), gamma(13), x_acceleration(13), y_acceleration(13);       /*     * 12th order symmetric method coefficients     *     * Reference: "Symmetric Multistep Methods for the Numerical     * Integration of Planetary Orbits", G. D. Quinlan and     * S. Tremaine, The Astronomical Journal, 100 (1990), page 1695.     *     * Note!! The beta below are actually 53,222,400 times the     * real beta.  This common factor is divided out in the     * symmetric multistep calculation itself, in order to minimize     * round-off     */    const double beta_factor = 53222400.0;    alpha = 1.0, -2.0, 2.0, -1.0, 0.0, 0.0, 0.0, 0.0, 0.0, -1.0, 2.0, -2.0, 1.0;    beta  = 0.0, 90987349.0, -229596838.0, 812627169.0, -1628539944.0,             2714971338.0, -3041896548.0, 2714971338.0, -1628539944.0,            812627169.0, -229596838.0, 90987349.0, 0.0;    /*     * 12th order Cowell predictor coefficients     *     * Reference:  "Astronomical Papers Prepared for the Use of the     * American Ephemeris and Nautical Almanac", C. J. Cohen, E. C.     * Hubbard, and C. Oesterwinter, 22 (1973), page 20-21.     *     * Note!!  The gamma below are actually 1,743,565,824,000 times     * the real gamma.  This common factor is divided out in the     * Cowell predictor calculation itself, in order to minimize     * round-off     */    const double gamma_factor = 1743565824000.0;    gamma = 9072652009253.0, -39726106418680.0, 140544566352762.0,        -344579280210129.0, 613137294629235.0, -811345852376496.0,       807012356281740.0, -602852367932304.0, 333888089374395.0,        -133228219027160.0, 36262456774618.0, -6033724094760.0,       463483373517.0;    // Initialize variables    const double time_step = 0.25,                 stop_time = 365000.0,                 radius    = 1.0;    double time = - time_step;    cout << " Position solution via 12th order symmetric multistep method\n"         << " Velocity solution via 12th order Cowell predictor method\n"         << "     radius = " << radius << ", time step = " << time_step         << endl;    // Define a constant which is needed later by the exact solution    const double gaussian_constant = 0.01720209895;    const double gravitational_constant = pow(gaussian_constant,2);    const double constant = sqrt(gravitational_constant/pow(radius,3));    // Initialize the first 12 numerical values using the exact values    double x_position_exact, y_position_exact;    for (int j=-1; j <= 11; ++j)    {        if (j >= 0)            time += time_step;        x_position_exact = radius * cos(constant * time);        y_position_exact = radius * sin(constant * time);        if (j >= 0)        {            x_position_numerical(j) = x_position_exact;            y_position_numerical(j) = y_position_exact;        }        x_acceleration(j+1) = -gravitational_constant/pow(radius,3)             * x_position_exact;        y_acceleration(j+1) = -gravitational_constant/pow(radius,3)            * y_position_exact;    }    /*     * Compute exact kinetic and potential energies, and the     * angular momentum.  These values are all divided by the mass     * of the object.  Since they are conserved, they will never change     * and hence do not have to be recalculated later.     */    double x_dot_exact = -radius * constant * sin(constant*time),         y_dot_exact =  radius * constant * cos(constant*time),         exact_velocity_squared = pow(x_dot_exact,2) + pow(y_dot_exact,2),         exact_kinetic_energy = 0.5 * exact_velocity_squared,         exact_potential_energy = -gravitational_constant / radius,         exact_total_energy = exact_potential_energy + exact_kinetic_energy,         exact_angular_momentum = x_position_exact * y_dot_exact             - y_position_exact * x_dot_exact;    double x_dot_numerical, y_dot_numerical;    // Perform loop over time    while (time <= stop_time)                               {        // Advance time step (eek!)        time += time_step;                // Calculate new acceleration of body at time=time-time_step        double numerical_radius_squared = pow(x_position_numerical(11),2)            + pow(y_position_numerical(11),2);        x_acceleration(12) = -gravitational_constant            / pow(numerical_radius_squared, 1.5) * x_position_numerical(11);        y_acceleration(12) = -gravitational_constant            / pow(numerical_radius_squared, 1.5) * y_position_numerical(11);        // Numerically solve for the new positions using a 12th order        // symmetric multistep method.        // First sum the first and second terms        double x_alpha_sum = dot(alpha(Range(0,11)),             x_position_numerical(Range(0,11)));        double y_alpha_sum = dot(alpha(Range(0,11)),             y_position_numerical(Range(0,11)));        double x_beta_sum = dot(beta(Range(0,11)), x_acceleration(Range(1,12)));        double y_beta_sum = dot(beta(Range(0,11)), y_acceleration(Range(1,12)));        x_position_numerical(12) = (-x_alpha_sum) + pow(time_step,2)             * (x_beta_sum / beta_factor);        y_position_numerical(12) = (-y_alpha_sum) + pow(time_step,2)            * (y_beta_sum / beta_factor);        // Numerically solve for the new velocities using a 12th order        // Cowell predictor method.        // First sum the gamma terms        double x_gamma_sum = dot(gamma, x_acceleration.reverse()),               y_gamma_sum = dot(gamma, y_acceleration.reverse());        x_dot_numerical = (x_position_numerical(11)            - x_position_numerical(10)) / time_step + time_step             * (x_gamma_sum / gamma_factor);        y_dot_numerical = (y_position_numerical(11)            - y_position_numerical(10)) / time_step + time_step            * (y_gamma_sum / gamma_factor);        // Push the stack down one        for (int j=0; j <= 11; ++j)        {            x_position_numerical(j) = x_position_numerical(j+1);            y_position_numerical(j) = y_position_numerical(j+1);            x_acceleration(j) = x_acceleration(j+1);            y_acceleration(j) = y_acceleration(j+1);        }    }    // Print results    // First compute energies and angular momenta (add divided by the mass    // of the object)    double numerical_velocity_squared = pow(x_dot_numerical,2) +               pow(y_dot_numerical,2),           numerical_radius = sqrt(pow(x_position_numerical(12),2)               + pow(y_position_numerical(12),2)),           numerical_kinetic_energy = 0.5 * numerical_velocity_squared,           numerical_potential_energy = -gravitational_constant                / numerical_radius,           numerical_total_energy = numerical_potential_energy               + numerical_kinetic_energy,           numerical_angular_momentum = x_position_numerical(12)               * y_dot_numerical - y_position_numerical(12) * x_dot_numerical;    // Compute exact results for comparison to the numerical results   x_position_exact = radius * cos(constant * time);   y_position_exact = radius * sin(constant * time);   x_dot_exact = -radius * constant * sin(constant * time);   y_dot_exact =  radius * constant * cos(constant * time);    // Next compute relative errors    double radius_error = relativeError(numerical_radius, radius),           x_error = relativeError(x_position_numerical(12), x_position_exact),           y_error = relativeError(y_position_numerical(12), y_position_exact),           x_dot_error = relativeError(x_dot_numerical, x_dot_exact),           y_dot_error = relativeError(y_dot_numerical, y_dot_exact);    double kinetic_energy_error = relativeError(numerical_kinetic_energy,               exact_kinetic_energy),           potential_energy_error = relativeError(numerical_potential_energy,               exact_potential_energy),           total_energy_error = relativeError(numerical_total_energy,               exact_total_energy),           angular_momentum_error = relativeError(numerical_angular_momentum,               exact_angular_momentum);    cout << " Time = " << time << endl         << "    x rel error  = " << x_error << " y rel error  = " << y_error         << endl         << "    vx rel error = " << x_dot_error << " vy rel error = "          << y_dot_error << endl         << "    KE rel error = " << kinetic_energy_error          << " PE rel error = " << potential_energy_error << endl         << "    TE rel error = " << total_energy_error << " AM rel error = "         << angular_momentum_error << endl         << "    numerical radius = " << numerical_radius          << " radius rel error = " << radius_error << endl;    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -