/*
tests.hh - This file is part of MUSIC -
a code to generate multi-scale initial conditions
for cosmological simulations
Copyright (C) 2010 Oliver Hahn
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#ifndef __TESTS_HH
#define __TESTS_HH
#include
inline double CIC_interp_back( const MeshvarBnd& A, double x, double y, double z )
{
int
ix = (int)x,
iy = (int)y,
iz = (int)z,
ix1 = (ix+1),
iy1 = (iy+1),
iz1 = (iz+1);
double
dx = (double)(x - (double)ix),
dy = (double)(y - (double)iy),
dz = (double)(z - (double)iz),
tx = 1.0-dx,
ty = 1.0-dy,
tz = 1.0-dz;
double
f_xyz = A(ix,iy,iz)*tx*ty*tz,
f_Xyz = A(ix1,iy,iz)*dx*ty*tz,
f_xYz = A(ix,iy1,iz)*tx*dy*tz,
f_xyZ = A(ix,iy,iz1)*tx*ty*dz,
f_XYz = A(ix1,iy1,iz)*dx*dy*tz,
f_XyZ = A(ix1,iy,iz1)*dx*ty*dz,
f_xYZ = A(ix,iy1,iz1)*tx*dy*dz,
f_XYZ = A(ix1,iy1,iz1)*dx*dy*dz;
return f_xyz + f_Xyz + f_xYz + f_xyZ + f_XYz + f_XyZ + f_xYZ + f_XYZ;
}
inline double TSC_interp_back( const MeshvarBnd& A, double x, double y, double z )
{
double val = 0.0;
int xngp = (int)x, yngp = (int)y, zngp = (int)z;
for( int xx = xngp-1; xx <= xngp+1; ++xx )
{
double weightx = 1.0;
double dx = fabs(x-(double)xx);
int axx(xx);
if( xx==xngp )
weightx *= 0.75-dx*dx;
else{
weightx *= 1.125 - 1.5*dx + 0.5*dx*dx;
}
for( int yy = yngp-1; yy <= yngp+1; ++yy )
{
double weighty = weightx;
double dy = fabs(y-(double)yy);
int ayy(yy);
if( yy==yngp )
weighty *= 0.75-dy*dy;
else{
weighty *= 1.125 - 1.5*dy + 0.5*dy*dy;
}
for( int zz = zngp-1; zz <= zngp+1; ++zz )
{
double weightz = weighty;
double dz = fabs(z-(double)zz);
int azz(zz);
if( zz==zngp )
weightz *= 0.75-dz*dz;
else{
weightz *= 1.125 - 1.5*dz + 0.5*dz*dz;
}
val += A(axx,ayy,azz) * weightz;
}
}
}
return val;
}
class TestProblem{
public:
MeshvarBnd m_rho, m_uana, m_ubnd, m_xgrad, m_ygrad, m_zgrad;
int m_nb, m_nres;
double m_h;
TestProblem( int nb, int nres )
: m_rho( nb, nres ), m_uana( nb, nres ), m_ubnd( nb, nres ),
m_xgrad( nb, nres ), m_ygrad( nb, nres ), m_zgrad( nb, nres ),
m_nb( nb ), m_nres( nres ), m_h( 1.0/((double)nres ) )//m_h( 1.0/((double)nres+1.0 ) )
{ }
};
class TSC_Test : public TestProblem{
public:
double m_q;
class TSCcube{
public:
std::vector m_data;
TSCcube()
{
m_data.assign(27,0.0);
//.. center
(*this)( 0, 0, 0) = 27./64.;
//.. faces
(*this)(-1, 0, 0) =
(*this)(+1, 0, 0) =
(*this)( 0,-1, 0) =
(*this)( 0,+1, 0) =
(*this)( 0, 0,-1) =
(*this)( 0, 0,+1) = 9./128.;
//.. edges
(*this)(-1,-1, 0) =
(*this)(-1,+1, 0) =
(*this)(+1,-1, 0) =
(*this)(+1,+1, 0) =
(*this)(-1, 0,-1) =
(*this)(-1, 0,+1) =
(*this)(+1, 0,-1) =
(*this)(+1, 0,+1) =
(*this)( 0,-1,-1) =
(*this)( 0,-1,+1) =
(*this)( 0,+1,-1) =
(*this)( 0,+1,+1) = 3./256.;
//.. corners
(*this)(-1,-1,-1) =
(*this)(-1,+1,-1) =
(*this)(-1,-1,+1) =
(*this)(-1,+1,+1) =
(*this)(+1,-1,-1) =
(*this)(+1,+1,-1) =
(*this)(+1,-1,+1) =
(*this)(+1,+1,+1) = 1./512.;
}
double& operator()(int i, int j, int k)
{ return m_data[ ((i+1)*3+(j+1))*3 +(k+1)]; }
const double& operator()(int i, int j, int k) const
{ return m_data[ ((i+1)*3+(j+1))*3 +(k+1)]; }
};
TSC_Test( int nb, int nres, double q=-1.0 )
: TestProblem(nb, nres), m_q(q)
{
TSCcube c;
int xm(nres/2-1), ym(nres/2-1), zm(nres/2-1);
double xxm((double)xm*m_h), yym((double)ym*m_h), zzm((double)zm*m_h);
double fourpi = 4.0*M_PI;
m_uana.zero();
m_ubnd.zero();
m_xgrad.zero();
m_ygrad.zero();
m_zgrad.zero();
for( int i=-nb; i