#include <iostream>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <valarray>
using namespace std;
const double G_SI = 6.67430E-11; // Newton's constant in SI units
const double M_EARTH = 5.9722E24; // Earth's mass in kg
const double M_MOON = 7.342E22; // Lunar mass in kg
const double xL = 384400000.0; // Lunar position in meters
const double yL = 0.0;
// Right-hand side function of the system of ODEs
std::valarray<double> rhs(double t, std::valarray<double> y) {
double r_Earth = sqrt(y[0] * y[0] + y[1] * y[1]);
double r3_Earth = r_Earth * r_Earth * r_Earth;
double dx_L = y[0] - xL;
double dy_L = y[1] - yL;
double r_Moon = sqrt(dx_L * dx_L + dy_L * dy_L);
double r3_Moon = r_Moon * r_Moon * r_Moon;
std::valarray<double> dydt(4);
dydt[0] = y[2]; // dx/dt = vx
dydt[1] = y[3]; // dy/dt = vy
dydt[2] = -G_SI * M_EARTH * y[0] / r3_Earth - G_SI * M_MOON * dx_L / r3_Moon; // dvx/dt
dydt[3] = -G_SI * M_EARTH * y[1] / r3_Earth - G_SI * M_MOON * dy_L / r3_Moon; // dvy/dt
return dydt;
}
// Euler's method
std::valarray<double> euler(double t0, std::valarray<double> y0, double h, double tf) {
double t = t0;
std::valarray<double> y = y0;
// Evolution loop for Euler's method
while (t < tf) {
y += h * rhs(t, y);
t += h;
}
return y;
}
// Runge-Kutta 4th order method
std::valarray<double> rungeKutta4(double t0, std::valarray<double> y0, double h, double tf) {
double t = t0;
std::valarray<double> y = y0;
// Evolution loop for RK4
while (t < tf) {
std::valarray<double> k1 = h * rhs(t, y);
std::valarray<double> k2 = h * rhs(t + 0.5 * h, y + 0.5 * k1);
std::valarray<double> k3 = h * rhs(t + 0.5 * h, y + 0.5 * k2);
std::valarray<double> k4 = h * rhs(t + h, y + k3);
y += (k1 + 2.0 * k2 + 2.0 * k3 + k4) / 6.0;
t += h;
}
return y;
}
// Function to solve the ODEs using specified method and output to a file
void solve_and_output(double t0, double t_end, double dt_output, const std::valarray<double>& y_init, const std::string& filename, char method) {
std::ofstream data_file(filename);
data_file << std::fixed << std::setprecision(5);
data_file << "Time\tX\tY\tVX\tVY" << std::endl;
std::valarray<double> result = y_init;
double t = t0;
double dt = 10.0; // Integration step size
data_file << t << "\t" << result[0] << "\t" << result[1] << "\t" << result[2] << "\t" << result[3] << std::endl;
for (int i = 0; t < t_end; ++i) {
if (method == 'E') {
result = euler(t, result, dt, t + dt);
} else if (method == 'R') {
result = rungeKutta4(t, result, dt, t + dt);
} else {
std::cerr << "Invalid method choice." << std::endl;
return;
}
t += dt;
// Output every dt_output seconds
if (i % static_cast<int>(dt_output / dt) == 0) {
data_file << t << "\t" << result[0] << "\t" << result[1] << "\t" << result[2] << "\t" << result[3] << std::endl;
}
}
data_file.close();
}
int main() {
// Initial conditions
double t0 = 0.0;
double x0 = 0.0;
double y0 = 26378100.0; // Initial position (m)
double vx0 = 3887.3; // Initial velocity (m/s)
double vy0 = 0.0;
// Time parameters
double t_end = 86400.0; // Final time (one day)
double dt_output = 60.0; // Output data every 60 seconds
// Solution vector [x, y, vx, vy]
std::valarray<double> y_init = {x0, y0, vx0, vy0};
// Solve using Euler's method
solve_and_output(t0, t_end, dt_output, y_init, "orbit_data_euler.dat", 'E');
// Solve using RK4 method
solve_and_output(t0, t_end, dt_output, y_init, "orbit_data_rk4_moon.dat", 'R');
std::cout << "Data has been written to 'orbit_data_euler.dat' and 'orbit_data_rk4_moon.dat'." << std::endl;
return 0;
}