mirror of
https://bitbucket.org/cosmicvoids/vide_public.git
synced 2025-07-08 01:01:11 +00:00
Update cosmotool 2nd part
This commit is contained in:
parent
64e05fc180
commit
003bc39d4a
70 changed files with 8708 additions and 0 deletions
101
external/cosmotool/src/fourier/fft/fftw_calls_mpi.hpp
vendored
Normal file
101
external/cosmotool/src/fourier/fft/fftw_calls_mpi.hpp
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
#ifndef __MPI_FFTW_UNIFIED_CALLS_HPP
|
||||
#define __MPI_FFTW_UNIFIED_CALLS_HPP
|
||||
|
||||
#include <complex>
|
||||
#include <mpi.h>
|
||||
#include <fftw3-mpi.h>
|
||||
|
||||
namespace CosmoTool
|
||||
{
|
||||
|
||||
static inline void init_fftw_mpi()
|
||||
{
|
||||
fftw_mpi_init();
|
||||
}
|
||||
|
||||
static inline void done_fftw_mpi()
|
||||
{
|
||||
fftw_mpi_cleanup();
|
||||
}
|
||||
|
||||
template<typename T> class FFTW_MPI_Calls {};
|
||||
|
||||
|
||||
#define FFTW_MPI_CALLS_BASE(rtype, prefix) \
|
||||
template<> \
|
||||
class FFTW_MPI_Calls<rtype> { \
|
||||
public: \
|
||||
typedef rtype real_type; \
|
||||
typedef prefix ## _complex complex_type; \
|
||||
typedef prefix ## _plan plan_type; \
|
||||
\
|
||||
static complex_type *alloc_complex(size_t N) { return prefix ## _alloc_complex(N); } \
|
||||
static real_type *alloc_real(size_t N) { return prefix ## _alloc_real(N); } \
|
||||
static void free(void *p) { fftw_free(p); } \
|
||||
\
|
||||
static ptrdiff_t local_size_2d(ptrdiff_t N0, ptrdiff_t N1, MPI_Comm comm, \
|
||||
ptrdiff_t *local_n0, ptrdiff_t *local_0_start) { \
|
||||
return prefix ## _mpi_local_size_2d(N0, N1, comm, local_n0, local_0_start); \
|
||||
} \
|
||||
\
|
||||
static ptrdiff_t local_size_3d(ptrdiff_t N0, ptrdiff_t N1, ptrdiff_t N2, MPI_Comm comm, \
|
||||
ptrdiff_t *local_n0, ptrdiff_t *local_0_start) { \
|
||||
return prefix ## _mpi_local_size_3d(N0, N1, N2, comm, local_n0, local_0_start); \
|
||||
} \
|
||||
\
|
||||
static void execute(plan_type p) { prefix ## _execute(p); } \
|
||||
static void execute_r2c(plan_type p, real_type *in, complex_type *out) { prefix ## _mpi_execute_dft_r2c(p, in, out); } \
|
||||
static void execute_c2r(plan_type p, std::complex<real_type> *in, real_type *out) { prefix ## _mpi_execute_dft_c2r(p, (complex_type*)in, out); } \
|
||||
static void execute_c2r(plan_type p, complex_type *in, real_type *out) { prefix ## _mpi_execute_dft_c2r(p, in, out); } \
|
||||
static void execute_r2c(plan_type p, real_type *in, std::complex<real_type> *out) { prefix ## _mpi_execute_dft_r2c(p, in, (complex_type*)out); } \
|
||||
\
|
||||
static plan_type plan_dft_r2c_2d(int Nx, int Ny, \
|
||||
real_type *in, complex_type *out, \
|
||||
MPI_Comm comm, unsigned flags) \
|
||||
{ \
|
||||
return prefix ## _mpi_plan_dft_r2c_2d(Nx, Ny, in, out, \
|
||||
comm, flags); \
|
||||
} \
|
||||
static plan_type plan_dft_c2r_2d(int Nx, int Ny, \
|
||||
complex_type *in, real_type *out, \
|
||||
MPI_Comm comm, unsigned flags) \
|
||||
{ \
|
||||
return prefix ## _mpi_plan_dft_c2r_2d(Nx, Ny, in, out, \
|
||||
comm, flags); \
|
||||
} \
|
||||
static plan_type plan_dft_r2c_3d(int Nx, int Ny, int Nz, \
|
||||
real_type *in, complex_type *out, \
|
||||
MPI_Comm comm, unsigned flags) \
|
||||
{ \
|
||||
return prefix ## _mpi_plan_dft_r2c_3d(Nx, Ny, Nz, in, out, comm, flags); \
|
||||
} \
|
||||
static plan_type plan_dft_c2r_3d(int Nx, int Ny, int Nz, \
|
||||
complex_type *in, real_type *out, \
|
||||
MPI_Comm comm, \
|
||||
unsigned flags) \
|
||||
{ \
|
||||
return prefix ## _mpi_plan_dft_c2r_3d(Nx, Ny, Nz, in, out, comm, flags); \
|
||||
} \
|
||||
\
|
||||
static plan_type plan_dft_r2c(int rank, const ptrdiff_t *n, real_type *in, \
|
||||
complex_type *out, MPI_Comm comm, unsigned flags) \
|
||||
{ \
|
||||
return prefix ## _mpi_plan_dft_r2c(rank, n, in, out, comm, flags); \
|
||||
} \
|
||||
static plan_type plan_dft_c2r(int rank, const ptrdiff_t *n, complex_type *in, \
|
||||
real_type *out, MPI_Comm comm, unsigned flags) \
|
||||
{ \
|
||||
return prefix ## _mpi_plan_dft_c2r(rank, n, in, out, comm, flags); \
|
||||
} \
|
||||
static void destroy_plan(plan_type plan) { prefix ## _destroy_plan(plan); } \
|
||||
}
|
||||
|
||||
|
||||
FFTW_MPI_CALLS_BASE(double, fftw);
|
||||
FFTW_MPI_CALLS_BASE(float, fftwf);
|
||||
|
||||
#undef FFTW_MPI_CALLS_BASE
|
||||
|
||||
};
|
||||
|
||||
#endif
|
42
external/cosmotool/src/fourier/fft/fftw_complex.hpp
vendored
Normal file
42
external/cosmotool/src/fourier/fft/fftw_complex.hpp
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef __COSMOTOOL_FFT_COMPLEX_HPP
|
||||
#define __COSMOTOOL_FFT_COMPLEX_HPP
|
||||
|
||||
#include <complex>
|
||||
#include <fftw3.h>
|
||||
|
||||
namespace CosmoTool
|
||||
{
|
||||
template<typename T>
|
||||
struct adapt_complex {
|
||||
};
|
||||
|
||||
template<> struct adapt_complex<fftw_complex> {
|
||||
typedef fftw_complex f_type;
|
||||
typedef std::complex<double> cpp_complex;
|
||||
|
||||
static inline cpp_complex *adapt(f_type *a) {
|
||||
return reinterpret_cast<cpp_complex *>(a);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct adapt_complex<fftwf_complex> {
|
||||
typedef fftwf_complex f_type;
|
||||
typedef std::complex<float> cpp_complex;
|
||||
|
||||
static inline cpp_complex *adapt(f_type *a) {
|
||||
return reinterpret_cast<cpp_complex *>(a);
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct adapt_complex<fftwl_complex> {
|
||||
typedef fftwl_complex f_type;
|
||||
typedef std::complex<long double> cpp_complex;
|
||||
|
||||
static inline cpp_complex *adapt(f_type *a) {
|
||||
return reinterpret_cast<cpp_complex *>(a);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
487
external/cosmotool/src/hdf5_array.hpp
vendored
Normal file
487
external/cosmotool/src/hdf5_array.hpp
vendored
Normal file
|
@ -0,0 +1,487 @@
|
|||
/*+
|
||||
This is CosmoTool (./src/hdf5_array.hpp) -- Copyright (C) Guilhem Lavaux (2007-2014)
|
||||
|
||||
guilhem.lavaux@gmail.com
|
||||
|
||||
This software is a computer program whose purpose is to provide a toolbox for cosmological
|
||||
data analysis (e.g. filters, generalized Fourier transforms, power spectra, ...)
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can use,
|
||||
modify and/ or redistribute the software under the terms of the CeCILL
|
||||
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
"http://www.cecill.info".
|
||||
|
||||
As a counterpart to the access to the source code and rights to copy,
|
||||
modify and redistribute granted by the license, users are provided only
|
||||
with a limited warranty and the software's author, the holder of the
|
||||
economic rights, and the successive licensors have only limited
|
||||
liability.
|
||||
|
||||
In this respect, the user's attention is drawn to the risks associated
|
||||
with loading, using, modifying and/or developing or reproducing the
|
||||
software by the user in light of its specific status of free software,
|
||||
sthat may mean that it is complicated to manipulate, and that also
|
||||
therefore means that it is reserved for developers and experienced
|
||||
professionals having in-depth computer knowledge. Users are therefore
|
||||
encouraged to load and test the software's suitability as regards their
|
||||
requirements in conditions enabling the security of their systems and/or
|
||||
data to be ensured and, more generally, to use and operate it in the
|
||||
same conditions as regards security.
|
||||
|
||||
The fact that you are presently reading this means that you have had
|
||||
knowledge of the CeCILL license and that you accept its terms.
|
||||
+*/
|
||||
#ifndef __COSMO_HDF5_ARRAY_HPP
|
||||
#define __COSMO_HDF5_ARRAY_HPP
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/mpl/assert.hpp>
|
||||
#include <boost/multi_array.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/is_floating_point.hpp>
|
||||
#include <boost/preprocessor/cat.hpp>
|
||||
#include <boost/preprocessor/stringize.hpp>
|
||||
#include <boost/preprocessor/seq/for_each.hpp>
|
||||
#include <vector>
|
||||
#include <H5Cpp.h>
|
||||
|
||||
namespace CosmoTool {
|
||||
#if (H5_VERS_MAJOR == 1) && (H5_VERS_MINOR <= 8)
|
||||
typedef H5::CommonFG H5_CommonFileGroup;
|
||||
#else
|
||||
typedef H5::Group H5_CommonFileGroup;
|
||||
#endif
|
||||
|
||||
//!_______________________________________________________________________________________
|
||||
//!
|
||||
//! map types to HDF5 types
|
||||
//!
|
||||
//!
|
||||
//! Leo Goodstadt (04 March 2013), improved with enable_if by Guilhem Lavaux (May 2014)
|
||||
//!_______________________________________________________________________________________
|
||||
|
||||
template<typename T, class Enable = void> struct get_hdf5_data_type
|
||||
{
|
||||
static H5::DataType type()
|
||||
{
|
||||
BOOST_MPL_ASSERT_MSG(0, Unknown_HDF5_data_type, ());
|
||||
return H5::PredType::NATIVE_DOUBLE;
|
||||
}
|
||||
};
|
||||
|
||||
//, typename boost::enable_if<boost::is_same<T, tl> >::type> \
|
||||
//
|
||||
#define HDF5_TYPE(tl, thdf5) \
|
||||
template<typename T> struct get_hdf5_data_type<T, typename boost::enable_if<boost::is_same<T,tl> >::type > \
|
||||
{ static H5::DataType type() { return H5::PredType::thdf5; }; }
|
||||
|
||||
#define HDF5_SAFE_TYPE(tl, othertl, thdf5) \
|
||||
template<typename T> struct get_hdf5_data_type<T, \
|
||||
typename boost::enable_if< \
|
||||
boost::integral_constant<bool, \
|
||||
boost::is_same<T, tl>::value \
|
||||
&& !boost::is_same<T,othertl>::value > \
|
||||
>::type \
|
||||
> \
|
||||
{ static H5::DataType type() { return H5::PredType::thdf5; }; }
|
||||
|
||||
|
||||
HDF5_SAFE_TYPE(long, int , NATIVE_LONG);
|
||||
HDF5_SAFE_TYPE(unsigned long, unsigned int , NATIVE_ULONG);
|
||||
HDF5_SAFE_TYPE(long long, long , NATIVE_LLONG);
|
||||
HDF5_SAFE_TYPE(unsigned long long, unsigned long, NATIVE_ULLONG);
|
||||
HDF5_TYPE(char , NATIVE_CHAR);
|
||||
HDF5_TYPE(unsigned char , NATIVE_UCHAR);
|
||||
HDF5_TYPE(int , NATIVE_INT);
|
||||
HDF5_TYPE(unsigned int , NATIVE_UINT);
|
||||
HDF5_TYPE(float , NATIVE_FLOAT);
|
||||
HDF5_TYPE(double , NATIVE_DOUBLE);
|
||||
|
||||
#undef HDF5_TYPE
|
||||
#undef HDF5_SAFE_TYPE
|
||||
|
||||
// Extent generator
|
||||
template<std::size_t r>
|
||||
struct hdf5_extent_gen {
|
||||
typedef typename boost::detail::multi_array::extent_gen<r> type;
|
||||
|
||||
static inline type build(hsize_t *d)
|
||||
{
|
||||
return (hdf5_extent_gen<r-1>::build(d))[d[r-1]];
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct hdf5_extent_gen<0> {
|
||||
static inline boost::multi_array_types::extent_gen build(hsize_t *d)
|
||||
{
|
||||
return boost::extents;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//!_______________________________________________________________________________________
|
||||
//!
|
||||
//! write_hdf5 multi_array
|
||||
//!
|
||||
//! \author Guilhem Lavaux (2014-2015)
|
||||
//! \author leo Goodstadt (04 March 2013)
|
||||
//!
|
||||
//!_______________________________________________________________________________________
|
||||
template<typename ArrayType, typename hdf5_data_type>
|
||||
void hdf5_write_array(H5_CommonFileGroup& fg, const std::string& data_set_name,
|
||||
const ArrayType& data,
|
||||
const hdf5_data_type& datatype,
|
||||
const std::vector<hsize_t>& dimensions,
|
||||
bool doCreate = true,
|
||||
bool useBases = false)
|
||||
{
|
||||
std::vector<hsize_t> memdims(data.shape(), data.shape() + data.num_dimensions());
|
||||
H5::DataSpace dataspace(dimensions.size(), dimensions.data());
|
||||
H5::DataSpace memspace(memdims.size(), memdims.data());
|
||||
|
||||
if (useBases) {
|
||||
std::vector<hsize_t> offsets(data.index_bases(), data.index_bases() + data.num_dimensions());
|
||||
dataspace.selectHyperslab(H5S_SELECT_SET, memdims.data(), offsets.data());
|
||||
}
|
||||
|
||||
H5::DataSet dataset;
|
||||
if (doCreate)
|
||||
dataset = fg.createDataSet(data_set_name, datatype, dataspace);
|
||||
else
|
||||
dataset = fg.openDataSet(data_set_name);
|
||||
|
||||
dataset.write(data.data(), datatype, memspace, dataspace);
|
||||
}
|
||||
|
||||
|
||||
template<typename ArrayType, typename hdf5_data_type>
|
||||
void hdf5_write_array(H5_CommonFileGroup& fg, const std::string& data_set_name,
|
||||
const ArrayType& data,
|
||||
const hdf5_data_type& datatype,
|
||||
bool doCreate = true,
|
||||
bool useBases = false)
|
||||
{
|
||||
std::vector<hsize_t> dimensions(data.shape(), data.shape() + data.num_dimensions());
|
||||
hdf5_write_array(fg, data_set_name, data, datatype, dimensions, doCreate, useBases);
|
||||
}
|
||||
|
||||
/* HDF5 complex type */
|
||||
template<typename T>
|
||||
class hdf5_ComplexType
|
||||
{
|
||||
public:
|
||||
H5::CompType type;
|
||||
|
||||
hdf5_ComplexType()
|
||||
: type(sizeof(std::complex<T>))
|
||||
{
|
||||
get_hdf5_data_type<T> hdf_data_type;
|
||||
type.insertMember("r", 0, hdf_data_type.type());
|
||||
type.insertMember("i", sizeof(T), hdf_data_type.type());
|
||||
type.pack();
|
||||
}
|
||||
|
||||
static const hdf5_ComplexType<T> *ctype()
|
||||
{
|
||||
static hdf5_ComplexType<T> singleton;
|
||||
|
||||
return &singleton;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct get_hdf5_data_type<std::complex<float> > {
|
||||
static H5::DataType type() {
|
||||
return hdf5_ComplexType<float>::ctype()->type;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct get_hdf5_data_type<std::complex<double> > {
|
||||
static H5::DataType type() {
|
||||
return hdf5_ComplexType<double>::ctype()->type;
|
||||
}
|
||||
};
|
||||
|
||||
class hdf5_StringType
|
||||
{
|
||||
public:
|
||||
H5::StrType type;
|
||||
|
||||
hdf5_StringType()
|
||||
: type(0, H5T_VARIABLE)
|
||||
{
|
||||
}
|
||||
|
||||
static const hdf5_StringType *ctype()
|
||||
{
|
||||
static hdf5_StringType singleton;
|
||||
return &singleton;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct get_hdf5_data_type<std::string> {
|
||||
static H5::DataType type() {
|
||||
return hdf5_StringType::ctype()->type;
|
||||
}
|
||||
};
|
||||
|
||||
class hdf5_BoolType
|
||||
{
|
||||
public:
|
||||
H5::EnumType type;
|
||||
|
||||
hdf5_BoolType()
|
||||
: type(sizeof(bool))
|
||||
{
|
||||
bool v;
|
||||
|
||||
v = true;
|
||||
type.insert("TRUE", &v);
|
||||
v = false;
|
||||
type.insert("FALSE", &v);
|
||||
}
|
||||
static const hdf5_BoolType *ctype()
|
||||
{
|
||||
static hdf5_BoolType singleton;
|
||||
|
||||
return &singleton;
|
||||
}
|
||||
};
|
||||
|
||||
template<> struct get_hdf5_data_type<bool> {
|
||||
static H5::DataType type() {
|
||||
return hdf5_BoolType::ctype()->type;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ArrayType>
|
||||
void hdf5_write_array(H5_CommonFileGroup& fg, const std::string& data_set_name, const ArrayType& data )
|
||||
{
|
||||
typedef typename ArrayType::element T;
|
||||
get_hdf5_data_type<T> hdf_data_type;
|
||||
|
||||
hdf5_write_array(fg, data_set_name, data, hdf_data_type.type());
|
||||
}
|
||||
|
||||
// HDF5 array reader
|
||||
//
|
||||
// Author Guilhem Lavaux (May 2014)
|
||||
|
||||
class InvalidDimensions: virtual std::exception {
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Conditional resize support
|
||||
// If the Array type support resize then it is called. Otherwise
|
||||
// the dimensions are checked and lead to a failure if they are different
|
||||
|
||||
template<typename Array> class array_has_resize {
|
||||
struct Fallback { int resize; };
|
||||
struct Derived: Array, Fallback {};
|
||||
|
||||
typedef char yes[1];
|
||||
typedef char no[2];
|
||||
|
||||
template<typename U, U> struct Check;
|
||||
|
||||
template<typename U>
|
||||
static yes& func(Check<int Fallback::*, &U::resize> *);
|
||||
|
||||
template<typename U>
|
||||
static no& func(...);
|
||||
public:
|
||||
typedef array_has_resize type;
|
||||
enum { value = sizeof(func<Derived>(0)) == sizeof(no) };
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename ArrayType>
|
||||
typename boost::enable_if<
|
||||
array_has_resize<ArrayType>
|
||||
>::type
|
||||
hdf5_resize_array(ArrayType& data, std::vector<hsize_t>& dims) {
|
||||
data.resize(
|
||||
hdf5_extent_gen<ArrayType::dimensionality>::build(dims.data())
|
||||
);
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
void hdf5_check_array(ArrayType& data, std::vector<hsize_t>& dims) {
|
||||
for (size_t i = 0; i < data.num_dimensions(); i++) {
|
||||
if (data.shape()[i] != dims[i]) {
|
||||
throw InvalidDimensions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
void hdf5_weak_check_array(ArrayType& data, std::vector<hsize_t>& dims) {
|
||||
for (size_t i = 0; i < data.num_dimensions(); i++) {
|
||||
if (data.index_bases()[i] < 0) {
|
||||
// Negative indexes are not supported right now.
|
||||
throw InvalidDimensions();
|
||||
}
|
||||
if (data.index_bases()[i]+data.shape()[i] > dims[i]) {
|
||||
throw InvalidDimensions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename ArrayType>
|
||||
typename boost::disable_if<
|
||||
array_has_resize<ArrayType>
|
||||
>::type
|
||||
hdf5_resize_array(ArrayType& data, std::vector<hsize_t>& dims) {
|
||||
hdf5_check_array(data, dims);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
template<typename ArrayType, typename hdf5_data_type>
|
||||
void hdf5_read_array_typed(H5_CommonFileGroup& fg, const std::string& data_set_name,
|
||||
ArrayType& data,
|
||||
const hdf5_data_type& datatype, bool auto_resize = true, bool useBases = false)
|
||||
{
|
||||
H5::DataSet dataset = fg.openDataSet(data_set_name);
|
||||
H5::DataSpace dataspace = dataset.getSpace();
|
||||
std::vector<hsize_t> dimensions(data.num_dimensions());
|
||||
|
||||
if ((size_t)dataspace.getSimpleExtentNdims() != (size_t)data.num_dimensions())
|
||||
{
|
||||
throw InvalidDimensions();
|
||||
}
|
||||
|
||||
dataspace.getSimpleExtentDims(dimensions.data());
|
||||
if (auto_resize)
|
||||
hdf5_resize_array(data, dimensions);
|
||||
else {
|
||||
if (useBases) {
|
||||
hdf5_weak_check_array(data, dimensions);
|
||||
|
||||
std::vector<hsize_t> memdims(data.shape(), data.shape() + data.num_dimensions());
|
||||
H5::DataSpace memspace(memdims.size(), memdims.data());
|
||||
|
||||
std::vector<hsize_t> offsets(data.index_bases(), data.index_bases() + data.num_dimensions());
|
||||
dataspace.selectHyperslab(H5S_SELECT_SET, memdims.data(), offsets.data());
|
||||
|
||||
dataset.read(data.data(), datatype, memspace, dataspace);
|
||||
return;
|
||||
} else {
|
||||
hdf5_check_array(data, dimensions);
|
||||
}
|
||||
}
|
||||
dataset.read(data.data(), datatype);
|
||||
}
|
||||
|
||||
template<typename ArrayType>
|
||||
void hdf5_read_array(H5_CommonFileGroup& fg, const std::string& data_set_name, ArrayType& data, bool auto_resize = true,
|
||||
bool useBases = false )
|
||||
{
|
||||
typedef typename ArrayType::element T;
|
||||
|
||||
hdf5_read_array_typed(fg, data_set_name, data, get_hdf5_data_type<T>::type(), auto_resize, useBases);
|
||||
}
|
||||
|
||||
|
||||
#define CTOOL_HDF5_NAME(STRUCT) BOOST_PP_CAT(hdf5_,STRUCT)
|
||||
#define CTOOL_HDF5_INSERT_ELEMENT(r, STRUCT, element) \
|
||||
{ \
|
||||
::CosmoTool::get_hdf5_data_type<BOOST_PP_TUPLE_ELEM(2, 0, element)> t; \
|
||||
position = HOFFSET(STRUCT, BOOST_PP_TUPLE_ELEM(2, 1, element)); \
|
||||
const char *field_name = BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2, 1, element)); \
|
||||
type.insertMember(field_name, position, t.type()); \
|
||||
}
|
||||
|
||||
#define CTOOL_STRUCT_TYPE(STRUCT, TNAME, ATTRIBUTES) \
|
||||
namespace CosmoTool { \
|
||||
class TNAME { \
|
||||
public: \
|
||||
H5::CompType type; \
|
||||
\
|
||||
TNAME() : type(sizeof(STRUCT)) \
|
||||
{ \
|
||||
long position; \
|
||||
BOOST_PP_SEQ_FOR_EACH(CTOOL_HDF5_INSERT_ELEMENT, STRUCT, ATTRIBUTES) \
|
||||
} \
|
||||
\
|
||||
static const TNAME *ctype() \
|
||||
{ \
|
||||
static TNAME singleton; \
|
||||
return &singleton; \
|
||||
} \
|
||||
}; \
|
||||
template<> struct get_hdf5_data_type<STRUCT> { \
|
||||
static H5::DataType type() { return TNAME::ctype()->type; }; \
|
||||
}; \
|
||||
};
|
||||
|
||||
|
||||
#define CTOOL_HDF5_INSERT_ENUM_ELEMENT(r, STRUCT, element) \
|
||||
{ \
|
||||
const char *field_name = BOOST_PP_STRINGIZE(element); \
|
||||
STRUCT a = element; \
|
||||
type.insert(field_name, &a); \
|
||||
}
|
||||
|
||||
|
||||
#define CTOOL_ENUM_TYPE(STRUCT, TNAME, ATTRIBUTES) \
|
||||
namespace CosmoTool { \
|
||||
class TNAME { \
|
||||
public: \
|
||||
H5::EnumType type; \
|
||||
\
|
||||
TNAME() : type(sizeof(STRUCT)) \
|
||||
{ \
|
||||
long position; \
|
||||
BOOST_PP_SEQ_FOR_EACH(CTOOL_HDF5_INSERT_ENUM_ELEMENT, STRUCT, ATTRIBUTES) \
|
||||
} \
|
||||
\
|
||||
static const TNAME *ctype() \
|
||||
{ \
|
||||
static TNAME singleton; \
|
||||
return &singleton; \
|
||||
} \
|
||||
}; \
|
||||
template<> struct get_hdf5_data_type<STRUCT> { \
|
||||
static H5::DataType type() { return TNAME::ctype()->type; }; \
|
||||
}; \
|
||||
};
|
||||
|
||||
#define CTOOL_ARRAY_TYPE(ARRAY_TYPE, DIM, TNAME) \
|
||||
namespace CosmoTool { \
|
||||
class TNAME { \
|
||||
public: \
|
||||
H5::ArrayType *type; \
|
||||
\
|
||||
TNAME() \
|
||||
{ \
|
||||
hsize_t dims[1] = { DIM }; \
|
||||
type = new H5::ArrayType(get_hdf5_data_type<ARRAY_TYPE>::type(), 1, dims); \
|
||||
} \
|
||||
~TNAME() { delete type; } \
|
||||
\
|
||||
static const TNAME *ctype() \
|
||||
{ \
|
||||
static TNAME singleton; \
|
||||
return &singleton; \
|
||||
} \
|
||||
}; \
|
||||
\
|
||||
template<> struct get_hdf5_data_type< ARRAY_TYPE[DIM] > { \
|
||||
static H5::DataType type() { return *(TNAME::ctype()->type); }; \
|
||||
}; \
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
217
external/cosmotool/src/octTree.tcc
vendored
Normal file
217
external/cosmotool/src/octTree.tcc
vendored
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*+
|
||||
This is CosmoTool (./src/octTree.cpp) -- Copyright (C) Guilhem Lavaux (2007-2014)
|
||||
|
||||
guilhem.lavaux@gmail.com
|
||||
|
||||
This software is a computer program whose purpose is to provide a toolbox for cosmological
|
||||
data analysis (e.g. filters, generalized Fourier transforms, power spectra, ...)
|
||||
|
||||
This software is governed by the CeCILL license under French law and
|
||||
abiding by the rules of distribution of free software. You can use,
|
||||
modify and/ or redistribute the software under the terms of the CeCILL
|
||||
license as circulated by CEA, CNRS and INRIA at the following URL
|
||||
"http://www.cecill.info".
|
||||
|
||||
As a counterpart to the access to the source code and rights to copy,
|
||||
modify and redistribute granted by the license, users are provided only
|
||||
with a limited warranty and the software's author, the holder of the
|
||||
economic rights, and the successive licensors have only limited
|
||||
liability.
|
||||
|
||||
In this respect, the user's attention is drawn to the risks associated
|
||||
with loading, using, modifying and/or developing or reproducing the
|
||||
software by the user in light of its specific status of free software,
|
||||
that may mean that it is complicated to manipulate, and that also
|
||||
therefore means that it is reserved for developers and experienced
|
||||
professionals having in-depth computer knowledge. Users are therefore
|
||||
encouraged to load and test the software's suitability as regards their
|
||||
requirements in conditions enabling the security of their systems and/or
|
||||
data to be ensured and, more generally, to use and operate it in the
|
||||
same conditions as regards security.
|
||||
|
||||
The fact that you are presently reading this means that you have had
|
||||
knowledge of the CeCILL license and that you accept its terms.
|
||||
+*/
|
||||
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
#include "config.hpp"
|
||||
#include "octTree.hpp"
|
||||
|
||||
namespace CosmoTool {
|
||||
|
||||
using namespace std;
|
||||
|
||||
//#define VERBOSE
|
||||
|
||||
static uint32_t mypow(uint32_t i, uint32_t p)
|
||||
{
|
||||
if (p == 0)
|
||||
return 1;
|
||||
else if (p == 1)
|
||||
return i;
|
||||
|
||||
uint32_t k = p/2;
|
||||
uint32_t j = mypow(i, k);
|
||||
if (2*k==p)
|
||||
return j*j;
|
||||
else
|
||||
return j*j*i;
|
||||
}
|
||||
|
||||
template<typename Updater, typename T>
|
||||
OctTree<Updater,T>::OctTree(const FCoordinates *particles, octPtr numParticles,
|
||||
uint32_t maxMeanTreeDepth, uint32_t maxAbsoluteDepth,
|
||||
uint32_t threshold)
|
||||
{
|
||||
cout << "MeanTree=" << maxMeanTreeDepth << endl;
|
||||
numCells = mypow(8, maxMeanTreeDepth);
|
||||
assert(numCells < invalidOctCell);
|
||||
//#ifdef VERBOSE
|
||||
cerr << "Allocating " << numCells << " octtree cells" << endl;
|
||||
//#endif
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
xMin[j] = particles[0][j];
|
||||
|
||||
for (octPtr i = 1; i < numParticles; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
if (particles[i][j] < xMin[j])
|
||||
xMin[j] = particles[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
lenNorm = 0;
|
||||
for (octPtr i = 0; i < numParticles; i++)
|
||||
{
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
float delta = particles[i][j]-xMin[j];
|
||||
if (delta > lenNorm)
|
||||
lenNorm = delta;
|
||||
}
|
||||
}
|
||||
cout << xMin[0] << " " << xMin[1] << " " << xMin[2] << " lNorm=" << lenNorm << endl;
|
||||
|
||||
cells = new OctCell<T>[numCells];
|
||||
Lbox = (float)(octCoordTypeNorm+1);
|
||||
|
||||
cells[0].numberLeaves = 0;
|
||||
for (int i = 0; i < 8; i++)
|
||||
cells[0].children[i] = emptyOctCell;
|
||||
|
||||
lastNode = 1;
|
||||
this->particles = particles;
|
||||
this->numParticles = numParticles;
|
||||
buildTree(maxAbsoluteDepth);
|
||||
//#ifdef VERBOSE
|
||||
cerr << "Used " << lastNode << " cells" << endl;
|
||||
//#endif
|
||||
}
|
||||
|
||||
template<typename Updater, typename T>
|
||||
OctTree<Updater,T>::~OctTree()
|
||||
{
|
||||
delete cells;
|
||||
}
|
||||
|
||||
template<typename Updater, typename T>
|
||||
void OctTree<Updater,T>::buildTree(uint32_t maxAbsoluteDepth)
|
||||
{
|
||||
for (octPtr i = 0; i < numParticles; i++)
|
||||
{
|
||||
OctCoords rootCenter = { octCoordCenter, octCoordCenter, octCoordCenter };
|
||||
insertParticle(0, // root node
|
||||
rootCenter,
|
||||
octCoordCenter,
|
||||
i,
|
||||
maxAbsoluteDepth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Updater, typename T>
|
||||
void OctTree<Updater,T>::insertParticle(octPtr node,
|
||||
const OctCoords& icoord,
|
||||
octCoordType halfNodeLength,
|
||||
octPtr particleId,
|
||||
uint32_t maxAbsoluteDepth)
|
||||
{
|
||||
|
||||
#ifdef VERBOSE
|
||||
cout << "Entering " << node << " (" << icoord[0] << "," << icoord[1] << "," << icoord[2] << ")" << endl;
|
||||
#endif
|
||||
int octPos = 0;
|
||||
int ipos[3] = { 0,0,0};
|
||||
octPtr newNode;
|
||||
OctCoords newCoord;
|
||||
|
||||
cells[node].numberLeaves++;
|
||||
if (maxAbsoluteDepth == 0)
|
||||
{
|
||||
// All children must be invalid.
|
||||
for (int i = 0 ; i < 8; i++)
|
||||
cells[node].children[i] = invalidOctCell;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
{
|
||||
float treePos = (particles[particleId][j]-xMin[j])*Lbox/lenNorm;
|
||||
if ((octPtr)(treePos) > icoord[j])
|
||||
{
|
||||
octPos |= (1 << j);
|
||||
ipos[j] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (cells[node].children[octPos] == emptyOctCell)
|
||||
{
|
||||
// Put the particle there.
|
||||
cells[node].children[octPos] = particleId | octParticleMarker;
|
||||
return;
|
||||
}
|
||||
|
||||
// If it is a node, explores it.
|
||||
if (!(cells[node].children[octPos] & octParticleMarker))
|
||||
{
|
||||
assert(halfNodeLength >= 2);
|
||||
// Compute coordinates
|
||||
for (int j = 0; j < 3; j++)
|
||||
newCoord[j] = icoord[j]+(2*ipos[j]-1)*halfNodeLength/2;
|
||||
insertParticle(cells[node].children[octPos], newCoord, halfNodeLength/2,
|
||||
particleId, maxAbsoluteDepth-1);
|
||||
return;
|
||||
}
|
||||
|
||||
// We have a particle there.
|
||||
// Make a new node and insert the old particle into this node.
|
||||
// Insert the new particle into the node also
|
||||
// Finally put the node in place
|
||||
|
||||
newNode = lastNode++;
|
||||
assert(lastNode != numCells);
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
cells[newNode].children[j] = emptyOctCell;
|
||||
cells[newNode].numberLeaves = 0;
|
||||
|
||||
// Compute coordinates
|
||||
for (int j = 0; j < 3; j++)
|
||||
newCoord[j] = icoord[j]+(2*ipos[j]-1)*halfNodeLength/2;
|
||||
|
||||
octPtr oldPartId = cells[node].children[octPos] & octParticleMask;
|
||||
|
||||
insertParticle(newNode, newCoord, halfNodeLength/2,
|
||||
oldPartId, maxAbsoluteDepth-1);
|
||||
insertParticle(newNode, newCoord, halfNodeLength/2,
|
||||
particleId, maxAbsoluteDepth-1);
|
||||
cells[node].children[octPos] = newNode;
|
||||
}
|
||||
|
||||
|
||||
};
|
44
external/cosmotool/src/openmp.hpp
vendored
Normal file
44
external/cosmotool/src/openmp.hpp
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
#ifndef __CTOOL_OPENMP_HPP
|
||||
#define __CTOOL_OPENMP_HPP
|
||||
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
|
||||
namespace CosmoTool {
|
||||
|
||||
static int smp_get_max_threads() {
|
||||
#ifdef _OPENMP
|
||||
return omp_get_max_threads();
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int smp_get_thread_id() {
|
||||
#ifdef _OPENMP
|
||||
return omp_get_thread_num();
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int smp_get_num_threads() {
|
||||
#ifdef _OPENMP
|
||||
return omp_get_num_threads();
|
||||
#else
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static void smp_set_nested(bool n) {
|
||||
#ifdef _OPENMP
|
||||
omp_set_nested(n ? 1 : 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
32
external/cosmotool/src/symbol_visible.hpp
vendored
Normal file
32
external/cosmotool/src/symbol_visible.hpp
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef __COSMOTOOL_SYMBOL_VISIBLE_HPP
|
||||
#define __COSMOTOOL_SYMBOL_VISIBLE_HPP
|
||||
|
||||
|
||||
#if defined _WIN32 || defined __CYGWIN__
|
||||
#ifdef BUILDING_DLL
|
||||
#ifdef __GNUC__
|
||||
#define CTOOL_DLL_PUBLIC __attribute__ ((dllexport))
|
||||
#else
|
||||
#define CTOOL_DLL_PUBLIC __declspec(dllexport) // Note: actually gcc seems to also supports this syntax.
|
||||
#endif
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define CTOOL_DLL_PUBLIC __attribute__ ((dllimport))
|
||||
#else
|
||||
#define CTOOL_DLL_PUBLIC __declspec(dllimport) // Note: actually gcc seems to also supports this syntax.
|
||||
#endif
|
||||
#endif
|
||||
#define CTOOL_DLL_LOCAL
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define CTOOL_DLL_PUBLIC __attribute__ ((visibility ("default")))
|
||||
#define CTOOL_DLL_LOCAL __attribute__ ((visibility ("hidden")))
|
||||
#else
|
||||
#define CTOOL_DLL_PUBLIC
|
||||
#define CTOOL_DLL_LOCAL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#endif
|
313
external/cosmotool/src/tf_fit.hpp
vendored
Normal file
313
external/cosmotool/src/tf_fit.hpp
vendored
Normal file
|
@ -0,0 +1,313 @@
|
|||
/* The following routines implement all of the fitting formulae in
|
||||
Eisenstein \& Hu (1997) */
|
||||
|
||||
/* There are two sets of routines here. The first set,
|
||||
|
||||
TFfit_hmpc(), TFset_parameters(), and TFfit_onek(),
|
||||
|
||||
calculate the transfer function for an arbitrary CDM+baryon universe using
|
||||
the fitting formula in Section 3 of the paper. The second set,
|
||||
|
||||
TFsound_horizon_fit(), TFk_peak(), TFnowiggles(), and TFzerobaryon(),
|
||||
|
||||
calculate other quantities given in Section 4 of the paper. */
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* ------------------------ DRIVER ROUTINE --------------------------- */
|
||||
/* The following is an example of a driver routine you might use. */
|
||||
/* Basically, the driver routine needs to call TFset_parameters() to
|
||||
set all the scalar parameters, and then call TFfit_onek() for each
|
||||
wavenumber k you desire. */
|
||||
|
||||
/* While the routines use Mpc^-1 units internally, this driver has been
|
||||
written to take an array of wavenumbers in units of h Mpc^-1. On the
|
||||
other hand, if you want to use Mpc^-1 externally, you can do this by
|
||||
altering the variables you pass to the driver:
|
||||
omega0 -> omega0*hubble*hubble, hubble -> 1.0 */
|
||||
|
||||
/* INPUT: omega0 -- the matter density (baryons+CDM) in units of critical
|
||||
f_baryon -- the ratio of baryon density to matter density
|
||||
hubble -- the Hubble constant, in units of 100 km/s/Mpc
|
||||
Tcmb -- the CMB temperature in Kelvin. T<=0 uses the COBE value 2.728.
|
||||
numk -- the length of the following zero-offset array
|
||||
k[] -- the array of wavevectors k[0..numk-1] */
|
||||
|
||||
/* INPUT/OUTPUT: There are three output arrays of transfer functions.
|
||||
All are zero-offset and, if used, must have storage [0..numk-1] declared
|
||||
in the calling program. However, if you substitute the NULL pointer for
|
||||
one or more of the arrays, then that particular transfer function won't
|
||||
be outputted. The transfer functions are:
|
||||
|
||||
tf_full[] -- The full fitting formula, eq. (16), for the matter
|
||||
transfer function.
|
||||
tf_baryon[] -- The baryonic piece of the full fitting formula, eq. 21.
|
||||
tf_cdm[] -- The CDM piece of the full fitting formula, eq. 17. */
|
||||
|
||||
/* Again, you can set these pointers to NULL in the function call if
|
||||
you don't want a particular output. */
|
||||
|
||||
/* Various intermediate scalar quantities are stored in global variables,
|
||||
so that you might more easily access them. However, this also means that
|
||||
you would be better off not simply #include'ing this file in your programs,
|
||||
but rather compiling it separately, calling only the driver, and using
|
||||
extern declarations to access the intermediate quantities. */
|
||||
|
||||
/* ------------------------ FITTING FORMULAE ROUTINES ----------------- */
|
||||
|
||||
/* There are two routines here. TFset_parameters() sets all the scalar
|
||||
parameters, while TFfit_onek() calculates the transfer function for a
|
||||
given wavenumber k. TFfit_onek() may be called many times after a single
|
||||
call to TFset_parameters() */
|
||||
|
||||
/* Global variables -- We've left many of the intermediate results as
|
||||
global variables in case you wish to access them, e.g. by declaring
|
||||
them as extern variables in your main program. */
|
||||
/* Note that all internal scales are in Mpc, without any Hubble constants! */
|
||||
|
||||
namespace CosmoTool {
|
||||
struct TF_Transfer {
|
||||
|
||||
float omhh, /* Omega_matter*h^2 */
|
||||
obhh, /* Omega_baryon*h^2 */
|
||||
theta_cmb, /* Tcmb in units of 2.7 K */
|
||||
z_equality, /* Redshift of matter-radiation equality, really 1+z */
|
||||
k_equality, /* Scale of equality, in Mpc^-1 */
|
||||
z_drag, /* Redshift of drag epoch */
|
||||
R_drag, /* Photon-baryon ratio at drag epoch */
|
||||
R_equality, /* Photon-baryon ratio at equality epoch */
|
||||
sound_horizon, /* Sound horizon at drag epoch, in Mpc */
|
||||
k_silk, /* Silk damping scale, in Mpc^-1 */
|
||||
alpha_c, /* CDM suppression */
|
||||
beta_c, /* CDM log shift */
|
||||
alpha_b, /* Baryon suppression */
|
||||
beta_b, /* Baryon envelope shift */
|
||||
beta_node, /* Sound horizon shift */
|
||||
k_peak, /* Fit to wavenumber of first peak, in Mpc^-1 */
|
||||
sound_horizon_fit, /* Fit to sound horizon, in Mpc */
|
||||
alpha_gamma; /* Gamma suppression in approximate TF */
|
||||
|
||||
/* Convenience from Numerical Recipes in C, 2nd edition */
|
||||
float sqrarg;
|
||||
#define SQR(a) ((sqrarg=(a)) == 0.0 ? 0.0 : sqrarg*sqrarg)
|
||||
float cubearg;
|
||||
#define CUBE(a) ((cubearg=(a)) == 0.0 ? 0.0 : cubearg*cubearg*cubearg)
|
||||
float pow4arg;
|
||||
#define POW4(a) ((pow4arg=(a)) == 0.0 ? 0.0 : pow4arg*pow4arg*pow4arg*pow4arg)
|
||||
/* Yes, I know the last one isn't optimal; it doesn't appear much */
|
||||
|
||||
void TFset_parameters(float omega0hh, float f_baryon, float Tcmb)
|
||||
/* Set all the scalars quantities for Eisenstein & Hu 1997 fitting formula */
|
||||
/* Input: omega0hh -- The density of CDM and baryons, in units of critical dens,
|
||||
multiplied by the square of the Hubble constant, in units
|
||||
of 100 km/s/Mpc */
|
||||
/* f_baryon -- The fraction of baryons to CDM */
|
||||
/* Tcmb -- The temperature of the CMB in Kelvin. Tcmb<=0 forces use
|
||||
of the COBE value of 2.728 K. */
|
||||
/* Output: Nothing, but set many global variables used in TFfit_onek().
|
||||
You can access them yourself, if you want. */
|
||||
/* Note: Units are always Mpc, never h^-1 Mpc. */
|
||||
{
|
||||
float z_drag_b1, z_drag_b2;
|
||||
float alpha_c_a1, alpha_c_a2, beta_c_b1, beta_c_b2, alpha_b_G, y;
|
||||
|
||||
if (f_baryon<=0.0 || omega0hh<=0.0) {
|
||||
fprintf(stderr, "TFset_parameters(): Illegal input.\n");
|
||||
exit(1);
|
||||
}
|
||||
omhh = omega0hh;
|
||||
obhh = omhh*f_baryon;
|
||||
if (Tcmb<=0.0) Tcmb=2.728; /* COBE FIRAS */
|
||||
theta_cmb = Tcmb/2.7;
|
||||
|
||||
z_equality = 2.50e4*omhh/POW4(theta_cmb); /* Really 1+z */
|
||||
k_equality = 0.0746*omhh/SQR(theta_cmb);
|
||||
|
||||
z_drag_b1 = 0.313*pow(omhh,-0.419)*(1+0.607*pow(omhh,0.674));
|
||||
z_drag_b2 = 0.238*pow(omhh,0.223);
|
||||
z_drag = 1291*pow(omhh,0.251)/(1+0.659*pow(omhh,0.828))*
|
||||
(1+z_drag_b1*pow(obhh,z_drag_b2));
|
||||
|
||||
R_drag = 31.5*obhh/POW4(theta_cmb)*(1000/(1+z_drag));
|
||||
R_equality = 31.5*obhh/POW4(theta_cmb)*(1000/z_equality);
|
||||
|
||||
sound_horizon = 2./3./k_equality*sqrt(6./R_equality)*
|
||||
log((sqrt(1+R_drag)+sqrt(R_drag+R_equality))/(1+sqrt(R_equality)));
|
||||
|
||||
k_silk = 1.6*pow(obhh,0.52)*pow(omhh,0.73)*(1+pow(10.4*omhh,-0.95));
|
||||
|
||||
alpha_c_a1 = pow(46.9*omhh,0.670)*(1+pow(32.1*omhh,-0.532));
|
||||
alpha_c_a2 = pow(12.0*omhh,0.424)*(1+pow(45.0*omhh,-0.582));
|
||||
alpha_c = pow(alpha_c_a1,-f_baryon)*
|
||||
pow(alpha_c_a2,-CUBE(f_baryon));
|
||||
|
||||
beta_c_b1 = 0.944/(1+pow(458*omhh,-0.708));
|
||||
beta_c_b2 = pow(0.395*omhh, -0.0266);
|
||||
beta_c = 1.0/(1+beta_c_b1*(pow(1-f_baryon, beta_c_b2)-1));
|
||||
|
||||
y = z_equality/(1+z_drag);
|
||||
alpha_b_G = y*(-6.*sqrt(1+y)+(2.+3.*y)*log((sqrt(1+y)+1)/(sqrt(1+y)-1)));
|
||||
alpha_b = 2.07*k_equality*sound_horizon*pow(1+R_drag,-0.75)*alpha_b_G;
|
||||
|
||||
beta_node = 8.41*pow(omhh, 0.435);
|
||||
beta_b = 0.5+f_baryon+(3.-2.*f_baryon)*sqrt(pow(17.2*omhh,2.0)+1);
|
||||
|
||||
k_peak = 2.5*3.14159*(1+0.217*omhh)/sound_horizon;
|
||||
sound_horizon_fit = 44.5*log(9.83/omhh)/sqrt(1+10.0*pow(obhh,0.75));
|
||||
|
||||
alpha_gamma = 1-0.328*log(431.0*omhh)*f_baryon + 0.38*log(22.3*omhh)*
|
||||
SQR(f_baryon);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
float TFfit_onek(float k, float *tf_baryon, float *tf_cdm)
|
||||
/* Input: k -- Wavenumber at which to calculate transfer function, in Mpc^-1.
|
||||
*tf_baryon, *tf_cdm -- Input value not used; replaced on output if
|
||||
the input was not NULL. */
|
||||
/* Output: Returns the value of the full transfer function fitting formula.
|
||||
This is the form given in Section 3 of Eisenstein & Hu (1997).
|
||||
*tf_baryon -- The baryonic contribution to the full fit.
|
||||
*tf_cdm -- The CDM contribution to the full fit. */
|
||||
/* Notes: Units are Mpc, not h^-1 Mpc. */
|
||||
{
|
||||
float T_c_ln_beta, T_c_ln_nobeta, T_c_C_alpha, T_c_C_noalpha;
|
||||
float q, xx, xx_tilde, q_eff;
|
||||
float T_c_f, T_c, s_tilde, T_b_T0, T_b, f_baryon, T_full;
|
||||
float T_0_L0, T_0_C0, T_0, gamma_eff;
|
||||
float T_nowiggles_L0, T_nowiggles_C0, T_nowiggles;
|
||||
|
||||
k = fabs(k); /* Just define negative k as positive */
|
||||
if (k==0.0) {
|
||||
if (tf_baryon!=NULL) *tf_baryon = 1.0;
|
||||
if (tf_cdm!=NULL) *tf_cdm = 1.0;
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
q = k/13.41/k_equality;
|
||||
xx = k*sound_horizon;
|
||||
|
||||
T_c_ln_beta = log(2.718282+1.8*beta_c*q);
|
||||
T_c_ln_nobeta = log(2.718282+1.8*q);
|
||||
T_c_C_alpha = 14.2/alpha_c + 386.0/(1+69.9*pow(q,1.08));
|
||||
T_c_C_noalpha = 14.2 + 386.0/(1+69.9*pow(q,1.08));
|
||||
|
||||
T_c_f = 1.0/(1.0+POW4(xx/5.4));
|
||||
T_c = T_c_f*T_c_ln_beta/(T_c_ln_beta+T_c_C_noalpha*SQR(q)) +
|
||||
(1-T_c_f)*T_c_ln_beta/(T_c_ln_beta+T_c_C_alpha*SQR(q));
|
||||
|
||||
s_tilde = sound_horizon*pow(1+CUBE(beta_node/xx),-1./3.);
|
||||
xx_tilde = k*s_tilde;
|
||||
|
||||
T_b_T0 = T_c_ln_nobeta/(T_c_ln_nobeta+T_c_C_noalpha*SQR(q));
|
||||
T_b = sin(xx_tilde)/(xx_tilde)*(T_b_T0/(1+SQR(xx/5.2))+
|
||||
alpha_b/(1+CUBE(beta_b/xx))*exp(-pow(k/k_silk,1.4)));
|
||||
|
||||
f_baryon = obhh/omhh;
|
||||
T_full = f_baryon*T_b + (1-f_baryon)*T_c;
|
||||
|
||||
/* Now to store these transfer functions */
|
||||
if (tf_baryon!=NULL) *tf_baryon = T_b;
|
||||
if (tf_cdm!=NULL) *tf_cdm = T_c;
|
||||
return T_full;
|
||||
}
|
||||
|
||||
/* ======================= Approximate forms =========================== */
|
||||
|
||||
float TFsound_horizon_fit(float omega0, float f_baryon, float hubble)
|
||||
/* Input: omega0 -- CDM density, in units of critical density
|
||||
f_baryon -- Baryon fraction, the ratio of baryon to CDM density.
|
||||
hubble -- Hubble constant, in units of 100 km/s/Mpc
|
||||
/* Output: The approximate value of the sound horizon, in h^-1 Mpc. */
|
||||
/* Note: If you prefer to have the answer in units of Mpc, use hubble -> 1
|
||||
and omega0 -> omega0*hubble^2. */
|
||||
{
|
||||
float omhh, sound_horizon_fit_mpc;
|
||||
omhh = omega0*hubble*hubble;
|
||||
sound_horizon_fit_mpc =
|
||||
44.5*log(9.83/omhh)/sqrt(1+10.0*pow(omhh*f_baryon,0.75));
|
||||
return sound_horizon_fit_mpc*hubble;
|
||||
}
|
||||
|
||||
float TFk_peak(float omega0, float f_baryon, float hubble)
|
||||
/* Input: omega0 -- CDM density, in units of critical density
|
||||
f_baryon -- Baryon fraction, the ratio of baryon to CDM density.
|
||||
hubble -- Hubble constant, in units of 100 km/s/Mpc
|
||||
/* Output: The approximate location of the first baryonic peak, in h Mpc^-1 */
|
||||
/* Note: If you prefer to have the answer in units of Mpc^-1, use hubble -> 1
|
||||
and omega0 -> omega0*hubble^2. */
|
||||
{
|
||||
float omhh, k_peak_mpc;
|
||||
omhh = omega0*hubble*hubble;
|
||||
k_peak_mpc = 2.5*3.14159*(1+0.217*omhh)/TFsound_horizon_fit(omhh,f_baryon,1.0);
|
||||
return k_peak_mpc/hubble;
|
||||
}
|
||||
|
||||
float TFnowiggles(float omega0, float f_baryon, float hubble,
|
||||
float Tcmb, float k_hmpc)
|
||||
/* Input: omega0 -- CDM density, in units of critical density
|
||||
f_baryon -- Baryon fraction, the ratio of baryon to CDM density.
|
||||
hubble -- Hubble constant, in units of 100 km/s/Mpc
|
||||
Tcmb -- Temperature of the CMB in Kelvin; Tcmb<=0 forces use of
|
||||
COBE FIRAS value of 2.728 K
|
||||
k_hmpc -- Wavenumber in units of (h Mpc^-1). */
|
||||
/* Output: The value of an approximate transfer function that captures the
|
||||
non-oscillatory part of a partial baryon transfer function. In other words,
|
||||
the baryon oscillations are left out, but the suppression of power below
|
||||
the sound horizon is included. See equations (30) and (31). */
|
||||
/* Note: If you prefer to use wavenumbers in units of Mpc^-1, use hubble -> 1
|
||||
and omega0 -> omega0*hubble^2. */
|
||||
{
|
||||
float k, omhh, theta_cmb, k_equality, q, xx, alpha_gamma, gamma_eff;
|
||||
float q_eff, T_nowiggles_L0, T_nowiggles_C0;
|
||||
|
||||
k = k_hmpc*hubble; /* Convert to Mpc^-1 */
|
||||
omhh = omega0*hubble*hubble;
|
||||
if (Tcmb<=0.0) Tcmb=2.728; /* COBE FIRAS */
|
||||
theta_cmb = Tcmb/2.7;
|
||||
|
||||
k_equality = 0.0746*omhh/SQR(theta_cmb);
|
||||
q = k/13.41/k_equality;
|
||||
xx = k*TFsound_horizon_fit(omhh, f_baryon, 1.0);
|
||||
|
||||
alpha_gamma = 1-0.328*log(431.0*omhh)*f_baryon + 0.38*log(22.3*omhh)*
|
||||
SQR(f_baryon);
|
||||
gamma_eff = omhh*(alpha_gamma+(1-alpha_gamma)/(1+POW4(0.43*xx)));
|
||||
q_eff = q*omhh/gamma_eff;
|
||||
|
||||
T_nowiggles_L0 = log(2.0*2.718282+1.8*q_eff);
|
||||
T_nowiggles_C0 = 14.2 + 731.0/(1+62.5*q_eff);
|
||||
return T_nowiggles_L0/(T_nowiggles_L0+T_nowiggles_C0*SQR(q_eff));
|
||||
}
|
||||
|
||||
/* ======================= Zero Baryon Formula =========================== */
|
||||
|
||||
float TFzerobaryon(float omega0, float hubble, float Tcmb, float k_hmpc)
|
||||
/* Input: omega0 -- CDM density, in units of critical density
|
||||
hubble -- Hubble constant, in units of 100 km/s/Mpc
|
||||
Tcmb -- Temperature of the CMB in Kelvin; Tcmb<=0 forces use of
|
||||
COBE FIRAS value of 2.728 K
|
||||
k_hmpc -- Wavenumber in units of (h Mpc^-1). */
|
||||
/* Output: The value of the transfer function for a zero-baryon universe. */
|
||||
/* Note: If you prefer to use wavenumbers in units of Mpc^-1, use hubble -> 1
|
||||
and omega0 -> omega0*hubble^2. */
|
||||
{
|
||||
float k, omhh, theta_cmb, k_equality, q, T_0_L0, T_0_C0;
|
||||
|
||||
k = k_hmpc*hubble; /* Convert to Mpc^-1 */
|
||||
omhh = omega0*hubble*hubble;
|
||||
if (Tcmb<=0.0) Tcmb=2.728; /* COBE FIRAS */
|
||||
theta_cmb = Tcmb/2.7;
|
||||
|
||||
k_equality = 0.0746*omhh/SQR(theta_cmb);
|
||||
q = k/13.41/k_equality;
|
||||
|
||||
T_0_L0 = log(2.0*2.718282+1.8*q);
|
||||
T_0_C0 = 14.2 + 731.0/(1+62.5*q);
|
||||
return T_0_L0/(T_0_L0+T_0_C0*q*q);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue