initial rust
This commit is contained in:
@@ -1,78 +0,0 @@
|
||||
#include "body.hpp"
|
||||
#include "calc.hpp"
|
||||
#include <cmath>
|
||||
#include <ranges>
|
||||
|
||||
Body::Body(const Position& X, const Velocity& V, const Mass& m, const std::string& name)
|
||||
: X(X), V(V), m(m), name(name) {
|
||||
A = Acceleration{Decimal(0), Decimal(0), Decimal(0)};
|
||||
}
|
||||
|
||||
void Body::addAcceleration(const Acceleration& new_A) {
|
||||
for (const auto& [new_a, cur_a]: std::views::zip(new_A, this->A)){
|
||||
cur_a += new_a;
|
||||
}
|
||||
}
|
||||
|
||||
void Body::subAcceleration(const Acceleration& new_A) {
|
||||
for (const auto& [new_a, cur_a]: std::views::zip(new_A, this->A)){
|
||||
cur_a -= new_a;
|
||||
}
|
||||
}
|
||||
|
||||
std::tuple<Position, Velocity, Mass> Body::save() const {
|
||||
return std::make_tuple(X, V, m);
|
||||
}
|
||||
|
||||
Body Body::load(const std::tuple<Position, Velocity, Mass>& tup) {
|
||||
return Body(std::get<0>(tup), std::get<1>(tup), std::get<2>(tup));
|
||||
}
|
||||
|
||||
void Body::step(Decimal step_size) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
X[i] += step_size * V[i];
|
||||
V[i] += step_size * A[i];
|
||||
A[i] = Decimal(0);
|
||||
}
|
||||
}
|
||||
|
||||
Decimal Body::E() const {
|
||||
return ke() + pe();
|
||||
}
|
||||
|
||||
Decimal Body::pe() const {
|
||||
return -m / dist_from_o();
|
||||
}
|
||||
|
||||
Decimal Body::dist_from_o() const {
|
||||
Decimal sum = Decimal(0);
|
||||
for (const auto& x : X) {
|
||||
sum += x * x;
|
||||
}
|
||||
return std::sqrt(sum);
|
||||
}
|
||||
|
||||
Decimal Body::ke() const {
|
||||
return Decimal(0.5) * m * (_speed() * _speed());
|
||||
}
|
||||
|
||||
Decimal Body::_speed() const {
|
||||
Decimal sum = Decimal(0);
|
||||
for (const auto& v : V) {
|
||||
sum += v * v;
|
||||
}
|
||||
return std::sqrt(sum);
|
||||
}
|
||||
|
||||
std::string Body::speed() const {
|
||||
return format_sig_figs(real_vel(_speed()), 5);
|
||||
}
|
||||
|
||||
std::string Body::toString() const {
|
||||
std::string pos_str, vel_str;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
pos_str += format_sig_figs(real_pos(X[i]), 10) + "m ";
|
||||
vel_str += format_sig_figs(real_vel(V[i]), 10) + "m/s ";
|
||||
}
|
||||
return name + ": X = " + pos_str + ", V = " + vel_str;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "units.hpp"
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <memory>
|
||||
|
||||
class Body {
|
||||
public:
|
||||
Body(const Position& X, const Velocity& V, const Mass& m,
|
||||
const std::string& name = "");
|
||||
|
||||
// Save and load state
|
||||
std::tuple<Position, Velocity, Mass> save() const;
|
||||
static Body load(const std::tuple<Position, Velocity, Mass>& tup);
|
||||
|
||||
// Physics calculations
|
||||
void step(Decimal step_size);
|
||||
Decimal E() const; // Total energy
|
||||
Decimal pe() const; // Potential energy
|
||||
Decimal ke() const; // Kinetic energy
|
||||
Decimal dist_from_o() const; // Distance from origin
|
||||
std::string speed() const; // Speed as formatted string
|
||||
|
||||
// Getters
|
||||
const Position& getPosition() const { return X; }
|
||||
const Velocity& getVelocity() const { return V; }
|
||||
const Acceleration& getAcceleration() const { return A; }
|
||||
const Mass& getMass() const { return m; }
|
||||
const std::string& getName() const { return name; }
|
||||
|
||||
// Setters
|
||||
void setAcceleration(const Acceleration& new_A) { A = new_A; }
|
||||
|
||||
void addAcceleration(const Acceleration& new_A);
|
||||
void subAcceleration(const Acceleration& new_A);
|
||||
// String representation
|
||||
std::string toString() const;
|
||||
|
||||
private:
|
||||
Position X;
|
||||
Velocity V;
|
||||
Acceleration A;
|
||||
Mass m;
|
||||
std::string name;
|
||||
|
||||
Decimal _speed() const; // Internal speed calculation
|
||||
};
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
#include "calc.hpp"
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <boost/multiprecision/cpp_dec_float.hpp>
|
||||
|
||||
std::vector<std::vector<Decimal>> calculate_distances(const std::vector<Position>& positions) {
|
||||
int N = positions.size();
|
||||
std::vector<std::vector<Decimal>> dists(N, std::vector<Decimal>(N, Decimal(0)));
|
||||
|
||||
for (int i = 0; i < N; ++i) {
|
||||
for (int j = i + 1; j < N; ++j) {
|
||||
Decimal sum = Decimal(0);
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
Decimal diff = positions[i][k] - positions[j][k];
|
||||
sum += diff * diff;
|
||||
}
|
||||
Decimal d = std::sqrt(sum);
|
||||
dists[i][j] = d;
|
||||
dists[j][i] = d;
|
||||
}
|
||||
}
|
||||
return dists;
|
||||
}
|
||||
|
||||
std::string format_sig_figs(Decimal value, int sig_figs) {
|
||||
if (value == 0) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::scientific << std::setprecision(sig_figs - 1) << value;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void print_progress_bar(int iteration, int total, std::chrono::time_point<std::chrono::steady_clock> start_time, int length, Decimal step_size) {
|
||||
float percent = (float)iteration / total * 100;
|
||||
int filled_length = length * iteration / total;
|
||||
|
||||
std::string bar;
|
||||
bar.reserve(length + 1);
|
||||
bar += '[';
|
||||
bar.append(filled_length, '#');
|
||||
bar.append(length - filled_length, '-');
|
||||
bar += ']';
|
||||
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - start_time).count();
|
||||
double steps_per_second = elapsed > 0 ? real_time(Decimal(iteration) * step_size) / elapsed : 0;
|
||||
|
||||
// Determine appropriate time unit
|
||||
std::string time_unit;
|
||||
if (steps_per_second >= 3600) {
|
||||
time_unit = "hour/s";
|
||||
steps_per_second /= 3600;
|
||||
} else if (steps_per_second >= 60) {
|
||||
time_unit = "min/s";
|
||||
steps_per_second /= 60;
|
||||
} else {
|
||||
time_unit = "s/s";
|
||||
}
|
||||
|
||||
// Clear the current line and move cursor to start
|
||||
std::cout << "\r\033[K";
|
||||
|
||||
// Print the progress bar
|
||||
std::cout << bar << " " << std::fixed << std::setprecision(2)
|
||||
<< percent << "% " << std::setprecision(1) << steps_per_second << " " << time_unit << std::flush;
|
||||
}
|
||||
|
||||
#ifdef NCURSES_ENABLED
|
||||
void plot_points_terminal(const std::vector<Position>& vectors, WINDOW* stdscr,
|
||||
Decimal scale, int grid_width, int grid_height) {
|
||||
if (vectors.empty()) {
|
||||
mvwaddstr(stdscr, 0, 0, "No vectors provided.");
|
||||
wrefresh(stdscr);
|
||||
return;
|
||||
}
|
||||
|
||||
// Scale and round vectors
|
||||
std::vector<std::pair<int, int>> scaled_vectors;
|
||||
for (const auto& vec : vectors) {
|
||||
scaled_vectors.emplace_back(
|
||||
std::round(vec[0] / scale),
|
||||
std::round(vec[1] / scale)
|
||||
);
|
||||
}
|
||||
|
||||
// Find bounds
|
||||
int min_x = scaled_vectors[0].first;
|
||||
int max_x = min_x;
|
||||
int min_y = scaled_vectors[0].second;
|
||||
int max_y = min_y;
|
||||
|
||||
for (const auto& vec : scaled_vectors) {
|
||||
min_x = std::min(min_x, vec.first);
|
||||
max_x = std::max(max_x, vec.first);
|
||||
min_y = std::min(min_y, vec.second);
|
||||
max_y = std::max(max_y, vec.second);
|
||||
}
|
||||
|
||||
// Center offsets
|
||||
int center_x = (grid_width / 2) - min_x;
|
||||
int center_y = (grid_height / 2) - min_y;
|
||||
|
||||
// Adjust coordinates
|
||||
std::vector<std::pair<int, int>> adjusted_vectors;
|
||||
for (const auto& vec : scaled_vectors) {
|
||||
adjusted_vectors.emplace_back(
|
||||
vec.first + center_x,
|
||||
vec.second + center_y
|
||||
);
|
||||
}
|
||||
|
||||
// Get terminal bounds
|
||||
int max_terminal_y, max_terminal_x;
|
||||
getmaxyx(stdscr, max_terminal_y, max_terminal_x);
|
||||
max_x = std::min(grid_width, max_terminal_x - 5);
|
||||
max_y = std::min(grid_height, max_terminal_y - 5);
|
||||
|
||||
// Draw grid
|
||||
for (int i = grid_height; i >= 0; --i) {
|
||||
std::string row = std::to_string(i - center_y) + " | ";
|
||||
for (int j = 0; j <= grid_width; ++j) {
|
||||
bool has_point = false;
|
||||
for (const auto& vec : adjusted_vectors) {
|
||||
if (vec.first == j && vec.second == i) {
|
||||
has_point = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
row += has_point ? "● " : ". ";
|
||||
}
|
||||
mvwaddstr(stdscr, max_y - i, 0, row.substr(0, max_terminal_x - 1).c_str());
|
||||
}
|
||||
|
||||
// Print X-axis labels
|
||||
std::string x_labels = " ";
|
||||
for (int j = 0; j <= max_x; ++j) {
|
||||
x_labels += std::to_string(j - center_x) + " ";
|
||||
}
|
||||
mvwaddstr(stdscr, max_y + 1, 0, x_labels.substr(0, max_terminal_x - 1).c_str());
|
||||
|
||||
wrefresh(stdscr);
|
||||
}
|
||||
#endif
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "units.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <chrono>
|
||||
|
||||
// Calculate distances between all bodies
|
||||
std::vector<std::vector<Decimal>> calculate_distances(const std::vector<Position>& positions);
|
||||
|
||||
// Format a number to a specified number of significant figures
|
||||
std::string format_sig_figs(Decimal value, int sig_figs);
|
||||
|
||||
// Print progress bar
|
||||
void print_progress_bar(int iteration, int total, std::chrono::time_point<std::chrono::steady_clock> start_time, int length, Decimal step_size);
|
||||
|
||||
// Terminal plotting functions (if needed)
|
||||
#ifdef NCURSES_ENABLED
|
||||
#include <ncurses.h>
|
||||
void plot_points_terminal(const std::vector<Position>& vectors, WINDOW* stdscr,
|
||||
Decimal scale = 500000, int grid_width = 30, int grid_height = 30);
|
||||
#endif
|
||||
-167
@@ -1,167 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/program_options.hpp>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "simulator.hpp"
|
||||
#include "body.hpp"
|
||||
#include "units.hpp"
|
||||
|
||||
using json = nlohmann::json;
|
||||
namespace po = boost::program_options;
|
||||
|
||||
struct SimulationConfig {
|
||||
std::string config_file;
|
||||
std::string output_file;
|
||||
int steps;
|
||||
int steps_per_save;
|
||||
Decimal step_size; // Changed to Decimal for normalized time
|
||||
bool overwrite_output;
|
||||
double simulation_time; // in seconds (real time)
|
||||
};
|
||||
|
||||
// Convert time string to seconds
|
||||
double parse_time(const std::string& time_str) {
|
||||
std::string value_str = time_str;
|
||||
std::string unit;
|
||||
|
||||
// Extract the unit (last character)
|
||||
if (!time_str.empty()) {
|
||||
unit = time_str.back();
|
||||
value_str = time_str.substr(0, time_str.length() - 1);
|
||||
}
|
||||
|
||||
double value = std::stod(value_str);
|
||||
|
||||
// Convert to seconds based on unit
|
||||
switch (unit[0]) {
|
||||
case 's': return value; // seconds
|
||||
case 'm': return value * 60; // minutes
|
||||
case 'h': return value * 3600; // hours
|
||||
case 'd': return value * 86400; // days
|
||||
default: throw std::runtime_error("Invalid time unit. Use s/m/h/d for seconds/minutes/hours/days");
|
||||
}
|
||||
}
|
||||
|
||||
SimulationConfig parse_command_line(int argc, char* argv[]) {
|
||||
SimulationConfig config;
|
||||
double temp_step_size; // Temporary variable for parsing
|
||||
|
||||
po::options_description desc("Orbital Simulator Options");
|
||||
desc.add_options()
|
||||
("help,h", "Show help message")
|
||||
("config,c", po::value<std::string>(&config.config_file)->required(),
|
||||
"Path to body configuration file (JSON)")
|
||||
("output,o", po::value<std::string>(&config.output_file)->required(),
|
||||
"Path to output file")
|
||||
("time,t", po::value<std::string>()->required(),
|
||||
"Simulation time with unit (e.g., 1h for 1 hour, 30m for 30 minutes, 2d for 2 days)")
|
||||
("step-size,s", po::value<double>(&temp_step_size)->default_value(1.0),
|
||||
"Simulation step size in seconds")
|
||||
("steps-per-save,p", po::value<int>(&config.steps_per_save)->default_value(100),
|
||||
"Number of steps between saves")
|
||||
("overwrite,w", po::bool_switch(&config.overwrite_output),
|
||||
"Overwrite output file if it exists");
|
||||
|
||||
po::variables_map vm;
|
||||
try {
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
|
||||
if (vm.count("help")) {
|
||||
std::cout << desc << "\n";
|
||||
exit(0);
|
||||
}
|
||||
|
||||
po::notify(vm);
|
||||
|
||||
// Parse simulation time
|
||||
config.simulation_time = parse_time(vm["time"].as<std::string>());
|
||||
|
||||
// Convert step size to Decimal and normalize
|
||||
config.step_size = norm_time(Decimal(temp_step_size));
|
||||
|
||||
// Calculate number of steps based on normalized time and step size
|
||||
config.steps = static_cast<int>(norm_time(config.simulation_time) / config.step_size);
|
||||
|
||||
} catch (const po::error& e) {
|
||||
std::cerr << "Error: " << e.what() << "\n";
|
||||
std::cerr << desc << "\n";
|
||||
exit(1);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error: " << e.what() << "\n";
|
||||
std::cerr << desc << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
std::vector<Body> load_bodies(const std::string& config_file) {
|
||||
std::ifstream f(config_file);
|
||||
if (!f.is_open()) {
|
||||
throw std::runtime_error("Could not open config file: " + config_file);
|
||||
}
|
||||
|
||||
json j;
|
||||
f >> j;
|
||||
|
||||
std::vector<Body> bodies;
|
||||
for (const auto& body : j["bodies"]) {
|
||||
std::string name = body["name"];
|
||||
double mass = body["mass"];
|
||||
|
||||
std::vector<double> pos = body["position"];
|
||||
std::vector<double> vel = body["velocity"];
|
||||
|
||||
if (pos.size() != 3 || vel.size() != 3) {
|
||||
throw std::runtime_error("Position and velocity must be 3D vectors");
|
||||
}
|
||||
|
||||
// Normalize units before creating the body
|
||||
Position position{norm_pos(pos[0]), norm_pos(pos[1]), norm_pos(pos[2])};
|
||||
Velocity velocity{norm_vel(vel[0]), norm_vel(vel[1]), norm_vel(vel[2])};
|
||||
Mass normalized_mass = norm_mass(mass);
|
||||
|
||||
bodies.emplace_back(position, velocity, normalized_mass, name);
|
||||
|
||||
std::cout << "Loaded " << name << " with mass " << mass << " kg\n";
|
||||
}
|
||||
|
||||
return bodies;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
try {
|
||||
// Parse command line options
|
||||
auto config = parse_command_line(argc, argv);
|
||||
|
||||
// Load bodies from config file
|
||||
auto bodies = load_bodies(config.config_file);
|
||||
|
||||
// Create and run simulator
|
||||
Simulator simulator(
|
||||
bodies,
|
||||
config.step_size,
|
||||
config.steps_per_save,
|
||||
config.output_file,
|
||||
0, // current_step
|
||||
config.overwrite_output
|
||||
);
|
||||
|
||||
std::cout << "Starting simulation with " << bodies.size() << " bodies\n";
|
||||
std::cout << "Step size: " << real_time(config.step_size) << " seconds\n";
|
||||
std::cout << "Simulation time: " << config.simulation_time << " seconds\n";
|
||||
std::cout << "Total steps: " << config.steps << "\n";
|
||||
std::cout << "Steps per save: " << config.steps_per_save << "\n";
|
||||
|
||||
simulator.run(config.steps);
|
||||
|
||||
std::cout << "Simulation completed successfully\n";
|
||||
return 0;
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Error: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
use clap::Parser;
|
||||
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(
|
||||
version,
|
||||
about="Orbital mechanics simulator",
|
||||
long_about = "Given initial conditions you provide to --config, \
|
||||
this program will numerically integrate and determinate their \
|
||||
paths based off Newton's law of gravity.")]
|
||||
struct Args {
|
||||
///Config file for initial conditions
|
||||
#[arg(short, long)]
|
||||
config: String,
|
||||
|
||||
///Step size for simulation (seconds)
|
||||
#[arg(short, long, default_value_t = 10)]
|
||||
step_size: u8,
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args = Args::parse();
|
||||
|
||||
println!("Loading initial parameters from {}", args.config);
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
#include "simulator.hpp"
|
||||
#include "calc.hpp"
|
||||
#include <fstream>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
Simulator::Simulator(const std::vector<Body>& bodies,
|
||||
Decimal step_size,
|
||||
int steps_per_save,
|
||||
const std::filesystem::path& output_file,
|
||||
int current_step,
|
||||
bool overwrite_output)
|
||||
: bodies(bodies),
|
||||
step_size(step_size),
|
||||
steps_per_save(steps_per_save),
|
||||
output_file(output_file),
|
||||
current_step(current_step) {
|
||||
|
||||
if (std::filesystem::exists(output_file) && !overwrite_output) {
|
||||
throw std::runtime_error("File " + output_file.string() + " exists and overwrite flag not given.");
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(output_file) && overwrite_output) {
|
||||
std::cout << "Warning! Overwriting file: " << output_file.string() << std::endl;
|
||||
// Clear the file if we're overwriting
|
||||
std::ofstream clear(output_file, std::ios::trunc);
|
||||
clear.close();
|
||||
}
|
||||
|
||||
out.open(output_file, std::ios::app);
|
||||
if (!out) {
|
||||
throw std::runtime_error("Failed to open output file: " + output_file.string());
|
||||
}
|
||||
|
||||
for (const auto& body : bodies) {
|
||||
out << body.getName() << ": mass=" << body.getMass();
|
||||
out << "\n";
|
||||
}
|
||||
out << "\n";
|
||||
|
||||
// Write initial state
|
||||
checkpoint();
|
||||
}
|
||||
|
||||
Simulator Simulator::from_checkpoint(const std::filesystem::path& output_file) {
|
||||
// TODO: Implement checkpoint loading
|
||||
// This would require implementing a binary format for saving/loading checkpoints
|
||||
throw std::runtime_error("Checkpoint loading not implemented yet");
|
||||
}
|
||||
|
||||
void Simulator::run(int steps) {
|
||||
auto start_time = std::chrono::steady_clock::now();
|
||||
|
||||
for (int i = 0; i < steps; ++i) {
|
||||
calculate_forces();
|
||||
move_bodies();
|
||||
if (i % steps_per_save == 0) {
|
||||
checkpoint();
|
||||
print_progress_bar(i + 1, steps, start_time, 50, step_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Simulator::calculate_forces() {
|
||||
std::vector<Position> positions;
|
||||
positions.reserve(bodies.size());
|
||||
for (const auto& body : bodies) {
|
||||
positions.push_back(body.getPosition());
|
||||
}
|
||||
|
||||
auto dists = calculate_distances(positions);
|
||||
|
||||
// Reset all accelerations to zero
|
||||
for (auto& body : bodies) {
|
||||
body.setAcceleration(Acceleration{Decimal(0), Decimal(0), Decimal(0)});
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < bodies.size(); i++) {
|
||||
for (size_t j = i + 1; j < bodies.size(); j++) {
|
||||
Position vec;
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
vec[k] = positions[i][k] - positions[j][k];
|
||||
}
|
||||
|
||||
Decimal dist = std::sqrt(vec[0] * vec[0] + vec[1] * vec[1] + vec[2] * vec[2]);
|
||||
|
||||
// Calculate force magnitude using Newton's law of gravitation
|
||||
// F = G * m1 * m2 / r^2 BUT G = 1, and we'll multiply by the opposite mass later
|
||||
// for the acceleration. Use r^3 to avoid normalizing vec when multiplying later
|
||||
Decimal force_magnitude = 1 / (dist * dist * dist);
|
||||
|
||||
Decimal acc_magnitude_i = force_magnitude * bodies[j].getMass();
|
||||
Decimal acc_magnitude_j = force_magnitude * bodies[i].getMass();
|
||||
|
||||
// Convert to vector form
|
||||
Acceleration acc_i, acc_j;
|
||||
for (int k = 0; k < 3; ++k) {
|
||||
acc_i[k] = -vec[k] * acc_magnitude_i;
|
||||
acc_j[k] = vec[k] * acc_magnitude_j;
|
||||
}
|
||||
|
||||
bodies[i].addAcceleration(acc_i);
|
||||
bodies[j].addAcceleration(acc_j);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Simulator::move_bodies() {
|
||||
for (auto& body : bodies) {
|
||||
body.step(step_size);
|
||||
}
|
||||
}
|
||||
|
||||
void Simulator::checkpoint() {
|
||||
for (const auto& body : bodies) {
|
||||
out << body.toString() << "\n";
|
||||
}
|
||||
out.flush();
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "body.hpp"
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <fstream>
|
||||
|
||||
class Simulator {
|
||||
public:
|
||||
Simulator(const std::vector<Body>& bodies,
|
||||
Decimal step_size,
|
||||
int steps_per_save,
|
||||
const std::filesystem::path& output_file,
|
||||
int current_step = 0,
|
||||
bool overwrite_output = false);
|
||||
|
||||
// Create simulator from checkpoint
|
||||
static Simulator from_checkpoint(const std::filesystem::path& output_file);
|
||||
|
||||
// Run simulation
|
||||
void run(int steps);
|
||||
|
||||
// Getters
|
||||
const std::vector<Body>& getBodies() const { return bodies; }
|
||||
Decimal getStepSize() const { return step_size; }
|
||||
int getStepsPerSave() const { return steps_per_save; }
|
||||
const std::filesystem::path& getOutputFile() const { return output_file; }
|
||||
int getCurrentStep() const { return current_step; }
|
||||
|
||||
private:
|
||||
void calculate_forces();
|
||||
void move_bodies();
|
||||
void checkpoint();
|
||||
|
||||
std::vector<Body> bodies;
|
||||
Decimal step_size;
|
||||
int steps_per_save;
|
||||
std::filesystem::path output_file;
|
||||
std::ofstream out;
|
||||
int current_step;
|
||||
};
|
||||
@@ -1,46 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
//#include <boost/multiprecision/cpp_dec_float.hpp>
|
||||
|
||||
using Decimal = long double; //boost::multiprecision::cpp_dec_float_50;
|
||||
|
||||
// Type aliases for clarity
|
||||
using Position = std::array<Decimal, 3>;
|
||||
using Velocity = std::array<Decimal, 3>;
|
||||
using Acceleration = std::array<Decimal, 3>;
|
||||
using Mass = Decimal;
|
||||
|
||||
// Constants
|
||||
const Decimal EARTH_MASS = 5972e21;//Decimal("5972e21"); // kg
|
||||
const Decimal EARTH_RADIUS = 6378e3;//Decimal("6378e3"); // meters
|
||||
const Decimal EARTH_ORBITAL_VELOCITY = 29780;//Decimal("29780"); // m/s
|
||||
const Decimal AU = 149597870700;//Decimal("149597870700"); // meters
|
||||
|
||||
const Decimal MOON_MASS = 734767309e14;//Decimal("734767309e14");
|
||||
const Decimal MOON_ORBITAL_VELOCITY = 1022;//Decimal("1022"); // m/s relative to earth
|
||||
|
||||
const Decimal SUN_MASS = 1989e27;//Decimal("1989e27"); // kg
|
||||
const Decimal SUN_RADIUS = 6957e5;//Decimal("6957e5"); // meters
|
||||
|
||||
const Decimal PI = 3.14159265358979323846264338327950288419716939937510;
|
||||
|
||||
// Normalizing constants
|
||||
const Decimal G = 6.67430e-11;
|
||||
const Decimal r_0 = EARTH_RADIUS;
|
||||
const Decimal m_0 = 5.972e24;
|
||||
const Decimal t_0 = std::sqrt((r_0 * r_0 * r_0) / (G * m_0));
|
||||
|
||||
// Utility functions
|
||||
inline Decimal norm_pos(Decimal pos) { return pos / r_0; }
|
||||
inline Decimal real_pos(Decimal pos) { return pos * r_0; }
|
||||
inline Decimal norm_mass(Decimal mass) { return mass / m_0; }
|
||||
inline Decimal real_mass(Decimal mass) { return mass * m_0; }
|
||||
inline Decimal norm_time(Decimal time) { return time / t_0; }
|
||||
inline Decimal real_time(Decimal time) { return time * t_0; }
|
||||
inline Decimal norm_vel(Decimal vel) { return vel / (r_0/t_0); }
|
||||
inline Decimal real_vel(Decimal vel) { return vel * (r_0/t_0); }
|
||||
inline Decimal norm_acc(Decimal acc) { return acc / (r_0/(t_0*t_0)); }
|
||||
inline Decimal real_acc(Decimal acc) { return acc * (r_0/(t_0*t_0)); }
|
||||
Reference in New Issue
Block a user