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