I am trying to obtain a code that will give me the numerical solutions of the Lane-Edmen equation, using the Runge-Kutta 4 steps method. I am not super into C++ and therefore there must be something I am missing, since the code is running, but the data calculated are clearly wrong. Untill now I am considering only the case n=0, for simplicity. Could you check it and give me an opinion, please?
#include <iostream>
#include <cmath>
#include <iomanip>
#include <fstream>
#define Nmax 400
using namespace std;
void RK4Step(double x, double *Y, double (*dYdx)(double, double), double (*dZdx)(double, double, double), double dx, int neq);
double dYdx(double x, double Y);
double dZdx(double x, double Y, double Z);
int main(){
cout << setprecision(6);
double Y[] = {1., 0.};
double xi0 = 0.1;
double xif = 20.;
double dxi = (xif-xi0)/Nmax;
int neq = 1;
ofstream fdata;
fdata.open("lane_emden.dat");
fdata << xi0 << " " << Y[0] << endl;
cout << "xi: " << scientific << xi0 << "; theta: " << Y[0] << endl;
for(int i=0; i<Nmax; i++){
RK4Step(xi0, Y, dYdx, dZdx, dxi, neq);
xi0 += dxi;
fdata << xi0 << " " << Y[0] << endl;
cout << "xi: " << scientific << xi0 << "; theta: " << Y[0] << "; f: " << Y[1] << endl;
}
fdata.close();
return 0;
}
void RK4Step(double xi, double *Y, double (*dYdx)(double, double), double (*dZdx)(double, double, double), double dxi, int neq){
double k1[2], k2[2], k3[2], k4[2];
k1[0] = dYdx(xi, Y[0]);
k1[1] = dZdx(xi, Y[0], Y[1]);
k2[0] = dYdx(xi+dxi*0.5, Y[1] + k1[1]*0.5);
k2[1] = dZdx(xi+dxi*0.5, Y[0] + k1[0]*0.5, Y[1] + k1[1]*0.5);
k3[0] = dYdx(xi+dxi*0.5, Y[1] + k2[1]*0.5);
k3[1] = dZdx(xi+dxi*0.5, Y[0] + k2[0]*0.5, Y[1] + k2[1]*0.5);
k4[0] = dYdx(xi+dxi, Y[1] + k3[1]);
k4[1] = dZdx(xi+dxi, Y[0] + k3[0], Y[1] + k3[1]);
for(int i=0; i<2; i++){Y[i] += (dxi/6.)*(k1[i] + 2*k2[i] + 2*k3[i] + k4[i]);}
}
double dYdx(double x, double Z){
double dY = Z;
return dY;
}
double dZdx(double xi, double Y, double Z){
double dZ = - 1. - (2.*Z)/xi;
return dZ;
}
You will find RK4 easier to use if it is set up to use array arguments, rather than multiple separate derivative functions. Here, I've used std::valarray, but I'm well aware that many programmers don't like that.
I've set n=1. The result is more interesting than n=0. For a comparison graph, see the Wikipedia article:
https://en.wikipedia.org/wiki/Lane%E2%80%93Emden_equation