mirror of
https://github.com/cosmo-sims/MUSIC.git
synced 2024-09-19 17:03:46 +02:00
Many minor changes
* Moved hybrid poisson solver from convolution_kernel.cc to poisson.cc * Fine-tuned deconvolution schemes for various running modes * Added lots of doxygen documentation
This commit is contained in:
parent
af02e4ef4e
commit
275753ede2
21 changed files with 779 additions and 443 deletions
|
@ -31,6 +31,7 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "Numerics.hh"
|
#include "Numerics.hh"
|
||||||
|
|
||||||
|
|
||||||
#ifndef REL_PRECISION
|
#ifndef REL_PRECISION
|
||||||
#define REL_PRECISION 1.e-4
|
#define REL_PRECISION 1.e-4
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "general.hh"
|
#include "general.hh"
|
||||||
|
|
||||||
|
|
||||||
real_t integrate( double (* func) (double x, void * params), double a, double b, void *params=NULL);
|
real_t integrate( double (* func) (double x, void * params), double a, double b, void *params=NULL);
|
||||||
|
|
||||||
typedef __attribute__((__may_alias__)) int aint;
|
typedef __attribute__((__may_alias__)) int aint;
|
||||||
|
|
|
@ -276,7 +276,8 @@ public:
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! runtime error that is thrown if identifier is not found in keys
|
||||||
class ErrIllegalIdentifier : public std::runtime_error{
|
class ErrIllegalIdentifier : public std::runtime_error{
|
||||||
public:
|
public:
|
||||||
ErrIllegalIdentifier( std::string errmsg )
|
ErrIllegalIdentifier( std::string errmsg )
|
||||||
|
|
|
@ -53,6 +53,7 @@ namespace convolution{
|
||||||
template< typename real_t >
|
template< typename real_t >
|
||||||
void perform( kernel * pk, void *pd )
|
void perform( kernel * pk, void *pd )
|
||||||
{
|
{
|
||||||
|
// return;
|
||||||
parameters cparam_ = pk->cparam_;
|
parameters cparam_ = pk->cparam_;
|
||||||
double fftnorm = pow(2.0*M_PI,1.5)/sqrt(cparam_.lx*cparam_.ly*cparam_.lz)/sqrt((double)(cparam_.nx*cparam_.ny*cparam_.nz));
|
double fftnorm = pow(2.0*M_PI,1.5)/sqrt(cparam_.lx*cparam_.ly*cparam_.lz)/sqrt((double)(cparam_.nx*cparam_.ny*cparam_.nz));
|
||||||
|
|
||||||
|
@ -88,10 +89,10 @@ namespace convolution{
|
||||||
for( int k=0; k<cparam_.nz/2+1; ++k )
|
for( int k=0; k<cparam_.nz/2+1; ++k )
|
||||||
{
|
{
|
||||||
unsigned ii = (i*cparam_.ny + j) * (cparam_.nz/2+1) + k;
|
unsigned ii = (i*cparam_.ny + j) * (cparam_.nz/2+1) + k;
|
||||||
|
|
||||||
std::complex<double> ccdata(cdata[ii].re,cdata[ii].im), cckernel(ckernel[ii].re,ckernel[ii].im);
|
std::complex<double> ccdata(cdata[ii].re,cdata[ii].im), cckernel(ckernel[ii].re,ckernel[ii].im);
|
||||||
ccdata = ccdata * cckernel *fftnorm;
|
ccdata = ccdata * cckernel *fftnorm;
|
||||||
|
|
||||||
cdata[ii].re = ccdata.real();
|
cdata[ii].re = ccdata.real();
|
||||||
cdata[ii].im = ccdata.imag();
|
cdata[ii].im = ccdata.imag();
|
||||||
}
|
}
|
||||||
|
@ -149,28 +150,30 @@ namespace convolution{
|
||||||
dy = cparam_.ly/cparam_.ny,
|
dy = cparam_.ly/cparam_.ny,
|
||||||
dz = cparam_.lz/cparam_.nz,
|
dz = cparam_.lz/cparam_.nz,
|
||||||
boxlength = cparam_.pcf->getValue<double>("setup","boxlength"),
|
boxlength = cparam_.pcf->getValue<double>("setup","boxlength"),
|
||||||
|
boxlength2 = 0.5*boxlength,
|
||||||
nspec = cparam_.pcf->getValue<double>("cosmology","nspec"),
|
nspec = cparam_.pcf->getValue<double>("cosmology","nspec"),
|
||||||
pnorm = cparam_.pcf->getValue<double>("cosmology","pnorm"),
|
pnorm = cparam_.pcf->getValue<double>("cosmology","pnorm"),
|
||||||
dplus = cparam_.pcf->getValue<double>("cosmology","dplus");
|
dplus = cparam_.pcf->getValue<double>("cosmology","dplus");
|
||||||
|
|
||||||
bool
|
bool
|
||||||
bavgfine = cparam_.pcf->getValueSafe<bool>("setup","avg_fine",false),
|
bavgfine = cparam_.pcf->getValueSafe<bool>("setup","avg_fine",false),
|
||||||
bdefd = cparam_.pcf->getValueSafe<bool> ( "poisson" , "deconvolve", false ),
|
bperiodic = cparam_.pcf->getValueSafe<bool>("setup","periodic_TF",true),
|
||||||
bperiodic = cparam_.pcf->getValueSafe<bool>("setup","periodic_TF",true);
|
kspacepoisson = (cparam_.pcf->getValueSafe<bool>("poisson","fft_fine",true)|
|
||||||
|
cparam_.pcf->getValueSafe<bool>("poisson","kspace",false));
|
||||||
unsigned
|
unsigned
|
||||||
levelmax = cparam_.pcf->getValue<unsigned>("setup","levelmax");
|
levelmax = cparam_.pcf->getValue<unsigned>("setup","levelmax");
|
||||||
|
|
||||||
|
|
||||||
if( bavgfine )
|
if( bavgfine )
|
||||||
cparam_.coarse_fact++;
|
cparam_.coarse_fact++;
|
||||||
|
|
||||||
const int ref_fac = (int)(pow(2,cparam_.coarse_fact)+0.5), ql = -ref_fac/2+1, qr=ql+ref_fac, rf8=(int)pow(ref_fac,3);
|
const int ref_fac = (int)(pow(2,cparam_.coarse_fact)+0.5), ql = -ref_fac/2+1, qr=ql+ref_fac, rf8=(int)pow(ref_fac,3);
|
||||||
|
|
||||||
std::cout << " - Computing transfer function kernel...\n";
|
std::cout << " - Computing transfer function kernel...\n";
|
||||||
|
|
||||||
if(! cparam_.is_finest )
|
if(! cparam_.is_finest )
|
||||||
kny *= pow(2,cparam_.coarse_fact);
|
kny *= pow(2,cparam_.coarse_fact);
|
||||||
|
|
||||||
|
|
||||||
TransferFunction_real *tfr =
|
TransferFunction_real *tfr =
|
||||||
new TransferFunction_real(type, cparam_.ptf,nspec,pnorm,dplus,
|
new TransferFunction_real(type, cparam_.ptf,nspec,pnorm,dplus,
|
||||||
|
@ -187,6 +190,11 @@ namespace convolution{
|
||||||
|
|
||||||
T0 = tfr->compute_real(0.0);
|
T0 = tfr->compute_real(0.0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(bavgfine)
|
||||||
|
cparam_.coarse_fact--;
|
||||||
|
|
||||||
//... obtain a grid-version of the real space transfer function
|
//... obtain a grid-version of the real space transfer function
|
||||||
if( bperiodic )
|
if( bperiodic )
|
||||||
{
|
{
|
||||||
|
@ -306,26 +314,32 @@ namespace convolution{
|
||||||
rrr[2] = rr[2]+(double)kkk*0.5*dx - 0.25*dx;
|
rrr[2] = rr[2]+(double)kkk*0.5*dx - 0.25*dx;
|
||||||
rrr2[2]= rrr[2]*rrr[2];
|
rrr2[2]= rrr[2]*rrr[2];
|
||||||
rr2 = rrr2[0]+rrr2[1]+rrr2[2];
|
rr2 = rrr2[0]+rrr2[1]+rrr2[2];
|
||||||
kdata_[idx] += (fftw_real)(tfr->compute_real(rr2)/rf8);
|
if( fabs(rr[0])<=boxlength2||fabs(rr[1])<=boxlength2||fabs(rr[2])<=boxlength2 )
|
||||||
|
kdata_[idx] += (fftw_real)(tfr->compute_real(rr2)/rf8)*fac;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
rr2 = rr[0]*rr[0]+rr[1]*rr[1]+rr[2]*rr[2];
|
rr2 = rr[0]*rr[0]+rr[1]*rr[1]+rr[2]*rr[2];
|
||||||
kdata_[idx] += (fftw_real)tfr->compute_real(rr2);
|
if( fabs(rr[0])<=boxlength2||fabs(rr[1])<=boxlength2||fabs(rr[2])<=boxlength2 )
|
||||||
|
kdata_[idx] += (fftw_real)tfr->compute_real(rr2)*fac;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( cparam_.is_finest )
|
if( cparam_.is_finest )
|
||||||
|
{
|
||||||
kdata_[0] = tfr->compute_real(0.0)*fac;
|
kdata_[0] = tfr->compute_real(0.0)*fac;
|
||||||
|
//std::cerr << "T(0) = " << kdata_[0] << std::endl;
|
||||||
|
//kdata_[0] = sqrt(8.0)*tfr->compute_real(0.5*sqrt(3.0)*dx/4)*fac;
|
||||||
|
//std::cerr << "T(0) = " << kdata_[0] << std::endl;
|
||||||
|
}
|
||||||
T0 = kdata_[0];
|
T0 = kdata_[0];
|
||||||
delete tfr;
|
delete tfr;
|
||||||
|
|
||||||
double k0 = kdata_[0];
|
double k0 = kdata_[0];
|
||||||
|
|
||||||
//... subtract white noise component before deconvolution
|
//... subtract white noise component before deconvolution
|
||||||
if( cparam_.deconvolve )//&& cparam_.is_finest)
|
if( cparam_.deconvolve )//&& cparam_.is_finest)
|
||||||
kdata_[0] = 0.0;
|
kdata_[0] = 0.0;
|
||||||
|
@ -336,6 +350,7 @@ namespace convolution{
|
||||||
rfftwnd_one_real_to_complex( plan, rkernel, NULL );
|
rfftwnd_one_real_to_complex( plan, rkernel, NULL );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//... do some k-space filter correction stuff
|
||||||
if( cparam_.deconvolve || cparam_.smooth )
|
if( cparam_.deconvolve || cparam_.smooth )
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -359,15 +374,6 @@ namespace convolution{
|
||||||
|
|
||||||
double ipix = 1.0;
|
double ipix = 1.0;
|
||||||
|
|
||||||
//... perform k-space 'averaging' for coarser grids
|
|
||||||
/*if( !cparam_.is_finest )
|
|
||||||
{
|
|
||||||
for( unsigned c=1; c<= cparam_.coarse_fact; ++c )
|
|
||||||
{
|
|
||||||
double kkmax = 0.5*kmax/pow(2,c-1);
|
|
||||||
ipix *= (cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax));
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
double kkmax = kmax;// / pow(2,cparam_.coarse_fact);
|
double kkmax = kmax;// / pow(2,cparam_.coarse_fact);
|
||||||
|
|
||||||
|
@ -387,17 +393,30 @@ namespace convolution{
|
||||||
|
|
||||||
if( !cparam_.smooth )
|
if( !cparam_.smooth )
|
||||||
{
|
{
|
||||||
|
if( cparam_.is_finest )
|
||||||
if(!(bdefd&&cparam_.is_finest))
|
|
||||||
{
|
{
|
||||||
kkernel[q].re *= ipix;
|
if( kspacepoisson )
|
||||||
kkernel[q].im *= ipix;
|
{
|
||||||
|
kkernel[q].re /= cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax);
|
||||||
|
kkernel[q].im /= cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax);
|
||||||
|
///////kkernel[q].re *= ipix;
|
||||||
|
///////kkernel[q].im *= ipix;
|
||||||
|
}else{
|
||||||
|
|
||||||
|
////////kkernel[q].re /= cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax);
|
||||||
|
////////kkernel[q].im /= cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax);
|
||||||
|
|
||||||
|
kkernel[q].re *= ipix;
|
||||||
|
kkernel[q].im *= ipix;
|
||||||
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
kkmax /= pow(2,cparam_.coarse_fact);
|
|
||||||
kkernel[q].re /= cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax);
|
kkernel[q].re /= cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax);
|
||||||
kkernel[q].im /= cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax);
|
kkernel[q].im /= cos(kx*kkmax)*cos(ky*kkmax)*cos(kz*kkmax);
|
||||||
|
////////kkernel[q].re *= ipix;
|
||||||
|
////////kkernel[q].im *= ipix;
|
||||||
}
|
}
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
//... if smooth==true, convolve with
|
//... if smooth==true, convolve with
|
||||||
//... NGP kernel to get CIC smoothness
|
//... NGP kernel to get CIC smoothness
|
||||||
|
@ -427,7 +446,7 @@ namespace convolution{
|
||||||
//... set white noise component to zero if smoothing is enabled
|
//... set white noise component to zero if smoothing is enabled
|
||||||
if( cparam_.smooth )
|
if( cparam_.smooth )
|
||||||
dk = 0.0;
|
dk = 0.0;
|
||||||
|
|
||||||
//... enforce the r=0 component by adjusting the k-space mean
|
//... enforce the r=0 component by adjusting the k-space mean
|
||||||
#pragma omp parallel for reduction(+:ksum,kcount)
|
#pragma omp parallel for reduction(+:ksum,kcount)
|
||||||
for( int i=0; i<cparam_.nx; ++i )
|
for( int i=0; i<cparam_.nx; ++i )
|
||||||
|
@ -441,8 +460,7 @@ namespace convolution{
|
||||||
|
|
||||||
rfftwnd_destroy_plan(plan);
|
rfftwnd_destroy_plan(plan);
|
||||||
|
|
||||||
if(bavgfine)
|
|
||||||
cparam_.coarse_fact--;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -525,305 +543,9 @@ namespace convolution{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
#pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
template<int order>
|
|
||||||
double deconv_kernel( int idir, int i, int j, int k, int n )
|
|
||||||
{
|
|
||||||
return 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline double deconv_kernel<2>(int idir, int i, int j, int k, int n )
|
|
||||||
{
|
|
||||||
double
|
|
||||||
ki(M_PI*(double)i/(double)n),
|
|
||||||
kj(M_PI*(double)j/(double)n),
|
|
||||||
kk(M_PI*(double)k/(double)n),
|
|
||||||
kr(sqrt(ki*ki+kj*kj+kk*kk));
|
|
||||||
|
|
||||||
double grad = 1.0, laplace = 1.0;
|
|
||||||
|
|
||||||
if( idir==0&&i!=0 )
|
|
||||||
grad = sin(ki)/ki;
|
|
||||||
else if( idir==1&&j!=0 )
|
|
||||||
grad = sin(kj)/kj;
|
|
||||||
else if( idir==2&&k!=0 )
|
|
||||||
grad = sin(kk)/kk;
|
|
||||||
|
|
||||||
laplace = 2.0*((-cos(ki)+1.0)+(-cos(kj)+1.0)+(-cos(kk)+1.0));
|
|
||||||
|
|
||||||
if(i!=0&&j!=0&&k!=0)
|
|
||||||
laplace /= (kr*kr);
|
|
||||||
else
|
|
||||||
laplace=1.0;
|
|
||||||
|
|
||||||
return laplace/grad;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline double deconv_kernel<4>(int idir, int i, int j, int k, int n )
|
|
||||||
{
|
|
||||||
double
|
|
||||||
ki(M_PI*(double)i/(double)n),
|
|
||||||
kj(M_PI*(double)j/(double)n),
|
|
||||||
kk(M_PI*(double)k/(double)n),
|
|
||||||
kr(sqrt(ki*ki+kj*kj+kk*kk));
|
|
||||||
|
|
||||||
double grad = 1.0, laplace = 1.0;
|
|
||||||
|
|
||||||
if( idir==0&&i!=0 )
|
|
||||||
grad = 0.166666666667*(-sin(2.*ki)+8.*sin(ki))/ki;
|
|
||||||
else if( idir==1&&j!=0 )
|
|
||||||
grad = 0.166666666667*(-sin(2.*kj)+8.*sin(kj))/kj;
|
|
||||||
else if( idir==2&&k!=0 )
|
|
||||||
grad = 0.166666666667*(-sin(2.*kk)+8.*sin(kk))/kk;
|
|
||||||
|
|
||||||
laplace = 0.1666666667*((cos(2*ki)-16.*cos(ki)+15.)
|
|
||||||
+(cos(2*kj)-16.*cos(kj)+15.)
|
|
||||||
+(cos(2*kk)-16.*cos(kk)+15.));
|
|
||||||
|
|
||||||
if(i!=0&&j!=0&&k!=0)
|
|
||||||
laplace /= (kr*kr);
|
|
||||||
else
|
|
||||||
laplace=1.0;
|
|
||||||
|
|
||||||
return laplace/grad;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
inline double deconv_kernel<6>(int idir, int i, int j, int k, int n )
|
|
||||||
{
|
|
||||||
double
|
|
||||||
ki(M_PI*(double)i/(double)n),
|
|
||||||
kj(M_PI*(double)j/(double)n),
|
|
||||||
kk(M_PI*(double)k/(double)n),
|
|
||||||
//ki(M_PI*(1.0-(double)(n-i)/(double)n)),
|
|
||||||
//kj(M_PI*(1.0-(double)(n-j)/(double)n)),
|
|
||||||
//kk(M_PI*(1.0-(double)(n-k)/(double)n)),
|
|
||||||
|
|
||||||
kr(sqrt(ki*ki+kj*kj+kk*kk));
|
|
||||||
|
|
||||||
if(i==0&&j==0&&k==0)
|
|
||||||
return 0.0;
|
|
||||||
|
|
||||||
double grad = 1.0, laplace = 1.0;
|
|
||||||
|
|
||||||
if( idir==0 )//&&i!=0&&i!=n )
|
|
||||||
grad = 0.0333333333333*(sin(3.*ki)-9.*sin(2.*ki)+45.*sin(ki));
|
|
||||||
else if( idir==1 )//&&j!=0&&j!=n )
|
|
||||||
grad = 0.0333333333333*(sin(3.*kj)-9.*sin(2.*kj)+45.*sin(kj));
|
|
||||||
else if( idir==2 ) //&&k!=0&&k!=n )
|
|
||||||
grad = 0.0333333333333*(sin(3.*kk)-9.*sin(2.*kk)+45.*sin(kk));
|
|
||||||
|
|
||||||
laplace = 0.01111111111111*(
|
|
||||||
(-2.*cos(3.0*ki)+27.*cos(2.*ki)-270.*cos(ki)+245.)
|
|
||||||
+(-2.*cos(3.0*kj)+27.*cos(2.*kj)-270.*cos(kj)+245.)
|
|
||||||
+(-2.*cos(3.0*kk)+27.*cos(2.*kk)-270.*cos(kk)+245.));
|
|
||||||
|
|
||||||
//if(i!=0&&j!=0&&k!=0)
|
|
||||||
/* if(i==0&&j==0&&k==0)
|
|
||||||
laplace=1.0;
|
|
||||||
else*/
|
|
||||||
//laplace -= (kr*kr);
|
|
||||||
|
|
||||||
|
|
||||||
double kgrad = 1.0;
|
|
||||||
if( idir==0 )
|
|
||||||
kgrad = ki;
|
|
||||||
else if( idir ==1)
|
|
||||||
kgrad = kj;
|
|
||||||
else if( idir ==2)
|
|
||||||
kgrad = kk;
|
|
||||||
|
|
||||||
return (kgrad/kr/kr-grad/laplace)*M_PI/n*M_PI/n;//laplace/grad;
|
|
||||||
//return kgrad/kr/kr*M_PI/n*M_PI/n;
|
|
||||||
//return grad/laplace*M_PI/n*M_PI/n;
|
|
||||||
//return (kgrad/kr/kr-grad/laplace);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<int order>
|
|
||||||
void do_deconvolve( fftw_real* data, int idir, int nxp, int nyp, int nzp, bool periodic )
|
|
||||||
{
|
|
||||||
double fftnorm = 1.0/(nxp*nyp*nzp);
|
|
||||||
|
|
||||||
|
|
||||||
if(periodic)
|
|
||||||
fftnorm *= nxp/(4.0*M_PI*M_PI);//sqrt(8.0);
|
|
||||||
|
|
||||||
|
|
||||||
/*if(periodic)
|
|
||||||
fftnorm *= M_PI*M_PI/nxp/nyp/nzp;
|
|
||||||
else
|
|
||||||
fftnorm *= M_PI*M_PI/nxp/nyp/nzp;
|
|
||||||
|
|
||||||
if( idir == 0 )
|
|
||||||
fftnorm *= nxp;
|
|
||||||
else if( idir == 1 )
|
|
||||||
fftnorm *= nyp;
|
|
||||||
else
|
|
||||||
fftnorm *= nzp;*/
|
|
||||||
|
|
||||||
fftw_complex *cdata = reinterpret_cast<fftw_complex*>(data);
|
|
||||||
rfftwnd_plan iplan, plan;
|
|
||||||
|
|
||||||
plan = rfftw3d_create_plan( nxp, nyp, nzp,
|
|
||||||
FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE|FFTW_IN_PLACE);
|
|
||||||
|
|
||||||
iplan = rfftw3d_create_plan( nxp, nyp, nzp,
|
|
||||||
FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE|FFTW_IN_PLACE);
|
|
||||||
|
|
||||||
#ifndef SINGLETHREAD_FFTW
|
|
||||||
rfftwnd_threads_one_real_to_complex( omp_get_max_threads(), plan, data, NULL );
|
|
||||||
#else
|
|
||||||
rfftwnd_one_real_to_complex( plan, data, NULL );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
double ksum = 0.0;
|
|
||||||
unsigned kcount = 0;
|
|
||||||
|
|
||||||
for( int i=0; i<nxp; ++i )
|
|
||||||
for( int j=0; j<nyp; ++j )
|
|
||||||
for( int k=0; k<nzp/2+1; ++k )
|
|
||||||
{
|
|
||||||
unsigned ii = (i*nyp + j) * (nzp/2+1) + k;
|
|
||||||
|
|
||||||
if( k==0 || k==nzp/2 )
|
|
||||||
{
|
|
||||||
ksum += cdata[ii].re;
|
|
||||||
kcount++;
|
|
||||||
}else{
|
|
||||||
ksum += 2.0*(cdata[ii].re);
|
|
||||||
kcount+=2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ksum /= kcount;
|
|
||||||
kcount = 0;
|
|
||||||
|
|
||||||
cdata[0].re = 0.0;
|
|
||||||
cdata[0].im = 0.0;
|
|
||||||
|
|
||||||
#pragma omp parallel for
|
|
||||||
for( int i=0; i<nxp; ++i )
|
|
||||||
for( int j=0; j<nyp; ++j )
|
|
||||||
for( int k=0; k<nzp/2+1; ++k )
|
|
||||||
{
|
|
||||||
unsigned ii = (i*nyp + j) * (nzp/2+1) + k;
|
|
||||||
|
|
||||||
int ki(i), kj(j);
|
|
||||||
if( ki > nxp/2 ) ki-=nxp;
|
|
||||||
if( kj > nyp/2 ) kj-=nyp;
|
|
||||||
|
|
||||||
double dk = deconv_kernel<order>(idir, ki, kj, k, nxp/2 );
|
|
||||||
//cdata[ii].re -= ksum;
|
|
||||||
|
|
||||||
double re = cdata[ii].re, im = cdata[ii].im;
|
|
||||||
|
|
||||||
cdata[ii].re = -im*dk*fftnorm;
|
|
||||||
cdata[ii].im = re*dk*fftnorm;
|
|
||||||
|
|
||||||
//cdata[ii].re += ksum*fftnorm;
|
|
||||||
|
|
||||||
}
|
|
||||||
cdata[0].re = 0.0;
|
|
||||||
cdata[0].im = 0.0;
|
|
||||||
|
|
||||||
#ifndef SINGLETHREAD_FFTW
|
|
||||||
rfftwnd_threads_one_complex_to_real( omp_get_max_threads(), iplan, cdata, NULL);
|
|
||||||
#else
|
|
||||||
rfftwnd_one_complex_to_real(iplan, cdata, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rfftwnd_destroy_plan(plan);
|
|
||||||
rfftwnd_destroy_plan(iplan);
|
|
||||||
|
|
||||||
}
|
|
||||||
void deconvolve( MeshvarBnd<double>& f, int idir, int order, bool periodic )
|
|
||||||
{
|
|
||||||
int nx=f.size(0), ny=f.size(1), nz=f.size(2), nxp, nyp, nzp;
|
|
||||||
fftw_real *data;
|
|
||||||
int xo=0,yo=0,zo=0;
|
|
||||||
int nmax = std::max(nx,std::max(ny,nz));
|
|
||||||
|
|
||||||
if(!periodic)
|
|
||||||
{
|
|
||||||
nxp = 2*nmax;
|
|
||||||
nyp = 2*nmax;
|
|
||||||
nzp = 2*nmax;
|
|
||||||
xo = nmax/2;
|
|
||||||
yo = nmax/2;
|
|
||||||
zo = nmax/2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nxp = nmax;
|
|
||||||
nyp = nmax;
|
|
||||||
nzp = nmax;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
data = new fftw_real[nxp*nyp*2*(nzp/2+1)];
|
|
||||||
|
|
||||||
if(idir==0)
|
|
||||||
std::cout << " - Performing de-convolution... (" << nxp << ", " << nyp << ", " << nzp << ")\n";
|
|
||||||
|
|
||||||
|
|
||||||
for( int i=0; i<nxp*nyp*2*(nzp/2+1); ++i )
|
|
||||||
data[i]=0.0;
|
|
||||||
|
|
||||||
for( int i=0; i<nx; ++i )
|
|
||||||
for( int j=0; j<ny; ++j )
|
|
||||||
for( int k=0; k<nz; ++k )
|
|
||||||
{
|
|
||||||
int idx = ((i+xo)*nyp + j+yo) * 2*(nzp/2+1) + k+zo;
|
|
||||||
data[idx] = f(i,j,k);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (order) {
|
|
||||||
case 2:
|
|
||||||
do_deconvolve<2>(data, idir, nxp, nyp, nzp, periodic);
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
do_deconvolve<4>(data, idir, nxp, nyp, nzp, periodic);
|
|
||||||
break;
|
|
||||||
case 6:
|
|
||||||
do_deconvolve<6>(data, idir, nxp, nyp, nzp, periodic);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
std::cerr << " - ERROR: invalid operator order specified in deconvolution.";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for( int i=0; i<nx; ++i )
|
|
||||||
for( int j=0; j<ny; ++j )
|
|
||||||
for( int k=0; k<nz; ++k )
|
|
||||||
{
|
|
||||||
//int idx = (i*nyp + j) * 2*(nzp/2+1) + k;
|
|
||||||
int idx = ((i+xo)*nyp + j+yo) * 2*(nzp/2+1) + k+zo;
|
|
||||||
|
|
||||||
f(i,j,k) = data[idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
delete[] data;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace{
|
namespace{
|
||||||
|
|
|
@ -102,8 +102,5 @@ namespace convolution{
|
||||||
|
|
||||||
} //namespace convolution
|
} //namespace convolution
|
||||||
|
|
||||||
|
|
||||||
void deconvolve( MeshvarBnd<double>& f, int idir, int order, bool periodic );
|
|
||||||
|
|
||||||
|
|
||||||
#endif //__CONVOLUTION_KERNELS_HH
|
#endif //__CONVOLUTION_KERNELS_HH
|
||||||
|
|
29
cosmology.cc
29
cosmology.cc
|
@ -291,15 +291,37 @@ void compute_2LPT_source_FFT( config_file& cf_, const grid_hierarchy& u, grid_hi
|
||||||
cdata_33[idx].re = -k[2]*k[2] * cdata[idx].re * norm;
|
cdata_33[idx].re = -k[2]*k[2] * cdata[idx].re * norm;
|
||||||
cdata_33[idx].im = -k[2]*k[2] * cdata[idx].im * norm;
|
cdata_33[idx].im = -k[2]*k[2] * cdata[idx].im * norm;
|
||||||
|
|
||||||
|
|
||||||
|
if( i==nx/2||j==ny/2||l==nz/2)
|
||||||
|
{
|
||||||
|
cdata_11[idx].re = 0.0;
|
||||||
|
cdata_11[idx].im = 0.0;
|
||||||
|
|
||||||
|
cdata_12[idx].re = 0.0;
|
||||||
|
cdata_12[idx].im = 0.0;
|
||||||
|
|
||||||
|
cdata_13[idx].re = 0.0;
|
||||||
|
cdata_13[idx].im = 0.0;
|
||||||
|
|
||||||
|
cdata_22[idx].re = 0.0;
|
||||||
|
cdata_22[idx].im = 0.0;
|
||||||
|
|
||||||
|
cdata_23[idx].re = 0.0;
|
||||||
|
cdata_23[idx].im = 0.0;
|
||||||
|
|
||||||
|
cdata_33[idx].re = 0.0;
|
||||||
|
cdata_33[idx].im = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] data;
|
delete[] data;
|
||||||
cdata_11[0].re = 0.0; cdata_11[0].im = 0.0;
|
/*cdata_11[0].re = 0.0; cdata_11[0].im = 0.0;
|
||||||
cdata_12[0].re = 0.0; cdata_12[0].im = 0.0;
|
cdata_12[0].re = 0.0; cdata_12[0].im = 0.0;
|
||||||
cdata_13[0].re = 0.0; cdata_13[0].im = 0.0;
|
cdata_13[0].re = 0.0; cdata_13[0].im = 0.0;
|
||||||
cdata_22[0].re = 0.0; cdata_22[0].im = 0.0;
|
cdata_22[0].re = 0.0; cdata_22[0].im = 0.0;
|
||||||
cdata_23[0].re = 0.0; cdata_23[0].im = 0.0;
|
cdata_23[0].re = 0.0; cdata_23[0].im = 0.0;
|
||||||
cdata_33[0].re = 0.0; cdata_33[0].im = 0.0;
|
cdata_33[0].re = 0.0; cdata_33[0].im = 0.0;*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef SINGLETHREAD_FFTW
|
#ifndef SINGLETHREAD_FFTW
|
||||||
|
@ -335,6 +357,9 @@ void compute_2LPT_source_FFT( config_file& cf_, const grid_hierarchy& u, grid_hi
|
||||||
(*fnew.get_grid(u.levelmax()))(i,j,k) = (( data_11[ii]*data_22[ii]-data_12[ii]*data_12[ii] ) +
|
(*fnew.get_grid(u.levelmax()))(i,j,k) = (( data_11[ii]*data_22[ii]-data_12[ii]*data_12[ii] ) +
|
||||||
( data_11[ii]*data_33[ii]-data_13[ii]*data_13[ii] ) +
|
( data_11[ii]*data_33[ii]-data_13[ii]*data_13[ii] ) +
|
||||||
( data_22[ii]*data_33[ii]-data_23[ii]*data_23[ii] ) );
|
( data_22[ii]*data_33[ii]-data_23[ii]*data_23[ii] ) );
|
||||||
|
|
||||||
|
//(*fnew.get_grid(u.levelmax()))(i,j,k) =
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//delete[] data;
|
//delete[] data;
|
||||||
|
|
20
cosmology.hh
20
cosmology.hh
|
@ -47,8 +47,8 @@ public:
|
||||||
|
|
||||||
//! constructor for a cosmology calculator object
|
//! constructor for a cosmology calculator object
|
||||||
/*!
|
/*!
|
||||||
* @params acosmo a cosmological parameters structure
|
* @param acosmo a cosmological parameters structure
|
||||||
* @params pTransferFunction pointer to an instance of a transfer function object
|
* @param pTransferFunction pointer to an instance of a transfer function object
|
||||||
*/
|
*/
|
||||||
|
|
||||||
CosmoCalc( const Cosmology acosmo, transfer_function_plugin *pTransferFunction )
|
CosmoCalc( const Cosmology acosmo, transfer_function_plugin *pTransferFunction )
|
||||||
|
@ -59,9 +59,9 @@ public:
|
||||||
|
|
||||||
//! returns the amplitude of amplitude of the power spectrum
|
//! returns the amplitude of amplitude of the power spectrum
|
||||||
/*!
|
/*!
|
||||||
* @params k the wave number in h/Mpc
|
* @param k the wave number in h/Mpc
|
||||||
* @params a the expansion factor of the universe
|
* @param a the expansion factor of the universe
|
||||||
* @return power spectrum amplitude for wave number k at time a
|
* @returns power spectrum amplitude for wave number k at time a
|
||||||
*/
|
*/
|
||||||
inline real_t Power( real_t k, real_t a ){
|
inline real_t Power( real_t k, real_t a ){
|
||||||
real_t m_Dplus = CalcGrowthFactor( a );
|
real_t m_Dplus = CalcGrowthFactor( a );
|
||||||
|
@ -166,8 +166,8 @@ public:
|
||||||
|
|
||||||
//! Computes the square of the transfer function
|
//! Computes the square of the transfer function
|
||||||
/*! Function evaluates the supplied transfer function m_pTransferFunction
|
/*! Function evaluates the supplied transfer function m_pTransferFunction
|
||||||
and returns the square of its value at wave number k
|
* and returns the square of its value at wave number k
|
||||||
\param k wave number at which to evaluate the transfer function
|
* @param k wave number at which to evaluate the transfer function
|
||||||
*/
|
*/
|
||||||
inline real_t TransferSq( real_t k ){
|
inline real_t TransferSq( real_t k ){
|
||||||
//.. parameter supplied transfer function
|
//.. parameter supplied transfer function
|
||||||
|
@ -199,9 +199,9 @@ public:
|
||||||
//! compute the jeans sound speed
|
//! compute the jeans sound speed
|
||||||
/*! given a density in g/cm^-3 and a mass in g it gives back the sound
|
/*! 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
|
* speed in cm/s for which the input mass is equal to the jeans mass
|
||||||
* @params rho density
|
* @param rho density
|
||||||
* @params mass mass scale
|
* @param mass mass scale
|
||||||
* @return jeans sound speed
|
* @returns jeans sound speed
|
||||||
*/
|
*/
|
||||||
inline double jeans_sound_speed( double rho, double mass )
|
inline double jeans_sound_speed( double rho, double mass )
|
||||||
{
|
{
|
||||||
|
|
30
densities.cc
30
densities.cc
|
@ -292,11 +292,37 @@ void GenerateDensityHierarchy( config_file& cf, transfer_function *ptf, tf_type
|
||||||
shift[1] = cf.getValue<int>("setup","shift_y");
|
shift[1] = cf.getValue<int>("setup","shift_y");
|
||||||
shift[2] = cf.getValue<int>("setup","shift_z");
|
shift[2] = cf.getValue<int>("setup","shift_z");
|
||||||
|
|
||||||
#ifdef SINGLE_PRECISION
|
/*#ifdef SINGLE_PRECISION
|
||||||
convolution::kernel_creator *the_kernel_creator = convolution::get_kernel_map()[ "tf_kernel_real_float" ];
|
convolution::kernel_creator *the_kernel_creator = convolution::get_kernel_map()[ "tf_kernel_real_float" ];
|
||||||
#else
|
#else
|
||||||
convolution::kernel_creator *the_kernel_creator = convolution::get_kernel_map()[ "tf_kernel_real_double" ];
|
convolution::kernel_creator *the_kernel_creator = convolution::get_kernel_map()[ "tf_kernel_real_double" ];
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
convolution::kernel_creator *the_kernel_creator;
|
||||||
|
|
||||||
|
if( kspaceTF )
|
||||||
|
{
|
||||||
|
if( levelmin!=levelmax )
|
||||||
|
throw std::runtime_error("k-space transfer function can only be used in unigrid density mode");
|
||||||
|
|
||||||
|
std::cout << " - Using k-space transfer function kernel.\n";
|
||||||
|
|
||||||
|
#ifdef SINGLE_PRECISION
|
||||||
|
the_kernel_creator = convolution::get_kernel_map()[ "tf_kernel_k_float" ];
|
||||||
|
#else
|
||||||
|
the_kernel_creator = convolution::get_kernel_map()[ "tf_kernel_k_double" ];
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cout << " - Using real-space transfer function kernel.\n";
|
||||||
|
|
||||||
|
#ifdef SINGLE_PRECISION
|
||||||
|
the_kernel_creator = convolution::get_kernel_map()[ "tf_kernel_real_float" ];
|
||||||
|
#else
|
||||||
|
the_kernel_creator = convolution::get_kernel_map()[ "tf_kernel_real_double" ];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
convolution::parameters conv_param;
|
convolution::parameters conv_param;
|
||||||
conv_param.ptf = ptf;
|
conv_param.ptf = ptf;
|
||||||
|
@ -886,7 +912,7 @@ void GenerateDensityHierarchy( config_file& cf, transfer_function *ptf, tf_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//std::cout << " - Top grid mean density is off by " << sum << ", correcting..." << std::endl;
|
std::cout << " - Top grid mean density is off by " << sum << ", correcting..." << std::endl;
|
||||||
|
|
||||||
for( unsigned i=levelmin; i<=levelmax; ++i )
|
for( unsigned i=levelmin; i<=levelmax; ++i )
|
||||||
{
|
{
|
||||||
|
|
20
densities.hh
20
densities.hh
|
@ -79,9 +79,9 @@ public:
|
||||||
|
|
||||||
//! constructor
|
//! constructor
|
||||||
/*! constructs an instance given the dimensions of the density field
|
/*! constructs an instance given the dimensions of the density field
|
||||||
* @params nx the number of cells in x
|
* @param nx the number of cells in x
|
||||||
* @params ny the number of cells in y
|
* @param ny the number of cells in y
|
||||||
* @params nz the number of cells in z
|
* @param nz the number of cells in z
|
||||||
*/
|
*/
|
||||||
DensityGrid( unsigned nx, unsigned ny, unsigned nz )
|
DensityGrid( unsigned nx, unsigned ny, unsigned nz )
|
||||||
: nx_(nx), ny_(ny), nz_(nz)
|
: nx_(nx), ny_(ny), nz_(nz)
|
||||||
|
@ -113,7 +113,7 @@ public:
|
||||||
|
|
||||||
//! query the 3D array sizes of the density object
|
//! query the 3D array sizes of the density object
|
||||||
/*! returns the size of the 3D density object along a specified dimension
|
/*! returns the size of the 3D density object along a specified dimension
|
||||||
* @params i the dimension for which size is to be returned
|
* @param i the dimension for which size is to be returned
|
||||||
* @returns array size along dimension i
|
* @returns array size along dimension i
|
||||||
*/
|
*/
|
||||||
int size( int i )
|
int size( int i )
|
||||||
|
@ -158,12 +158,12 @@ public:
|
||||||
|
|
||||||
//! fills the density field with random number values
|
//! fills the density field with random number values
|
||||||
/*! given a pointer to a random_numbers object, fills the field with random values
|
/*! given a pointer to a random_numbers object, fills the field with random values
|
||||||
* @params prc pointer to a random_numbers object
|
* @param prc pointer to a random_numbers object
|
||||||
* @params variance the variance of the random numbers (the values returned by prc are multiplied by this)
|
* @param variance the variance of the random numbers (the values returned by prc are multiplied by this)
|
||||||
* @params i0 x-offset (shift) in cells of the density field with respect to the random number field
|
* @param i0 x-offset (shift) in cells of the density field with respect to the random number field
|
||||||
* @params j0 y-offset (shift) in cells of the density field with respect to the random number field
|
* @param j0 y-offset (shift) in cells of the density field with respect to the random number field
|
||||||
* @params k0 z-offset (shift) in cells of the density field with respect to the random number field
|
* @param k0 z-offset (shift) in cells of the density field with respect to the random number field
|
||||||
* @params setzero boolean, if true, the global mean will be subtracted
|
* @param setzero boolean, if true, the global mean will be subtracted
|
||||||
*/
|
*/
|
||||||
void fill_rand( /*const*/ random_numbers<real_t>* prc, real_t variance, int i0, int j0, int k0, bool setzero=false )
|
void fill_rand( /*const*/ random_numbers<real_t>* prc, real_t variance, int i0, int j0, int k0, bool setzero=false )
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
|
|
||||||
//... abstract implementation of the Poisson/Force scheme
|
//! abstract implementation of the Poisson/Force scheme
|
||||||
template< class L, class G, typename real_t=double >
|
template< class L, class G, typename real_t=double >
|
||||||
class scheme
|
class scheme
|
||||||
{
|
{
|
||||||
|
@ -39,22 +39,27 @@ public:
|
||||||
laplacian m_laplacian;
|
laplacian m_laplacian;
|
||||||
gradient m_gradient;
|
gradient m_gradient;
|
||||||
|
|
||||||
|
//! gradient along x-direction
|
||||||
template< class C >
|
template< class C >
|
||||||
inline real_t grad_x( const C&c, const int i, const int j, const int k )
|
inline real_t grad_x( const C&c, const int i, const int j, const int k )
|
||||||
{ return m_gradient.apply_x( c,i,j,k ); }
|
{ return m_gradient.apply_x( c,i,j,k ); }
|
||||||
|
|
||||||
|
//! gradient along y-direction
|
||||||
template< class C >
|
template< class C >
|
||||||
inline real_t grad_y( const C&c, const int i, const int j, const int k )
|
inline real_t grad_y( const C&c, const int i, const int j, const int k )
|
||||||
{ return m_gradient.apply_y( c,i,j,k ); }
|
{ return m_gradient.apply_y( c,i,j,k ); }
|
||||||
|
|
||||||
|
//! gradient along z-direction
|
||||||
template< class C >
|
template< class C >
|
||||||
inline real_t grad_z( const C&c, const int i, const int j, const int k )
|
inline real_t grad_z( const C&c, const int i, const int j, const int k )
|
||||||
{ return m_gradient.apply_z( c,i,j,k ); }
|
{ return m_gradient.apply_z( c,i,j,k ); }
|
||||||
|
|
||||||
|
//! apply Laplace operator
|
||||||
template< class C >
|
template< class C >
|
||||||
inline real_t L_apply( const C&c, const int i, const int j, const int k )
|
inline real_t L_apply( const C&c, const int i, const int j, const int k )
|
||||||
{ return m_laplacian.apply( c,i,j,k ); }
|
{ return m_laplacian.apply( c,i,j,k ); }
|
||||||
|
|
||||||
|
//! compute an explicit solution for the central component of the discrete Poisson's equation
|
||||||
template< class C >
|
template< class C >
|
||||||
inline real_t L_rhs( const C&c, const int i, const int j, const int k )
|
inline real_t L_rhs( const C&c, const int i, const int j, const int k )
|
||||||
{ return m_laplacian.rhs( c,i,j,k ); }
|
{ return m_laplacian.rhs( c,i,j,k ); }
|
||||||
|
@ -64,7 +69,7 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! base class for finite difference gradients
|
||||||
template< int nextent, typename T >
|
template< int nextent, typename T >
|
||||||
class gradient
|
class gradient
|
||||||
{
|
{
|
||||||
|
@ -117,6 +122,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! base class for finite difference stencils
|
||||||
template< int nextent, typename real_t >
|
template< int nextent, typename real_t >
|
||||||
class base_stencil
|
class base_stencil
|
||||||
{
|
{
|
||||||
|
@ -200,7 +206,7 @@ public:
|
||||||
|
|
||||||
//... Implementation of the Laplacian schemes..........................................
|
//... Implementation of the Laplacian schemes..........................................
|
||||||
|
|
||||||
|
//! 7-point, 2nd order finite difference Laplacian
|
||||||
template< typename real_t >
|
template< typename real_t >
|
||||||
class stencil_7P : public base_stencil<1,real_t>
|
class stencil_7P : public base_stencil<1,real_t>
|
||||||
{
|
{
|
||||||
|
@ -235,7 +241,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! 13-point, 4th order finite difference Laplacian
|
||||||
template< typename real_t >
|
template< typename real_t >
|
||||||
class stencil_13P : public base_stencil<2,real_t>
|
class stencil_13P : public base_stencil<2,real_t>
|
||||||
{
|
{
|
||||||
|
@ -283,6 +289,8 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! 19-point, 6th order finite difference Laplacian
|
||||||
template< typename real_t >
|
template< typename real_t >
|
||||||
class stencil_19P : public base_stencil<3,real_t>
|
class stencil_19P : public base_stencil<3,real_t>
|
||||||
{
|
{
|
||||||
|
@ -342,12 +350,19 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! flux operator for the 4th order FD Laplacian
|
||||||
template< typename real_t >
|
template< typename real_t >
|
||||||
class Laplace_flux_O4
|
class Laplace_flux_O4
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*! computes flux across a surface normal to x-direction
|
||||||
//.. idir is -1 for left boundary, +1 for right boundary
|
* @param idir idir is -1 for left boundary, +1 for right boundary
|
||||||
|
* @param c array on which to apply the operator
|
||||||
|
* @param i grid x-index
|
||||||
|
* @param j grid y-index
|
||||||
|
* @param k grid z-index
|
||||||
|
* @returns flux value
|
||||||
|
*/
|
||||||
template< class C >
|
template< class C >
|
||||||
inline double apply_x( int idir, const C& c, const int i, const int j, const int k )
|
inline double apply_x( int idir, const C& c, const int i, const int j, const int k )
|
||||||
{
|
{
|
||||||
|
@ -355,6 +370,14 @@ public:
|
||||||
return fac*(-c(i-2,j,k)+15.0*c(i-1,j,k)-15.0*c(i,j,k)+c(i+1,j,k));
|
return fac*(-c(i-2,j,k)+15.0*c(i-1,j,k)-15.0*c(i,j,k)+c(i+1,j,k));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! computes flux across a surface normal to y-direction
|
||||||
|
* @param idir idir is -1 for left boundary, +1 for right boundary
|
||||||
|
* @param c array on which to apply the operator
|
||||||
|
* @param i grid x-index
|
||||||
|
* @param j grid y-index
|
||||||
|
* @param k grid z-index
|
||||||
|
* @returns flux value
|
||||||
|
*/
|
||||||
template< class C >
|
template< class C >
|
||||||
inline double apply_y( int idir, const C& c, const int i, const int j, const int k )
|
inline double apply_y( int idir, const C& c, const int i, const int j, const int k )
|
||||||
{
|
{
|
||||||
|
@ -362,6 +385,14 @@ public:
|
||||||
return fac*(-c(i,j-2,k)+15.0*c(i,j-1,k)-15.0*c(i,j,k)+c(i,j+1,k));
|
return fac*(-c(i,j-2,k)+15.0*c(i,j-1,k)-15.0*c(i,j,k)+c(i,j+1,k));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! computes flux across a surface normal to z-direction
|
||||||
|
* @param idir idir is -1 for left boundary, +1 for right boundary
|
||||||
|
* @param c array on which to apply the operator
|
||||||
|
* @param i grid x-index
|
||||||
|
* @param j grid y-index
|
||||||
|
* @param k grid z-index
|
||||||
|
* @returns flux value
|
||||||
|
*/
|
||||||
template< class C >
|
template< class C >
|
||||||
inline double apply_z( int idir, const C& c, const int i, const int j, const int k )
|
inline double apply_z( int idir, const C& c, const int i, const int j, const int k )
|
||||||
{
|
{
|
||||||
|
@ -372,12 +403,20 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! flux operator for the 6th order FD Laplacian
|
||||||
template< typename real_t >
|
template< typename real_t >
|
||||||
class Laplace_flux_O6
|
class Laplace_flux_O6
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//.. idir is -1 for left boundary, +1 for right boundary
|
/*! computes flux across a surface normal to x-direction
|
||||||
|
* @param idir idir is -1 for left boundary, +1 for right boundary
|
||||||
|
* @param c array on which to apply the operator
|
||||||
|
* @param i grid x-index
|
||||||
|
* @param j grid y-index
|
||||||
|
* @param k grid z-index
|
||||||
|
* @returns flux value
|
||||||
|
*/
|
||||||
template< class C >
|
template< class C >
|
||||||
inline double apply_x( int idir, const C& c, const int i, const int j, const int k )
|
inline double apply_x( int idir, const C& c, const int i, const int j, const int k )
|
||||||
{
|
{
|
||||||
|
@ -385,6 +424,14 @@ public:
|
||||||
return fac*(2.*c(i-3,j,k)-25.*c(i-2,j,k)+245.*c(i-1,j,k)-245.0*c(i,j,k)+25.*c(i+1,j,k)-2.*c(i+2,j,k));
|
return fac*(2.*c(i-3,j,k)-25.*c(i-2,j,k)+245.*c(i-1,j,k)-245.0*c(i,j,k)+25.*c(i+1,j,k)-2.*c(i+2,j,k));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! computes flux across a surface normal to y-direction
|
||||||
|
* @param idir idir is -1 for left boundary, +1 for right boundary
|
||||||
|
* @param c array on which to apply the operator
|
||||||
|
* @param i grid x-index
|
||||||
|
* @param j grid y-index
|
||||||
|
* @param k grid z-index
|
||||||
|
* @returns flux value
|
||||||
|
*/
|
||||||
template< class C >
|
template< class C >
|
||||||
inline double apply_y( int idir, const C& c, const int i, const int j, const int k )
|
inline double apply_y( int idir, const C& c, const int i, const int j, const int k )
|
||||||
{
|
{
|
||||||
|
@ -392,6 +439,14 @@ public:
|
||||||
return fac*(2.*c(i,j-3,k)-25.*c(i,j-2,k)+245.*c(i,j-1,k)-245.0*c(i,j,k)+25.*c(i,j+1,k)-2.*c(i,j+2,k));
|
return fac*(2.*c(i,j-3,k)-25.*c(i,j-2,k)+245.*c(i,j-1,k)-245.0*c(i,j,k)+25.*c(i,j+1,k)-2.*c(i,j+2,k));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! computes flux across a surface normal to z-direction
|
||||||
|
* @param idir idir is -1 for left boundary, +1 for right boundary
|
||||||
|
* @param c array on which to apply the operator
|
||||||
|
* @param i grid x-index
|
||||||
|
* @param j grid y-index
|
||||||
|
* @param k grid z-index
|
||||||
|
* @returns flux value
|
||||||
|
*/
|
||||||
template< class C >
|
template< class C >
|
||||||
inline double apply_z( int idir, const C& c, const int i, const int j, const int k )
|
inline double apply_z( int idir, const C& c, const int i, const int j, const int k )
|
||||||
{
|
{
|
||||||
|
|
44
general.hh
44
general.hh
|
@ -65,51 +65,55 @@ typedef MeshvarBnd<real_t> meshvar_bnd;
|
||||||
typedef Meshvar<real_t> meshvar;
|
typedef Meshvar<real_t> meshvar;
|
||||||
|
|
||||||
|
|
||||||
/* Convenience from Numerical Recipes in C, 2nd edition */
|
//! compute square of argument
|
||||||
template< typename T >
|
template< typename T >
|
||||||
inline T SQR( T a ){
|
inline T SQR( T a ){
|
||||||
return a*a;
|
return a*a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! compute cube of argument
|
||||||
template< typename T >
|
template< typename T >
|
||||||
inline T CUBE( T a ){
|
inline T CUBE( T a ){
|
||||||
return a*a*a;
|
return a*a*a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! compute 4th power of argument
|
||||||
template< typename T >
|
template< typename T >
|
||||||
inline T POW4( T a ){
|
inline T POW4( T a ){
|
||||||
return a*a*a*a;
|
return SQR(SQR(a));
|
||||||
|
//return a*a*a*a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// --- structure for cosmological parameters --- //
|
//! structure for cosmological parameters
|
||||||
typedef struct cosmology{
|
typedef struct cosmology{
|
||||||
double
|
double
|
||||||
Omega_m, // baryon+dark matter density
|
Omega_m, //!< baryon+dark matter density
|
||||||
Omega_b, // baryon matter density
|
Omega_b, //!< baryon matter density
|
||||||
Omega_L, // dark energy density
|
Omega_L, //!< dark energy density
|
||||||
H0, // Hubble constant
|
H0, //!< Hubble constant
|
||||||
nspect, // long-wave spectral index (scale free is nspect=1)
|
nspect, //!< long-wave spectral index (scale free is nspect=1)
|
||||||
sigma8, // power spectrum normalization
|
sigma8, //!< power spectrum normalization
|
||||||
//Gamma, // shape parameter (of historical interest, as a free parameter)
|
//Gamma, //!< shape parameter (of historical interest, as a free parameter)
|
||||||
//fnl, // non-gaussian contribution parameter
|
//fnl, //!< non-gaussian contribution parameter
|
||||||
//w0, // dark energy equation of state parameter (not implemented, i.e. =1 at the moment)
|
//w0, //!< dark energy equation of state parameter (not implemented, i.e. =1 at the moment)
|
||||||
//wa, // dark energy equation of state parameter (not implemented, i.e. =1 at the moment)
|
//wa, //!< dark energy equation of state parameter (not implemented, i.e. =1 at the moment)
|
||||||
dplus,
|
dplus, //!< linear perturbation growth factor
|
||||||
pnorm,
|
pnorm, //!< actual power spectrum normalisation factor
|
||||||
vfact,
|
vfact, //!< velocity<->displacement conversion factor in Zel'dovich approx.
|
||||||
WDMmass,
|
WDMmass, //!< Warm DM particle mass
|
||||||
WDMg_x,
|
WDMg_x, //!< Warm DM particle degrees of freedom
|
||||||
astart; // expansion factor a for which to generate initial conditions
|
astart; //!< expansion factor a for which to generate initial conditions
|
||||||
}Cosmology;
|
}Cosmology;
|
||||||
|
|
||||||
|
//! basic box/grid/refinement structure parameters
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned levelmin, levelmax;
|
unsigned levelmin, levelmax;
|
||||||
double boxlength;
|
double boxlength;
|
||||||
std::vector<unsigned> offx,offy,offz,llx,lly,llz;
|
std::vector<unsigned> offx,offy,offz,llx,lly,llz;
|
||||||
}Parameters;
|
}Parameters;
|
||||||
|
|
||||||
|
//! measure elapsed wallclock time
|
||||||
inline double time_seconds( void )
|
inline double time_seconds( void )
|
||||||
{
|
{
|
||||||
#ifdef WITH_MPI
|
#ifdef WITH_MPI
|
||||||
|
|
15
main.cc
15
main.cc
|
@ -237,6 +237,8 @@ void subtract_finest_mean( grid_hierarchy& u )
|
||||||
* (*u.get_grid(u.levelmax())).size(1)
|
* (*u.get_grid(u.levelmax())).size(1)
|
||||||
* (*u.get_grid(u.levelmax())).size(2);
|
* (*u.get_grid(u.levelmax())).size(2);
|
||||||
|
|
||||||
|
std::cout << " component mean is " << sum << std::endl;
|
||||||
|
|
||||||
for( unsigned ilevel=u.levelmin(); ilevel<=u.levelmax(); ++ilevel )
|
for( unsigned ilevel=u.levelmin(); ilevel<=u.levelmax(); ++ilevel )
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for( int ix = 0; ix < (int)(*u.get_grid(ilevel)).size(0); ++ix )
|
for( int ix = 0; ix < (int)(*u.get_grid(ilevel)).size(0); ++ix )
|
||||||
|
@ -411,7 +413,7 @@ int main (int argc, const char * argv[])
|
||||||
|
|
||||||
refinement_hierarchy rh_TF( rh_Poisson );
|
refinement_hierarchy rh_TF( rh_Poisson );
|
||||||
modify_grid_for_TF( rh_Poisson, rh_TF, cf );
|
modify_grid_for_TF( rh_Poisson, rh_TF, cf );
|
||||||
//rh_TF.output();
|
rh_TF.output();
|
||||||
|
|
||||||
|
|
||||||
if( !the_transfer_function_plugin->tf_is_distinct() && do_baryons )
|
if( !the_transfer_function_plugin->tf_is_distinct() && do_baryons )
|
||||||
|
@ -468,7 +470,7 @@ int main (int argc, const char * argv[])
|
||||||
if( bdefd )
|
if( bdefd )
|
||||||
{
|
{
|
||||||
data_forIO = f;
|
data_forIO = f;
|
||||||
deconvolve(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
poisson_hybrid(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
||||||
the_poisson_solver->gradient_add(icoord, u, data_forIO );
|
the_poisson_solver->gradient_add(icoord, u, data_forIO );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -529,7 +531,7 @@ int main (int argc, const char * argv[])
|
||||||
{
|
{
|
||||||
data_forIO.zero();
|
data_forIO.zero();
|
||||||
*data_forIO.get_grid(data_forIO.levelmax()) = *f.get_grid(f.levelmax());
|
*data_forIO.get_grid(data_forIO.levelmax()) = *f.get_grid(f.levelmax());
|
||||||
deconvolve(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
poisson_hybrid(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
||||||
the_poisson_solver->gradient_add(icoord, u, data_forIO );
|
the_poisson_solver->gradient_add(icoord, u, data_forIO );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -590,6 +592,7 @@ int main (int argc, const char * argv[])
|
||||||
|
|
||||||
u2 *= 6.0/7.0;
|
u2 *= 6.0/7.0;
|
||||||
u1 += u2;
|
u1 += u2;
|
||||||
|
//u1 = u2;
|
||||||
u2.deallocate();
|
u2.deallocate();
|
||||||
|
|
||||||
grid_hierarchy data_forIO(u1);
|
grid_hierarchy data_forIO(u1);
|
||||||
|
@ -599,13 +602,13 @@ int main (int argc, const char * argv[])
|
||||||
//... displacement
|
//... displacement
|
||||||
//the_poisson_solver->gradient(icoord, u1, data_forIO );
|
//the_poisson_solver->gradient(icoord, u1, data_forIO );
|
||||||
//if(bdefd)
|
//if(bdefd)
|
||||||
// deconvolve(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
// poisson_hybrid(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
||||||
|
|
||||||
if(bdefd)
|
if(bdefd)
|
||||||
{
|
{
|
||||||
data_forIO.zero();
|
data_forIO.zero();
|
||||||
*data_forIO.get_grid(data_forIO.levelmax()) = *f.get_grid(f.levelmax());
|
*data_forIO.get_grid(data_forIO.levelmax()) = *f.get_grid(f.levelmax());
|
||||||
deconvolve(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
poisson_hybrid(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
||||||
the_poisson_solver->gradient_add(icoord, u1, data_forIO );
|
the_poisson_solver->gradient_add(icoord, u1, data_forIO );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -677,7 +680,7 @@ int main (int argc, const char * argv[])
|
||||||
{
|
{
|
||||||
data_forIO.zero();
|
data_forIO.zero();
|
||||||
*data_forIO.get_grid(data_forIO.levelmax()) = *f.get_grid(f.levelmax());
|
*data_forIO.get_grid(data_forIO.levelmax()) = *f.get_grid(f.levelmax());
|
||||||
deconvolve(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
poisson_hybrid(*data_forIO.get_grid(data_forIO.levelmax()), icoord, grad_order, data_forIO.levelmin()==data_forIO.levelmax());
|
||||||
the_poisson_solver->gradient_add(icoord, u1, data_forIO );
|
the_poisson_solver->gradient_add(icoord, u1, data_forIO );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
99
mesh.hh
99
mesh.hh
|
@ -287,7 +287,9 @@ class MeshvarBnd : public Meshvar< T >{
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef T real_t;
|
typedef T real_t;
|
||||||
unsigned m_nbnd;
|
|
||||||
|
//! number of boundary (ghost) cells
|
||||||
|
unsigned m_nbnd;
|
||||||
|
|
||||||
//! most general constructor
|
//! most general constructor
|
||||||
MeshvarBnd( unsigned nbnd, unsigned nx, unsigned ny, unsigned nz, unsigned xoff, unsigned yoff, unsigned zoff )
|
MeshvarBnd( unsigned nbnd, unsigned nx, unsigned ny, unsigned nz, unsigned xoff, unsigned yoff, unsigned zoff )
|
||||||
|
@ -693,6 +695,7 @@ public:
|
||||||
m_levelmin = lmax;
|
m_levelmin = lmax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! multiply entire grid hierarchy by a constant
|
||||||
GridHierarchy<T>& operator*=( T x )
|
GridHierarchy<T>& operator*=( T x )
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
||||||
|
@ -700,6 +703,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! divide entire grid hierarchy by a constant
|
||||||
GridHierarchy<T>& operator/=( T x )
|
GridHierarchy<T>& operator/=( T x )
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
||||||
|
@ -707,6 +711,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! add a constant to the entire grid hierarchy
|
||||||
GridHierarchy<T>& operator+=( T x )
|
GridHierarchy<T>& operator+=( T x )
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
||||||
|
@ -714,6 +719,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! subtract a constant from the entire grid hierarchy
|
||||||
GridHierarchy<T>& operator-=( T x )
|
GridHierarchy<T>& operator-=( T x )
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
||||||
|
@ -721,6 +727,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! multiply (element-wise) two grid hierarchies
|
||||||
GridHierarchy<T>& operator*=( const GridHierarchy& gh )
|
GridHierarchy<T>& operator*=( const GridHierarchy& gh )
|
||||||
{
|
{
|
||||||
if( !is_consistent(gh) )
|
if( !is_consistent(gh) )
|
||||||
|
@ -731,6 +738,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! divide (element-wise) two grid hierarchies
|
||||||
GridHierarchy<T>& operator/=( const GridHierarchy& gh )
|
GridHierarchy<T>& operator/=( const GridHierarchy& gh )
|
||||||
{
|
{
|
||||||
if( !is_consistent(gh) )
|
if( !is_consistent(gh) )
|
||||||
|
@ -741,6 +749,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! add (element-wise) two grid hierarchies
|
||||||
GridHierarchy<T>& operator+=( const GridHierarchy& gh )
|
GridHierarchy<T>& operator+=( const GridHierarchy& gh )
|
||||||
{
|
{
|
||||||
if( !is_consistent(gh) )
|
if( !is_consistent(gh) )
|
||||||
|
@ -751,6 +760,7 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! subtract (element-wise) two grid hierarchies
|
||||||
GridHierarchy<T>& operator-=( const GridHierarchy& gh )
|
GridHierarchy<T>& operator-=( const GridHierarchy& gh )
|
||||||
{
|
{
|
||||||
if( !is_consistent(gh) )
|
if( !is_consistent(gh) )
|
||||||
|
@ -763,8 +773,14 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//... Xoff is in units of the coarser grid,
|
/*! add a new refinement patch to the so-far finest level
|
||||||
//... nX is the extent in fine grid cells
|
* @param xoff x-offset in units of the coarser grid (finest grid before adding new patch)
|
||||||
|
* @param yoff y-offset in units of the coarser grid (finest grid before adding new patch)
|
||||||
|
* @param zoff z-offset in units of the coarser grid (finest grid before adding new patch)
|
||||||
|
* @param nx x-extent in fine grid cells
|
||||||
|
* @param ny y-extent in fine grid cells
|
||||||
|
* @param nz z-extent in fine grid cells
|
||||||
|
*/
|
||||||
void add_patch( unsigned xoff, unsigned yoff, unsigned zoff, unsigned nx, unsigned ny, unsigned nz )
|
void add_patch( unsigned xoff, unsigned yoff, unsigned zoff, unsigned nx, unsigned ny, unsigned nz )
|
||||||
{
|
{
|
||||||
m_pgrids.push_back( new MeshvarBnd<T>( m_nbnd, nx, ny, nz, xoff, yoff, zoff ) );
|
m_pgrids.push_back( new MeshvarBnd<T>( m_nbnd, nx, ny, nz, xoff, yoff, zoff ) );
|
||||||
|
@ -776,6 +792,15 @@ public:
|
||||||
m_zoffabs.push_back( 2*(m_zoffabs.back() + zoff) );
|
m_zoffabs.push_back( 2*(m_zoffabs.back() + zoff) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! cut a refinement patch to the specified size
|
||||||
|
* @param ilevel grid level on which to perform the size adjustment
|
||||||
|
* @param xoff new x-offset in units of the coarser grid (finest grid before adding new patch)
|
||||||
|
* @param yoff new y-offset in units of the coarser grid (finest grid before adding new patch)
|
||||||
|
* @param zoff new z-offset in units of the coarser grid (finest grid before adding new patch)
|
||||||
|
* @param nx new x-extent in fine grid cells
|
||||||
|
* @param ny new y-extent in fine grid cells
|
||||||
|
* @param nz new z-extent in fine grid cells
|
||||||
|
*/
|
||||||
void cut_patch( unsigned ilevel, unsigned xoff, unsigned yoff, unsigned zoff, unsigned nx, unsigned ny, unsigned nz)
|
void cut_patch( unsigned ilevel, unsigned xoff, unsigned yoff, unsigned zoff, unsigned nx, unsigned ny, unsigned nz)
|
||||||
{
|
{
|
||||||
unsigned dx,dy,dz,dxtop,dytop,dztop;
|
unsigned dx,dy,dz,dxtop,dytop,dztop;
|
||||||
|
@ -815,6 +840,7 @@ public:
|
||||||
find_new_levelmin();
|
find_new_levelmin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! determine level for which grid extends over entire domain */
|
||||||
void find_new_levelmin( void )
|
void find_new_levelmin( void )
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<=levelmax(); ++i )
|
for( unsigned i=0; i<=levelmax(); ++i )
|
||||||
|
@ -829,16 +855,19 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! return maximum level in refinement hierarchy
|
||||||
unsigned levelmax( void ) const
|
unsigned levelmax( void ) const
|
||||||
{
|
{
|
||||||
return m_pgrids.size()-1;
|
return m_pgrids.size()-1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! return minimum level in refinement hierarchy (the level which extends over the entire domain)
|
||||||
unsigned levelmin( void ) const
|
unsigned levelmin( void ) const
|
||||||
{
|
{
|
||||||
return m_levelmin;
|
return m_levelmin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! assignment operator
|
||||||
GridHierarchy& operator=( const GridHierarchy<T>& gh )
|
GridHierarchy& operator=( const GridHierarchy<T>& gh )
|
||||||
{
|
{
|
||||||
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
for( unsigned i=0; i<m_pgrids.size(); ++i )
|
||||||
|
@ -862,23 +891,52 @@ public:
|
||||||
//! class that computes the refinement structure given parameters
|
//! class that computes the refinement structure given parameters
|
||||||
class refinement_hierarchy
|
class refinement_hierarchy
|
||||||
{
|
{
|
||||||
std::vector<double> x0_,y0_,z0_,xl_,yl_,zl_;
|
std::vector<double>
|
||||||
std::vector<unsigned> ox_,oy_,oz_,oax_,oay_,oaz_;
|
x0_, //!< x-coordinates of grid origins (in [0..1[)
|
||||||
std::vector<unsigned> nx_,ny_,nz_;
|
y0_, //!< y-coordinates of grid origins (in [0..1[)
|
||||||
unsigned levelmin_, levelmax_, levelmin_tf_, padding_;
|
z0_, //!< z-coordinates of grid origins (in [0..1[)
|
||||||
config_file& cf_;
|
xl_, //!< x-extent of grids (in [0..1[)
|
||||||
bool align_top_;
|
yl_, //!< y-extent of grids (in [0..1[)
|
||||||
double x0ref_[3], lxref_[3];
|
zl_; //!< z-extent of grids (in [0..1[)
|
||||||
int xshift_[3];
|
|
||||||
|
std::vector<unsigned>
|
||||||
|
ox_, //!< relative x-coordinates of grid origins (in coarser grid cells)
|
||||||
|
oy_, //!< relative y-coordinates of grid origins (in coarser grid cells)
|
||||||
|
oz_, //!< relative z-coordinates of grid origins (in coarser grid cells)
|
||||||
|
oax_, //!< absolute x-coordinates of grid origins (in fine grid cells)
|
||||||
|
oay_, //!< absolute y-coordinates of grid origins (in fine grid cells)
|
||||||
|
oaz_, //!< absolute z-coordinates of grid origins (in fine grid cells)
|
||||||
|
nx_, //!< x-extent of grids (in fine grid cells)
|
||||||
|
ny_, //!< y-extent of grids (in fine grid cells)
|
||||||
|
nz_; //!< z-extent of grids (in fine grid cells)
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
levelmin_, //!< minimum grid level for Poisson solver
|
||||||
|
levelmax_, //!< maximum grid level for all operations
|
||||||
|
levelmin_tf_, //!< minimum grid level for density calculation
|
||||||
|
padding_; //!< padding in number of coarse cells between refinement levels
|
||||||
|
|
||||||
|
|
||||||
|
config_file& cf_; //!< reference to config_file
|
||||||
|
|
||||||
|
bool align_top_; //!< bool whether to align all grids with coarsest grid cells
|
||||||
|
|
||||||
|
double
|
||||||
|
x0ref_[3], //!< coordinates of refinement region origin (in [0..1[)
|
||||||
|
lxref_[3]; //!< extent of refinement region (int [0..1[)
|
||||||
|
|
||||||
|
int xshift_[3]; //!< shift of refinement region in coarse cells (in order to center it in the domain)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//! copy constructor
|
||||||
refinement_hierarchy( const refinement_hierarchy& rh )
|
refinement_hierarchy( const refinement_hierarchy& rh )
|
||||||
: cf_( rh.cf_ )
|
: cf_( rh.cf_ )
|
||||||
{
|
{
|
||||||
*this = rh;
|
*this = rh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! constructor from a config_file holding information about the desired refinement geometry
|
||||||
explicit refinement_hierarchy( config_file& cf )
|
explicit refinement_hierarchy( config_file& cf )
|
||||||
: cf_( cf )
|
: cf_( cf )
|
||||||
{
|
{
|
||||||
|
@ -1058,6 +1116,7 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! asignment operator
|
||||||
refinement_hierarchy& operator=( const refinement_hierarchy& o )
|
refinement_hierarchy& operator=( const refinement_hierarchy& o )
|
||||||
{
|
{
|
||||||
levelmin_ = o.levelmin_;
|
levelmin_ = o.levelmin_;
|
||||||
|
@ -1081,6 +1140,16 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! cut a grid level to the specified size
|
||||||
|
* @param ilevel grid level on which to perform the size adjustment
|
||||||
|
* @param nx new x-extent in fine grid cells
|
||||||
|
* @param ny new y-extent in fine grid cells
|
||||||
|
* @param nz new z-extent in fine grid cells
|
||||||
|
* @param oax new x-offset in units fine grid units
|
||||||
|
* @param oay new y-offset in units fine grid units
|
||||||
|
* @param oaz new z-offset in units fine grid units
|
||||||
|
|
||||||
|
*/
|
||||||
void adjust_level( unsigned ilevel, int nx, int ny, int nz, int oax, int oay, int oaz )
|
void adjust_level( unsigned ilevel, int nx, int ny, int nz, int oax, int oay, int oaz )
|
||||||
{
|
{
|
||||||
double h = 1.0/pow(2,ilevel);
|
double h = 1.0/pow(2,ilevel);
|
||||||
|
@ -1122,6 +1191,7 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! determine level for which grid extends over entire domain */
|
||||||
void find_new_levelmin( bool print=false )
|
void find_new_levelmin( bool print=false )
|
||||||
{
|
{
|
||||||
unsigned old_levelmin( levelmin_ );
|
unsigned old_levelmin( levelmin_ );
|
||||||
|
@ -1140,6 +1210,7 @@ public:
|
||||||
std::cerr << " - refinement_hierarchy: set new levelmin to " << levelmin_ << std::endl;
|
std::cerr << " - refinement_hierarchy: set new levelmin to " << levelmin_ << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! get absolute grid offset for a specified level along a specified dimension (in fine grid units)
|
||||||
unsigned offset_abs( unsigned ilevel, int dim ) const
|
unsigned offset_abs( unsigned ilevel, int dim ) const
|
||||||
{
|
{
|
||||||
if( dim==0 )
|
if( dim==0 )
|
||||||
|
@ -1149,6 +1220,7 @@ public:
|
||||||
return oaz_.at(ilevel);
|
return oaz_.at(ilevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! get relative grid offset for a specified level along a specified dimension (in coarser grid units)
|
||||||
unsigned offset( unsigned ilevel, int dim ) const
|
unsigned offset( unsigned ilevel, int dim ) const
|
||||||
{
|
{
|
||||||
if( dim==0 )
|
if( dim==0 )
|
||||||
|
@ -1158,6 +1230,7 @@ public:
|
||||||
return oz_.at(ilevel);
|
return oz_.at(ilevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! get grid size for a specified level along a specified dimension
|
||||||
unsigned size( unsigned ilevel, int dim ) const
|
unsigned size( unsigned ilevel, int dim ) const
|
||||||
{
|
{
|
||||||
if( dim==0 )
|
if( dim==0 )
|
||||||
|
@ -1167,14 +1240,16 @@ public:
|
||||||
return nz_.at(ilevel);
|
return nz_.at(ilevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! get minimum grid level (the level for which the grid covers the entire domain)
|
||||||
unsigned levelmin( void ) const
|
unsigned levelmin( void ) const
|
||||||
{ return levelmin_; }
|
{ return levelmin_; }
|
||||||
|
|
||||||
|
//! get maximum grid level
|
||||||
unsigned levelmax( void ) const
|
unsigned levelmax( void ) const
|
||||||
{ return levelmax_; }
|
{ return levelmax_; }
|
||||||
|
|
||||||
|
|
||||||
|
//! write refinement hierarchy to stdout
|
||||||
void output( void )
|
void output( void )
|
||||||
{
|
{
|
||||||
std::cout << "-------------------------------------------------------------\n";
|
std::cout << "-------------------------------------------------------------\n";
|
||||||
|
|
34
mg_interp.hh
34
mg_interp.hh
|
@ -21,6 +21,7 @@ struct coarse_fine_interpolation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! general 2nd order polynomial interpolation
|
||||||
inline double interp2( double x1, double x2, double x3, double f1, double f2, double f3, double x )
|
inline double interp2( double x1, double x2, double x3, double f1, double f2, double f3, double x )
|
||||||
{
|
{
|
||||||
double a,b,c;
|
double a,b,c;
|
||||||
|
@ -32,28 +33,33 @@ inline double interp2( double x1, double x2, double x3, double f1, double f2, do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! optimized 4th order polynomial interpolation across a left boundary for i-1 values
|
||||||
inline double interp4left( double f0, double f1, double f2, double f3, double f4 )
|
inline double interp4left( double f0, double f1, double f2, double f3, double f4 )
|
||||||
{
|
{
|
||||||
//return -4.0/231.0*f0+4.0/7.0*f1+5.0/7.0*f2-1.0/3.0*f3+5./77.0*f4;
|
//return -4.0/231.0*f0+4.0/7.0*f1+5.0/7.0*f2-1.0/3.0*f3+5./77.0*f4;
|
||||||
return 1.0/13.0*f0-21./55.*f1+7.0/9.0*f2+8./15.*f3-8./1287*f4;
|
return 1.0/13.0*f0-21./55.*f1+7.0/9.0*f2+8./15.*f3-8./1287*f4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 4th order polynomial interpolation across a right boundary for i+1 values
|
||||||
inline double interp4right( double f0, double f1, double f2, double f3, double f4 )
|
inline double interp4right( double f0, double f1, double f2, double f3, double f4 )
|
||||||
{
|
{
|
||||||
return interp4left(f4,f3,f2,f1,f0);
|
return interp4left(f4,f3,f2,f1,f0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 4th order polynomial interpolation across a left boundary for i-2 values
|
||||||
inline double interp4lleft( double f0, double f1, double f2, double f3, double f4 )
|
inline double interp4lleft( double f0, double f1, double f2, double f3, double f4 )
|
||||||
{
|
{
|
||||||
//return 16./231.*f0+48.0/35.0*f1-6.0/7.0*f2-8.0/15.0*f3-9./77.*f4;
|
//return 16./231.*f0+48.0/35.0*f1-6.0/7.0*f2-8.0/15.0*f3-9./77.*f4;
|
||||||
return -15./91.*f0+8./11.*f1+-10./9.*f2+32./21.*f3+32./1287.*f4;
|
return -15./91.*f0+8./11.*f1+-10./9.*f2+32./21.*f3+32./1287.*f4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 4th order polynomial interpolation across a right boundary for i+2 values
|
||||||
inline double interp4rright( double f0, double f1, double f2, double f3, double f4 )
|
inline double interp4rright( double f0, double f1, double f2, double f3, double f4 )
|
||||||
{
|
{
|
||||||
return interp4lleft(f4,f3,f2,f1,f0);
|
return interp4lleft(f4,f3,f2,f1,f0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! general 4th order polynomial interpolation
|
||||||
inline double interp4( double fm2, double fm1, double f0, double fp1, double fp2, double x )
|
inline double interp4( double fm2, double fm1, double f0, double fp1, double fp2, double x )
|
||||||
{
|
{
|
||||||
double x2 = x*x, x3=x2*x, x4=x3*x;
|
double x2 = x*x, x3=x2*x, x4=x3*x;
|
||||||
|
@ -68,6 +74,7 @@ inline double interp4( double fm2, double fm1, double f0, double fp1, double fp2
|
||||||
return a*x4+b*x3+c*x2+d*x+e;
|
return a*x4+b*x3+c*x2+d*x+e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! general 4th order polynomial interpolation
|
||||||
inline double interp4( double* f, double x )
|
inline double interp4( double* f, double x )
|
||||||
{
|
{
|
||||||
double x2 = x*x, x3=x2*x, x4=x3*x;
|
double x2 = x*x, x3=x2*x, x4=x3*x;
|
||||||
|
@ -82,7 +89,7 @@ inline double interp4( double* f, double x )
|
||||||
return a*x4+b*x3+c*x2+d*x+e;
|
return a*x4+b*x3+c*x2+d*x+e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! general 6th order polynomial interpolation
|
||||||
inline double interp6( double *f, double x )
|
inline double interp6( double *f, double x )
|
||||||
{
|
{
|
||||||
double x2 = x*x, x3=x2*x, x4=x3*x, x5=x4*x, x6=x5*x;
|
double x2 = x*x, x3=x2*x, x4=x3*x, x5=x4*x, x6=x5*x;
|
||||||
|
@ -100,6 +107,7 @@ inline double interp6( double *f, double x )
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! general 6th order polynomial interpolation
|
||||||
inline double interp6( double f0, double f1, double f2, double f3, double f4, double f5, double f6, double x )
|
inline double interp6( double f0, double f1, double f2, double f3, double f4, double f5, double f6, double x )
|
||||||
{
|
{
|
||||||
double x2 = x*x, x3=x2*x, x4=x3*x, x5=x4*x, x6=x5*x;
|
double x2 = x*x, x3=x2*x, x4=x3*x, x5=x4*x, x6=x5*x;
|
||||||
|
@ -120,6 +128,7 @@ inline double interp6( double f0, double f1, double f2, double f3, double f4, do
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! general 2nd order polynomial interpolation
|
||||||
inline double interp2( double fleft, double fcenter, double fright, double x )
|
inline double interp2( double fleft, double fcenter, double fright, double x )
|
||||||
{
|
{
|
||||||
double a,b,c;
|
double a,b,c;
|
||||||
|
@ -130,7 +139,7 @@ inline double interp2( double fleft, double fcenter, double fright, double x )
|
||||||
return a*x*x+b*x+c;
|
return a*x*x+b*x+c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 2nd order polynomial interpolation for i-1 values
|
||||||
inline double interp2left( double fleft, double fcenter, double fright )
|
inline double interp2left( double fleft, double fcenter, double fright )
|
||||||
{
|
{
|
||||||
double a,b,c;
|
double a,b,c;
|
||||||
|
@ -141,6 +150,7 @@ inline double interp2left( double fleft, double fcenter, double fright )
|
||||||
return a-b+c;
|
return a-b+c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 2nd order polynomial interpolation for i+1 values
|
||||||
inline double interp2right( double fleft, double fcenter, double fright )
|
inline double interp2right( double fleft, double fcenter, double fright )
|
||||||
{
|
{
|
||||||
double a,b,c;
|
double a,b,c;
|
||||||
|
@ -151,6 +161,7 @@ inline double interp2right( double fleft, double fcenter, double fright )
|
||||||
return a+b+c;
|
return a+b+c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 2nd order polynomial interpolation for i-2 values
|
||||||
inline double interp2lleft( double fleft, double fcenter, double fright )
|
inline double interp2lleft( double fleft, double fcenter, double fright )
|
||||||
{
|
{
|
||||||
double a,b,c;
|
double a,b,c;
|
||||||
|
@ -161,6 +172,7 @@ inline double interp2lleft( double fleft, double fcenter, double fright )
|
||||||
return a-b+c;
|
return a-b+c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 2nd order polynomial interpolation for i+2 values
|
||||||
inline double interp2rright( double fleft, double fcenter, double fright )
|
inline double interp2rright( double fleft, double fcenter, double fright )
|
||||||
{
|
{
|
||||||
double a,b,c;
|
double a,b,c;
|
||||||
|
@ -171,33 +183,37 @@ inline double interp2rright( double fleft, double fcenter, double fright )
|
||||||
return a-b+c;
|
return a-b+c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 6th order polynomial interpolation for i-1 values
|
||||||
inline double interp6left( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
inline double interp6left( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
||||||
{
|
{
|
||||||
//return -77./2565.*f6+44./221.*f5-14./25.*f4+308./351.*f3+352./675.*f2-16./1755.*f1+112./104975.*f0;
|
|
||||||
return 4./2431.*f0-24./1001.*f1+4./7.*f2+60./77.*f3-6./13.*f4+12./77.*f5-5./221.*f6;
|
return 4./2431.*f0-24./1001.*f1+4./7.*f2+60./77.*f3-6./13.*f4+12./77.*f5-5./221.*f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 6th order polynomial interpolation for i-2 values
|
||||||
inline double interp6lleft( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
inline double interp6lleft( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
||||||
{
|
{
|
||||||
//return -16./4199.*f0+16./429.*f1+32./21.*f2-675./1547.*f5-50./39.*f3+12./11.*f4+4./57.*f6;
|
|
||||||
return -12./2431.*f0+40./429.*f1+4./3.*f2-10./11.*f3+28./39.*f4-3./11.*f5+28./663.*f6;
|
return -12./2431.*f0+40./429.*f1+4./3.*f2-10./11.*f3+28./39.*f4-3./11.*f5+28./663.*f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 6th order polynomial interpolation for i-3 values
|
||||||
inline double interp6llleft( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
inline double interp6llleft( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
||||||
{
|
{
|
||||||
//return -432./20995.*f0+112./429.*f1+32./15.*f2-324./221.*f5-140./39.*f3+189./55.*f4+14./57.*f6;
|
|
||||||
return -36./2431.*f0+600./1001.*f1+20./21.*f2-100./77.*f3+15./13.*f4-36./77.*f5+50./663.*f6;
|
return -36./2431.*f0+600./1001.*f1+20./21.*f2-100./77.*f3+15./13.*f4-36./77.*f5+50./663.*f6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 6th order polynomial interpolation for i+1 values
|
||||||
inline double interp6right( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
inline double interp6right( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
||||||
{
|
{
|
||||||
return interp6left(f6,f5,f4,f3,f2,f1,f0);
|
return interp6left(f6,f5,f4,f3,f2,f1,f0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 6th order polynomial interpolation for i+2 values
|
||||||
inline double interp6rright( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
inline double interp6rright( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
||||||
{
|
{
|
||||||
return interp6lleft(f6,f5,f4,f3,f2,f1,f0);
|
return interp6lleft(f6,f5,f4,f3,f2,f1,f0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! optimized 6th order polynomial interpolation for i+3 values
|
||||||
inline double interp6rrright( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
inline double interp6rrright( double f0, double f1, double f2, double f3, double f4, double f5, double f6 )
|
||||||
{
|
{
|
||||||
return interp6llleft(f6,f5,f4,f3,f2,f1,f0);
|
return interp6llleft(f6,f5,f4,f3,f2,f1,f0);
|
||||||
|
@ -208,6 +224,7 @@ inline double interp6rrright( double f0, double f1, double f2, double f3, double
|
||||||
|
|
||||||
#include "fd_schemes.hh"
|
#include "fd_schemes.hh"
|
||||||
|
|
||||||
|
//! tri-cubic interpolation for non-conservative injection
|
||||||
struct cubic_interp
|
struct cubic_interp
|
||||||
: public coarse_fine_interpolation
|
: public coarse_fine_interpolation
|
||||||
{
|
{
|
||||||
|
@ -413,7 +430,7 @@ struct cubic_interp
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! 3rd order flux-corrected coarse-fine interpolation
|
||||||
struct interp_O3_fluxcorr
|
struct interp_O3_fluxcorr
|
||||||
: public coarse_fine_interpolation
|
: public coarse_fine_interpolation
|
||||||
{
|
{
|
||||||
|
@ -617,6 +634,7 @@ struct interp_O3_fluxcorr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! 5th order flux-corrected coarse-fine interpolation
|
||||||
struct interp_O5_fluxcorr
|
struct interp_O5_fluxcorr
|
||||||
: public coarse_fine_interpolation
|
: public coarse_fine_interpolation
|
||||||
{
|
{
|
||||||
|
@ -923,7 +941,7 @@ struct interp_O5_fluxcorr
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! 7th order flux-corrected coarse-fine interpolation
|
||||||
struct interp_O7_fluxcorr
|
struct interp_O7_fluxcorr
|
||||||
: public coarse_fine_interpolation
|
: public coarse_fine_interpolation
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#ifndef __MG_OPERATORS_HH
|
#ifndef __MG_OPERATORS_HH
|
||||||
#define __MG_OPERATORS_HH
|
#define __MG_OPERATORS_HH
|
||||||
|
|
||||||
//! injection operator based Catmull-Rom splines with arbitrary refinement factor
|
//! injection operator based on Catmull-Rom splines with arbitrary refinement factor
|
||||||
class mg_cubic_mult
|
class mg_cubic_mult
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -598,7 +598,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
class mg_lin
|
class mg_lin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -739,9 +739,9 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
//! linear grid injection/restriction operator
|
||||||
|
|
||||||
//template< typename T >
|
//template< typename T >
|
||||||
class mg_linear
|
class mg_linear
|
||||||
{
|
{
|
||||||
|
@ -1004,14 +1004,11 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! zero order grid injection/restriction operator
|
||||||
//template< typename T >
|
|
||||||
class mg_straight
|
class mg_straight
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//typedef T real_t;
|
|
||||||
|
|
||||||
template< typename m1, typename m2 >
|
template< typename m1, typename m2 >
|
||||||
inline void restrict_bnd( const m1& v, m2& V ) const
|
inline void restrict_bnd( const m1& v, m2& V ) const
|
||||||
{
|
{
|
||||||
|
@ -1164,7 +1161,7 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//... prolongs V to v
|
//... prolongs V to v on grid boundary cells
|
||||||
template< typename m1, typename m2 >
|
template< typename m1, typename m2 >
|
||||||
inline void prolong_bnd( const m1& V, m2& v ) const
|
inline void prolong_bnd( const m1& V, m2& v ) const
|
||||||
{
|
{
|
||||||
|
@ -1285,6 +1282,7 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! prolongs V and adds it to v
|
||||||
template< typename m1, typename m2 >
|
template< typename m1, typename m2 >
|
||||||
inline void prolong_add( const m1& V, m2& v ) const
|
inline void prolong_add( const m1& V, m2& v ) const
|
||||||
{
|
{
|
||||||
|
|
38
mg_solver.hh
38
mg_solver.hh
|
@ -37,12 +37,13 @@
|
||||||
|
|
||||||
BEGIN_MULTIGRID_NAMESPACE
|
BEGIN_MULTIGRID_NAMESPACE
|
||||||
|
|
||||||
|
//! options for multigrid smoothing operation
|
||||||
namespace opt {
|
namespace opt {
|
||||||
enum smtype { sm_jacobi, sm_gauss_seidel, sm_sor };
|
enum smtype { sm_jacobi, sm_gauss_seidel, sm_sor };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//! actual implementation of FAS adaptive multigrid solver
|
||||||
template< class S, class I, class O, typename T=double >
|
template< class S, class I, class O, typename T=double >
|
||||||
class solver
|
class solver
|
||||||
{
|
{
|
||||||
|
@ -52,51 +53,68 @@ public:
|
||||||
typedef I interp;
|
typedef I interp;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
scheme m_scheme;
|
scheme m_scheme; //!< finite difference scheme
|
||||||
mgop m_gridop;
|
mgop m_gridop; //!< grid prolongation and restriction operator
|
||||||
unsigned m_npresmooth, m_npostsmooth;
|
unsigned m_npresmooth, //!< number of pre sweeps
|
||||||
opt::smtype m_smoother;
|
m_npostsmooth; //!< number of post sweeps
|
||||||
unsigned m_ilevelmin;
|
opt::smtype m_smoother; //!< smoothing method to be applied
|
||||||
|
unsigned m_ilevelmin; //!< index of the top grid level
|
||||||
|
|
||||||
const static bool m_bperiodic = true;
|
const static bool m_bperiodic = true; //!< flag whether top grid is periodic
|
||||||
|
|
||||||
std::vector<double> m_residu_ini;
|
std::vector<double> m_residu_ini; //!< vector of initial residuals for each level
|
||||||
bool m_is_ini;
|
bool m_is_ini; //!< bool that is true for first iteration
|
||||||
|
|
||||||
GridHierarchy<T> *m_pu, *m_pf, *m_pfsave;
|
GridHierarchy<T> *m_pu, //!< pointer to GridHierarchy for solution u
|
||||||
|
*m_pf, //!< pointer to GridHierarchy for right-hand-side
|
||||||
|
*m_pfsave; //!< pointer to saved state of right-hand-side (unused)
|
||||||
|
|
||||||
const MeshvarBnd<T> *m_pubnd;
|
const MeshvarBnd<T> *m_pubnd;
|
||||||
|
|
||||||
|
//! compute residual for a level
|
||||||
double compute_error( const MeshvarBnd<T>& u, const MeshvarBnd<T>& unew );
|
double compute_error( const MeshvarBnd<T>& u, const MeshvarBnd<T>& unew );
|
||||||
|
|
||||||
|
//! compute residuals for entire grid hierarchy
|
||||||
double compute_error( const GridHierarchy<T>& uh, const GridHierarchy<T>& uhnew, bool verbose );
|
double compute_error( const GridHierarchy<T>& uh, const GridHierarchy<T>& uhnew, bool verbose );
|
||||||
|
|
||||||
|
//! compute residuals for entire grid hierarchy
|
||||||
double compute_RMS_resid( const GridHierarchy<T>& uh, const GridHierarchy<T>& fh, bool verbose );
|
double compute_RMS_resid( const GridHierarchy<T>& uh, const GridHierarchy<T>& fh, bool verbose );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
//! Jacobi smoothing
|
||||||
void Jacobi( T h, MeshvarBnd<T>* u, const MeshvarBnd<T>* f );
|
void Jacobi( T h, MeshvarBnd<T>* u, const MeshvarBnd<T>* f );
|
||||||
|
|
||||||
|
//! Gauss-Seidel smoothing
|
||||||
void GaussSeidel( T h, MeshvarBnd<T>* u, const MeshvarBnd<T>* f );
|
void GaussSeidel( T h, MeshvarBnd<T>* u, const MeshvarBnd<T>* f );
|
||||||
|
|
||||||
|
//! Successive-Overrelaxation smoothing
|
||||||
void SOR( T h, MeshvarBnd<T>* u, const MeshvarBnd<T>* f );
|
void SOR( T h, MeshvarBnd<T>* u, const MeshvarBnd<T>* f );
|
||||||
|
|
||||||
|
//! main two-grid (V-cycle) for multi-grid iterations
|
||||||
void twoGrid( unsigned ilevel );
|
void twoGrid( unsigned ilevel );
|
||||||
|
|
||||||
|
//! apply boundary conditions
|
||||||
void setBC( unsigned ilevel );
|
void setBC( unsigned ilevel );
|
||||||
|
|
||||||
|
//! make top grid periodic boundary conditions
|
||||||
void make_periodic( MeshvarBnd<T> *u );
|
void make_periodic( MeshvarBnd<T> *u );
|
||||||
|
|
||||||
//void interp_coarse_fine_cubic( unsigned ilevel, MeshvarBnd<T>& coarse, MeshvarBnd<T>& fine );
|
//void interp_coarse_fine_cubic( unsigned ilevel, MeshvarBnd<T>& coarse, MeshvarBnd<T>& fine );
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//! constructor
|
||||||
solver( GridHierarchy<T>& f, opt::smtype smoother, unsigned npresmooth, unsigned npostsmooth );
|
solver( GridHierarchy<T>& f, opt::smtype smoother, unsigned npresmooth, unsigned npostsmooth );
|
||||||
|
|
||||||
|
//! destructor
|
||||||
~solver()
|
~solver()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
//! solve Poisson's equation
|
||||||
double solve( GridHierarchy<T>& u, double accuracy, double h=-1.0, bool verbose=false );
|
double solve( GridHierarchy<T>& u, double accuracy, double h=-1.0, bool verbose=false );
|
||||||
|
|
||||||
|
//! solve Poisson's equation
|
||||||
double solve( GridHierarchy<T>& u, double accuracy, bool verbose=false )
|
double solve( GridHierarchy<T>& u, double accuracy, bool verbose=false )
|
||||||
{
|
{
|
||||||
return this->solve ( u, accuracy, -1.0, verbose );
|
return this->solve ( u, accuracy, -1.0, verbose );
|
||||||
|
|
|
@ -528,6 +528,22 @@ public:
|
||||||
shift[2] = -(double)cf_.getValue<int>( "setup", "shift_z" )*h;
|
shift[2] = -(double)cf_.getValue<int>( "setup", "shift_z" )*h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( !cf_.getValueSafe<bool>("output","stagger_particles",false ) )
|
||||||
|
{
|
||||||
|
double h = 1.0/pow(2,levelmax_);
|
||||||
|
if( shift==NULL )
|
||||||
|
{
|
||||||
|
shift = new double[3];
|
||||||
|
shift[0] = -0.5*h;
|
||||||
|
shift[1] = -0.5*h;
|
||||||
|
shift[2] = -0.5*h;
|
||||||
|
}else{
|
||||||
|
shift[0] -= 0.5*h;
|
||||||
|
shift[1] -= 0.5*h;
|
||||||
|
shift[2] -= 0.5*h;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
//...
|
//...
|
||||||
header_.npart[1] = npfine;
|
header_.npart[1] = npfine;
|
||||||
|
|
317
poisson.cc
317
poisson.cc
|
@ -24,6 +24,8 @@
|
||||||
/****** ABSTRACT FACTORY PATTERN IMPLEMENTATION *******/
|
/****** ABSTRACT FACTORY PATTERN IMPLEMENTATION *******/
|
||||||
|
|
||||||
#include "poisson.hh"
|
#include "poisson.hh"
|
||||||
|
#include "Numerics.hh"
|
||||||
|
|
||||||
std::map< std::string, poisson_plugin_creator *>&
|
std::map< std::string, poisson_plugin_creator *>&
|
||||||
get_poisson_plugin_map()
|
get_poisson_plugin_map()
|
||||||
{
|
{
|
||||||
|
@ -512,11 +514,10 @@ double fft_poisson_plugin::solve( grid_hierarchy& f, grid_hierarchy& u )
|
||||||
double kk2 = kfac*kfac*(ki*ki+kj*kj+kk*kk);
|
double kk2 = kfac*kfac*(ki*ki+kj*kj+kk*kk);
|
||||||
|
|
||||||
unsigned idx = (i*ny+j)*nzp/2+k;
|
unsigned idx = (i*ny+j)*nzp/2+k;
|
||||||
double re = cdata[idx].re;
|
|
||||||
double im = cdata[idx].im;
|
|
||||||
|
|
||||||
cdata[idx].re = -re/kk2*fac;
|
cdata[idx].re *= -1.0/kk2*fac;
|
||||||
cdata[idx].im = -im/kk2*fac;
|
cdata[idx].im *= -1.0/kk2*fac;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cdata[0].re = 0.0;
|
cdata[0].re = 0.0;
|
||||||
|
@ -592,6 +593,7 @@ double fft_poisson_plugin::gradient( int dir, grid_hierarchy& u, grid_hierarchy&
|
||||||
for( int j=0; j<ny; ++j )
|
for( int j=0; j<ny; ++j )
|
||||||
for( int k=0; k<nz/2+1; ++k )
|
for( int k=0; k<nz/2+1; ++k )
|
||||||
{
|
{
|
||||||
|
unsigned idx = (i*ny+j)*nzp/2+k;
|
||||||
int ii = i; if(ii>nx/2) ii-=nx;
|
int ii = i; if(ii>nx/2) ii-=nx;
|
||||||
int jj = j; if(jj>ny/2) jj-=ny;
|
int jj = j; if(jj>ny/2) jj-=ny;
|
||||||
double ki = (double)ii;
|
double ki = (double)ii;
|
||||||
|
@ -606,12 +608,19 @@ double fft_poisson_plugin::gradient( int dir, grid_hierarchy& u, grid_hierarchy&
|
||||||
else //if( dir == 2 )
|
else //if( dir == 2 )
|
||||||
kdir = kfac*kk;
|
kdir = kfac*kk;
|
||||||
|
|
||||||
unsigned idx = (i*ny+j)*nzp/2+k;
|
|
||||||
double re = cdata[idx].re;
|
double re = cdata[idx].re;
|
||||||
double im = cdata[idx].im;
|
double im = cdata[idx].im;
|
||||||
|
|
||||||
|
if( i==nx/2||j==ny/2||k==nz/2 )
|
||||||
|
{
|
||||||
|
cdata[idx].re = 0.0;
|
||||||
|
cdata[idx].im = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
cdata[idx].re = fac*im*kdir;
|
cdata[idx].re = fac*im*kdir;
|
||||||
cdata[idx].im = -fac*re*kdir;
|
cdata[idx].im = -fac*re*kdir;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cdata[0].re = 0.0;
|
cdata[0].re = 0.0;
|
||||||
|
@ -627,24 +636,318 @@ double fft_poisson_plugin::gradient( int dir, grid_hierarchy& u, grid_hierarchy&
|
||||||
rfftwnd_destroy_plan(iplan);
|
rfftwnd_destroy_plan(iplan);
|
||||||
|
|
||||||
//... copy data ..........................................
|
//... copy data ..........................................
|
||||||
|
double dmax = 0.0;
|
||||||
for( int i=0; i<nx; ++i )
|
for( int i=0; i<nx; ++i )
|
||||||
for( int j=0; j<ny; ++j )
|
for( int j=0; j<ny; ++j )
|
||||||
for( int k=0; k<nz; ++k )
|
for( int k=0; k<nz; ++k )
|
||||||
{
|
{
|
||||||
unsigned idx = (i*ny+j)*nzp+k;
|
unsigned idx = (i*ny+j)*nzp+k;
|
||||||
(*Du.get_grid(u.levelmax()))(i,j,k) = data[idx];
|
(*Du.get_grid(u.levelmax()))(i,j,k) = data[idx];
|
||||||
|
if(fabs(data[idx])>dmax)
|
||||||
|
dmax = fabs(data[idx]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cerr << " - component max. is " << dmax*nx << std::endl;
|
||||||
|
|
||||||
delete[] data;
|
delete[] data;
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
template<int order>
|
||||||
|
double poisson_hybrid_kernel( int idir, int i, int j, int k, int n )
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline double poisson_hybrid_kernel<2>(int idir, int i, int j, int k, int n )
|
||||||
|
{
|
||||||
|
double
|
||||||
|
ki(M_PI*(double)i/(double)n),
|
||||||
|
kj(M_PI*(double)j/(double)n),
|
||||||
|
kk(M_PI*(double)k/(double)n),
|
||||||
|
kr(sqrt(ki*ki+kj*kj+kk*kk));
|
||||||
|
|
||||||
|
double grad = 1.0, laplace = 1.0;
|
||||||
|
|
||||||
|
if( idir==0&&i!=0 )
|
||||||
|
grad = sin(ki);
|
||||||
|
else if( idir==1&&j!=0 )
|
||||||
|
grad = sin(kj);
|
||||||
|
else if( idir==2&&k!=0 )
|
||||||
|
grad = sin(kk);
|
||||||
|
|
||||||
|
laplace = 2.0*((-cos(ki)+1.0)+(-cos(kj)+1.0)+(-cos(kk)+1.0));
|
||||||
|
|
||||||
|
double kgrad = 1.0;
|
||||||
|
if( idir==0 )
|
||||||
|
kgrad = ki;
|
||||||
|
else if( idir ==1)
|
||||||
|
kgrad = kj;
|
||||||
|
else if( idir ==2)
|
||||||
|
kgrad = kk;
|
||||||
|
|
||||||
|
return (kgrad/kr/kr-grad/laplace)*M_PI/n*M_PI/n;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline double poisson_hybrid_kernel<4>(int idir, int i, int j, int k, int n )
|
||||||
|
{
|
||||||
|
|
||||||
|
if(i==0&&j==0&&k==0)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
double
|
||||||
|
ki(M_PI*(double)i/(double)n),
|
||||||
|
kj(M_PI*(double)j/(double)n),
|
||||||
|
kk(M_PI*(double)k/(double)n),
|
||||||
|
kr(sqrt(ki*ki+kj*kj+kk*kk));
|
||||||
|
|
||||||
|
double grad = 1.0, laplace = 1.0;
|
||||||
|
|
||||||
|
if( idir==0 )
|
||||||
|
grad = 0.166666666667*(-sin(2.*ki)+8.*sin(ki));
|
||||||
|
else if( idir==1 )
|
||||||
|
grad = 0.166666666667*(-sin(2.*kj)+8.*sin(kj));
|
||||||
|
else if( idir==2 )
|
||||||
|
grad = 0.166666666667*(-sin(2.*kk)+8.*sin(kk));
|
||||||
|
|
||||||
|
laplace = 0.1666666667*((cos(2*ki)-16.*cos(ki)+15.)
|
||||||
|
+(cos(2*kj)-16.*cos(kj)+15.)
|
||||||
|
+(cos(2*kk)-16.*cos(kk)+15.));
|
||||||
|
|
||||||
|
double kgrad = 1.0;
|
||||||
|
if( idir==0 )
|
||||||
|
kgrad = ki;
|
||||||
|
else if( idir ==1)
|
||||||
|
kgrad = kj;
|
||||||
|
else if( idir ==2)
|
||||||
|
kgrad = kk;
|
||||||
|
|
||||||
|
return (kgrad/kr/kr-grad/laplace)*M_PI/n*M_PI/n;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline double poisson_hybrid_kernel<6>(int idir, int i, int j, int k, int n )
|
||||||
|
{
|
||||||
|
double
|
||||||
|
ki(M_PI*(double)i/(double)n),
|
||||||
|
kj(M_PI*(double)j/(double)n),
|
||||||
|
kk(M_PI*(double)k/(double)n),
|
||||||
|
kr(sqrt(ki*ki+kj*kj+kk*kk));
|
||||||
|
|
||||||
|
if(i==0&&j==0&&k==0)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
double grad = 1.0, laplace = 1.0;
|
||||||
|
|
||||||
|
if( idir==0 )
|
||||||
|
grad = 0.0333333333333*(sin(3.*ki)-9.*sin(2.*ki)+45.*sin(ki));
|
||||||
|
else if( idir==1 )
|
||||||
|
grad = 0.0333333333333*(sin(3.*kj)-9.*sin(2.*kj)+45.*sin(kj));
|
||||||
|
else if( idir==2 )
|
||||||
|
grad = 0.0333333333333*(sin(3.*kk)-9.*sin(2.*kk)+45.*sin(kk));
|
||||||
|
|
||||||
|
laplace = 0.01111111111111*(
|
||||||
|
(-2.*cos(3.0*ki)+27.*cos(2.*ki)-270.*cos(ki)+245.)
|
||||||
|
+(-2.*cos(3.0*kj)+27.*cos(2.*kj)-270.*cos(kj)+245.)
|
||||||
|
+(-2.*cos(3.0*kk)+27.*cos(2.*kk)-270.*cos(kk)+245.));
|
||||||
|
|
||||||
|
double kgrad = 1.0;
|
||||||
|
if( idir==0 )
|
||||||
|
kgrad = ki;
|
||||||
|
else if( idir ==1)
|
||||||
|
kgrad = kj;
|
||||||
|
else if( idir ==2)
|
||||||
|
kgrad = kk;
|
||||||
|
|
||||||
|
return (kgrad/kr/kr-grad/laplace)*M_PI/n*M_PI/n;//laplace/grad;
|
||||||
|
//return kgrad/kr/kr*M_PI/n*M_PI/n;
|
||||||
|
//return grad/laplace*M_PI/n*M_PI/n;
|
||||||
|
//return (kgrad/kr/kr-grad/laplace);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<int order>
|
||||||
|
void do_poisson_hybrid( fftw_real* data, int idir, int nxp, int nyp, int nzp, bool periodic )
|
||||||
|
{
|
||||||
|
double fftnorm = 1.0/(nxp*nyp*nzp);
|
||||||
|
|
||||||
|
|
||||||
|
if(periodic)
|
||||||
|
fftnorm *= nxp/(4.0*M_PI*M_PI);//sqrt(8.0);
|
||||||
|
|
||||||
|
|
||||||
|
/*if(periodic)
|
||||||
|
fftnorm *= M_PI*M_PI/nxp/nyp/nzp;
|
||||||
|
else
|
||||||
|
fftnorm *= M_PI*M_PI/nxp/nyp/nzp;
|
||||||
|
|
||||||
|
if( idir == 0 )
|
||||||
|
fftnorm *= nxp;
|
||||||
|
else if( idir == 1 )
|
||||||
|
fftnorm *= nyp;
|
||||||
|
else
|
||||||
|
fftnorm *= nzp;*/
|
||||||
|
|
||||||
|
fftw_complex *cdata = reinterpret_cast<fftw_complex*>(data);
|
||||||
|
rfftwnd_plan iplan, plan;
|
||||||
|
|
||||||
|
plan = rfftw3d_create_plan( nxp, nyp, nzp,
|
||||||
|
FFTW_REAL_TO_COMPLEX, FFTW_ESTIMATE|FFTW_IN_PLACE);
|
||||||
|
|
||||||
|
iplan = rfftw3d_create_plan( nxp, nyp, nzp,
|
||||||
|
FFTW_COMPLEX_TO_REAL, FFTW_ESTIMATE|FFTW_IN_PLACE);
|
||||||
|
|
||||||
|
#ifndef SINGLETHREAD_FFTW
|
||||||
|
rfftwnd_threads_one_real_to_complex( omp_get_max_threads(), plan, data, NULL );
|
||||||
|
#else
|
||||||
|
rfftwnd_one_real_to_complex( plan, data, NULL );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
double ksum = 0.0;
|
||||||
|
unsigned kcount = 0;
|
||||||
|
|
||||||
|
for( int i=0; i<nxp; ++i )
|
||||||
|
for( int j=0; j<nyp; ++j )
|
||||||
|
for( int k=0; k<nzp/2+1; ++k )
|
||||||
|
{
|
||||||
|
unsigned ii = (i*nyp + j) * (nzp/2+1) + k;
|
||||||
|
|
||||||
|
if( k==0 || k==nzp/2 )
|
||||||
|
{
|
||||||
|
ksum += cdata[ii].re;
|
||||||
|
kcount++;
|
||||||
|
}else{
|
||||||
|
ksum += 2.0*(cdata[ii].re);
|
||||||
|
kcount+=2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ksum /= kcount;
|
||||||
|
kcount = 0;
|
||||||
|
|
||||||
|
cdata[0].re = 0.0;
|
||||||
|
cdata[0].im = 0.0;
|
||||||
|
|
||||||
|
#pragma omp parallel for
|
||||||
|
for( int i=0; i<nxp; ++i )
|
||||||
|
for( int j=0; j<nyp; ++j )
|
||||||
|
for( int k=0; k<nzp/2+1; ++k )
|
||||||
|
{
|
||||||
|
unsigned ii = (i*nyp + j) * (nzp/2+1) + k;
|
||||||
|
|
||||||
|
int ki(i), kj(j);
|
||||||
|
if( ki > nxp/2 ) ki-=nxp;
|
||||||
|
if( kj > nyp/2 ) kj-=nyp;
|
||||||
|
|
||||||
|
//... apply hybrid correction
|
||||||
|
double dk = poisson_hybrid_kernel<order>(idir, ki, kj, k, nxp/2 );
|
||||||
|
cdata[ii].re -= ksum;
|
||||||
|
|
||||||
|
double re = cdata[ii].re, im = cdata[ii].im;
|
||||||
|
|
||||||
|
cdata[ii].re = -im*dk*fftnorm;
|
||||||
|
cdata[ii].im = re*dk*fftnorm;
|
||||||
|
|
||||||
|
cdata[ii].re += ksum*fftnorm;
|
||||||
|
|
||||||
|
}
|
||||||
|
cdata[0].re = 0.0;
|
||||||
|
cdata[0].im = 0.0;
|
||||||
|
|
||||||
|
#ifndef SINGLETHREAD_FFTW
|
||||||
|
rfftwnd_threads_one_complex_to_real( omp_get_max_threads(), iplan, cdata, NULL);
|
||||||
|
#else
|
||||||
|
rfftwnd_one_complex_to_real(iplan, cdata, NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
rfftwnd_destroy_plan(plan);
|
||||||
|
rfftwnd_destroy_plan(iplan);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void poisson_hybrid( MeshvarBnd<double>& f, int idir, int order, bool periodic )
|
||||||
|
{
|
||||||
|
int nx=f.size(0), ny=f.size(1), nz=f.size(2), nxp, nyp, nzp;
|
||||||
|
fftw_real *data;
|
||||||
|
int xo=0,yo=0,zo=0;
|
||||||
|
int nmax = std::max(nx,std::max(ny,nz));
|
||||||
|
|
||||||
|
if(!periodic)
|
||||||
|
{
|
||||||
|
nxp = 2*nmax;
|
||||||
|
nyp = 2*nmax;
|
||||||
|
nzp = 2*nmax;
|
||||||
|
xo = nmax/2;
|
||||||
|
yo = nmax/2;
|
||||||
|
zo = nmax/2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nxp = nmax;
|
||||||
|
nyp = nmax;
|
||||||
|
nzp = nmax;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
data = new fftw_real[nxp*nyp*2*(nzp/2+1)];
|
||||||
|
|
||||||
|
if(idir==0)
|
||||||
|
std::cout << " - Performing hybrid Poisson step... (" << nxp << ", " << nyp << ", " << nzp << ")\n";
|
||||||
|
|
||||||
|
|
||||||
|
for( int i=0; i<nxp*nyp*2*(nzp/2+1); ++i )
|
||||||
|
data[i]=0.0;
|
||||||
|
|
||||||
|
for( int i=0; i<nx; ++i )
|
||||||
|
for( int j=0; j<ny; ++j )
|
||||||
|
for( int k=0; k<nz; ++k )
|
||||||
|
{
|
||||||
|
int idx = ((i+xo)*nyp + j+yo) * 2*(nzp/2+1) + k+zo;
|
||||||
|
data[idx] = f(i,j,k);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (order) {
|
||||||
|
case 2:
|
||||||
|
do_poisson_hybrid<2>(data, idir, nxp, nyp, nzp, periodic);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
do_poisson_hybrid<4>(data, idir, nxp, nyp, nzp, periodic);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
do_poisson_hybrid<6>(data, idir, nxp, nyp, nzp, periodic);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
std::cerr << " - ERROR: invalid operator order specified in deconvolution.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for( int i=0; i<nx; ++i )
|
||||||
|
for( int j=0; j<ny; ++j )
|
||||||
|
for( int k=0; k<nz; ++k )
|
||||||
|
{
|
||||||
|
int idx = ((i+xo)*nyp + j+yo) * 2*(nzp/2+1) + k+zo;
|
||||||
|
f(i,j,k) = data[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
delete[] data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************************/
|
||||||
|
/**************************************************************************************/
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
namespace{
|
namespace{
|
||||||
poisson_plugin_creator_concrete<multigrid_poisson_plugin> multigrid_poisson_creator("mg_poisson");
|
poisson_plugin_creator_concrete<multigrid_poisson_plugin> multigrid_poisson_creator("mg_poisson");
|
||||||
|
|
43
poisson.hh
43
poisson.hh
|
@ -29,6 +29,7 @@
|
||||||
|
|
||||||
#include "general.hh"
|
#include "general.hh"
|
||||||
|
|
||||||
|
//! abstract base class for Poisson solvers and gradient calculations
|
||||||
class poisson_plugin
|
class poisson_plugin
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
@ -47,8 +48,13 @@ public:
|
||||||
virtual ~poisson_plugin()
|
virtual ~poisson_plugin()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
//! solve Poisson's equation Du=f
|
||||||
virtual double solve( grid_hierarchy& f, grid_hierarchy& u ) = 0;
|
virtual double solve( grid_hierarchy& f, grid_hierarchy& u ) = 0;
|
||||||
|
|
||||||
|
//! compute the gradient of u
|
||||||
virtual double gradient( int dir, grid_hierarchy& u, grid_hierarchy& Du ) = 0;
|
virtual double gradient( int dir, grid_hierarchy& u, grid_hierarchy& Du ) = 0;
|
||||||
|
|
||||||
|
//! compute the gradient and add
|
||||||
virtual double gradient_add( int dir, grid_hierarchy& u, grid_hierarchy& Du ) = 0;
|
virtual double gradient_add( int dir, grid_hierarchy& u, grid_hierarchy& Du ) = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -97,30 +103,55 @@ struct poisson_plugin_creator_concrete : public poisson_plugin_creator
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
|
//! adaptive FAS multigrid implementation of abstract base class poisson_plugin
|
||||||
class multigrid_poisson_plugin : public poisson_plugin
|
class multigrid_poisson_plugin : public poisson_plugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//! constructor
|
||||||
explicit multigrid_poisson_plugin( config_file& cf )
|
explicit multigrid_poisson_plugin( config_file& cf )
|
||||||
: poisson_plugin( cf )
|
: poisson_plugin( cf )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
//! solve Poisson's equation Du=f
|
||||||
double solve( grid_hierarchy& f, grid_hierarchy& u );
|
double solve( grid_hierarchy& f, grid_hierarchy& u );
|
||||||
|
|
||||||
|
//! compute the gradient of u
|
||||||
double gradient( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
double gradient( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
|
|
||||||
|
//! compute the gradient and add
|
||||||
double gradient_add( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
double gradient_add( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
//! various FD approximation implementations
|
||||||
struct implementation
|
struct implementation
|
||||||
{
|
{
|
||||||
|
//! solve 2nd order FD approximation to Poisson's equation
|
||||||
double solve_O2( grid_hierarchy& f, grid_hierarchy& u );
|
double solve_O2( grid_hierarchy& f, grid_hierarchy& u );
|
||||||
|
|
||||||
|
//! solve 4th order FD approximation to Poisson's equation
|
||||||
double solve_O4( grid_hierarchy& f, grid_hierarchy& u );
|
double solve_O4( grid_hierarchy& f, grid_hierarchy& u );
|
||||||
|
|
||||||
|
//! solve 6th order FD approximation to Poisson's equation
|
||||||
double solve_O6( grid_hierarchy& f, grid_hierarchy& u );
|
double solve_O6( grid_hierarchy& f, grid_hierarchy& u );
|
||||||
|
|
||||||
|
//! compute 2nd order FD gradient
|
||||||
void gradient_O2( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
void gradient_O2( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
|
|
||||||
|
//! compute and add 2nd order FD gradient
|
||||||
void gradient_add_O2( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
void gradient_add_O2( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
|
|
||||||
|
//! compute 4th order FD gradient
|
||||||
void gradient_O4( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
void gradient_O4( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
|
|
||||||
|
//! compute and add 4th order FD gradient
|
||||||
void gradient_add_O4( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
void gradient_add_O4( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
|
|
||||||
|
//! compute 6th order FD gradient
|
||||||
void gradient_O6( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
void gradient_O6( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
|
|
||||||
|
//! compute and add 6th order FD gradient
|
||||||
void gradient_add_O6( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
void gradient_add_O6( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -129,23 +160,33 @@ protected:
|
||||||
/**************************************************************************************/
|
/**************************************************************************************/
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
|
||||||
|
//! FFT based implementation of abstract base class poisson_plugin
|
||||||
class fft_poisson_plugin : public poisson_plugin
|
class fft_poisson_plugin : public poisson_plugin
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//! constructor
|
||||||
explicit fft_poisson_plugin( config_file& cf )
|
explicit fft_poisson_plugin( config_file& cf )
|
||||||
: poisson_plugin( cf )
|
: poisson_plugin( cf )
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
//! solve Poisson's equation Du=f
|
||||||
double solve( grid_hierarchy& f, grid_hierarchy& u );
|
double solve( grid_hierarchy& f, grid_hierarchy& u );
|
||||||
|
|
||||||
|
//! compute the gradient of u
|
||||||
double gradient( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
double gradient( int dir, grid_hierarchy& u, grid_hierarchy& Du );
|
||||||
|
|
||||||
|
//! compute the gradient and add
|
||||||
double gradient_add( int dir, grid_hierarchy& u, grid_hierarchy& Du ){ return 0.0; }
|
double gradient_add( int dir, grid_hierarchy& u, grid_hierarchy& Du ){ return 0.0; }
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**************************************************************************************/
|
||||||
|
/**************************************************************************************/
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
void poisson_hybrid( MeshvarBnd<double>& f, int idir, int order, bool periodic );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -226,10 +226,10 @@ protected:
|
||||||
|
|
||||||
{
|
{
|
||||||
std::cerr << " - degrading field for 1 level...(" << res_ << ")\n";
|
std::cerr << " - degrading field for 1 level...(" << res_ << ")\n";
|
||||||
//unsigned ixoff=51,iyoff=51,izoff=51;
|
unsigned ixoff=51,iyoff=51,izoff=51;
|
||||||
//unsigned nx=52, ny=52, nz=52;
|
unsigned nx=52, ny=52, nz=52;
|
||||||
unsigned ixoff=102, iyoff=102, izoff=102;
|
//unsigned ixoff=102, iyoff=102, izoff=102;
|
||||||
unsigned nx=104, ny=104, nz=104;
|
//unsigned nx=104, ny=104, nz=104;
|
||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for( unsigned ix=0; ix<res_; ix+=2 )
|
for( unsigned ix=0; ix<res_; ix+=2 )
|
||||||
|
|
|
@ -55,12 +55,13 @@ enum tf_type{
|
||||||
*/
|
*/
|
||||||
class transfer_function_plugin{
|
class transfer_function_plugin{
|
||||||
public:
|
public:
|
||||||
Cosmology cosmo_;
|
Cosmology cosmo_; //!< cosmological parameter, read from config_file
|
||||||
config_file *pcf_;
|
config_file *pcf_; //!< pointer to config_file from which to read parameters
|
||||||
bool tf_distinct_;
|
bool tf_distinct_; //!< bool if transfer function is distinct for baryons and DM
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
//! constructor
|
||||||
transfer_function_plugin( config_file& cf )
|
transfer_function_plugin( config_file& cf )
|
||||||
: pcf_( &cf )
|
: pcf_( &cf )
|
||||||
{
|
{
|
||||||
|
@ -74,34 +75,50 @@ public:
|
||||||
cosmo_.sigma8 = pcf_->getValue<real_t>( "cosmology", "sigma_8" );
|
cosmo_.sigma8 = pcf_->getValue<real_t>( "cosmology", "sigma_8" );
|
||||||
cosmo_.nspect = pcf_->getValue<real_t>( "cosmology", "nspec" );
|
cosmo_.nspect = pcf_->getValue<real_t>( "cosmology", "nspec" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! destructor
|
||||||
virtual ~transfer_function_plugin(){ };
|
virtual ~transfer_function_plugin(){ };
|
||||||
|
|
||||||
|
//! compute value of transfer function at waven umber
|
||||||
virtual double compute( double k, tf_type type) = 0;
|
virtual double compute( double k, tf_type type) = 0;
|
||||||
|
|
||||||
|
//! return maximum wave number allowed
|
||||||
virtual double get_kmax( void ) = 0;
|
virtual double get_kmax( void ) = 0;
|
||||||
|
|
||||||
|
//! return minimum wave number allowed
|
||||||
virtual double get_kmin( void ) = 0;
|
virtual double get_kmin( void ) = 0;
|
||||||
|
|
||||||
|
//! return if transfer function is distinct for baryons and DM
|
||||||
bool tf_is_distinct( void )
|
bool tf_is_distinct( void )
|
||||||
{ return tf_distinct_; }
|
{ return tf_distinct_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//! Implements abstract factory design pattern for transfer function plug-ins
|
||||||
struct transfer_function_plugin_creator
|
struct transfer_function_plugin_creator
|
||||||
{
|
{
|
||||||
|
//! create an instance of a transfer function plug-in
|
||||||
virtual transfer_function_plugin * create( config_file& cf ) const = 0;
|
virtual transfer_function_plugin * create( config_file& cf ) const = 0;
|
||||||
|
|
||||||
|
//! destroy an instance of a plug-in
|
||||||
virtual ~transfer_function_plugin_creator() { }
|
virtual ~transfer_function_plugin_creator() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! Write names of registered transfer function plug-ins to stdout
|
||||||
std::map< std::string, transfer_function_plugin_creator *>& get_transfer_function_plugin_map();
|
std::map< std::string, transfer_function_plugin_creator *>& get_transfer_function_plugin_map();
|
||||||
void print_transfer_function_plugins( void );
|
void print_transfer_function_plugins( void );
|
||||||
|
|
||||||
|
//! Concrete factory pattern for transfer function plug-ins
|
||||||
template< class Derived >
|
template< class Derived >
|
||||||
struct transfer_function_plugin_creator_concrete : public transfer_function_plugin_creator
|
struct transfer_function_plugin_creator_concrete : public transfer_function_plugin_creator
|
||||||
{
|
{
|
||||||
|
//! register the plug-in by its name
|
||||||
transfer_function_plugin_creator_concrete( const std::string& plugin_name )
|
transfer_function_plugin_creator_concrete( const std::string& plugin_name )
|
||||||
{
|
{
|
||||||
get_transfer_function_plugin_map()[ plugin_name ] = this;
|
get_transfer_function_plugin_map()[ plugin_name ] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! create an instance of the plug-in
|
||||||
transfer_function_plugin * create( config_file& cf ) const
|
transfer_function_plugin * create( config_file& cf ) const
|
||||||
{
|
{
|
||||||
return new Derived( cf );
|
return new Derived( cf );
|
||||||
|
@ -117,6 +134,7 @@ transfer_function_plugin *select_transfer_function_plugin( config_file& cf );
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
|
||||||
|
//! k-space transfer function
|
||||||
class TransferFunction_k
|
class TransferFunction_k
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -132,6 +150,19 @@ public:
|
||||||
nspec_ = nspec;
|
nspec_ = nspec;
|
||||||
sqrtpnorm_ = sqrt( pnorm_ );
|
sqrtpnorm_ = sqrt( pnorm_ );
|
||||||
type_ = type;
|
type_ = type;
|
||||||
|
|
||||||
|
std::ofstream ofs("input_powerspec.txt");
|
||||||
|
double kmin=-3, kmax=3, dk=(kmax-kmin)/100.;
|
||||||
|
|
||||||
|
for( int i=0; i<100; ++i )
|
||||||
|
{
|
||||||
|
double k = pow(10.0,kmin+i*dk);
|
||||||
|
ofs << std::setw(16) << k
|
||||||
|
<< std::setw(16) << pow(dplus_*sqrtpnorm_*pow(k,0.5*nspec_)*ptf_->compute(k,type_),2)
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline real_t compute( real_t k ) const
|
inline real_t compute( real_t k ) const
|
||||||
|
@ -400,9 +431,12 @@ public:
|
||||||
//.. need a factor sqrt( 2*kny^2_x + 2*kny^2_y + 2*kny^2_z )/2 = sqrt(3/2)kny (in equilateral case)
|
//.. need a factor sqrt( 2*kny^2_x + 2*kny^2_y + 2*kny^2_z )/2 = sqrt(3/2)kny (in equilateral case)
|
||||||
//#warning Need to integrate from Boxsize (see below)?
|
//#warning Need to integrate from Boxsize (see below)?
|
||||||
gsl_integration_qag (&F, 0.0, sqrt(1.5)*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
gsl_integration_qag (&F, 0.0, sqrt(1.5)*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
||||||
|
//gsl_integration_qag (&F, 0.0, 1.24070098*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
||||||
|
//gsl_integration_qag (&F, 0.0, 1.280788*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
||||||
|
//gsl_integration_qag (&F, 0.0, knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
||||||
//gsl_integration_qag (&F, 0.0, 1.116*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
//gsl_integration_qag (&F, 0.0, 1.116*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
||||||
//gsl_integration_qag (&F, 0.0, sqrt(3)*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
//gsl_integration_qag (&F, 0.0, sqrt(3)*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
||||||
//gsl_integration_qag (&F, 0.0, knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
//gsl_integration_qag (&F, 0.0, 0.5*knymax, 0, 1e-8, 20000, GSL_INTEG_GAUSS21, wp, &Tr0_, &error);
|
||||||
|
|
||||||
gsl_integration_workspace_free(wp);
|
gsl_integration_workspace_free(wp);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue