I'm making a program which allow me to find the numerical solution of a 2-body problem involving the Sun and the Earth by using a Runge-Kutta scheme. I'm using a structure to define the solution properties, another one to define the numerical method used and a class to define the planet properties. The result is finally wrote on a file. I have no problem in running the program with every Runge-Kutta method defined but the Runge-Kutta of order 7 (RK7). The problem is in the cycle inside the RK function of the main file: after a random number of iterations (usually no more than i = 4) the program stops ("Main.exe stopped working"). I checked what could be the reason of that and it seems the problem is at
supp = f(fa, fb, Ms);
which is a support vector that receives the result of the 2-body system of differential equations (function F2 for instance). I don't understand what could be the reason since the program works fine in any other case (I already checked the RK7 Butcher tableau values). I don't know if this can help, but trying to print the values of the p vector from the F2 function, I noticed that, after the aforementioned random number of iterations, the program stops sometimes without printing all the values of p.
Main.cpp
#include<iostream>
#include<math.h>
#include<vector>
#include "celestial_body.cpp"
#include "solution.cpp"
#include "RK_schemes.cpp"
using namespace std;
const double P = 365.25;
const double G = 1.000009448418457;
const double Ms = 1.0;
const double pi = 3.14159265358979323846;
typedef vector<double> (* fun) (double, vector<double>, double);
vector<double> F1(double t, vector<double> x, double m) {
vector<double> p(4,0);
//r system
p[0] = x[1];
p[1] = x[0]*pow(x[3],2) - (G*m)/pow(x[0],2);
//theta system
p[2] = x[3];
p[3] = -2*x[1]*x[3]/x[0];
cout << p[0] << " " << p[1] << " " << p[2] << " " << p[3] << endl;
return p;
}
vector<double> F2(double t, vector<double> x, double m) {
vector<double> p(4,0);
double d = sqrt(pow(x[0],2) + pow(x[2],2));
//x system
p[0] = x[1];
p[1] = -(G*m*(x[0]))/pow(d,3);
//y system
p[2] = x[3];
p[3] = -(G*m*x[2])/pow(d,3);
return p;
}
void RK(fun f, CB ob1, int N, double tf, double t0 = 0) {
double fa, h = (tf - t0)/N;
cout << "h is: " << h << endl;
Sol U(N, 4); //U.dim = 4
U.set_starting_values(t0, ob1.CB::getparam());
//RK_model RK(4);
RK_model RK(7);
//RK.set_RK4();
RK.set_RK7();
vector<double> sum1(U.dim,0);
vector<double> sum2(U.dim,0);
vector<double> K(U.dim*U.dim,0);
vector<double> fb(U.dim,0);
vector<double> supp(U.dim,0);
int k = 0;
for (int n = 0; n < N-1; n++) {
U.t[n+1] = t0 + (n+1)*h;
for (int i = 0; i < RK.nu; i++) {
fa = U.t[n] + RK.c[i]*h;
for (int j = 0; j < RK.nu; j++) {
if (i == j || i < j) {
break;
}
while (k < U.dim) {
sum1[k] += RK.a[j*RK.nu + i]*K[k*RK.nu + j];
k++;
}
k = 0;
}
while (k < U.dim) {
fb[k] = U.u[k*N+n] + h*sum1[k];
k++;
}
k = 0;
fill(sum1.begin(), sum1.end(), 0);
supp = f(fa, fb, Ms);
while (k < U.dim) {
K[k*RK.nu + i] = supp[k];
sum2[k] += RK.b[i]*K[k*RK.nu + i];
k++;
}
k = 0;
}
while (k < U.dim) {
U.u[k*N+n+1] = U.u[k*N+n] + h*sum2[k];
k++;
}
k = 0;
fill(sum2.begin(), sum2.end(), 0);
}
U.write_to_file();
U.del();
RK.del();
vector<double>().swap(sum1);
vector<double>().swap(sum2);
vector<double>().swap(K);
vector<double>().swap(fb);
}
int main() {
CB E(3.002513826043238e-06);
int fn;
double N, tf;
cout << "Choose function (1: polar; 2: cartesian): ";
cin >> fn;
assert(fn == 1 || fn == 2);
cout << "Choose final time (starting time have been set to zero): ";
cin >> tf;
cout << "Choose number of iterations: ";
cin >> N;
//Set starting position and velocity of Earth
if (fn == 1) {
//start apocenter
//E.CB::setpos(1.016719016709908, 0);
//E.CB::setvel(0, 0.016638215898855);
//start pericenter
E.CB::setpos(0.983249288988710, 0);
E.CB::setvel(0, 0.017791966932260);
RK(F1, E, N, tf);
} else if(fn == 2) {
//start apocenter
//E.CB::setpos(1.016719016709908, 0);
//E.CB::setvel(0, 0.983372498367391);
//start pericenter
E.CB::setpos(0.983249288988710, 0);
E.CB::setvel(0, 1.016789362554682);
RK(F2, E, N, tf);
}
solution.cpp
#ifndef SOLUTION_4D
#define SOLUTION_4D
#include<iostream>
#include<fstream>
#include<vector>
using namespace std;
struct Sol {
vector<double> u;
vector<double> t;
int N;
int dim;
Sol(int n, int d) {
dim = d;
N = n;
for (int i = 0; i < dim*N; i++) {
u.push_back(0);
if (i < N) {
t.push_back(0);
}
}
}
void set_starting_values(double t0, vector<double> p) {
t[0] = t0;
for (int i = 0; i < dim; i++) {
u[i*N] = p[i];
}
}
void write_to_file() {
ofstream myfile("result.m", ios_base::out);
myfile.setf(ios_base::left, ios_base::adjustfield);
myfile.setf(ios_base::scientific);
myfile.precision(15);
int k = 0;
myfile << "u" << " = [ " << endl;
for (int i = 0; i < N; i++) {
myfile << t[i] << " ";
while (k < dim) {
if (k == dim-1) {
myfile << u[k*N+i] << endl;
} else {
myfile << u[k*N+i] << " ";
}
k++;
}
k = 0;
}
myfile << "]; \n";
myfile.close();
}
void del() {
vector<double>().swap(t);
vector<double>().swap(u);;
}
};
#endif
celestial_body.cpp
#ifndef CELESTIAL_BODY
#define CELESTIAL_BODY
#include<vector>
using namespace std;
class CB {
private:
double M;
vector<double> param; //contain xpos, xvel, ypos, yvel in this order
public:
CB(double m) {
M = m;
for (int i = 0; i < 4; i++) {
param.push_back(0);
}
}
void setpos(double x, double y) {
param[0] = x;
param[2] = y;
}
vector<double> getpos() {
vector<double> pos(2,0);
pos[0] = param[0];
pos[1] = param[2];
return pos;
}
void setvel(double vx, double vy) {
param[1] = vx;
param[3] = vy;
}
vector<double> getvel() {
vector<double> vel(2,0);
vel[0] = param[1];
vel[1] = param[3];
return vel;
}
vector<double> getparam() {
return param;
}
double getmass() {
return M;
}
};
#endif
RK_schemes.cpp
#ifndef RK_SCHEMES
#define RK_SCHEMES
#include<cassert>
#include<iomanip>
#include<vector>
#include<math.h>
struct RK_model {
vector<double> c;
vector<double> b;
vector<double> a;
int nu;
RK_model(int stages) {
nu = stages;
for (int i = 0; i < nu*nu; i++) {
if (i < nu) {
c.push_back(0);
b.push_back(0);
}
a.push_back(0);
}
}
void set_EE() {
assert(nu == 1);
b[0] = 1;
}
void set_Heun() {
assert(nu == 2);
c[1] = 1.0;
b[0] = 1.0/2.0;
b[1] = 1.0/2.0;
a[1] = 1.0;
}
void set_modified_Euler() {
assert(nu == 2);
c[1] = 1.0/2.0;
b[1] = 1.0;
a[1] = 1.0/2.0;
}
void set_Shu() {
assert(nu == 3);
c[1] = 1.0/3.0;
c[2] = 2.0/3.0;
b[0] = 1.0/4.0;
b[2] = 3.0/4.0;
a[1] = 1.0/3.0;
a[5] = 2.0/3.0;
}
void set_RK4() {
assert(nu == 4);
c[1] = 1.0/2.0;
c[2] = 1.0/2.0;
c[3] = 1.0;
b[0] = 1.0/6.0;
b[1] = 1.0/3.0;
b[2] = 1.0/3.0;
b[3] = 1.0/6.0;
a[1] = 1.0/2.0;
a[6] = 1.0/2.0;
a[11] = 1.0;
}
void set_RK7() {
assert(nu == 7);
double r = sqrt(21);
c[1] = 1.0;
c[2] = 0.5;
c[3] = 2.0/3.0;
c[4] = (7.0 - r)/14.0;
c[5] = (7.0 + r)/14.0;
c[6] = 1.0;
b[0] = 1.0/20.0;
b[2] = 16.0/45.0;
b[4] = 49.0/180.0;
b[5] = 49.0/180.0;
b[6] = 1.0/20.0;
a[1] = 1;
a[2] = 3.0/8.0;
a[3] = 8.0/27.0;
a[4] = 3*(3*r - 7)/392.0;
a[5] = -(231 + 51*r)/392.0;
a[6] = (22 + 7*r)/12.0;
a[9] = 1.0/8.0;
a[10] = 2.0/27.0;
a[11] = (7 - r)/49.0;
a[12] = -(7 + r)/49.0;
a[13] = 2.0/3.0;
a[17] = 8.0/27.0;
a[18] = 6*(7 - r)/49.0;
a[19] = -40*r/245.0;
a[20] = 2*(7*r - 5)/9.0;
a[25] = 3*(21 - r)/392.0;
a[26] = 3*(21 + 121*r)/1960.0;
a[27] = -63*(3*r - 2)/180.0;
a[33] = (6 + r)/5.0;
a[34] = -7*(49 + 9*r)/90.0;
a[41] = 7*(7 - r)/18.0;
}
void del() {
vector<double>().swap(a);
vector<double>().swap(b);
vector<double>().swap(c);
}
void print_tab() {
cout << endl;
cout << "Butcher tableau" << endl;
for (int i = 0; i < nu; i++) {
cout << c[i] << setprecision(2) << " " << "|" << " ";
for (int j = 0; j < nu; j++) {
cout << setw(3) << left << a[j*nu + i];
}
cout << endl;
}
for (int i = 0; i < nu + 5; i++) {
cout << "-";
}
cout << endl;
for (int i = 0; i < nu; i++) {
cout << b[i] << " ";
}
cout << endl;
}
};
#endif
Aucun commentaire:
Enregistrer un commentaire