Fast Methods for Cosmological Simulations
FastSim serves as a tool for quick N-body simulations in modified gravity.
poisson.cpp File Reference
#include <complex>
#include <fstream>
#include <iostream>
#include <fftw3.h>
#include "poisson_solver.h"
Include dependency graph for poisson.cpp:

Go to the source code of this file.

Macros

#define _NDIM   1
 

Typedefs

typedef std::complex< doubleDType
 

Functions

void solve_with_fft (Grid< 1, std::complex< double > > &drho, Grid< 1, std::complex< double > > &sol)
 
void solve_with_fft (Grid< 1, double > &drho, Grid< 1, double > &sol)
 
void set_rho (MultiGrid< 1, DType > &rho_mg, Grid< 1, DType > &analytical_solution)
 
DType f_analytical (double x)
 
DType laplacian_f_analytical (double x)
 
int main (int argv, char **argc)
 

Macro Definition Documentation

#define _NDIM   1

Definition at line 24 of file poisson.cpp.

Referenced by solve_with_fft().

Typedef Documentation

typedef std::complex<double> DType

Definition at line 29 of file poisson.cpp.

Function Documentation

std::complex< double > f_analytical ( double  x)

Definition at line 44 of file poisson.cpp.

Referenced by set_rho().

44  {
45  const double pi = std::acos(-1);
46  const std::complex<double> I(0, 1);
47  return std::exp(2.0 * pi * I * x);
48 }
static CCL_BEGIN_DECLS double x[111][8]
std::complex< double > laplacian_f_analytical ( double  x)

Definition at line 50 of file poisson.cpp.

Referenced by set_rho().

50  {
51  const double pi = std::acos(-1);
52  const std::complex<double> I(0, 1);
53  return - 4.0 * pi * pi * std::exp(2.0 * pi * I * x);
54 }
static CCL_BEGIN_DECLS double x[111][8]
int main ( int  argv,
char **  argc 
)

Definition at line 151 of file poisson.cpp.

References MultiGridSolver< NDIM, T >::add_external_grid(), MultiGridSolver< NDIM, T >::clear(), Catch::cout(), MultiGrid< NDIM, T >::get_grid(), MultiGridSolver< NDIM, T >::get_grid(), MultiGridSolver< NDIM, T >::get_N(), Grid< NDIM, T >::rms_norm(), MultiGridSolver< NDIM, T >::set_epsilon(), MultiGridSolver< NDIM, T >::set_ngs_sweeps(), set_rho(), MultiGridSolver< NDIM, T >::solve(), and solve_with_fft().

151  {
152 
153  int NgridPerDim = 256;
154  bool verbose = true;
155  MultiGrid<_NDIM, DType> rho(NgridPerDim);
156  Grid<_NDIM, DType> analytical_solution(NgridPerDim);
157 
158  // Make density grid
159  set_rho(rho, analytical_solution);
160 
161  // Set up solver
162  PoissonSolver<_NDIM, DType> sol(NgridPerDim, verbose);
163 
164  // Add pointer to the source grid to the solver
165  sol.add_external_grid(&rho);
166 
167  // Set options
168  sol.set_epsilon(1e-10);
169  sol.set_ngs_sweeps(2,2);
170 
171  // Solve the equation
172  sol.solve();
173 
174  // Copy over solution
175  Grid<_NDIM, DType> solution = sol.get_grid();
176 
177  // Compute the fractional error wrt the analytical solution
178  Grid<_NDIM, DType> err = (solution - analytical_solution) / (analytical_solution) * std::complex<double>(100.0);
179  std::cout << "The rms error in the solution: " << err.rms_norm() << " %" << std::endl;
180 
181  Grid<_NDIM,DType> fft_sol = rho.get_grid(0);
182  solve_with_fft(rho.get_grid(0), fft_sol);
183 
184  // Output solution(s)
185  std::ofstream fp("test_poisson_solver_complex.txt");
186  int N = sol.get_N(0);
187  for(int i = 0; i < N; i++){
188  fp << (i+0.5)/double(N) << " " << solution[i].real() << " " << fft_sol[i].real() << " " << analytical_solution[i].real() << std::endl;
189  }
190 
191  // Clean up all memory
192  sol.clear();
193 }
double double
Definition: precision.hpp:19
void solve_with_fft(Grid< 1, std::complex< double > > &drho, Grid< 1, std::complex< double > > &sol)
Definition: poisson.cpp:102
Definition: grid.h:21
void set_rho(MultiGrid< 1, DType > &rho_mg, Grid< 1, DType > &analytical_solution)
Definition: poisson.cpp:60
std::ostream & cout()
void clear()
Definition: grid.cpp:197
double rms_norm()
Definition: grid.h:238
void set_rho ( MultiGrid< 1, DType > &  rho_mg,
Grid< 1, DType > &  analytical_solution 
)

Definition at line 60 of file poisson.cpp.

References Catch::cout(), f_analytical(), MultiGrid< NDIM, T >::get_N(), MultiGrid< NDIM, T >::get_Ntot(), Grid< NDIM, T >::get_y(), MultiGrid< NDIM, T >::get_y(), laplacian_f_analytical(), MultiGrid< NDIM, T >::restrict_down_all(), and sqrt().

Referenced by main().

60  {
61  int N = rho_mg.get_N();
62  int Ntot = rho_mg.get_Ntot();
63  DType *rho = rho_mg.get_y(0);
64  DType *yanal = analytical_solution.get_y();
65 
66  DType rhomean = 0.0;
67  for(int i = 0; i < Ntot; i++){
68  double xx = ((i % N) + 0.5) / double(N);
69 
70  // Set source rho such that solution to D^2 phi = rho is phi = e^{ 2 pi i x}
71  rho[i] = laplacian_f_analytical(xx);
72  yanal[i] = f_analytical(xx);
73 
74  // Box average of rho
75  rhomean += rho[i];
76  }
77  rhomean = rhomean/double(Ntot);
78  std::cout << "set_rho :: Box average of source |<rho>| = " << std::sqrt(std::norm(rhomean)) << std::endl;
79 
80  // Restrict down source to all levels
81  rho_mg.restrict_down_all();
82 }
double double
Definition: precision.hpp:19
void restrict_down_all()
Definition: multigrid.cpp:209
size_t get_Ntot(size_t level=0) const
Definition: multigrid.cpp:98
size_t get_N(size_t level=0) const
Definition: multigrid.cpp:90
T * get_y()
Definition: grid.cpp:41
std::ostream & cout()
Grid< NDIM, T > sqrt(Grid< NDIM, T > lhs)
Definition: grid.h:231
T * get_y(size_t level=0)
Definition: multigrid.cpp:49
DType laplacian_f_analytical(double x)
Definition: poisson.cpp:50
DType f_analytical(double x)
Definition: poisson.cpp:44
std::complex< double > DType
Definition: poisson.cpp:29
void solve_with_fft ( Grid< 1, std::complex< double > > &  drho,
Grid< 1, std::complex< double > > &  sol 
)

Definition at line 102 of file poisson.cpp.

References _NDIM.

Referenced by main(), and solve_with_fft().

102  {
103  int N = drho.get_N(), Nover2 = N/2, Ntot = drho.get_Ntot();
104 
105  fftw_complex *in = reinterpret_cast<fftw_complex*>(drho.get_y());
106  fftw_complex *out = reinterpret_cast<fftw_complex*>(sol.get_y());
107 
108 #if _NDIM == 1
109  fftw_plan fwd = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
110  fftw_plan bwd = fftw_plan_dft_1d(N, out, out, FFTW_BACKWARD, FFTW_ESTIMATE);
111 #elif _NDIM == 2
112  fftw_plan fwd = fftw_plan_dft_2d(N, N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
113  fftw_plan bwd = fftw_plan_dft_2d(N, N, out, out, FFTW_BACKWARD, FFTW_ESTIMATE);
114 #elif _NDIM == 3
115  fftw_plan fwd = fftw_plan_dft_3d(N, N, N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
116  fftw_plan bwd = fftw_plan_dft_3d(N, N, N, out, out, FFTW_BACKWARD, FFTW_ESTIMATE);
117 #else
118  std::vector<int> inds(_NDIM, N);
119  fftw_plan fwd = fftw_plan_dft(_NDIM, &inds[0], in, out, FFTW_FORWARD, FFTW_ESTIMATE);
120  fftw_plan bwd = fftw_plan_dft(_NDIM, &inds[0], out, out, FFTW_BACKWARD, FFTW_ESTIMATE);
121 #endif
122 
123  // Transform
124  fftw_execute(fwd);
125 
126  // Divide by laplacian and normalize
127  double fac = -1.0 / ( 4.0 * std::acos(-1) * std::acos(-1) * double(Ntot) );
128  for(int i = 0; i < Ntot; i++){
129  double k2 = 0.0;
130  int ind = 0;
131  for(int j = 0, Npow = 1; j < _NDIM; j++, Npow *= N){
132  int coord = i / Npow % N;
133  int kval = coord < Nover2 ? coord : coord - N;
134  k2 += kval * kval;
135  ind += coord * Npow;
136  }
137  if(i > 0){
138  double facnow = fac/k2;
139  out[ind][0] *= facnow;
140  out[ind][1] *= facnow;
141  } else {
142  out[0][0] = 0.0;
143  out[0][1] = 0.0;
144  }
145  }
146 
147  // Transform back
148  fftw_execute(bwd);
149 }
double double
Definition: precision.hpp:19
size_t get_N() const
Definition: grid.cpp:135
T * get_y()
Definition: grid.cpp:41
size_t get_Ntot() const
Definition: grid.cpp:141
#define _NDIM
Definition: poisson.cpp:24
void solve_with_fft ( Grid< 1, double > &  drho,
Grid< 1, double > &  sol 
)

Definition at line 88 of file poisson.cpp.

References Grid< NDIM, T >::get_Ntot(), and solve_with_fft().

88  {
89  int Ntot = drho.get_Ntot();
90  Grid<_NDIM, std::complex<double> > drho_complex (Ntot);
91  Grid<_NDIM, std::complex<double> > sol_complex (Ntot);
92  for(int i = 0; i < Ntot; i++){
93  drho_complex[i] = drho[i];
94  sol_complex[i] = drho[i];
95  }
96  solve_with_fft(drho_complex, sol_complex);
97  for(int i = 0; i < Ntot; i++){
98  sol[i] = sol_complex[i].real();
99  }
100 }
void solve_with_fft(Grid< 1, std::complex< double > > &drho, Grid< 1, std::complex< double > > &sol)
Definition: poisson.cpp:102
Definition: grid.h:21
size_t get_Ntot() const
Definition: grid.cpp:141