-
Notifications
You must be signed in to change notification settings - Fork 0
/
sequential-simulation.cpp
128 lines (101 loc) · 3.81 KB
/
sequential-simulation.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/* sequential-simulation.cpp *
* Sequential n-body simulation *
* By: Gareth Ferneyhough *
* University of Nevada, Reno */
#define BOOST_CHRONO_HEADER_ONLY
#include <fstream>
#include <boost/chrono.hpp>
#include "n-body-physics.h"
void saveSimToFile(const std::vector<Body>& saved_states, const int num_bodies);
void loadStateFromFile(std::vector<Body>& initial_state, const int num_bodies);
void writePosition(const std::vector<Body>& saved_states,
std::vector<Body>::const_iterator start,
std::vector<Body>::const_iterator end,
std::ostream& fout);
int main(int argc, char* argv[])
{
// Simulation parameters
const int dt = 60; // one minute time step
const int day_count = 365 * 284; // sim for 284 years
const int output_frequency = 120; // output state every 120 minutes
const int num_bodies = 25; // total number of bodies
const int bodies_per_process = num_bodies; // 1 process here (sequential)
const long runtime = (long long)day_count * 86400 / dt; // runtime in seconds
// Load initial state
NBodyPhysics *physics = new NBodyPhysics();
std::vector<Body> state;
state.reserve(num_bodies);
// This is leftover from parallel version, but its fine.
const int my_rank = 0;
const int my_body_begin = my_rank * bodies_per_process;
std::vector<Body> saved_states;
if (my_rank == 0){
loadStateFromFile(state, num_bodies);
saved_states.reserve(output_frequency / runtime);
}
// Start timer and go
boost::chrono::system_clock::time_point start = boost::chrono::system_clock::now();
// Main Loop
for (int t = 0; t < runtime; ++t){
physics->updateState(state, my_body_begin, bodies_per_process, dt); // update my portion
// Save state and output progress if root
if (my_rank == 0){
if (t % output_frequency == 0){
cout << (float)t / runtime * 100 << endl;
saved_states.insert(saved_states.end(), state.begin(), state.end());
}
}
}
// Done. Write state if root.
boost::chrono::duration<double> sec = boost::chrono::system_clock::now() - start;
if (my_rank == 0){
std::cout << "took " << sec.count() << " seconds\n";
saveSimToFile(saved_states, num_bodies);
}
return 0;
}
void writePosition(const std::vector<Body>& saved_states,
std::vector<Body>::const_iterator start,
std::vector<Body>::const_iterator end,
std::ostream& fout)
{
std::vector<Body>::const_iterator it = start;
while (it != end){
double x = it->position.x;
double y = it->position.y;
double z = it->position.z;
fout.write(reinterpret_cast<char*>(&x), sizeof(x));
fout.write(reinterpret_cast<char*>(&y), sizeof(y));
fout.write(reinterpret_cast<char*>(&z), sizeof(z));
it++;
}
}
void saveSimToFile(const std::vector<Body>& saved_states, const int num_bodies)
{
// Done. Write state at specified interval
assert( saved_states.size() % num_bodies == 0);
std::ofstream fout;
fout.open("data.bin", std::ios::out | std::ios::binary);
typedef std::vector<Body>::const_iterator vec_iter;
for (vec_iter it = saved_states.begin(); it < saved_states.end(); ++it){
writePosition(saved_states, it, it + num_bodies, fout);
}
fout.close();
}
void loadStateFromFile(std::vector<Body>& initial_state, const int num_bodies)
{
// Read state file
std::ifstream fin;
fin.open("solar_system.csv");
const int KM = 1000;
for (int i = 0; i < num_bodies; ++i){
double pos_x, pos_y, pos_z;
double dx, dy, dz;
double mass;
fin >> pos_x >> pos_y >> pos_z >> dx >> dy >> dz >> mass;
Body body( Vector(pos_x*KM, pos_y*KM, pos_z*KM),
Vector(dx*KM, dy*KM, dz*KM), mass);
initial_state.push_back(body);
}
fin.close();
}