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

added non-MPI version of MUSIC1 randum number generator

This commit is contained in:
Oliver Hahn 2020-08-23 16:09:13 +02:00
parent 5c46890468
commit 7086442712
3 changed files with 124 additions and 76 deletions

View file

@ -70,17 +70,31 @@ ZeroRadiation = true # For Back-scaling: set to false if your simulation code
#########################################################################################
[random]
## generator = ... specifies the random field generator plugin module
generator = NGENIC
seed = 9001
# generator = PANPHASIA
# descriptor = [Panph1,L10,(800,224,576),S9,CH1564365824,MXXL]
## > NGenIC compatible random number generator module compatible with V. Springel's original code
## (https://www.h-its.org/2014/11/05/ngenic-code/) as well as the 2LPT code by Pueblas&Scoccmiarro
## (https://cosmo.nyu.edu/roman/2LPT/)
generator = NGENIC
seed = 12345
## > The PANPHASIA generator uses a plugin based on original code by A. Jenkins
## Warning: Before using this module, please make sure you read and agree to the distinct license
## requirements by registering on the website http://icc.dur.ac.uk/Panphasia.php
# generator = PANPHASIA
# descriptor = [Panph1,L10,(800,224,576),S9,CH1564365824,MXXL]
## > The MUSIC1 multi-scale random number generator is provided for convenience
## warning: MUSIC1 generator is not MPI parallel (yet) (memory is needed for full field on each task)
# generator = MUSIC1
# seed[7] = 12345
# seed[8] = 23456
# seed[9] = 34567
# Add a possible constraint field here:
# ConstraintFieldFile = initial_conditions.hdf5
# ConstraintFieldName = ic_white_noise
#########################################################################################
[testing]
# enables diagnostic output
@ -90,6 +104,7 @@ test = none
#########################################################################################
[execution]
# Specify the number of threads / task
NumThreads = 8
@ -97,20 +112,29 @@ NumThreads = 8
[output]
## format = .... specifies the output plugin module
##> RAMSES / GRAFIC2 compatible format
# format = grafic2
# filename = ics_ramses
# grafic_use_SPT = no # if no then uses PPT, otherwise linear SPT
##> Gadget-2/3 'fortran unformatted binary'-style format
# format = gadget2
# filename = ics_gadget.dat
# UseLongids = false
##> Gadget-2/3 HDF5 format
# format = gadget_hdf5
# filename = ics_gadget.hdf5
##> Arepo HDF5 format (virtually identical to gadget_hdf5)
# format = AREPO
# filename = ics_arepo.hdf5
##> HACC compatible generic-io format
# format = genericio
# filename = ics_hacc
##> Generic HDF5 output format for testing or PT-based calculations
# format = generic
# filename = debug.hdf5
# generic_out_eulerian = yes # if yes then uses PPT for output

View file

@ -24,6 +24,7 @@ class RNG_music : public RNG_plugin
protected:
std::vector<long> rngseeds_;
std::vector<std::string> rngfnames_;
std::vector<rng *> randc_;
unsigned ran_cube_size_;
int levelmin_, levelmax_, levelmin_seed_;
@ -49,21 +50,73 @@ protected:
//! store the white noise fields in memory or on disk
//void store_rnd(int ilevel, rng *prng);
public:
explicit RNG_music(config_file &cf) : RNG_plugin(cf), initialized_(false) {}
bool is_power_of_two(size_t x) const
{
return (x & (x - 1)) == 0;
}
~RNG_music() {}
unsigned int_log2( size_t v ) const
{
unsigned r{0}; // r will be lg(v)
while (v >>= 1) r++;
return r;
}
public:
explicit RNG_music(config_file &cf) : RNG_plugin(cf), initialized_(false)
{
// we need to make sure that the chosen resolution is a power of 2 resolution
size_t res = pcf_->get_value<size_t>("setup", "GridRes");
if( !is_power_of_two(res) ){
std::string errmsg("MUSIC random number plugin requires [setup]/GridRes to be a power of 2!");
music::flog << errmsg << std::endl;
throw std::runtime_error(errmsg.c_str());
}
levelmin_ = int_log2(res);
levelmax_ = levelmin_;
music::ilog << "MUSIC1 RNG plugin: setting levelmin = levelmax = " << levelmin_ << std::endl;
this->initialize_for_grid_structure( );
}
~RNG_music()
{
for( auto rr : randc_ ){
if( rr != nullptr ) delete rr;
}
}
bool isMultiscale() const { return true; }
void Fill_Grid( Grid_FFT<real_t>& g ) {} //const { }
void initialize_for_grid_structure()//const refinement_hierarchy &refh)
void Fill_Grid( Grid_FFT<real_t>& g )
{
//prefh_ = &refh;
levelmin_ = pcf_->get_value<unsigned>("setup", "levelmin");
levelmax_ = pcf_->get_value<unsigned>("setup", "levelmax");
// determine extent of grid to be filled (can be a slab with MPI)
const size_t i0 = g.local_0_start_, j0{0}, k0{0};
const size_t Ni = g.rsize(0), Nj = g.rsize(1), Nk = g.rsize(2);
// make sure we're in real space
g.FourierTransformBackward();
// copy over
#pragma omp parallel for
for( auto i = i0; i<Ni; ++i )
{
size_t ip = i-i0; // index in g
for( auto j = j0; j<Nj; ++j )
{
auto jp = j-j0; // index in g
for( auto k = k0; k<Nk; ++k )
{
auto kp = k-k0; // index in g
g.relem(ip,jp,kp) = (*randc_[levelmin_])(i,j,k);
}
}
}
}
void initialize_for_grid_structure()
{
ran_cube_size_ = pcf_->get_value_safe<unsigned>("random", "cubesize", DEF_RAN_CUBE_SIZE);
disk_cached_ = pcf_->get_value_safe<bool>("random", "disk_cached", true);
restart_ = pcf_->get_value_safe<bool>("random", "restart", false);
@ -159,17 +212,18 @@ void RNG_music::compute_random_numbers(void)
{
bool rndsign = pcf_->get_value_safe<bool>("random", "grafic_sign", false);
std::vector<rng *> randc(std::max(levelmax_, levelmin_seed_) + 1, (rng *)NULL);
//--- FILL ALL WHITE NOISE ARRAYS FOR WHICH WE NEED THE FULL FIELD ---//
randc_.assign(std::max(levelmax_, levelmin_seed_) + 1, nullptr);
//... seeds are given for a level coarser than levelmin
if (levelmin_seed_ < levelmin_)
{
if (rngfnames_[levelmin_seed_].size() > 0)
randc[levelmin_seed_] = new rng(1 << levelmin_seed_, rngfnames_[levelmin_seed_], rndsign);
randc_[levelmin_seed_] = new rng(1 << levelmin_seed_, rngfnames_[levelmin_seed_], rndsign);
else
randc[levelmin_seed_] = new rng(1 << levelmin_seed_, ran_cube_size_, rngseeds_[levelmin_seed_], true);
randc_[levelmin_seed_] = new rng(1 << levelmin_seed_, ran_cube_size_, rngseeds_[levelmin_seed_], true);
for (int i = levelmin_seed_ + 1; i <= levelmin_; ++i)
{
@ -178,9 +232,9 @@ void RNG_music::compute_random_numbers(void)
if (rngfnames_[i].size() > 0)
music::ilog.Print("Warning: Cannot use filenames for higher levels currently! Ignoring!");
randc[i] = new rng(*randc[i - 1], ran_cube_size_, rngseeds_[i], true);
delete randc[i - 1];
randc[i - 1] = NULL;
randc_[i] = new rng(*randc_[i - 1], ran_cube_size_, rngseeds_[i], true);
delete randc_[i - 1];
randc_[i - 1] = NULL;
}
}
@ -188,9 +242,9 @@ void RNG_music::compute_random_numbers(void)
if (levelmin_seed_ > levelmin_)
{
if (rngfnames_[levelmin_seed_].size() > 0)
randc[levelmin_seed_] = new rng(1 << levelmin_seed_, rngfnames_[levelmin_seed_], rndsign);
randc_[levelmin_seed_] = new rng(1 << levelmin_seed_, rngfnames_[levelmin_seed_], rndsign);
else
randc[levelmin_seed_] =
randc_[levelmin_seed_] =
new rng(1 << levelmin_seed_, ran_cube_size_, rngseeds_[levelmin_seed_], true); //, x0, lx );
for (int ilevel = levelmin_seed_ - 1; ilevel >= (int)levelmin_; --ilevel)
@ -201,14 +255,14 @@ void RNG_music::compute_random_numbers(void)
ilevel, levelmin_seed_);
// if( brealspace_tf && ilevel < levelmax_ )
// randc[ilevel] = new rng( *randc[ilevel+1], false );
// randc_[ilevel] = new rng( *randc_[ilevel+1], false );
// else // do k-space averaging
randc[ilevel] = new rng(*randc[ilevel + 1], true);
randc_[ilevel] = new rng(*randc_[ilevel + 1], true);
if (ilevel + 1 > levelmax_)
{
delete randc[ilevel + 1];
randc[ilevel + 1] = NULL;
delete randc_[ilevel + 1];
randc_[ilevel + 1] = NULL;
}
}
}
@ -216,12 +270,12 @@ void RNG_music::compute_random_numbers(void)
//--- GENERATE AND STORE ALL LEVELS, INCLUDING REFINEMENTS ---//
//... levelmin
if (randc[levelmin_] == NULL)
if (randc_[levelmin_] == NULL)
{
if (rngfnames_[levelmin_].size() > 0)
randc[levelmin_] = new rng(1 << levelmin_, rngfnames_[levelmin_], rndsign);
randc_[levelmin_] = new rng(1 << levelmin_, rngfnames_[levelmin_], rndsign);
else
randc[levelmin_] = new rng(1 << levelmin_, ran_cube_size_, rngseeds_[levelmin_], true);
randc_[levelmin_] = new rng(1 << levelmin_, ran_cube_size_, rngseeds_[levelmin_], true);
}
// if( levelmax_ == levelmin_ )
@ -232,11 +286,11 @@ void RNG_music::compute_random_numbers(void)
//... constraints.apply will return without doing anything
int x0[3] = { 0, 0, 0 };
int lx[3] = { 1<<levelmin_, 1<<levelmin_, 1<<levelmin_ };
constraints.apply( levelmin_, x0, lx, randc[levelmin_] );
constraints.apply( levelmin_, x0, lx, randc_[levelmin_] );
}
#endif
// store_rnd(levelmin_, randc[levelmin_]);
// store_rnd(levelmin_, randc_[levelmin_]);
//... refinement levels
// for (int ilevel = levelmin_ + 1; ilevel <= levelmax_; ++ilevel)
@ -258,22 +312,22 @@ void RNG_music::compute_random_numbers(void)
// x0[1] = prefh_->offset_abs(ilevel, 1) - lfac * shift[1] - lx[1] / 4;
// x0[2] = prefh_->offset_abs(ilevel, 2) - lfac * shift[2] - lx[2] / 4;
// if (randc[ilevel] == NULL)
// randc[ilevel] =
// new rng(*randc[ilevel - 1], ran_cube_size_, rngseeds_[ilevel], kavg, ilevel == levelmin_ + 1, x0, lx);
// delete randc[ilevel - 1];
// randc[ilevel - 1] = NULL;
// if (randc_[ilevel] == NULL)
// randc_[ilevel] =
// new rng(*randc_[ilevel - 1], ran_cube_size_, rngseeds_[ilevel], kavg, ilevel == levelmin_ + 1, x0, lx);
// delete randc_[ilevel - 1];
// randc_[ilevel - 1] = NULL;
// //... apply constraints to this level, if any
// // if( ilevel == levelmax_ )
// // constraints.apply( ilevel, x0, lx, randc[ilevel] );
// // constraints.apply( ilevel, x0, lx, randc_[ilevel] );
// //... store numbers
// store_rnd(ilevel, randc[ilevel]);
// store_rnd(ilevel, randc_[ilevel]);
// }
delete randc[levelmax_];
randc[levelmax_] = NULL;
// delete randc_[levelmax_];
// randc_[levelmax_] = NULL;
//... make sure that the coarse grid contains oct averages where it overlaps with a fine grid
//... this also ensures that constraints enforced on fine grids are carried to the coarser grids
@ -287,9 +341,9 @@ void RNG_music::compute_random_numbers(void)
/*if( levelmax_rand_ >= (int)levelmin_ )
{
std::cerr << "lmaxread >= (int)levelmin\n";
randc[levelmax_rand_] = new rng( (unsigned)pow(2,levelmax_rand_), rngfnames_[levelmax_rand_] );
randc_[levelmax_rand_] = new rng( (unsigned)pow(2,levelmax_rand_), rngfnames_[levelmax_rand_] );
for( int ilevel = levelmax_rand_-1; ilevel >= (int)levelmin_; --ilevel )
randc[ilevel] = new rng( *randc[ilevel+1] );
randc_[ilevel] = new rng( *randc_[ilevel+1] );
}*/
}
@ -297,5 +351,5 @@ void RNG_music::compute_random_numbers(void)
namespace
{
RNG_plugin_creator_concrete<RNG_music> creator("MUSIC");
RNG_plugin_creator_concrete<RNG_music> creator("MUSIC1");
}

View file

@ -41,38 +41,8 @@ music_wnoise_generator<T>::music_wnoise_generator(unsigned res, unsigned cubesiz
double mean = 0.0;
size_t res_l = res;
bool musicnoise = true;
if (!musicnoise)
cubesize_ = res_;
if (!musicnoise)
music::elog.Print("This currently breaks compatibility. Need to disable by hand! Make sure to not check into repo");
initialize();
if (musicnoise)
mean = fill_all();
else
{
rnums_.push_back(new Meshvar<T>(res, 0, 0, 0));
cubemap_[0] = 0; // create dummy map index
register_cube(0, 0, 0);
//rapid_proto_ngenic_rng( res_, baseseed_, *this );
}
/*
if( musicnoise )
mean = fill_all();
else
{
rnums_.push_back( new Meshvar<T>( res, 0, 0, 0 ) );
cubemap_[0] = 0; // create dummy map index
register_cube(0,0,0);
rapid_proto_ngenic_rng( res_, baseseed_, *this );
}
*/
mean = fill_all();
if (zeromean)
{