Fast Methods for Cosmological Simulations
FastSim serves as a tool for quick N-body simulations in modified gravity.
fofr.cpp
Go to the documentation of this file.
1 #include "fofr_solver.h"
2 #include <fstream>
3 
4 //=====================================
5 //
6 // This is an example of how to use the
7 // multigrid solver class for solving
8 //
9 // D[b(u) D f(u)] = g(u,rho)
10 //
11 // where b(u) = e^u
12 //
13 //=====================================
14 
15 //=====================================
16 // The dim of the equation we solve
17 //=====================================
18 #define _NDIM 3
19 
20 //=====================================
21 // Particle data container
22 //=====================================
23 class Particle{
24  public:
25  double x, y, z;
26  Particle() {};
27 };
28 
29 //=====================================
30 // Methods below
31 //=====================================
32 void read_particles(std::string filename, std::vector<Particle> &P);
33 void assign_to_grid(Grid<_NDIM, double>& f, std::vector<Particle> &P, std::string store_grid_filename);
34 bool exists(std::string filename);
35 
36 //=====================================
37 // Read particles from ascii file
38 //
39 // ------------------------------------
40 // Format:
41 // ------------------------------------
42 // npart
43 // x1 y1 z1 vx1 vy1 vz1
44 // x2 y2 z2 vx2 vy2 vz2
45 // ...
46 // xn yn zn vxn vyn vzn
47 // ------------------------------------
48 //
49 //=====================================
50 void read_particles(std::string filename, std::vector<Particle> &P){
51  unsigned int npart = 0;
52 
53  // Check if file exists
54  if( ! exists(filename) ){
55  std::cout << "File [" << filename << "] does not exist" << std::endl;
56  exit(1);
57  } else {
58  std::cout << "Reading particles from file [" << filename << "]" << std::endl;
59  }
60 
61  // Open particle file
62  std::ifstream fp;
63  fp.open( filename.c_str() );
64 
65  fp >> npart;
66  std::cout << "Npart: " << npart << std::endl;
67 
68  // Allocate memory
69  P = std::vector<Particle>(npart);
70 
71  // Read particles into memory
72  for(unsigned int i = 0; i < npart; i++){
73  double vx, vy, vz;
74  fp >> P[i].x;
75  fp >> P[i].y;
76  fp >> P[i].z;
77  fp >> vx;
78  fp >> vy;
79  fp >> vz;
80  }
81  std::cout << "Particles read" << std::endl;
82 }
83 
84 //=============================================
85 // Read particle-file and assign the particles
86 // to grid to compute rho(x,y,z,...)
87 //=============================================
88 void assign_to_grid(Grid<_NDIM, double>& f, std::vector<Particle> &P, std::string store_grid_filename){
89  unsigned int npart = P.size();
90  unsigned int N = f.get_N();
91  unsigned int Ntot = f.get_Ntot();
92  double *y = f.get_y();
93 
94  std::cout << "Assigning " << npart << " particles to grid with N: " << N << " Ntot: " << Ntot << std::endl;
95 
96  // Assign to grid
97  for(unsigned int i = 0; i < npart; i++){
98  unsigned int ix = int(P[i].x * N);
99  unsigned int iy = int(P[i].y * N);
100  unsigned int iz = int(P[i].z * N);
101 
102  if(ix == N) ix = 0;
103  if(iy == N) iy = 0;
104  if(iz == N) iz = 0;
105 
106  unsigned int index = ix + N * (iy + N * iz);
107 
108  y[index] += 1.0;
109  }
110 
111  // Normalize to delta = rho/rho_mean - 1
112  double rhomean = double(npart) / double(Ntot);
113  double sum = 0.0, max = -1e30, min = 1e30;
114  for(unsigned int i = 0; i < Ntot; i++){
115  y[i] = y[i] / rhomean - 1.0;
116  if(y[i] > max) max = y[i];
117  if(y[i] < min) min = y[i];
118  sum += y[i];
119  }
120  std::cout << "Average: " << sum / double(Ntot) << " Max: " << max << " Min: " << min << std::endl;
121 
122  // Save grid to file...
123  f.dump_to_file(store_grid_filename);
124 }
125 
126 //=============================================
127 // Check if file exists
128 //=============================================
129 bool exists(std::string filename){
130  std::ifstream fp(filename.c_str());
131  return fp.good();
132 }
133 
134 int main(int argc, char **argv){
135  int NgridPerDim = 64;
136  bool verbose = true;
137  std::string prefix = "../test_data/rho_";
138  std::string grid_filename = prefix + std::to_string(NgridPerDim) + ".dat";
139  std::string part_filename = "../test_data/data.ascii";
141 
142  // Read grid from file or read particles from file and then assign to grid
143  if(exists(grid_filename)){
144 
145  // Read domain grid from file
147  tmp.read_from_file(grid_filename);
148 
149  // Make multigrid from grid read from file
150  rho = MultiGrid<_NDIM, double>(tmp);
151 
152  // Read data from other levels if availiable
153  for(unsigned int i = 1; i < rho.get_Nlevel(); i++){
154  int Ntot = rho.get_N(i);
155  Grid<_NDIM, double> &r = rho.get_grid(i);
156 
157  std::string cur_filename = prefix + std::to_string(Ntot) + ".dat";
158  if(exists(cur_filename)) {
159  r.read_from_file(prefix + std::to_string(Ntot) + ".dat");
160  } else {
161  // File do not exist: restict down from upper level
162  rho.restrict_down(i-1);
163  }
164  }
165 
166  // Alternative to the above: restict down density to all levels
167  // rho.restrict_down_all();
168 
169  } else {
170 
171  // Read particles
172  std::vector<Particle> P;
173  read_particles(part_filename, P);
174 
175  // Allocate the density-grid
176  rho = MultiGrid<_NDIM, double>(NgridPerDim);
177 
178  // Assign particles to grid
179  for(unsigned int i = 0; i < rho.get_Nlevel(); i++) {
180  int Ntot = rho.get_N(i);
181  assign_to_grid(rho.get_grid(i), P, prefix + std::to_string(Ntot) + ".dat");
182  }
183  }
184 
185  // Set up solver
186  FofrSolver<_NDIM, double> sol(NgridPerDim, verbose);
187 
188  // Parameters
189  double boxsize = 200.0;
190  double omegam = 0.3;
191  double aexp = 1.0;
192  double nfofr = 1.0;
193  double fofr0 = 1e-5;
194 
195  // Set some options in the solver
196  sol.set_parameters(boxsize, omegam, aexp, nfofr, fofr0);
197  sol.set_ngs_sweeps(30, 10);
198  sol.set_epsilon(1e-8);
199 
200  // Make initial guess
201  sol.set_initial_guess( log(fofr0) );
202 
203  // Add pointer to the source grid to the solver
204  sol.add_external_grid(&rho);
205 
206  // Solve the equation
207  sol.solve();
208 
209  // Fetch a reference to the solution
210  Grid<_NDIM,double> solution = sol.get_grid(0);
211 
212  // Output max and min values for |f_R / f_R0|
213  std::cout << "Solution min/max: " << exp(-solution.min()) / fofr0 << " " << exp(-solution.max()) / fofr0 << std::endl;
214 }
215 
double double
Definition: precision.hpp:19
void restrict_down(size_t from_level)
Definition: multigrid.cpp:204
Particle()
Definition: fofr.cpp:26
double max()
Definition: grid.h:71
double z
Definition: fofr.cpp:25
void dump_to_file(std::string filename)
Definition: grid.cpp:147
Definition: grid.h:21
void read_particles(std::string filename, std::vector< Particle > &P)
Definition: fofr.cpp:50
size_t get_N(size_t level=0) const
Definition: multigrid.cpp:90
size_t get_Nlevel() const
Definition: multigrid.cpp:111
int iz
Definition: mfunc_bm.py:17
size_t get_N() const
Definition: grid.cpp:135
T * get_y()
Definition: grid.cpp:41
void assign_to_grid(Grid< 3, double > &f, std::vector< Particle > &P, std::string store_grid_filename)
Definition: fofr.cpp:88
int main(int argc, char **argv)
Definition: fofr.cpp:134
std::ostream & cout()
size_t get_Ntot() const
Definition: grid.cpp:141
double y
Definition: fofr.cpp:25
static T max(const std::vector< T > &data)
Definition: core_app.cpp:61
bool exists(std::string filename)
Definition: fofr.cpp:129
T min(const std::vector< T > &data)
Definition: chameleon.cpp:140
void read_from_file(std::string filename)
Definition: grid.cpp:165
Grid< NDIM, T > & get_grid(size_t level=0)
Definition: multigrid.cpp:17
double x
Definition: fofr.cpp:25
double min()
Definition: grid.h:84