Runge-Kutta第四阶在C++中的实现 所以我应该先说这是我第一次尝试一个可执行脚本,也是我的第一个C++脚本。考虑到这一点,我的问题如下。我正在尝试创建一个脚本,该脚本将使用四阶龙格-库塔方法集成投射物运动。目前,我的脚本使用的是Euler方法,工作正常。然而,当我试图实现我的Runge-Kutta函数时,我得到了绝对的垃圾

Runge-Kutta第四阶在C++中的实现 所以我应该先说这是我第一次尝试一个可执行脚本,也是我的第一个C++脚本。考虑到这一点,我的问题如下。我正在尝试创建一个脚本,该脚本将使用四阶龙格-库塔方法集成投射物运动。目前,我的脚本使用的是Euler方法,工作正常。然而,当我试图实现我的Runge-Kutta函数时,我得到了绝对的垃圾,c++,physics,projectile,runge-kutta,C++,Physics,Projectile,Runge Kutta,例如,通过我当前的Euler积分,我得到以下结果: #include <iostream> // Statndard Input Output #include <stdlib.h> // Standard Library atof #include <cmath> // Use Of Math Functions #include <fstream> // File Stream Input Output #include <string&

例如,通过我当前的Euler积分,我得到以下结果:

#include <iostream> // Statndard Input Output
#include <stdlib.h> // Standard Library atof
#include <cmath> // Use Of Math Functions
#include <fstream> // File Stream Input Output
#include <string> // String Manipulation c_str
#include <sstream> // Used For Variable String Name

/* Allows for abbrevaited names
** without having to use std::cout
** for example we may simply type
** cout
*/
using namespace std; 

// Required Function Delcarations
double toRadians(double angle);
double xVelocity(double vel,double angle);
double yVelocity(double vel,double angle);
double rc4(double initState, double (*eqn)(double,double),double now,double dt);
double updatePosX(double currentPos,double vel,double deltaT);
double updatePosY(double currentPos,double vel,double deltaT);
double updateVelY(double yVel,double deltaT);
double updateVelX(double xVel,double deltaT);

int main(int argc, char *argv[]) //In Brackets Allows Command Line Input
{
    /* atof Parses the C string str, interpreting its 
    ** content as a floating point number and 
    ** returns its value as a double. */
    double v0 = atof(argv[1]);  
    double theta = atof(argv[2]);
    double timeStep = atof(argv[3]);
    double duration = atof(argv[4]);

    /* Simple printed message to the 
    ** console informing the user
    ** what set of initial conditions
    ** are currently being executed
    */
    cout << "Running Simulation" << endl;
    cout << "Velocity: " << v0 << " m/s" << endl;
    cout << "Angle: " << theta << " deg" << endl;
    cout << endl;

    //Setting x and y velocity 
    double vx = xVelocity(v0,toRadians(theta));
    double vy = yVelocity(v0,toRadians(theta));

    //Initial Conditions 
    double xPos = 0;
    double yPos = 0;
    double time = 0;

    /*Creating File Name With Vars
    ** Note: stringsteam is a stream
    ** for operating on strings. In 
    ** order to concatinate strings
    ** or produce statements like 
    ** those if java, we must use
    ** this stream. We CANNOT 
    ** simply concationate strings
    ** and variables
    */
    stringstream ss; 
    ss << "v0_" << v0 << "_ang_" << theta << ".txt";
    string fileName = ss.str();

    //Opening File For Writing
    ofstream myFile;
    myFile.open(fileName.c_str()); //Must be c style string

    // Checking Status of Attempt To Open   
    if(myFile.fail())
    {
        cout << "Failed To Open File For Writing" << endl;
    }

    else
    {   
        //myFile << "x pos \t y pos \t vx \t vy" << endl;

        // Doing Required Integration
        while (time <= duration && yPos >=0)
        {

            vx = updateVelX(vx,timeStep);
            vy = updateVelY(vy,timeStep);

            xPos = updatePosX(xPos,vx,timeStep);
            yPos = updatePosY(yPos,vy,timeStep);
            cout << "x Pos: " << xPos <<"\t y Pos: " << yPos << endl;

            time+=timeStep;

            myFile << xPos << "  " << yPos << "  " << vx << "  " << vy << endl; 

        }
    }

    //Closing File After Finished   
    myFile.close();

    return 0;
}

/* This function shall take a given
** angle in degrees and convert it
** to radians
*/
double toRadians(double angle)
{
    return (M_PI * (90-angle)) / 180.0;
}

/* This function shall take the inital
** angle at which the projectile is 
** launched and return the x componet
** of its velocity 
*/
double xVelocity(double vel,double angle)
{
    return vel * sin(angle);
}

/* This function shall take the inital
** angle at which the projectile is 
** launched and return the y componet
** of its velocity 
*/
double yVelocity(double vel,double angle)
{
    return vel * cos(angle);
}

/* This function shall be
** the X position of our 
** projectile
*/
double updatePosX(double currentPos,double vel,double deltaT)
{
    return currentPos + vel*deltaT;
}

/* This function shall be
** the Y posistion of our
** projecticle
*/
double updatePosY(double currentPos,double vel,double deltaT)
{
    return currentPos + vel*deltaT;
}

/* This function shall update
** the Y component of our 
** projectile's velocity 
*/
double updateVelY(double yVel,double deltaT)
{
    double g = 9.81;
    return yVel - g*deltaT;
}

/* This function shall update
** the X component of our
** projecticle's velocity
*/
double updateVelX(double xVel,double deltaT)
{
    return xVel;
}

/* This function shall be the fourth
** order Runge Kutta integration method
** and shall take as input y0 and return
** y+1.
**
** initState: Inital state of function
** (*eqn): Equation to be integrated
** now: Initial time to start integration
** dt: Timestep
*/
double rc4(double initState, double (*eqn)(double,double),double now,double dt)
{
    double k1 = dt * eqn(initState,now);
    double k2 = dt * eqn(initState + k1 / 2.0, now + dt / 2.0);
    double k3 = dt * eqn(initState + k2 / 2.0, now + dt / 2.0);
    double k4 = dt * eqn(initState + k3, now + dt);

    return  initState + (k1 + 2 * k2 + 2 * k3 + k4) / 6.0;
}
最后,我使用gnuplot脚本将结果绘制到

#!/usr/bin/gnuplot

set terminal pdf color solid
set output "test.pdf"
set yrange[0:20000]
set xrange[0:55000]
plot for [i=30 : 60 : 5] 'v0_700_ang_'.i.'.txt' using 1:2 with lines title  'Angle '.i.' deg' 
如前所述,我的Euler与上面所示代码的集成产生了下面的图,我知道这是正确的

然而,当我试图更改代码以使用Runge Kutta时,就像我说的绝对垃圾一样

#include <iostream> // Statndard Input Output
#include <stdlib.h> // Standard Library atof
#include <cmath> // Use Of Math Functions
#include <fstream> // File Stream Input Output
#include <string> // String Manipulation c_str
#include <sstream> // Used For Variable String Name

/* Allows for abbrevaited names
** without having to use std::cout
** for example we may simply type
** cout
*/
using namespace std; 

// Required Function Delcarations
double toRadians(double angle);
double xVelocity(double vel,double angle);
double yVelocity(double vel,double angle);
double rc4(double initState, double (*eqn)(double,double),double now,double dt);
double updatePosX(double currentPos,double vel,double deltaT);
double updatePosY(double currentPos,double vel,double deltaT);
double updateVelY(double yVel,double deltaT);
double updateVelX(double xVel,double deltaT);

int main(int argc, char *argv[]) //In Brackets Allows Command Line Input
{
    /* atof Parses the C string str, interpreting its 
    ** content as a floating point number and 
    ** returns its value as a double. */
    double v0 = atof(argv[1]);  
    double theta = atof(argv[2]);
    double timeStep = atof(argv[3]);
    double duration = atof(argv[4]);

    /* Simple printed message to the 
    ** console informing the user
    ** what set of initial conditions
    ** are currently being executed
    */
    cout << "Running Simulation" << endl;
    cout << "Velocity: " << v0 << " m/s" << endl;
    cout << "Angle: " << theta << " deg" << endl;
    cout << endl;

    //Setting x and y velocity 
    double vx = xVelocity(v0,toRadians(theta));
    double vy = yVelocity(v0,toRadians(theta));

    //Initial Conditions 
    double xPos = 0;
    double yPos = 0;
    double time = 0;

    /*Creating File Name With Vars
    ** Note: stringsteam is a stream
    ** for operating on strings. In 
    ** order to concatinate strings
    ** or produce statements like 
    ** those if java, we must use
    ** this stream. We CANNOT 
    ** simply concationate strings
    ** and variables
    */
    stringstream ss; 
    ss << "v0_" << v0 << "_ang_" << theta << ".txt";
    string fileName = ss.str();

    //Opening File For Writing
    ofstream myFile;
    myFile.open(fileName.c_str()); //Must be c style string

    // Checking Status of Attempt To Open   
    if(myFile.fail())
    {
        cout << "Failed To Open File For Writing" << endl;
    }

    else
    {   
        //myFile << "x pos \t y pos \t vx \t vy" << endl;

        // Doing Required Integration
        while (time <= duration && yPos >=0)
        {

            vx = rc4(vx,updateVelX,time,timeStep);
            vy = rc4(vy,updateVelY,time,timeStep);

            xPos = updatePosX(xPos,vx,timeStep);
            yPos = updatePosY(yPos,vy,timeStep);
            cout << "x Pos: " << xPos <<"\t y Pos: " << yPos << endl;

            time+=timeStep;

            myFile << xPos << "  " << yPos << "  " << vx << "  " << vy << endl; 

        }
    }

    //Closing File After Finished   
    myFile.close();

    return 0;
}

/* This function shall take a given
** angle in degrees and convert it
** to radians
*/
double toRadians(double angle)
{
    return (M_PI * (90-angle)) / 180.0;
}

/* This function shall take the inital
** angle at which the projectile is 
** launched and return the x componet
** of its velocity 
*/
double xVelocity(double vel,double angle)
{
    return vel * sin(angle);
}

/* This function shall take the inital
** angle at which the projectile is 
** launched and return the y componet
** of its velocity 
*/
double yVelocity(double vel,double angle)
{
    return vel * cos(angle);
}

/* This function shall be
** the X position of our 
** projectile
*/
double updatePosX(double currentPos,double vel,double deltaT)
{
    return currentPos + vel*deltaT;
}

/* This function shall be
** the Y posistion of our
** projecticle
*/
double updatePosY(double currentPos,double vel,double deltaT)
{
    return currentPos + vel*deltaT;
}

/* This function shall update
** the Y component of our 
** projectile's velocity 
*/
double updateVelY(double yVel,double deltaT)
{
    double g = 9.81;
    return yVel - g*deltaT;
}

/* This function shall update
** the X component of our
** projecticle's velocity
*/
double updateVelX(double xVel,double deltaT)
{
    return xVel;
}

/* This function shall be the fourth
** order Runge Kutta integration method
** and shall take as input y0 and return
** y+1.
**
** initState: Inital state of function
** (*eqn): Equation to be integrated
** now: Initial time to start integration
** dt: Timestep
*/
double rc4(double initState, double (*eqn)(double,double),double now,double dt)
{
    double k1 = dt * eqn(initState,now);
    double k2 = dt * eqn(initState + k1 / 2.0, now + dt / 2.0);
    double k3 = dt * eqn(initState + k2 / 2.0, now + dt / 2.0);
    double k4 = dt * eqn(initState + k3, now + dt);

    return  initState + (k1 + 2 * k2 + 2 * k3 + k4) / 6.0;
}

这些应该是Boost Numeric odeint的一部分,请参见以及这些标题

boost/numeric/odeint/stepper/runge_kutta4.hpp
boost/numeric/odeint/stepper/runge_kutta4_classic.hpp
boost/numeric/odeint/stepper/runge_kutta_cash_karp54.hpp
boost/numeric/odeint/stepper/runge_kutta_cash_karp54_classic.hpp
boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp
boost/numeric/odeint/stepper/runge_kutta_fehlberg78.hpp

和概述页。

请在发布前阅读。不幸的是,我被迫编写自己的代码,而不使用库。代码不再可用…我不同意。我通过软件包更新了eg R的Boost,它已经有了。Boost也出现在每个Linux发行版中。另外:。也许你想撤回否决票?我很乐意向上投票,但我的投票是锁定的,直到你编辑答案,也许链接到适当的例子回购。
boost/numeric/odeint/stepper/runge_kutta4.hpp
boost/numeric/odeint/stepper/runge_kutta4_classic.hpp
boost/numeric/odeint/stepper/runge_kutta_cash_karp54.hpp
boost/numeric/odeint/stepper/runge_kutta_cash_karp54_classic.hpp
boost/numeric/odeint/stepper/runge_kutta_dopri5.hpp
boost/numeric/odeint/stepper/runge_kutta_fehlberg78.hpp