/*
* Copyright (c) 2025 Konrad Gębik
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
*/
#include
#include "Simulation.hpp"
#include "Vector.hpp"
Vector Simulation::getPosition() const {
return {position.x, position.y, position.z};
}
Vector Simulation::getVelocity() const {
return {velocity.x, velocity.y, velocity.z};
}
double Simulation::getTime() const {
return time;
}
double Simulation::getEnergy() const {
double m = mass1 + mass2, mprod = mass1 * mass2;
double energy = 0;
energy += mprod / m * getVelocity().normSq() / 2 - mprod / getPosition().norm();
energy -= mprod * (mass1*mass1*mass1 + mass2*mass2*mass2) / (m*m*m*m) * getVelocity().normSq()*getVelocity().normSq();
energy += m * mprod / getPosition().normSq() / 2;
return energy;
}
Vector Simulation::PNapprox(double time, Vector pos, Vector vel) {
double m = mass1 + mass2, eta = mass1*mass2 / (m*m);
double r = pos.norm(), v = vel.norm();
double rdot = pos.dotProduct(vel) / r;
Vector value;
value = -1*m/(r*r*r)*pos;
if (PNorder >= 1) {
double APN = 3/2*eta*rdot*rdot + (4 + 2*eta)*m/r - (1 + 3*eta)*v*v;
double BPN = 4 - 2*eta;
if (PNorder >= 2) {
APN += -eta*(3 - 4*eta)*v*v*v*v + eta*(13 - 4*eta)*v*v*m/r/2 + 3*eta*(3 - 4*eta)*v*v*rdot*rdot/2 + (2 + 25*eta + 2*eta*eta)*rdot*rdot*m/r
-15*eta*(1 - 3*eta)*rdot*rdot*rdot*rdot/8 - 3*(12 + 29*eta)*m*m/r/r/4;
BPN += eta*(15 + 4*eta)*v*v/2 - 3*eta*(3 + 2*eta)*rdot*rdot/2 - (4 + 41*eta + 8*eta*eta)*m/r/2;
}
value += (APN/r*pos + rdot*BPN*vel)*m/r/r;
}
return value;
}
void Simulation::simulate() {
Vector k1vel = PNapprox(time, position, velocity);
Vector k1pos = velocity;
Vector k2vel = PNapprox(time + deltaTime / 2, position + deltaTime / 2 * k1pos, velocity + deltaTime / 2 * k1vel);
Vector k2pos = velocity + deltaTime / 2 * k1vel;
Vector k3vel = PNapprox(time + deltaTime / 2, position + deltaTime / 2 * k2pos, velocity + deltaTime / 2 * k2vel);
Vector k3pos = velocity + deltaTime / 2 * k2vel;
Vector k4vel = PNapprox(time + deltaTime, position + deltaTime * k3pos, velocity + deltaTime * k3vel);
Vector k4pos = velocity + deltaTime * k3vel;
position += deltaTime / 6 * (k1pos + 2 * k2pos + 2 * k3pos + k4pos);
velocity += deltaTime / 6 * (k1vel + 2 * k2vel + 2 * k3vel + k4vel);
time += deltaTime;
}