1
0
Fork 0
mirror of https://github.com/cosmo-sims/MUSIC.git synced 2024-09-16 13:33:46 +02:00

WIP transition to monofonic infrastructure

This commit is contained in:
Oliver Hahn 2023-02-15 06:10:50 -08:00
parent 30feb0ed4a
commit 0bf5a6cfe7
30 changed files with 1700 additions and 2371 deletions

View file

@ -1,410 +0,0 @@
/*
This file is part of MUSIC -
a tool to generate initial conditions for cosmological simulations
Copyright (C) 2008-12 Oliver Hahn, ojha@gmx.de
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __TRANSFERFUNCTION_HH
#define __TRANSFERFUNCTION_HH
#include <vector>
#include <sstream>
#include <fstream>
#include <iostream>
#include <cmath>
#include <stdexcept>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_spline.h>
#include <gsl/gsl_sf_gamma.h>
#include "Numerics.hh"
#include "general.hh"
#include <complex>
#define NZERO_Q
typedef std::complex<double> complex;
//! Abstract base class for transfer functions
/*!
This class implements a purely virtual interface that can be
used to derive instances implementing various transfer functions.
*/
class TransferFunction{
public:
Cosmology m_Cosmology;
public:
TransferFunction( Cosmology acosm ) : m_Cosmology( acosm ) { };
virtual double compute( double k ) = 0;
virtual ~TransferFunction(){ };
virtual double get_kmax( void ) = 0;
virtual double get_kmin( void ) = 0;
};
class TransferFunction_real
{
public:
gsl_interp_accel *accp, *accn;
gsl_spline *splinep, *splinen;
double Tr0_, Tmin_, Tmax_, Tscale_;
double rneg_, rneg2_;
static TransferFunction *ptf_;
static double nspec_;
protected:
double krgood( double mu, double q, double dlnr, double kr )
{
double krnew = kr;
complex cdgamma, zm, zp;
double arg, iarg, xm, xp, y;
gsl_sf_result g_a, g_p;
xp = 0.5*(mu+1.0+q);
xm = 0.5*(mu+1.0-q);
y = M_PI/(2.0*dlnr);
zp=complex(xp,y);
zm=complex(xm,y);
gsl_sf_lngamma_complex_e (zp.real(), zp.imag(), &g_a, &g_p);
zp=std::polar(exp(g_a.val),g_p.val);
double zpa = g_p.val;
gsl_sf_lngamma_complex_e (zm.real(), zm.imag(), &g_a, &g_p);
zm=std::polar(exp(g_a.val),g_p.val);
double zma = g_p.val;
arg=log(2.0/kr)/dlnr+(zpa+zma)/M_PI;
iarg=(double)((int)(arg + 0.5));
if( arg!=iarg )
krnew=kr*exp((arg-iarg)*dlnr);
return krnew;
}
void transform( double pnorm, double dplus, unsigned N, double q, std::vector<double>& rr, std::vector<double>& TT )
{
const double mu = 0.5;
double qmin = 1.0e-6, qmax = 1.0e+6;
q = 0.0;
N = 16384;
#ifdef NZERO_Q
//q = 0.4;
q = 0.2;
#endif
double kmin = qmin, kmax=qmax;
double rmin = qmin, rmax = qmax;
double k0 = exp(0.5*(log(kmax)+log(kmin)));
double r0 = exp(0.5*(log(rmax)+log(rmin)));
double L = log(rmax)-log(rmin);
double k0r0 = k0*r0;
double dlnk = L/N, dlnr = L/N;
double sqrtpnorm = sqrt(pnorm);
double dir = 1.0;
double fftnorm = 1.0/N;
complex_t in[N], out[N];
fftw_plan p,ip;
//... perform anti-ringing correction from Hamilton (2000)
k0r0 = krgood( mu, q, dlnr, k0r0 );
std::ofstream ofsk("transfer_k.txt");
double sum_in = 0.0;
for( unsigned i=0; i<N; ++i )
{
double k = k0*exp(((int)i - (int)N/2+1) * dlnk);
//double k = k0*exp(((int)i - (int)N/2) * dlnk);
//double k = k0*exp(ii * dlnk);
//... some constants missing ...//
in[i].re = dplus*sqrtpnorm*ptf_->compute( k )*pow(k,0.5*nspec_)*pow(k,1.5-q);
in[i].im = 0.0;
sum_in += in[i].re;
ofsk << std::setw(16) << k <<std::setw(16) << in[i].re << std::endl;
}
ofsk.close();
p = fftw_create_plan(N, FFTW_FORWARD, FFTW_ESTIMATE);
ip = fftw_create_plan(N, FFTW_BACKWARD, FFTW_ESTIMATE);
//fftw_one(p, in, out);
fftw_one(p, in, out);
//... compute the Hankel transform by convolution with the Bessel function
for( unsigned i=0; i<N; ++i )
{
int ii=i;
if( ii > (int)N/2 )
ii -= N;
#ifndef NZERO_Q
double y=ii*M_PI/L;
complex zp((mu+1.0)*0.5,y);
gsl_sf_result g_a, g_p;
gsl_sf_lngamma_complex_e(zp.real(), zp.imag(), &g_a, &g_p);
double arg = 2.0*(log(2.0/k0r0)*y+g_p.val);
complex cu = complex(out[i].re,out[i].im)*std::polar(1.0,arg);
out[i].re = cu.real()*fftnorm;
out[i].im = cu.imag()*fftnorm;
#else
//complex x(dir*q, (double)ii*2.0*M_PI/L);
complex x(dir*q, (double)ii*2.0*M_PI/L);
gsl_sf_result g_a, g_p;
complex g1, g2, garg, U, phase;
complex twotox = pow(complex(2.0,0.0),x);
/////////////////////////////////////////////////////////
//.. evaluate complex Gamma functions
garg = 0.5*(mu+1.0+x);
gsl_sf_lngamma_complex_e (garg.real(), garg.imag(), &g_a, &g_p);
g1 = std::polar(exp(g_a.val),g_p.val);
garg = 0.5*(mu+1.0-x);
gsl_sf_lngamma_complex_e (garg.real(), garg.imag(), &g_a, &g_p);
g2 = std::polar(exp(g_a.val),g_p.val);
/////////////////////////////////////////////////////////
//.. compute U
if( (fabs(g2.real()) < 1e-19 && fabs(g2.imag()) < 1e-19) )
{
//std::cerr << "Warning : encountered possible singularity in TransferFunction_real::transform!\n";
g1 = 1.0; g2 = 1.0;
}
U = twotox * g1 / g2;
phase = pow(complex(k0r0,0.0),complex(0.0,2.0*M_PI*(double)ii/L));
complex cu = complex(out[i].re,out[i].im)*U*phase*fftnorm;
out[i].re = cu.real();
out[i].im = cu.imag();
if( (out[i].re != out[i].re)||(out[i].im != out[i].im) )
{ std::cerr << "NaN @ i=" << i << ", U= " << U << ", phase = " << phase << ", g1 = " << g1 << ", g2 = " << g2 << std::endl;
std::cerr << "mu+1+q = " << mu+1.0+q << std::endl;
//break;
}
#endif
}
/*out[N/2].im = 0.0;
out[N/2+1].im = 0.0;
out[N/2+1].re = out[N/2].re;
out[N/2].im = 0.0;*/
fftw_one(ip, out, in);
rr.assign(N,0.0);
TT.assign(N,0.0);
r0 = k0r0/k0;
for( unsigned i=0; i<N; ++i )
{
int ii = i;
ii -= N/2-1;
//ii -= N/2;
//if( ii>N/2)
// ii-=N;
double r = r0*exp(-ii*dlnr);
rr[N-i-1] = r;
TT[N-i-1] = 4.0*M_PI* sqrt(M_PI/2.0) * in[i].re*pow(r,-(1.5+q));
//TT[N-i-1] = 4.0*M_PI* sqrt(M_PI/2.0) * in[i].re*exp( -dir*(q+1.5)*ii*dlnr +q*log(k0r0))/r0;
//rr[i] = r;
//TT[i] = 4.0*M_PI* sqrt(M_PI/2.0) * in[i].re*pow(r,-(1.5+q));
}
{
std::ofstream ofs("transfer_real_new.txt");
for( unsigned i=0; i<N; ++i )
{
int ii = i;
ii -= N/2-1;
double r = r0*exp(-ii*dlnr);//r0*exp(ii*dlnr);
double T = 4.0*M_PI* sqrt(M_PI/2.0) * in[i].re*pow(r,-(1.5+q));
ofs << r << "\t\t" << T << "\t\t" << in[i].im << std::endl;
}
}
fftw_destroy_plan(p);
fftw_destroy_plan(ip);
}
public:
TransferFunction_real( TransferFunction *tf, double nspec, double pnorm, double dplus, double rmin, double rmax, double knymax, unsigned nr )
{
ptf_ = tf;
nspec_ = nspec;
double q = 0.8;
std::vector<double> r,T,xp,yp,xn,yn;
transform( pnorm, dplus, nr, q, r, T );
//... determine r=0 zero component by integrating up to the Nyquist frequency
gsl_integration_workspace * wp;
gsl_function F;
wp = gsl_integration_workspace_alloc(20000);
F.function = &call_wrapper;
double par[2]; par[0] = dplus*sqrt(pnorm); //par[1] = M_PI/kny;
F.params = (void*)par;
double error;
//#warning factor of sqrt(1.5) needs to be adjusted for non-equilateral boxes
//.. need a factor sqrt( 2*kny^2_x + 2*kny^2_y + 2*kny^2_z )/2 = sqrt(3/2)kny (in equilateral case)
gsl_integration_qag (&F, 0.0, sqrt(1.5)*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
//Tr0_ = 0.0;
gsl_integration_workspace_free(wp);
for( unsigned i=0; i<r.size(); ++i )
{
// spline positive and negative part separately
/*if( T[i] > 0.0 )
{
xp.push_back( 2.0*log10(r[i]) );
yp.push_back( log10(T[i]) );
rneg_ = r[i];
rneg2_ = rneg_*rneg_;
}else {
xn.push_back( 2.0*log10(r[i]) );
yn.push_back( log10(-T[i]) );
}*/
if( r[i] > rmin && r[i] < rmax )
{
xp.push_back( 2.0*log10(r[i]) );
yp.push_back( log10(fabs(T[i])) );
xn.push_back( 2.0*log10(r[i]) );
if( T[i] >= 0.0 )
yn.push_back( 1.0 );
else
yn.push_back( -1.0 );
//ofs << std::setw(16) << xp.back() << std::setw(16) << yp.back() << std::endl;
}
}
accp = gsl_interp_accel_alloc ();
accn = gsl_interp_accel_alloc ();
//... spline interpolation is only marginally slower here
splinep = gsl_spline_alloc (gsl_interp_cspline, xp.size() );
splinen = gsl_spline_alloc (gsl_interp_cspline, xn.size() );
//... set up everything for spline interpolation
gsl_spline_init (splinep, &xp[0], &yp[0], xp.size() );
gsl_spline_init (splinen, &xn[0], &yn[0], xn.size() );
{
double dlogr = (log10(rmax)-log10(rmin))/100;
std::ofstream ofs("transfer_splinep.txt");
for( int i=0; i< 100; ++i )
{
double r = rmin*pow(10.0,i*dlogr);
ofs << std::setw(16) << r << std::setw(16) << compute_real(r*r) << std::endl;
}
}
}
static double call_wrapper( double k, void *arg )
{
double *a = (double*)arg;
return 4.0*M_PI*a[0]*ptf_->compute( k )*pow(k,0.5*nspec_)*k*k;
}
~TransferFunction_real()
{
gsl_spline_free (splinen);
gsl_interp_accel_free (accn);
gsl_spline_free (splinep);
gsl_interp_accel_free (accp);
}
inline double compute_real( double r2 ) const
{
const double EPS = 1e-8;
const double Reps2 = EPS*EPS;
if( r2 <Reps2 )
return Tr0_;
double q;
/*if( r2 < rneg2_ )
q = pow(10.0,gsl_spline_eval (splinep, log10(r2), accp));
else
q = -pow(10.0,gsl_spline_eval(splinen, log10(r2), accn));*/
double logr2 = log10(r2);
q = pow(10.0,gsl_spline_eval(splinep, logr2, accp));
double sign = 1.0;
if( gsl_spline_eval(splinen, logr2, accn) < 0.0 )
sign = -1.0;
return q*sign;
}
};
#endif

View file

@ -31,7 +31,7 @@ double dsigma2_tophat( double k, void *pparams )
double w = 3.0*(sin(x)-x*cos(x))/(x*x*x);
double tfk = ptf->compute(k,total);
double tfk = ptf->compute(k,delta_matter);
return k*k * w*w * pow(k,nspect) * tfk*tfk;
}
@ -48,7 +48,7 @@ double dsigma2_gauss( double k, void *pparams )
double w = exp(-x*x*0.5);
double tfk = ptf->compute(k,total);
double tfk = ptf->compute(k,delta_matter);
return k*k * w*w * pow(k,nspect) * tfk*tfk;
}
@ -76,15 +76,15 @@ void compute_sigma_tophat( config_file& cf, transfer_function *ptf, double R, st
z.clear();
sigma.clear();
cosmology cosm( cf );
CosmoCalc ccalc( cosm, ptf );
cosmology::parameters cosm( cf );
cosmology::calculator ccalc( cf );
double zmin = 0.0, zmax = 200.0;
int nz = 100;
for( int i=0; i <nz; ++i )
z.push_back( zmax - i*(zmax-zmin)/(nz-1.0) );
double D0 = ccalc.CalcGrowthFactor(1.0);
double D0 = ccalc.get_growth_factor(1.0);
double sigma8 = cf.get_value<double>("cosmology","sigma_8");
double nspec = cf.get_value<double>("cosmology","nspec");
@ -109,7 +109,7 @@ void compute_sigma_tophat( config_file& cf, transfer_function *ptf, double R, st
params[2] = reinterpret_cast<char*> (&nspec);
double sig = sqrt(4.0*M_PI*integrate( &dsigma2_tophat, 1e-4, 1e4, reinterpret_cast<void*>(params) ));
double Dz = ccalc.CalcGrowthFactor(1./(1.+z[i]));
double Dz = ccalc.get_growth_factor(1./(1.+z[i]));
sigma.push_back( sig*sigma8/sigma0*Dz/D0 );
}
}
@ -119,15 +119,15 @@ void compute_sigma_gauss( config_file& cf, transfer_function *ptf, double R, std
z.clear();
sigma.clear();
cosmology cosm( cf );
CosmoCalc ccalc( cosm, ptf );
cosmology::parameters cosm( cf );
cosmology::calculator ccalc( cf );
double zmin = 0.0, zmax = 200.0;
int nz = 100;
for( int i=0; i <nz; ++i )
z.push_back( zmax - i*(zmax-zmin)/(nz-1.0) );
double D0 = ccalc.CalcGrowthFactor(1.0);
double D0 = ccalc.get_growth_factor(1.0);
double sigma8 = cf.get_value<double>("cosmology","sigma_8");
double nspec = cf.get_value<double>("cosmology","nspec");
@ -152,7 +152,7 @@ void compute_sigma_gauss( config_file& cf, transfer_function *ptf, double R, std
params[2] = reinterpret_cast<char*> (&nspec);
double sig = sqrt(4.0*M_PI*integrate( &dsigma2_gauss, 1e-4, 1e4, reinterpret_cast<void*>(params) ));
double Dz = ccalc.CalcGrowthFactor(1./(1.+z[i]));
double Dz = ccalc.get_growth_factor(1./(1.+z[i]));
//std::cerr << z[i] << " " << sig << std::endl;
sigma.push_back( sig*sigma8/sigma0*Dz/D0 );
@ -163,8 +163,8 @@ void compute_sigma_gauss( config_file& cf, transfer_function *ptf, double R, std
constraint_set::constraint_set( config_file& cf, transfer_function *ptf )
: pcf_( &cf ), ptf_( ptf )
{
pcosmo_ = new Cosmology( cf );
pccalc_ = new CosmoCalc( *pcosmo_, ptf_ );
pcosmo_ = new cosmology::parameters( cf );
pccalc_ = new cosmology::calculator( cf );
dplus0_ = 1.0;//pccalc_->CalcGrowthFactor( 1.0 );
@ -218,9 +218,9 @@ constraint_set::constraint_set( config_file& cf, transfer_function *ptf )
double zcoll = cf.get_value<double>( "constraints", temp1 );
new_c.Rg = pow((mass/pow(2.*M_PI,1.5)/rhom),1./3.);
new_c.sigma = 1.686/(pccalc_->CalcGrowthFactor(1./(1.+zcoll))/pccalc_->CalcGrowthFactor(1.0));
new_c.sigma = 1.686/(pccalc_->get_growth_factor(1./(1.+zcoll))/pccalc_->get_growth_factor(1.0));
music::ilog.Print("sigma of constraint : %g", new_c.sigma );
new_c.sigma *=pccalc_->CalcGrowthFactor(astart)/pccalc_->CalcGrowthFactor(1.0);
new_c.sigma *=pccalc_->get_growth_factor(astart)/pccalc_->get_growth_factor(1.0);
music::ilog.Print("Constraint %d : halo with %g h-1 M_o",i,pow(2.*M_PI,1.5)*rhom*pow(new_c.Rg,3));
}
else if( new_c.type == peak )
@ -324,7 +324,7 @@ void constraint_set::wnoise_constr_corr( double dx, size_t nx, size_t ny, size_t
double k = sqrt(iix*iix+iiy*iiy+iiz*iiz)*(double)nx/lsub;
double T = ptf_->compute(k,total);
double T = ptf_->compute(k,delta_matter);
double Pk = pnorm*T*T*pow(k,nspec)*d3k;
size_t q = ((size_t)ix*ny+(size_t)iy)*nzp+(size_t)iz;
@ -407,7 +407,7 @@ void constraint_set::wnoise_constr_corr( double dx, complex_t* cw, size_t nx, si
iiz *= 2.0*M_PI/nx;
double k = sqrt(iix*iix+iiy*iiy+iiz*iiz)*(double)nx/lsub;
double T = ptf_->compute(k,total);
double T = ptf_->compute(k,delta_matter);
std::complex<double> v(std::conj(eval_constr(i,iix,iiy,iiz)));
@ -472,7 +472,7 @@ void constraint_set::icov_constr( double dx, size_t nx, size_t ny, size_t nz, ma
iiz *= 2.0*M_PI/nx;
double k = sqrt(iix*iix+iiy*iiy+iiz*iiz)*(double)nx/lsub;
double T = ptf_->compute(k,total);
double T = ptf_->compute(k,delta_matter);
std::complex<double> v(std::conj(eval_constr(i,iix,iiy,iiz)));
v *= eval_constr(j,iix,iiy,iiz);
v *= pnorm * pow(k,nspec) * T * T * d3k;

View file

@ -17,7 +17,7 @@
#include <general.hh>
#include <config_file.hh>
#include <transfer_function.hh>
#include <cosmology.hh>
#include <cosmology_calculator.hh>
//! matrix class serving as a gsl wrapper
class matrix
@ -119,8 +119,8 @@ protected:
config_file *pcf_;
std::vector<constraint> cset_;
transfer_function *ptf_;
CosmoCalc *pccalc_;
Cosmology *pcosmo_;
const cosmology::calculator *pccalc_;
const cosmology::parameters *pcosmo_;
double dplus0_;
unsigned constr_level_;

View file

@ -157,7 +157,7 @@ class kernel_k : public kernel
{
protected:
/**/
double boxlength_, patchlength_, nspec_, pnorm_, volfac_, kfac_, kmax_;
double boxlength_, patchlength_, nspec_, pnorm_, kfac_, kmax_;
TransferFunction_k *tfk_;
public:
@ -165,9 +165,8 @@ public:
: kernel(cf, ptf, refh, type)
{
boxlength_ = pcf_->get_value<double>("setup", "boxlength");
nspec_ = pcf_->get_value<double>("cosmology", "nspec");
pnorm_ = pcf_->get_value<double>("cosmology", "pnorm");
volfac_ = 1.0; //pow(boxlength,3)/pow(2.0*M_PI,3);
nspec_ = ptf->cosmo_params_["n_s"];
pnorm_ = ptf->cosmo_params_["pnorm"];
kfac_ = 2.0 * M_PI / boxlength_;
kmax_ = kfac_ / 2;
tfk_ = new TransferFunction_k(type_, ptf_, nspec_, pnorm_);
@ -231,7 +230,7 @@ public:
for (size_t i = 0; i < len; ++i)
{
double kk = kfac_ * in_k[i];
out_Tk[i] = volfac_ * tfk_->compute(kk);
out_Tk[i] = tfk_->compute(kk);
}
}

View file

@ -1,224 +0,0 @@
/*
cosmology.hh - This file is part of MUSIC -
a code to generate multi-scale initial conditions
for cosmological simulations
Copyright (C) 2010 Oliver Hahn
*/
#ifndef _COSMOLOGY_HH
#define _COSMOLOGY_HH
#include "transfer_function.hh"
#include "mesh.hh"
#include "general.hh"
/*!
* @class CosmoCalc
* @brief provides functions to compute cosmological quantities
*
* This class provides member functions to compute cosmological quantities
* related to the Friedmann equations and linear perturbation theory
*/
class CosmoCalc
{
public:
//! data structure to store cosmological parameters
Cosmology m_Cosmology;
//! pointer to an instance of a transfer function plugin
transfer_function_plugin *m_pTransferFunction;
//! constructor for a cosmology calculator object
/*!
* @param acosmo a cosmological parameters structure
* @param pTransferFunction pointer to an instance of a transfer function object
*/
CosmoCalc( const Cosmology acosmo, transfer_function_plugin *pTransferFunction )
{
m_Cosmology = acosmo;
m_pTransferFunction = pTransferFunction;
}
//! returns the amplitude of amplitude of the power spectrum
/*!
* @param k the wave number in h/Mpc
* @param a the expansion factor of the universe
* @returns power spectrum amplitude for wave number k at time a
*/
inline real_t Power( real_t k, real_t a ){
real_t m_Dplus = CalcGrowthFactor( a );
real_t m_DplusOne = CalcGrowthFactor( 1.0 );
real_t m_pNorm = ComputePNorm( 1e4 );
m_Dplus /= m_DplusOne;
m_DplusOne = 1.0;
real_t scale = m_Dplus/m_DplusOne;
return m_pNorm*scale*scale*TransferSq(k)*pow((double)k,(double)m_Cosmology.nspect);
}
inline static double H_of_a( double a, void *Params )
{
Cosmology *cosm = (Cosmology*)Params;
double a2 = a*a;
double Ha = sqrt(cosm->Omega_m/(a2*a) + cosm->Omega_k/a2
+ cosm->Omega_DE * pow(a,-3.*(1.+cosm->w_0+cosm->w_a)) * exp(-3.*(1.0-a)*cosm->w_a) );
return Ha;
}
inline static double Hprime_of_a( double a, void *Params )
{
Cosmology *cosm = (Cosmology*)Params;
double a2 = a*a;
double H = H_of_a( a, Params );
double Hprime = 1/(a*H) * ( -1.5 * cosm->Omega_m / (a2*a) - cosm->Omega_k / a2
- 1.5 * cosm->Omega_DE * pow( a, -3.*(1.+cosm->w_0+cosm->w_a) ) * exp( -3.*(1.0-a)*cosm->w_a )
* ( 1. + cosm->w_0 + (1.-a) * cosm->w_a ) );
return Hprime;
}
//! Integrand used by function CalcGrowthFactor to determine the linear growth factor D+
inline static double GrowthIntegrand( double a, void *Params )
{
double Ha = a * H_of_a( a, Params );
return 2.5/( Ha * Ha * Ha );
}
//! Computes the linear theory growth factor D+
/*! Function integrates over member function GrowthIntegrand and computes
* /a
* D+(a) = 5/2 H(a) * | [a'^3 * H(a')^3]^(-1) da'
* /0
*/
real_t CalcGrowthFactor( real_t a )
{
real_t integral = integrate( &GrowthIntegrand, 0.0, a, (void*)&m_Cosmology );
return H_of_a( a, (void*)&m_Cosmology ) * integral;
}
//! Compute the factor relating particle displacement and velocity
/*! Function computes
*
* vfac = a^2 * H(a) * dlogD+ / d log a = a^2 * H'(a) + 5/2 * [ a * D+(a) * H(a) ]^(-1)
*
*/
real_t CalcVFact( real_t a )
{
real_t Dp = CalcGrowthFactor( a );
real_t H = H_of_a( a, (void*)&m_Cosmology );
real_t Hp = Hprime_of_a( a, (void*)&m_Cosmology );
real_t a2 = a*a;
return ( a2 * Hp + 2.5 / ( a * Dp * H ) ) * 100.0;
}
//! Integrand for the sigma_8 normalization of the power spectrum
/*! Returns the value of the primordial power spectrum multiplied with
the transfer function and the window function of 8 Mpc/h at wave number k */
static double dSigma8( double k, void *Params )
{
if( k<=0.0 )
return 0.0f;
transfer_function *ptf = (transfer_function *)Params;
double x = k*8.0;
double w = 3.0*(sin(x)-x*cos(x))/(x*x*x);
static double nspect = (double)ptf->cosmo_.nspect;
double tf = ptf->compute(k, total);
//... no growth factor since we compute at z=0 and normalize so that D+(z=0)=1
return k*k * w*w * pow((double)k,(double)nspect) * tf*tf;
}
//! Integrand for the sigma_8 normalization of the power spectrum
/*! Returns the value of the primordial power spectrum multiplied with
the transfer function and the window function of 8 Mpc/h at wave number k */
static double dSigma8_0( double k, void *Params )
{
if( k<=0.0 )
return 0.0f;
transfer_function *ptf = (transfer_function *)Params;
double x = k*8.0;
double w = 3.0*(sin(x)-x*cos(x))/(x*x*x);
static double nspect = (double)ptf->cosmo_.nspect;
double tf = ptf->compute(k, total0);
//... no growth factor since we compute at z=0 and normalize so that D+(z=0)=1
return k*k * w*w * pow((double)k,(double)nspect) * tf*tf;
}
//! Computes the square of the transfer function
/*! Function evaluates the supplied transfer function m_pTransferFunction
* and returns the square of its value at wave number k
* @param k wave number at which to evaluate the transfer function
*/
inline real_t TransferSq( real_t k ){
//.. parameter supplied transfer function
real_t tf1 = m_pTransferFunction->compute(k, total);
return tf1*tf1;
}
//! Computes the normalization for the power spectrum
/*!
* integrates the power spectrum to fix the normalization to that given
* by the sigma_8 parameter
*/
real_t ComputePNorm( real_t kmax )
{
real_t sigma0, kmin;
kmax = m_pTransferFunction->get_kmax();//m_Cosmology.H0/8.0;
kmin = m_pTransferFunction->get_kmin();//0.0;
if( !m_pTransferFunction->tf_has_total0() )
sigma0 = 4.0 * M_PI * integrate( &dSigma8, (double)kmin, (double)kmax, (void*)m_pTransferFunction );
else
sigma0 = 4.0 * M_PI * integrate( &dSigma8_0, (double)kmin, (double)kmax, (void*)m_pTransferFunction );
return m_Cosmology.sigma8*m_Cosmology.sigma8/sigma0;
}
};
//! compute the jeans sound speed
/*! given a density in g/cm^-3 and a mass in g it gives back the sound
* speed in cm/s for which the input mass is equal to the jeans mass
* @param rho density
* @param mass mass scale
* @returns jeans sound speed
*/
inline double jeans_sound_speed( double rho, double mass )
{
const double G = 6.67e-8;
return pow( 6.0*mass/M_PI*sqrt(rho)*pow(G,1.5), 1.0/3.0 );
}
//! computes the density from the potential using the Laplacian
void compute_Lu_density( const grid_hierarchy& u, grid_hierarchy& fnew, unsigned order=4 );
//! computes the 2nd order density perturbations using also off-diagonal terms in the potential Hessian
void compute_LLA_density( const grid_hierarchy& u, grid_hierarchy& fnew, unsigned order=4 );
//! computes the source term for the 2nd order perturbations in the displacements
void compute_2LPT_source( const grid_hierarchy& u, grid_hierarchy& fnew, unsigned order=4 );
void compute_2LPT_source_FFT( config_file& cf_, const grid_hierarchy& u, grid_hierarchy& fnew );
#endif // _COSMOLOGY_HH

View file

@ -17,11 +17,11 @@
#pragma once
#include <array>
#include <vec.hh>
#include "math/vec.hh"
#include <cosmology_parameters.hh>
#include <physical_constants.hh>
#include <transfer_function_plugin.hh>
#include <transfer_function.hh>
#include <math/ode_integrate.hh>
#include <logger.hh>
@ -30,7 +30,7 @@
#include <gsl/gsl_integration.h>
#include <gsl/gsl_errno.h>
namespace cosmology_new
namespace cosmology
{
/*!
@ -48,7 +48,7 @@ public:
cosmology::parameters cosmo_param_;
//! pointer to an instance of a transfer function plugin
std::unique_ptr<TransferFunction_plugin> transfer_function_;
std::unique_ptr<transfer_function_plugin> transfer_function_;
private:
static constexpr double REL_PRECISION = 1e-10;
@ -90,7 +90,7 @@ private:
*/
void compute_growth( std::vector<double>& tab_a, std::vector<double>& tab_D, std::vector<double>& tab_f )
{
using v_t = vec_t<3, double>;
using v_t = vec_t<3,double>;
// set ICs, very deep in radiation domination
const double a0 = 1e-10;
@ -177,9 +177,10 @@ public:
Dplus_target_ = D_of_a_( atarget_ ) / Dnow_;
music::ilog << "Linear growth factors: D+_target = " << Dplus_target_ << ", D+_start = " << Dplus_start_ << std::endl;
music::ilog << "-------------------------------------------------------------------------------" << std::endl;
// set up transfer functions and compute normalisation
transfer_function_ = select_TransferFunction_plugin(cf, cosmo_param_);
transfer_function_ = select_transfer_function_plugin(cf, cosmo_param_);
transfer_function_->intialise();
if( !transfer_function_->tf_isnormalised_ ){
cosmo_param_.set("pnorm", this->compute_pnorm_from_sigma8() );
@ -190,9 +191,14 @@ public:
}
cosmo_param_.set("sqrtpnorm", std::sqrt(cosmo_param_["pnorm"]));
music::ilog << std::setw(32) << std::left << "TF supports distinct CDM+baryons"
// if (!transfer_function_->tf_is_distinct())
// music::wlog << " - WARNING: The selected transfer function does not support" << std::endl
// << " distinct amplitudes for baryon and DM fields!" << std::endl
// << " Perturbation amplitudes will be identical!" << std::endl;
music::ilog << std::setw(32) << std::left << " . TF supports distinct CDM+baryons"
<< " : " << (transfer_function_->tf_is_distinct() ? "yes" : "no") << std::endl;
music::ilog << std::setw(32) << std::left << "TF maximum wave number"
music::ilog << std::setw(32) << std::left << " . TF maximum wave number"
<< " : " << transfer_function_->get_kmax() << " h/Mpc" << std::endl;
m_n_s_ = cosmo_param_["n_s"];

View file

@ -21,7 +21,7 @@
* @brief namespace encapsulating all things cosmology
*
*/
namespace cosmology_new{
namespace cosmology{
//! we store here the preset cosmological paramters
parameters::defaultmmap_t parameters::default_pmaps_

View file

@ -23,7 +23,7 @@
#include <config_file.hh>
#include <general.hh>
namespace cosmology_new
namespace cosmology
{
//! structure for cosmological parameters
class parameters
@ -50,6 +50,19 @@ namespace cosmology_new
return it->second;
}
//! get routine for cosmological parameter key-value pairs
double& get(const std::string &key)
{
auto it = pmap_.find(key);
if (it == pmap_.end())
{
auto errmsg = std::string("Cosmological parameter \'") + key + std::string("\' does not exist in internal list.");
music::elog << errmsg << std::endl;
throw std::runtime_error(errmsg.c_str());
}
return it->second;
}
//! set routine for cosmological parameter key-value pairs
void set(const std::string &key, const double value)
{
@ -69,6 +82,9 @@ namespace cosmology_new
//! shortcut get routine for cosmological parameter key-value pairs through bracket operator
inline double operator[](const std::string &key) const { return this->get(key); }
//! shortcut get routine for cosmological parameter key-value pairs through bracket operator
inline double& operator[](const std::string &key) { return this->get(key); }
//! default constructor does nothing
parameters() {}

View file

@ -253,9 +253,10 @@ void fft_interpolate(m1 &V, m2 &v, bool from_basegrid = false)
/*******************************************************************************************/
/*******************************************************************************************/
void GenerateDensityUnigrid(config_file &cf, transfer_function *ptf, tf_type type,
void GenerateDensityUnigrid(config_file &cf, const cosmology::calculator* cc, tf_type type,
refinement_hierarchy &refh, noise_generator &rand, grid_hierarchy &delta, bool smooth, bool shift)
{
auto ptf = cc->transfer_function_.get();
unsigned levelmin, levelmax, levelminPoisson;
levelminPoisson = cf.get_value<unsigned>("setup", "levelmin");
@ -308,10 +309,11 @@ void GenerateDensityUnigrid(config_file &cf, transfer_function *ptf, tf_type typ
/*******************************************************************************************/
/*******************************************************************************************/
void GenerateDensityHierarchy(config_file &cf, transfer_function *ptf, tf_type type,
void GenerateDensityHierarchy(config_file &cf, const cosmology::calculator* cc, tf_type type,
refinement_hierarchy &refh, noise_generator &rand,
grid_hierarchy &delta, bool smooth, bool shift)
{
auto ptf = cc->transfer_function_.get();
unsigned levelmin, levelmax, levelminPoisson;
std::vector<long> rngseeds;
std::vector<std::string> rngfnames;

View file

@ -15,16 +15,14 @@
#include "general.hh"
#include "config_file.hh"
// #include "density_grid.hh"
#include "random.hh"
#include "cosmology.hh"
#include "transfer_function.hh"
#include "general.hh"
void GenerateDensityHierarchy(config_file &cf, transfer_function *ptf, tf_type type,
void GenerateDensityHierarchy(config_file &cf, const cosmology::calculator* cc, tf_type type,
refinement_hierarchy &refh, noise_generator &rand, grid_hierarchy &delta, bool smooth, bool shift);
void GenerateDensityUnigrid(config_file &cf, transfer_function *ptf, tf_type type,
void GenerateDensityUnigrid(config_file &cf, const cosmology::calculator*, tf_type type,
refinement_hierarchy &refh, noise_generator &rand, grid_hierarchy &delta, bool smooth, bool shift);
void normalize_density(grid_hierarchy &delta);

View file

@ -12,9 +12,10 @@
#include <logger.hh>
#include <config_file.hh>
#include <memory>
#include <cassert>
#include <omp.h>
#include <complex>
#include <fftw3.h>
@ -35,6 +36,8 @@
#define FFTW_PREFIX fftwl
#endif
using ccomplex_t = std::complex<real_t>;
#define FFTW_GEN_NAME_PRIM(a, b) a##_##b
#define FFTW_GEN_NAME(a, b) FFTW_GEN_NAME_PRIM(a, b)
#define FFTW_API(x) FFTW_GEN_NAME(FFTW_PREFIX, x)
@ -46,14 +49,13 @@ using fftw_plan_t = FFTW_GEN_NAME(FFTW_PREFIX, plan);
#include <vector>
#include <array>
using vec3_t = std::array<real_t,3>;
namespace CONFIG
{
// extern int MPI_thread_support;
// extern int MPI_task_rank;
// extern int MPI_task_size;
// extern bool MPI_ok;
extern int MPI_task_rank;
extern int MPI_task_size;
extern bool MPI_ok;
// extern bool MPI_threads_ok;
extern bool FFTW_threads_ok;
extern int num_threads;
@ -80,7 +82,8 @@ inline T POW4( T a ){
//! structure for cosmological parameters
typedef struct cosmology{
/*
typedef struct cosmology_old{
double
Omega_m, //!< baryon+dark matter density
Omega_b, //!< baryon matter density
@ -133,7 +136,7 @@ typedef struct cosmology{
{
}
}Cosmology;
}Cosmology;*/
//! basic box/grid/refinement structure parameters
typedef struct {

View file

@ -44,7 +44,9 @@ extern "C"
#include <densities.hh>
#include <convolution_kernel.hh>
#include <cosmology.hh>
#include <perturbation_theory.hh>
#include <cosmology_parameters.hh>
#include <cosmology_calculator.hh>
#include <transfer_function.hh>
#define THE_CODE_NAME "music!"
@ -53,9 +55,9 @@ extern "C"
// initialise with "default" values
namespace CONFIG{
// int MPI_thread_support = -1;
// int MPI_task_rank = 0;
// int MPI_task_size = 1;
// bool MPI_ok = false;
int MPI_task_rank = 0;
int MPI_task_size = 1;
bool MPI_ok = false;
// bool MPI_threads_ok = false;
bool FFTW_threads_ok = false;
int num_threads = 1;
@ -67,7 +69,7 @@ namespace music
struct framework
{
transfer_function *the_transfer_function;
// transfer_function *the_transfer_function;
// poisson_solver *the_poisson_solver;
config_file *the_config_file;
refinement_hierarchy *the_refinement_hierarchy;
@ -76,13 +78,15 @@ namespace music
}
//... declare static class members here
transfer_function *TransferFunction_real::ptf_ = NULL;
// transfer_function *TransferFunction_real::ptf_ = NULL;
transfer_function *TransferFunction_k::ptf_ = NULL;
tf_type TransferFunction_k::type_;
tf_type TransferFunction_real::type_;
real_t TransferFunction_real::nspec_ = -1.0;
// tf_type TransferFunction_real::type_;
// real_t TransferFunction_real::nspec_ = -1.0;
real_t TransferFunction_k::nspec_ = -1.0;
std::unique_ptr<cosmology::calculator> the_cosmo_calc;
//... prototypes for routines used in main driver routine
void splash(void);
void modify_grid_for_TF(const refinement_hierarchy &rh_full, refinement_hierarchy &rh_TF, config_file &cf);
@ -95,17 +99,24 @@ void splash(void)
{
music::ilog << std::endl
<< " __ __ __ __ ______ __ ______ " << std::endl
<< " /\\ \"-./ \\ /\\ \\/\\ \\ /\\ ___\\ /\\ \\ /\\ ___\\ " << std::endl
<< " \\ \\ \\-./\\ \\ \\ \\ \\_\\ \\ \\ \\___ \\ \\ \\ \\ \\ \\ \\____ " << std::endl
<< " \\ \\_\\ \\ \\_\\ \\ \\_____\\ \\/\\_____\\ \\ \\_\\ \\ \\_____\\ " << std::endl
<< " \\/_/ \\/_/ \\/_____/ \\/_____/ \\/_/ \\/_____/ " << std::endl << std::endl
<< " this is " << THE_CODE_NAME << " version " << THE_CODE_VERSION << std::endl << std::endl;
<< " __ __ __ __ ______ __ ______ " << std::endl
<< " /\\ \"-./ \\ /\\ \\/\\ \\ /\\ ___\\ /\\ \\ /\\ ___\\ " << std::endl
<< " \\ \\ \\-./\\ \\ \\ \\ \\_\\ \\ \\ \\___ \\ \\ \\ \\ \\ \\ \\____ " << std::endl
<< " \\ \\_\\ \\ \\_\\ \\ \\_____\\ \\/\\_____\\ \\ \\_\\ \\ \\_____\\ " << std::endl
<< " \\/_/ \\/_/ \\/_____/ \\/_____/ \\/_/ \\/_____/ " << std::endl << std::endl
<< " this is " << THE_CODE_NAME << " version " << THE_CODE_VERSION << std::endl << std::endl;
#if defined(CMAKE_BUILD)
music::ilog.Print("Version built from git rev.: %s, tag: %s, branch: %s", GIT_REV, GIT_TAG, GIT_BRANCH);
// git and versioning info:
music::ilog << "Version: git rev.: " << GIT_REV << ", tag: " << GIT_TAG << ", branch: " << GIT_BRANCH << std::endl;
// Compilation CMake configuration, time etc info:
music::ilog << "This " << CMAKE_BUILDTYPE_STR << " build was compiled at " << __TIME__ << " on " << __DATE__ << std::endl;
#ifdef __GNUC__
music::ilog << "Compiled with GNU C++ version " << __VERSION__ <<std::endl;
#else
music::ilog << "Compiled with " << __VERSION__ << std::endl;
#endif
music::ilog << std::endl << std::endl;
}
void modify_grid_for_TF(const refinement_hierarchy &rh_full, refinement_hierarchy &rh_TF, config_file &cf)
@ -378,6 +389,7 @@ int main(int argc, const char *argv[])
splash();
std::cout << " This version is compiled with the following plug-ins:\n";
cosmology::print_ParameterSets();
print_region_generator_plugins();
print_transfer_function_plugins();
print_RNG_plugins();
@ -407,8 +419,6 @@ int main(int argc, const char *argv[])
config_file cf(argv[1]);
std::string tfname, randfname, temp;
bool force_shift(false);
double boxlength;
//------------------------------------------------------------------------------
//... init multi-threading
@ -424,7 +434,6 @@ int main(int argc, const char *argv[])
//... initialize some parameters about grid set-up
//------------------------------------------------------------------------------
boxlength = cf.get_value<double>("setup", "boxlength");
lbase = cf.get_value<unsigned>("setup", "levelmin");
lmax = cf.get_value<unsigned>("setup", "levelmax");
lbaseTF = cf.get_value_safe<unsigned>("setup", "levelmin_TF", lbase);
@ -463,39 +472,42 @@ int main(int argc, const char *argv[])
do_LLA = cf.get_value_safe<bool>("setup", "use_LLA", false),
do_counter_mode = cf.get_value_safe<bool>("setup", "zero_zoom_velocity", false);
transfer_function_plugin *the_transfer_function_plugin = select_transfer_function_plugin(cf);
the_cosmo_calc = std::make_unique<cosmology::calculator>(cf);
cosmology cosmo(cf);
bool tf_has_velocities = the_cosmo_calc.get()->transfer_function_.get()->tf_has_velocities();
//--------------------------------------------------------------------------------------------------------
//! starting redshift
const real_t zstart = cf.get_value<double>("setup", "zstart");
const real_t astart = 1.0/(1.0+zstart);
music::ilog << "- starting at a=" << 1.0/(1.0+zstart) << std::endl;
music::ilog << "- starting at a=" << cosmo.astart << std::endl;
CosmoCalc ccalc(cosmo, the_transfer_function_plugin);
cosmo.pnorm = ccalc.ComputePNorm(2.0 * M_PI / boxlength);
cosmo.dplus = ccalc.CalcGrowthFactor(cosmo.astart) / ccalc.CalcGrowthFactor(1.0);
cosmo.vfact = ccalc.CalcVFact(cosmo.astart);
if (!the_transfer_function_plugin->tf_has_total0())
cosmo.pnorm *= cosmo.dplus * cosmo.dplus;
double cosmo_dplus = the_cosmo_calc->get_growth_factor(astart) / the_cosmo_calc->get_growth_factor(1.0);
double cosmo_vfact = the_cosmo_calc->get_vfact(astart);
if (!the_cosmo_calc.get()->transfer_function_.get()->tf_has_total0()){
the_cosmo_calc->cosmo_param_["pnorm"] *= cosmo_dplus * cosmo_dplus;
}
double cosmo_pnorm = the_cosmo_calc->cosmo_param_["pnorm"];
//... directly use the normalisation via a parameter rather than the calculated one
cosmo.pnorm = cf.get_value_safe<double>("setup", "force_pnorm", cosmo.pnorm);
cosmo_pnorm = cf.get_value_safe<double>("setup", "force_pnorm", cosmo_pnorm);
double vfac2lpt = 1.0;
if (the_transfer_function_plugin->tf_velocity_units() && do_baryons)
if (the_cosmo_calc->transfer_function_->tf_velocity_units() && do_baryons)
{
vfac2lpt = cosmo.vfact; // if the velocities are in velocity units, we need to divide by vfact for the 2lPT term
cosmo.vfact = 1.0;
vfac2lpt = cosmo_vfact; // if the velocities are in velocity units, we need to divide by vfact for the 2lPT term
cosmo_vfact = 1.0;
}
//
{
char tmpstr[128];
snprintf(tmpstr, 128, "%.12g", cosmo.pnorm);
snprintf(tmpstr, 128, "%.12g", cosmo_pnorm);
cf.insert_value("cosmology", "pnorm", tmpstr);
snprintf(tmpstr, 128, "%.12g", cosmo.dplus);
snprintf(tmpstr, 128, "%.12g", cosmo_dplus);
cf.insert_value("cosmology", "dplus", tmpstr);
snprintf(tmpstr, 128, "%.12g", cosmo.vfact);
snprintf(tmpstr, 128, "%.12g", cosmo_vfact);
cf.insert_value("cosmology", "vfact", tmpstr);
}
@ -505,16 +517,13 @@ int main(int argc, const char *argv[])
//... determine run parameters
//------------------------------------------------------------------------------
if (!the_transfer_function_plugin->tf_is_distinct() && do_baryons)
music::wlog << " - WARNING: The selected transfer function does not support" << std::endl
<< " distinct amplitudes for baryon and DM fields!" << std::endl
<< " Perturbation amplitudes will be identical!" << std::endl;
//------------------------------------------------------------------------------
//... start up the random number generator plugin
//... see if we need to set some grid building constraints
noise_generator rand( cf, the_transfer_function_plugin );
noise_generator rand( cf );
//------------------------------------------------------------------------------
//... determine the refinement hierarchy
@ -549,13 +558,11 @@ int main(int argc, const char *argv[])
music::ilog << " GENERATING WHITE NOISE\n";
music::ilog << "-------------------------------------------------------------------------------" << std::endl;
music::ilog << "Computing white noise..." << std::endl;
// rand_gen rand(cf, rh_TF, the_transfer_function_plugin);
rand.initialize_for_grid_structure( rh_TF );
//------------------------------------------------------------------------------
//... initialize the Poisson solver
//------------------------------------------------------------------------------
// bool bdefd = cf.get_value_safe<bool> ( "poisson" , "fft_fine", true );
bool bdefd = true; // we set this by default and don't allow it to be changed outside any more
bool bglass = cf.get_value_safe<bool>("output", "glass", false);
bool bsph = cf.get_value_safe<bool>("setup", "do_SPH", false) && do_baryons;
@ -610,11 +617,11 @@ int main(int argc, const char *argv[])
music::ulog.Print("Computing dark matter displacements...");
grid_hierarchy f(nbnd); //, u(nbnd);
tf_type my_tf_type = cdm;
if (!do_baryons || !the_transfer_function_plugin->tf_is_distinct())
my_tf_type = total;
tf_type my_tf_type = delta_cdm;
if (!do_baryons)
my_tf_type = delta_matter;
GenerateDensityHierarchy(cf, the_transfer_function_plugin, my_tf_type, rh_TF, rand, f, false, false);
GenerateDensityHierarchy(cf, the_cosmo_calc.get(), my_tf_type, rh_TF, rand, f, false, false);
coarsen_density(rh_Poisson, f, bspectral_sampling);
f.add_refinement_mask(rh_Poisson.get_coord_shift());
@ -678,7 +685,7 @@ int main(int argc, const char *argv[])
music::ilog << " COMPUTING BARYON DENSITY\n";
music::ilog << "-------------------------------------------------------------------------------" << std::endl;
music::ulog.Print("Computing baryon density...");