1
0
Fork 0
mirror of https://github.com/cosmo-sims/monofonIC.git synced 2024-09-19 17:03:45 +02:00

Merge branch 'random' into 'master'

Merge in new RNG structures and other changes

See merge request ohahn/fastlpt!1
This commit is contained in:
Oliver Hahn 2019-05-20 17:42:58 +02:00
commit 9e04da5c92
9 changed files with 433 additions and 131 deletions

View file

@ -10,6 +10,10 @@ fbase_analysis = output
format = gadget2
filename = ics_gadget.dat
[random]
generator = NGENIC
seed = 9001
[cosmology]
transfer = CLASS #eisenstein
Omega_m = 0.302

View file

@ -5,16 +5,215 @@
#include <general.hh>
#include <grid_fft.hh>
//! convolution class, respecting Orszag's 3/2 rule
template< typename data_t >
class OrszagConvolver
template< typename data_t, typename derived_t >
class BaseConvolver
{
protected:
std::array<size_t,3> np_;
std::array<real_t,3> length_;
public:
BaseConvolver( const std::array<size_t, 3> &N, const std::array<real_t, 3> &L )
: np_( N ), length_( L ) {}
virtual ~BaseConvolver() {}
// implements convolution of two Fourier-space fields
template< typename kfunc1, typename kfunc2, typename opp >
void convolve2( kfunc1 kf1, kfunc2 kf2, Grid_FFT<data_t> & res, opp op ) {}
// implements convolution of three Fourier-space fields
template< typename kfunc1, typename kfunc2, typename kfunc3, typename opp >
void convolve3( kfunc1 kf1, kfunc2 kf2, kfunc3 kf3, Grid_FFT<data_t> & res, opp op ) {}
public:
template< typename opp >
void convolve_Hessians( Grid_FFT<data_t> & inl, const std::array<int,2>& d2l, Grid_FFT<data_t> & inr, const std::array<int,2>& d2r, Grid_FFT<data_t> & res, opp op ){
// transform to FS in case fields are not
inl.FourierTransformForward();
inr.FourierTransformForward();
// perform convolution of Hessians
static_cast<derived_t&>(*this).convolve2(
[&]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inl.template get_k<real_t>(i,j,k);
return -kk[d2l[0]] * kk[d2l[1]] * inl.kelem(i,j,k);
},
[&]( size_t i, size_t j, size_t k ){
auto kk = inr.template get_k<real_t>(i,j,k);
return -kk[d2r[0]] * kk[d2r[1]] * inr.kelem(i,j,k);
}, res, op );
}
template< typename opp >
void convolve_Hessians( Grid_FFT<data_t> & inl, const std::array<int,2>& d2l,
Grid_FFT<data_t> & inm, const std::array<int,2>& d2m,
Grid_FFT<data_t> & inr, const std::array<int,2>& d2r,
Grid_FFT<data_t> & res, opp op )
{
// transform to FS in case fields are not
inl.FourierTransformForward();
inm.FourierTransformForward();
inr.FourierTransformForward();
// perform convolution of Hessians
static_cast<derived_t&>(*this).convolve3(
[&inl,&d2l]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inl.template get_k<real_t>(i,j,k);
return -kk[d2l[0]] * kk[d2l[1]] * inl.kelem(i,j,k);
},
[&inm,&d2m]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inm.template get_k<real_t>(i,j,k);
return -kk[d2m[0]] * kk[d2m[1]] * inm.kelem(i,j,k);
},
[&inr,&d2r]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inr.template get_k<real_t>(i,j,k);
return -kk[d2r[0]] * kk[d2r[1]] * inr.kelem(i,j,k);
}, res, op );
}
template< typename opp >
void convolve_SumHessians( Grid_FFT<data_t> & inl, const std::array<int,2>& d2l, Grid_FFT<data_t> & inr, const std::array<int,2>& d2r1,
const std::array<int,2>& d2r2, Grid_FFT<data_t> & res, opp op ){
// transform to FS in case fields are not
inl.FourierTransformForward();
inr.FourierTransformForward();
// perform convolution of Hessians
static_cast<derived_t&>(*this).convolve2(
[&inl,&d2l]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inl.template get_k<real_t>(i,j,k);
return -kk[d2l[0]] * kk[d2l[1]] * inl.kelem(i,j,k);
},
[&inr,&d2r1,&d2r2]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inr.template get_k<real_t>(i,j,k);
return (-kk[d2r1[0]] * kk[d2r1[1]] -kk[d2r2[0]] * kk[d2r2[1]]) * inr.kelem(i,j,k);
}, res, op );
}
};
//! naive convolution class, disrespecting aliasing
template< typename data_t >
class NaiveConvolver : public BaseConvolver<data_t, NaiveConvolver<data_t>>
{
protected:
Grid_FFT<data_t> *fbuf1_, *fbuf2_;
using BaseConvolver<data_t, NaiveConvolver<data_t>>::np_;
using BaseConvolver<data_t, NaiveConvolver<data_t>>::length_;
public:
NaiveConvolver( const std::array<size_t, 3> &N, const std::array<real_t, 3> &L )
: BaseConvolver<data_t, NaiveConvolver<data_t>>( N, L )
{
fbuf1_ = new Grid_FFT<data_t>(N, length_, kspace_id);
fbuf2_ = new Grid_FFT<data_t>(N, length_, kspace_id);
}
~NaiveConvolver()
{
delete fbuf1_;
delete fbuf2_;
}
template< typename kfunc1, typename kfunc2, typename opp >
void convolve2( kfunc1 kf1, kfunc2 kf2, Grid_FFT<data_t> & res, opp op )
{
//... prepare data 1
fbuf1_->FourierTransformForward(false);
this->copy_in( kf1, *fbuf1_ );
//... prepare data 2
fbuf2_->FourierTransformForward(false);
this->copy_in( kf2, *fbuf2_ );
//... convolve
fbuf1_->FourierTransformBackward();
fbuf2_->FourierTransformBackward();
#pragma omp parallel for
for (size_t i = 0; i < fbuf1_->ntot_; ++i){
(*fbuf2_).relem(i) *= (*fbuf1_).relem(i);
}
fbuf2_->FourierTransformForward();
//... copy data back
res.FourierTransformForward();
copy_out( *fbuf2_, op, res );
}
template< typename kfunc1, typename kfunc2, typename kfunc3, typename opp >
void convolve3( kfunc1 kf1, kfunc2 kf2, kfunc3 kf3, Grid_FFT<data_t> & res, opp op )
{
//... prepare data 1
fbuf1_->FourierTransformForward(false);
this->copy_in( kf1, *fbuf1_ );
//... prepare data 2
fbuf2_->FourierTransformForward(false);
this->copy_in( kf2, *fbuf2_ );
//... convolve
fbuf1_->FourierTransformBackward();
fbuf2_->FourierTransformBackward();
#pragma omp parallel for
for (size_t i = 0; i < fbuf1_->ntot_; ++i){
(*fbuf2_).relem(i) *= (*fbuf1_).relem(i);
}
//... prepare data 2
fbuf1_->FourierTransformForward(false);
this->copy_in( kf3, *fbuf1_ );
//... convolve
fbuf1_->FourierTransformBackward();
#pragma omp parallel for
for (size_t i = 0; i < fbuf1_->ntot_; ++i){
(*fbuf2_).relem(i) *= (*fbuf1_).relem(i);
}
fbuf2_->FourierTransformForward();
//... copy data back
res.FourierTransformForward();
copy_out( *fbuf2_, op, res );
}
private:
template< typename kfunc >
void copy_in( kfunc kf, Grid_FFT<data_t>& g )
{
#pragma omp parallel for
for (size_t i = 0; i < g.size(0); ++i){
for (size_t j = 0; j < g.size(1); ++j){
for (size_t k = 0; k < g.size(2); ++k){
g.kelem(i, j, k) = kf(i, j, k);
}
}
}
}
template< typename opp >
void copy_out( Grid_FFT<data_t>& f, opp op, Grid_FFT<data_t>& res )
{
#pragma omp parallel for
for (size_t i = 0; i < f.size(0); ++i){
for (size_t j = 0; j < f.size(1); ++j){
for (size_t k = 0; k < f.size(2); ++k){
res.kelem(i, j, k) = op(f.kelem(i, j, k), res.kelem(i, j, k));
}
}
}
}
};
//! convolution class, respecting Orszag's 3/2 rule
template< typename data_t >
class OrszagConvolver : public BaseConvolver<data_t, OrszagConvolver<data_t>>
{
private:
Grid_FFT<data_t> *f1p_, *f2p_;
Grid_FFT<data_t> *fbuf_, *fbuf2_;
std::array<size_t,3> np_;
std::array<real_t,3> length_;
using BaseConvolver<data_t, OrszagConvolver<data_t>>::np_;
using BaseConvolver<data_t, OrszagConvolver<data_t>>::length_;
ccomplex_t *crecvbuf_;
real_t *recvbuf_;
@ -22,8 +221,6 @@ protected:
std::vector<ptrdiff_t> offsets_, offsetsp_;
std::vector<size_t> sizes_, sizesp_;
private:
int get_task(ptrdiff_t index, const std::vector<ptrdiff_t>& offsets, const std::vector<size_t>& sizes, const int ntasks )
{
int itask = 0;
@ -35,7 +232,8 @@ public:
OrszagConvolver( const std::array<size_t, 3> &N, const std::array<real_t, 3> &L )
: np_({3*N[0]/2,3*N[1]/2,3*N[2]/2}), length_(L)
: BaseConvolver<data_t,OrszagConvolver<data_t>>( {3*N[0]/2,3*N[1]/2,3*N[2]/2}, L )
//: np_({3*N[0]/2,3*N[1]/2,3*N[2]/2}), length_(L)
{
//... create temporaries
f1p_ = new Grid_FFT<data_t>(np_, length_, kspace_id);
@ -80,67 +278,6 @@ public:
#endif
}
template< typename opp >
void convolve_Hessians( Grid_FFT<data_t> & inl, const std::array<int,2>& d2l, Grid_FFT<data_t> & inr, const std::array<int,2>& d2r, Grid_FFT<data_t> & res, opp op ){
// transform to FS in case fields are not
inl.FourierTransformForward();
inr.FourierTransformForward();
// perform convolution of Hessians
this->convolve2(
[&]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inl.template get_k<real_t>(i,j,k);
return -kk[d2l[0]] * kk[d2l[1]] * inl.kelem(i,j,k);
},
[&]( size_t i, size_t j, size_t k ){
auto kk = inr.template get_k<real_t>(i,j,k);
return -kk[d2r[0]] * kk[d2r[1]] * inr.kelem(i,j,k);
}, res, op );
}
template< typename opp >
void convolve_Hessians( Grid_FFT<data_t> & inl, const std::array<int,2>& d2l,
Grid_FFT<data_t> & inm, const std::array<int,2>& d2m,
Grid_FFT<data_t> & inr, const std::array<int,2>& d2r,
Grid_FFT<data_t> & res, opp op )
{
// transform to FS in case fields are not
inl.FourierTransformForward();
inm.FourierTransformForward();
inr.FourierTransformForward();
// perform convolution of Hessians
this->convolve3(
[&inl,&d2l]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inl.template get_k<real_t>(i,j,k);
return -kk[d2l[0]] * kk[d2l[1]] * inl.kelem(i,j,k);
},
[&inm,&d2m]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inm.template get_k<real_t>(i,j,k);
return -kk[d2m[0]] * kk[d2m[1]] * inm.kelem(i,j,k);
},
[&inr,&d2r]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inr.template get_k<real_t>(i,j,k);
return -kk[d2r[0]] * kk[d2r[1]] * inr.kelem(i,j,k);
}, res, op );
}
template< typename opp >
void convolve_SumHessians( Grid_FFT<data_t> & inl, const std::array<int,2>& d2l, Grid_FFT<data_t> & inr, const std::array<int,2>& d2r1,
const std::array<int,2>& d2r2, Grid_FFT<data_t> & res, opp op ){
// transform to FS in case fields are not
inl.FourierTransformForward();
inr.FourierTransformForward();
// perform convolution of Hessians
this->convolve2(
[&inl,&d2l]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inl.template get_k<real_t>(i,j,k);
return -kk[d2l[0]] * kk[d2l[1]] * inl.kelem(i,j,k);
},
[&inr,&d2r1,&d2r2]( size_t i, size_t j, size_t k ) -> ccomplex_t{
auto kk = inr.template get_k<real_t>(i,j,k);
return (-kk[d2r1[0]] * kk[d2r1[1]] -kk[d2r2[0]] * kk[d2r2[1]]) * inr.kelem(i,j,k);
}, res, op );
}
template< typename kfunc1, typename kfunc2, typename opp >
void convolve2( kfunc1 kf1, kfunc2 kf2, Grid_FFT<data_t> & res, opp op )
{

View file

@ -90,6 +90,11 @@ public:
size_t size(size_t i) const { return sizes_[i]; }
const bounding_box<size_t>& get_global_range( void ) const
{
return global_range_;
}
void zero()
{
#pragma omp parallel for
@ -148,8 +153,7 @@ public:
}
void cell_pos( int ilevel, size_t i, size_t j, size_t k, double* x ) const {
#warning needs to be fixed for MPI
x[0] = double(i)/size(0);
x[0] = double(i+local_0_start_)/size(0);
x[1] = double(j)/size(1);
x[2] = double(k)/size(2);
}

View file

@ -2,6 +2,8 @@
#include <map>
#include <config_file.hh>
#include <general.hh>
#include <grid_fft.hh>
#define DEF_RAN_CUBE_SIZE 32
@ -16,6 +18,7 @@ class RNG_plugin
}
virtual ~RNG_plugin() {}
virtual bool isMultiscale() const = 0;
virtual void Fill_Grid( Grid_FFT<real_t>& g ) const = 0;
//virtual void FillGrid(int level, DensityGrid<real_t> &R) = 0;
};

View file

@ -87,6 +87,8 @@ void Grid_FFT<data_t>::Setup(void)
local_0_size_ = n_[0];
local_1_size_ = n_[1];
local_0_start_= 0;
local_1_start_= 0;
if (space_ == rspace_id)
{
@ -562,9 +564,7 @@ void Grid_FFT<data_t>::Write_PowerSpectrum( std::string ofname )
{
#endif
std::ofstream ofs( ofname.c_str());
std::size_t numcells = size(0) * size(1) * size(2);
//ofs << "# a = " << aexp << std::endl;
ofs << "# " << std::setw(14) << "k" << std::setw(16) << "P(k)" << std::setw(16) << "err. P(k)"
<< std::setw(16) <<"#modes" << "\n";

View file

@ -71,7 +71,7 @@ int main( int argc, char** argv )
{
// print_region_generator_plugins();
print_TransferFunction_plugins();
// print_RNG_plugins();
print_RNG_plugins();
print_output_plugins();
csoca::elog << "In order to run, you need to specify a parameter file!" << std::endl;
@ -146,8 +146,19 @@ int main( int argc, char** argv )
Grid_FFT<real_t> phi3b({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen});
OrszagConvolver<real_t> Conv({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen});
// NaiveConvolver<real_t> Conv({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen});
//--------------------------------------------------------------------
// Some operators to add or subtract terms
auto assign_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return res; };
auto add_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return val+res; };
auto add2_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return val+2.0*res; };
auto sub_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return val-res; };
auto sub2_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return val-2.0*res; };
//--------------------------------------------------------------------
phi.FillRandomReal(6519);
//phi.FillRandomReal(6519);
the_random_number_generator->Fill_Grid( phi );
//======================================================================
//... compute 1LPT displacement potential ....
@ -163,19 +174,15 @@ int main( int argc, char** argv )
ccomplex_t delta = x * the_cosmo_calc->GetAmplitude(kmod, total);
return -delta / (kmod * kmod) * phifac / volfac;
});
phi.zero_DC_mode();
csoca::ilog << " took " << get_wtime()-wtime << "s" << std::endl;
//////////////////////////////////////////////////////////////////////////////////////////////////
auto assign_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return res; };
auto add_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return val+res; };
auto add2_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return val+2.0*res; };
auto sub_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return val-res; };
auto sub2_op = []( ccomplex_t res, ccomplex_t val ) -> ccomplex_t{ return val-2.0*res; };
//======================================================================
//... compute 2LPT displacement potential ....
wtime = get_wtime();
csoca::ilog << "Computing phi(2) term..." << std::flush;
// Compute the source term for phi(2)
Conv.convolve_SumHessians( phi, {0,0}, phi, {1,1}, {2,2}, phi2, assign_op );
Conv.convolve_Hessians( phi, {1,1}, phi, {2,2}, phi2, add_op );
Conv.convolve_Hessians( phi, {0,1}, phi, {0,1}, phi2, sub_op );
@ -184,58 +191,36 @@ int main( int argc, char** argv )
phi2.apply_InverseLaplacian();
phi2 /= phifac;
csoca::ilog << " took " << get_wtime()-wtime << "s" << std::endl;
// phi2.FourierTransformForward();
// phi2.apply_function_k_dep([&](auto x, auto k) {
// real_t kmod2 = k.norm_squared();
// return x * (-1.0 / kmod2) * phifac / phifac / phifac;
// });
// phi2.zero_DC_mode();
//======================================================================
//... compute 3LPT displacement potential
wtime = get_wtime();
csoca::ilog << "Computing phi(3a) term..." << std::flush;
Conv.convolve_SumHessians( phi, {0,0}, phi2, {1,1}, {2,2}, phi3a, assign_op );
Conv.convolve_SumHessians( phi, {1,1}, phi2, {2,2}, {0,0}, phi3a, add_op );
Conv.convolve_SumHessians( phi, {2,2}, phi2, {0,0}, {1,1}, phi3a, add_op );
Conv.convolve_Hessians( phi, {0,1}, phi2, {0,1}, phi3a, sub2_op );
Conv.convolve_Hessians( phi, {0,2}, phi2, {0,2}, phi3a, sub2_op );
Conv.convolve_Hessians( phi, {1,2}, phi2, {1,2}, phi3a, sub2_op );
Conv.convolve_Hessians( phi, {0,0}, phi, {1,1}, phi, {2,2}, phi3a, assign_op );
Conv.convolve_Hessians( phi, {0,1}, phi, {0,2}, phi, {1,2}, phi3a, add2_op );
Conv.convolve_Hessians( phi, {1,2}, phi, {1,2}, phi, {0,0}, phi3a, sub_op );
Conv.convolve_Hessians( phi, {0,2}, phi, {0,2}, phi, {1,1}, phi3a, sub_op );
Conv.convolve_Hessians( phi, {0,1}, phi, {0,1}, phi, {2,2}, phi3a, sub_op );
phi3a.apply_InverseLaplacian();
phi3a *= 0.5/phifac; // factor 1/2 from definition of phi(3a)!
// phi3a.apply_function_k_dep([&](auto x, auto k) {
// return 0.5 * x;
// });
phi3a /= phifac*phifac;
csoca::ilog << " took " << get_wtime()-wtime << "s" << std::endl;
// phi3a.FourierTransformForward();
// phi3a.apply_function_k_dep([&](auto x, auto k) {
// real_t kmod2 = k.norm_squared();
// return x * (-1.0 / kmod2) * phifac / phifac / phifac;
// });
// phi3a.zero_DC_mode();
//...
wtime = get_wtime();
csoca::ilog << "Computing phi(3b) term..." << std::flush;
Conv.convolve_Hessians( phi, {0,0}, phi, {1,1}, phi, {2,2}, phi3b, assign_op );
Conv.convolve_Hessians( phi, {0,1}, phi, {0,2}, phi, {1,2}, phi3b, add2_op );
Conv.convolve_Hessians( phi, {1,2}, phi, {1,2}, phi, {0,0}, phi3b, sub_op );
Conv.convolve_Hessians( phi, {0,2}, phi, {0,2}, phi, {1,1}, phi3b, sub_op );
Conv.convolve_Hessians( phi, {0,1}, phi, {0,1}, phi, {2,2}, phi3b, sub_op );
// phi3b.FourierTransformForward();
// phi3b.apply_function_k_dep([&](auto x, auto k) {
// real_t kmod2 = k.norm_squared();
// return x * (-1.0 / kmod2) * phifac / phifac / phifac/phifac;
// });
// phi3b.zero_DC_mode();
Conv.convolve_SumHessians( phi, {0,0}, phi2, {1,1}, {2,2}, phi3b, assign_op );
Conv.convolve_SumHessians( phi, {1,1}, phi2, {2,2}, {0,0}, phi3b, add_op );
Conv.convolve_SumHessians( phi, {2,2}, phi2, {0,0}, {1,1}, phi3b, add_op );
Conv.convolve_Hessians( phi, {0,1}, phi2, {0,1}, phi3b, sub2_op );
Conv.convolve_Hessians( phi, {0,2}, phi2, {0,2}, phi3b, sub2_op );
Conv.convolve_Hessians( phi, {1,2}, phi2, {1,2}, phi3b, sub2_op );
phi3b.apply_InverseLaplacian();
phi3b /= phifac*phifac;
phi3b *= 0.5/phifac; // factor 1/2 from definition of phi(3a)!
csoca::ilog << " took " << get_wtime()-wtime << "s" << std::endl;
///////////////////////////////////////////////////////////////////////
// we store the densities here if we compute them
const bool compute_densities = true;

View file

@ -40,6 +40,8 @@ public:
bool isMultiscale() const { return true; }
void Fill_Grid( Grid_FFT<real_t>& g ) const { }
void initialize_for_grid_structure()//const refinement_hierarchy &refh)
{
//prefh_ = &refh;

View file

@ -0,0 +1,162 @@
#include <general.hh>
#include <random_plugin.hh>
#include <config_file.hh>
#include <vector>
#include <cmath>
#include <grid_fft.hh>
#include <gsl/gsl_rng.h>
class RNG_ngenic : public RNG_plugin
{
private:
gsl_rng *pRandomGenerator_;
long RandomSeed_;
size_t nres_;
std::vector<unsigned int> SeedTable_;
public:
explicit RNG_ngenic(ConfigFile &cf) : RNG_plugin(cf)
{
RandomSeed_ = cf.GetValue<long>("random", "seed");
nres_ = cf.GetValue<size_t>("setup", "GridRes");
pRandomGenerator_ = gsl_rng_alloc(gsl_rng_ranlxd1);
SeedTable_.assign(nres_ * nres_, 0u);
for (size_t i = 0; i < nres_ / 2; ++i)
{
for (size_t j = 0; j < i; j++)
SeedTable_[i * nres_ + j] = 0x7fffffff * gsl_rng_uniform(pRandomGenerator_);
for (size_t j = 0; j < i + 1; j++)
SeedTable_[j * nres_ + i] = 0x7fffffff * gsl_rng_uniform(pRandomGenerator_);
for (size_t j = 0; j < i; j++)
SeedTable_[(nres_ - 1 - i) * nres_ + j] = 0x7fffffff * gsl_rng_uniform(pRandomGenerator_);
for (size_t j = 0; j < i + 1; j++)
SeedTable_[(nres_ - 1 - j) * nres_ + i] = 0x7fffffff * gsl_rng_uniform(pRandomGenerator_);
for (size_t j = 0; j < i; j++)
SeedTable_[i * nres_ + (nres_ - 1 - j)] = 0x7fffffff * gsl_rng_uniform(pRandomGenerator_);
for (size_t j = 0; j < i + 1; j++)
SeedTable_[j * nres_ + (nres_ - 1 - i)] = 0x7fffffff * gsl_rng_uniform(pRandomGenerator_);
for (size_t j = 0; j < i; j++)
SeedTable_[(nres_ - 1 - i) * nres_ + (nres_ - 1 - j)] = 0x7fffffff * gsl_rng_uniform(pRandomGenerator_);
for (size_t j = 0; j < i + 1; j++)
SeedTable_[(nres_ - 1 - j) * nres_ + (nres_ - 1 - i)] = 0x7fffffff * gsl_rng_uniform(pRandomGenerator_);
}
}
virtual ~RNG_ngenic()
{
gsl_rng_free(pRandomGenerator_);
}
bool isMultiscale() const { return false; }
void Fill_Grid(Grid_FFT<real_t> &g) const
{
double fnorm = std::pow((double)nres_, -1.5);
g.FourierTransformForward(false);
#ifdef USE_MPI
// transform is transposed!
for (size_t j = 0; j < g.size(0); ++j)
{
for (size_t i = 0; i < g.size(1); ++i)
{
#else
for (size_t i = 0; i < g.size(0); ++i)
{
for (size_t j = 0; j < g.size(1); ++j)
{
#endif
ptrdiff_t ii = (i>0)? g.size(1) - i : 0;
gsl_rng_set( pRandomGenerator_, SeedTable_[i * nres_ + j]);
for (size_t k = 0; k < g.size(2); ++k)
{
double phase = gsl_rng_uniform(pRandomGenerator_) * 2 * M_PI;
double ampl;
do
{
ampl = gsl_rng_uniform(pRandomGenerator_);
} while (ampl == 0);
if (i == nres_ / 2 || j == nres_ / 2 || k == nres_ / 2)
continue;
if (i == 0 && j == 0 && k == 0)
continue;
real_t rp = -std::sqrt(-std::log(ampl)) * std::cos(phase);// * fnorm;
real_t ip = -std::sqrt(-std::log(ampl)) * std::sin(phase);// * fnorm;
ccomplex_t zrand(rp,ip);
if (k > 0)
{
g.kelem(i,j,k) = zrand;
// RE(knoise[(i * res + j) * (res / 2 + 1) + k]) = rp;
// IM(knoise[(i * res + j) * (res / 2 + 1) + k]) = ip;
}
else /* k=0 plane needs special treatment */
{
if (i == 0)
{
if (j >= nres_ / 2)
{
continue;
}
else
{
int jj = (int)nres_ - (int)j; /* note: j!=0 surely holds at this point */
g.kelem(i,j,k) = zrand;
g.kelem(i,jj,k) = std::conj(zrand);
// RE(knoise[(i * res + j) * (res / 2 + 1) + k]) = rp;
// IM(knoise[(i * res + j) * (res / 2 + 1) + k]) = ip;
// RE(knoise[(i * res + jj) * (res / 2 + 1) + k]) = rp;
// IM(knoise[(i * res + jj) * (res / 2 + 1) + k]) = -ip;
}
}
else
{
if (i >= nres_ / 2)
{
continue;
}
else
{
ptrdiff_t ii = (i>0)? nres_ - i : 0;
ptrdiff_t jj = (j>0)? nres_ - j : 0;
g.kelem(i,j,k) = zrand;
// RE(knoise[(i * res + j) * (res / 2 + 1) + k]) = rp;
// IM(knoise[(i * res + j) * (res / 2 + 1) + k]) = ip;
if (ii >= 0 && ii < (int)nres_)
{
// RE(knoise[(ii * res + jj) * (res / 2 + 1) + k]) = rp;
// IM(knoise[(ii * res + jj) * (res / 2 + 1) + k]) = -ip;
g.kelem(ii,jj,k) = std::conj(zrand);
}
}
}
}
}
}
}
}
};
namespace
{
RNG_plugin_creator_concrete<RNG_ngenic> creator("NGENIC");
}

View file

@ -25,10 +25,10 @@ private:
std::vector<double> tab_lnk_, tab_dtot_, tab_dc_, tab_db_, tab_ttot_, tab_tc_, tab_tb_;
gsl_interp_accel *gsl_ia_dtot_, *gsl_ia_dc_, *gsl_ia_db_, *gsl_ia_ttot_, *gsl_ia_tc_, *gsl_ia_tb_;
gsl_spline *gsl_sp_dtot_, *gsl_sp_dc_, *gsl_sp_db_, *gsl_sp_ttot_, *gsl_sp_tc_, *gsl_sp_tb_;
double Omega_m_, Omega_b_, zstart_, ztarget_, kmax_, kmin_, h_;
double Omega_m_, Omega_b_, N_ur_, zstart_, ztarget_, kmax_, kmin_, h_;
void ClassEngine_get_data( void ){
std::vector<double> d_g, d_ur, t_g, t_ur, phi, psi;
std::vector<double> d_ncdm, t_ncdm, phi, psi;
csoca::ilog << "Computing transfer function via ClassEngine..." << std::flush;
double wtime = get_wtime();
@ -41,9 +41,13 @@ private:
pars.add("P_k_max_h/Mpc", kmax_);
pars.add("h",h_);
pars.add("Omega_b",Omega_b_);
pars.add("Omega_ur",0.0);
// pars.add("Omega_k",0.0);
// pars.add("Omega_ur",0.0);
pars.add("N_ur",N_ur_);
pars.add("Omega_cdm",Omega_m_-Omega_b_);
pars.add("Omega_Lambda",1.0-Omega_m_);
// pars.add("Omega_fld",0.0);
// pars.add("Omega_scf",0.0);
pars.add("A_s",2.42e-9);
pars.add("n_s",.96);
pars.add("output","dTk,vTk");
@ -51,8 +55,8 @@ private:
std::unique_ptr<ClassEngine> CE = std::make_unique<ClassEngine>(pars, false);
CE->getTk(target_redshift, tab_lnk_, d_g, tab_db_, tab_dc_, d_ur, tab_dtot_,
phi, psi, t_g, tab_tb_, t_ur, tab_ttot_);
CE->getTk(target_redshift, tab_lnk_, tab_dc_, tab_db_, d_ncdm, tab_dtot_,
tab_tc_, tab_tb_, t_ncdm, tab_ttot_, phi, psi );
tab_tc_ = tab_ttot_;
#warning need to fix CDM velocities
@ -67,8 +71,9 @@ public:
h_ = cf.GetValue<double>("cosmology","H0") / 100.0;
Omega_m_ = cf.GetValue<double>("cosmology","Omega_m");
Omega_b_ = cf.GetValue<double>("cosmology","Omega_b");
zstart_ = cf.GetValue<double>("setup","zstart");
N_ur_ = cf.GetValueSafe<double>("cosmology","N_ur", 3.046);
ztarget_ = cf.GetValueSafe<double>("cosmology","ztarget",0.0);
zstart_ = cf.GetValue<double>("setup","zstart");
kmax_ = 1000.0;
this->ClassEngine_get_data();
@ -130,12 +135,12 @@ public:
}
double d = (k<=kmin_)? gsl_spline_eval(splineT, std::log(kmin_), accT)
: gsl_spline_eval(splineT, std::log(k), accT);
: gsl_spline_eval(splineT, std::log(k*h_), accT);
return -d/(k*k);
}
inline double get_kmin(void) const { return std::exp(tab_lnk_[0]); }
inline double get_kmax(void) const { return std::exp(tab_lnk_[tab_lnk_.size()-1]); }
inline double get_kmin(void) const { return std::exp(tab_lnk_[0])/h_; }
inline double get_kmax(void) const { return std::exp(tab_lnk_[tab_lnk_.size()-1])/h_; }
};
namespace {