mirror of
https://github.com/cosmo-sims/monofonIC.git
synced 2024-09-19 17:03:45 +02:00
commit
da12cb1cb9
41 changed files with 1663 additions and 1776 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
|||
[submodule "external/class"]
|
||||
path = external/class
|
||||
url = https://github.com/ohahn/class_public.git
|
|
@ -15,9 +15,8 @@
|
|||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
cmake_minimum_required(VERSION 3.9)
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
set(PRGNAME monofonIC)
|
||||
|
||||
project(monofonIC C CXX)
|
||||
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -march=native -Wall -fno-omit-frame-pointer -g -fsanitize=address")
|
||||
|
@ -32,8 +31,7 @@ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}" CACHE STRING "Flags used by t
|
|||
set(CMAKE_C_FLAGS_DEBUGSANADD "${CMAKE_CXX_FLAGS_DEBUGSANADD}" CACHE STRING "Flags used by the compiler during Debug builds with Sanitizer for address." FORCE)
|
||||
set(CMAKE_C_FLAGS_DEBUGSANUNDEF "${CMAKE_CXX_FLAGS_DEBUGSANUNDEF}" CACHE STRING "Flags used by the compiler during Debug builds with Sanitizer for undefineds." FORCE)
|
||||
|
||||
|
||||
set(default_build_type "Release")
|
||||
set(default_build_type "RelWithDebInfo")
|
||||
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
|
||||
|
@ -47,12 +45,7 @@ mark_as_advanced(CMAKE_C_FLAGS_DEBUGSANADD CMAKE_C_FLAGS_DEBUGSANUNDEF)
|
|||
mark_as_advanced(CMAKE_EXECUTABLE_FORMAT CMAKE_OSX_ARCHITECTURES CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT)
|
||||
|
||||
|
||||
########################################################################################################################
|
||||
# include class submodule
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/external/class.cmake)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${PROJECT_SOURCE_DIR}")
|
||||
|
||||
|
||||
|
@ -187,7 +180,7 @@ configure_file(
|
|||
)
|
||||
|
||||
add_executable(${PRGNAME} ${SOURCES} ${PLUGINS})
|
||||
target_setup_class(${PRGNAME})
|
||||
# target_setup_class(${PRGNAME})
|
||||
|
||||
set_target_properties(${PRGNAME} PROPERTIES CXX_STANDARD 14)
|
||||
|
||||
|
@ -259,7 +252,19 @@ endif(ENABLE_PLT)
|
|||
|
||||
target_link_libraries(${PRGNAME} PRIVATE GSL::gsl)
|
||||
|
||||
# GenericIO
|
||||
|
||||
########################################################################################################################
|
||||
# include CLASS
|
||||
option(ENABLE_CLASS "Enable CLASS support (as a submodule)." ON)
|
||||
|
||||
if(ENABLE_CLASS)
|
||||
include(${CMAKE_CURRENT_SOURCE_DIR}/external/class.cmake)
|
||||
target_link_libraries(${PRGNAME} PRIVATE class::libclass_cpp)
|
||||
target_compile_definitions(${PRGNAME} PRIVATE "USE_CLASS")
|
||||
endif()
|
||||
|
||||
########################################################################################################################
|
||||
# include GenericIO (only if MPI available)
|
||||
include(CMakeDependentOption)
|
||||
cmake_dependent_option(ENABLE_GENERICIO "Enable GenericIO (HACC) output support" off "ENABLE_MPI;MPI_CXX_FOUND" off)
|
||||
|
||||
|
|
40
example.conf
40
example.conf
|
@ -14,6 +14,7 @@ zstart = 24.0 # starting redshift
|
|||
LPTorder = 3 # order of the LPT to be used (1,2 or 3)
|
||||
|
||||
DoBaryons = no # also do baryon ICs?
|
||||
DoBaryonVrel = no # if doing baryons, incl. also relative velocity to linear order?
|
||||
|
||||
DoFixing = yes # do mode fixing à la Angulo&Pontzen (https://arxiv.org/abs/1603.05253)
|
||||
DoInversion = no # invert phases (for paired simulations)
|
||||
|
@ -29,23 +30,30 @@ ParticleLoad = sc # particle load, can be 'sc' (1x), 'bcc' (2x) or 'fcc
|
|||
[cosmology]
|
||||
## transfer = ... specifies the Einstein-Boltzmann plugin module
|
||||
|
||||
# main cosmological parameters
|
||||
Omega_m = 0.302
|
||||
Omega_b = 0.045
|
||||
Omega_L = 0.698
|
||||
H0 = 70.3
|
||||
nspec = 0.961
|
||||
sigma_8 = 0.811
|
||||
ParameterSet = Planck2018EE+BAO+SN # specify a pre-defined parameter set, or set to 'none' and set manually below
|
||||
|
||||
## cosmological parameters, to set, choose ParameterSet = none,
|
||||
## default values (those not specified) are set to the values
|
||||
## from 'Planck2018EE+BAO+SN', we currently assume flatness
|
||||
# Omega_m = 0.3158
|
||||
# Omega_b = 0.0494
|
||||
# Omega_L = 0.6842
|
||||
# H0 = 67.321
|
||||
# n_s = 0.9661
|
||||
# sigma_8 = 0.8102
|
||||
# A_s = 2.148752e-09 # can use A_s instead of sigma_8 when using CLASS
|
||||
# Tcmb = 2.7255
|
||||
# k_p = 0.05
|
||||
# N_ur = 2.046
|
||||
# m_nu1 = 0.06
|
||||
# m_nu2 = 0.0
|
||||
# m_nu3 = 0.0
|
||||
# w_0 = -1.0 # not supported yet!
|
||||
# w_a = 0.0 # not supported yet!
|
||||
|
||||
ZeroRadiation = false # For Back-scaling only: set to true if your simulation code
|
||||
# cannot deal with Omega_r!=0 in its background FLRW model
|
||||
|
||||
## Additional cosmological parameters (set by default to the given values)
|
||||
# w0 = -1.0 # not supported yet!
|
||||
# wa = 0.0 # not supported yet!
|
||||
# Tcmb = 2.7255
|
||||
# Neff = 3.046
|
||||
|
||||
## Use below for anisotropic large scale tidal field ICs up to 2LPT
|
||||
## see Stuecker+2020 (https://arxiv.org/abs/2003.06427)
|
||||
# LSS_aniso_lx = +0.1
|
||||
|
@ -72,7 +80,6 @@ ZeroRadiation = false # For Back-scaling only: set to true if your simulation
|
|||
|
||||
transfer = CLASS
|
||||
ztarget = 2.5 # target redshift for CLASS module, output at ztarget will be back-scaled to zstart
|
||||
# A_s = 2.148752e-09 # can use A_s instead of sigma_8 when using CLASS
|
||||
|
||||
|
||||
#########################################################################################
|
||||
|
@ -136,8 +143,11 @@ NumThreads = 8
|
|||
# format = genericio
|
||||
# filename = ics_hacc
|
||||
|
||||
##> SWIFT compatible HDF5 format
|
||||
# format = SWIFT
|
||||
# filename = ics_swift.hdf5
|
||||
|
||||
##> Generic HDF5 output format for testing or PT-based calculations
|
||||
# format = generic
|
||||
# filename = debug.hdf5
|
||||
# generic_out_eulerian = yes # if yes then uses PPT for output
|
||||
|
||||
|
|
1
external/class
vendored
1
external/class
vendored
|
@ -1 +0,0 @@
|
|||
Subproject commit 414e89597d6eb93f713bad33c63aa62348f02e62
|
156
external/class.cmake
vendored
156
external/class.cmake
vendored
|
@ -1,141 +1,17 @@
|
|||
option(ENABLE_CLASS "Enable CLASS support (as a submodule)." ON)
|
||||
cmake_minimum_required(VERSION 3.11)
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
class
|
||||
GIT_REPOSITORY https://github.com/ohahn/class_public.git
|
||||
GIT_TAG master
|
||||
GIT_SHALLOW YES
|
||||
GIT_PROGRESS TRUE
|
||||
USES_TERMINAL_DOWNLOAD TRUE # <---- this is needed only for Ninja
|
||||
)
|
||||
|
||||
if(ENABLE_CLASS)
|
||||
|
||||
# initialize the class submodule if necessary
|
||||
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/class/Makefile")
|
||||
message(STATUS "class submodule is initialized.")
|
||||
else()
|
||||
message(STATUS "class submodule is NOT initialized: executing git command")
|
||||
execute_process(COMMAND git submodule update --init -- external/class
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endif()
|
||||
|
||||
# include directories
|
||||
set(CLASS_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/class/include)
|
||||
set(CLASS_INCLUDE_CPP_DIR ${CMAKE_CURRENT_LIST_DIR}/class/cpp)
|
||||
|
||||
# build method for class
|
||||
option(USE_CLASS_MAKEFILE "Build CLASS using its own Makefile." OFF)
|
||||
|
||||
if(USE_CLASS_MAKEFILE)
|
||||
# list of object files generated by class
|
||||
set(CLASS_OBJECT_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/arrays.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/background.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/common.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/dei_rkck.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/evolver_ndf15.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/evolver_rkck.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/growTable.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/helium.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/history.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/hydrogen.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/hyperspherical.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/trigonometric_integrals.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/hyrectools.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/input.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/lensing.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/nonlinear.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/output.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/parser.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/perturbations.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/primordial.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/quadrature.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/sparse.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/spectra.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/thermodynamics.o
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/build/transfer.o
|
||||
)
|
||||
|
||||
# python3
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
|
||||
# command to build class using its own makefile
|
||||
add_custom_command(OUTPUT ${CLASS_OBJECT_FILES}
|
||||
COMMAND PYTHON=${Python3_EXECUTABLE} CC=${CMAKE_C_COMPILER} make
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/class
|
||||
)
|
||||
|
||||
# target for class objects
|
||||
add_custom_target(class_objects DEPENDS ${CLASS_OBJECT_FILES})
|
||||
|
||||
# library for class cpp wrappers
|
||||
add_library(class_cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/cpp/Engine.cc
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/cpp/ClassEngine.cc)
|
||||
target_include_directories(class_cpp
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/class/include)
|
||||
else(USE_CLASS_MAKEFILE)
|
||||
|
||||
# list of CLASS source files
|
||||
set(CLASS_SOURCE_FILES
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/growTable.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/dei_rkck.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/sparse.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/evolver_rkck.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/evolver_ndf15.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/arrays.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/parser.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/quadrature.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/hyperspherical.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/trigonometric_integrals.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/tools/common.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/input.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/background.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/thermodynamics.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/perturbations.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/primordial.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/nonlinear.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/transfer.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/spectra.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/lensing.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/hyrec/hyrectools.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/hyrec/helium.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/hyrec/hydrogen.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/hyrec/history.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/source/output.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/cpp/Engine.cc
|
||||
${CMAKE_CURRENT_LIST_DIR}/class/cpp/ClassEngine.cc
|
||||
)
|
||||
|
||||
# create the library
|
||||
add_library(class ${CLASS_SOURCE_FILES})
|
||||
target_include_directories(class PRIVATE ${CLASS_INCLUDE_DIR})
|
||||
target_include_directories(class PRIVATE ${CLASS_INCLUDE_CPP_DIR})
|
||||
target_compile_options(class PRIVATE "-ffast-math")
|
||||
target_compile_definitions(class PRIVATE "__CLASSDIR__=\"${CMAKE_CURRENT_LIST_DIR}/class\"")
|
||||
set_property(TARGET class PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
target_include_directories(class PRIVATE ${CMAKE_CURRENT_LIST_DIR}/class/hyrec)
|
||||
target_compile_definitions(class PRIVATE "HYREC")
|
||||
set_target_properties(class PROPERTIES CXX_STANDARD 14 C_STANDARD 11)
|
||||
# target_compile_options(class PRIVATE "-Wall")
|
||||
# target_compile_options(class PRIVATE "-Wextra")
|
||||
# target_compile_options(class PRIVATE "-pedantic")
|
||||
endif(USE_CLASS_MAKEFILE)
|
||||
endif(ENABLE_CLASS)
|
||||
|
||||
# macro to setup include dir and link libraries for target using class
|
||||
macro(target_setup_class target_name)
|
||||
if(ENABLE_CLASS)
|
||||
target_include_directories(${target_name}
|
||||
PRIVATE ${CLASS_INCLUDE_DIR})
|
||||
target_include_directories(${target_name}
|
||||
PRIVATE ${CLASS_INCLUDE_CPP_DIR})
|
||||
if(USE_CLASS_MAKEFILE)
|
||||
target_link_libraries(${target_name} ${CLASS_OBJECT_FILES})
|
||||
target_link_libraries(${target_name} class_cpp)
|
||||
add_dependencies(${target_name} class_objects)
|
||||
else(USE_CLASS_MAKEFILE)
|
||||
target_link_libraries(${target_name} PRIVATE class)
|
||||
endif(USE_CLASS_MAKEFILE)
|
||||
target_compile_definitions(${target_name} PRIVATE "USE_CLASS")
|
||||
endif(ENABLE_CLASS)
|
||||
endmacro(target_setup_class)
|
||||
|
||||
# if(ENABLE_CLASS)
|
||||
# # test executable
|
||||
# add_executable(testTk
|
||||
# ${CMAKE_CURRENT_LIST_DIR}/class/cpp/testTk.cc)
|
||||
# target_setup_class(testTk)
|
||||
# endif(ENABLE_CLASS)
|
||||
FetchContent_GetProperties(class)
|
||||
if(NOT class_POPULATED)
|
||||
set(FETCHCONTENT_QUIET OFF)
|
||||
FetchContent_Populate(class)
|
||||
add_subdirectory(${class_SOURCE_DIR} ${class_BINARY_DIR})
|
||||
endif()
|
||||
|
|
4
external/genericio.cmake
vendored
4
external/genericio.cmake
vendored
|
@ -4,10 +4,14 @@ FetchContent_Declare(
|
|||
genericio
|
||||
GIT_REPOSITORY https://xgitlab.cels.anl.gov/hacc/genericio.git
|
||||
GIT_TAG master
|
||||
GIT_SHALLOW YES
|
||||
GIT_PROGRESS TRUE
|
||||
USES_TERMINAL_DOWNLOAD TRUE # <---- this is needed only for Ninja
|
||||
)
|
||||
|
||||
FetchContent_GetProperties(genericio)
|
||||
if(NOT genericio_POPULATED)
|
||||
set(FETCHCONTENT_QUIET OFF)
|
||||
FetchContent_Populate(genericio)
|
||||
add_subdirectory(${genericio_SOURCE_DIR} ${genericio_BINARY_DIR})
|
||||
endif()
|
||||
|
|
|
@ -427,19 +427,18 @@ public:
|
|||
// }
|
||||
|
||||
private:
|
||||
template <typename kdep_functor>
|
||||
void pad_insert(kdep_functor kfunc, Grid_FFT<data_t> &fp)
|
||||
{
|
||||
assert(fp.space_ == kspace_id);
|
||||
|
||||
template <typename kdep_functor>
|
||||
void pad_insert( kdep_functor kfunc, Grid_FFT<data_t> &fp)
|
||||
{
|
||||
const real_t rfac = std::pow(1.5, 1.5);
|
||||
|
||||
#if !defined(USE_MPI)
|
||||
const size_t nhalf[3] = {fp.n_[0] / 3, fp.n_[1] / 3, fp.n_[2] / 3};
|
||||
|
||||
fp.zero();
|
||||
|
||||
#if !defined(USE_MPI) ////////////////////////////////////////////////////////////////////////////////////
|
||||
const size_t nhalf[3] = {fp.n_[0] / 3, fp.n_[1] / 3, fp.n_[2] / 3};
|
||||
|
||||
#pragma omp parallel for
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < 2 * fp.size(0) / 3; ++i)
|
||||
{
|
||||
size_t ip = (i > nhalf[0]) ? i + nhalf[0] : i;
|
||||
|
@ -453,37 +452,10 @@ private:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /// then USE_MPI is defined ////////////////////////////////////////////////////////////
|
||||
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
#else
|
||||
fbuf_->FourierTransformForward(false);
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
double tstart = get_wtime();
|
||||
music::dlog << "[MPI] Started scatter for convolution" << std::endl;
|
||||
|
||||
//... collect offsets
|
||||
|
||||
assert(fbuf_->space_ == kspace_id);
|
||||
|
||||
size_t nf[3] = {fbuf_->size(0), fbuf_->size(1), fbuf_->size(2)};
|
||||
size_t nfp[3] = {fp.size(0), fp.size(1), fp.size(2)};
|
||||
size_t fny[3] = {fbuf_->n_[1] / 2, fbuf_->n_[0] / 2, fbuf_->n_[2] / 2};
|
||||
|
||||
//... local size must be divisible by 2, otherwise this gets too complicated
|
||||
assert(fbuf_->n_[1] % 2 == 0);
|
||||
size_t slicesz = fbuf_->size(1) * fbuf_->size(3);
|
||||
|
||||
MPI_Datatype datatype =
|
||||
(typeid(data_t) == typeid(float)) ? MPI_C_FLOAT_COMPLEX
|
||||
: (typeid(data_t) == typeid(double)) ? MPI_C_DOUBLE_COMPLEX
|
||||
: (typeid(data_t) == typeid(long double)) ? MPI_C_LONG_DOUBLE_COMPLEX
|
||||
: MPI_BYTE;
|
||||
|
||||
// fill MPI send buffer with results of kfunc
|
||||
|
||||
#pragma omp parallel for
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < fbuf_->size(0); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < fbuf_->size(1); ++j)
|
||||
|
@ -495,125 +467,13 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
MPI_Status status;
|
||||
|
||||
std::vector<MPI_Request> req;
|
||||
MPI_Request temp_req;
|
||||
|
||||
// send data from buffer
|
||||
for (size_t i = 0; i < nf[0]; ++i)
|
||||
{
|
||||
size_t iglobal = i + offsets_[CONFIG::MPI_task_rank];
|
||||
|
||||
if (iglobal <= fny[0])
|
||||
{
|
||||
int sendto = get_task(iglobal, offsetsp_, sizesp_, CONFIG::MPI_task_size);
|
||||
MPI_Isend(&fbuf_->kelem(i * slicesz), (int)slicesz, datatype, sendto,
|
||||
(int)iglobal, MPI_COMM_WORLD, &temp_req);
|
||||
req.push_back(temp_req);
|
||||
// std::cout << "task " << CONFIG::MPI_task_rank << " : added request No" << req.size()-1 << ": Isend #" << iglobal << " to task " << sendto << ", size = " << slicesz << std::endl;
|
||||
}
|
||||
if (iglobal >= fny[0])
|
||||
{
|
||||
int sendto = get_task(iglobal + fny[0], offsetsp_, sizesp_, CONFIG::MPI_task_size);
|
||||
MPI_Isend(&fbuf_->kelem(i * slicesz), (int)slicesz, datatype, sendto,
|
||||
(int)(iglobal + fny[0]), MPI_COMM_WORLD, &temp_req);
|
||||
req.push_back(temp_req);
|
||||
// std::cout << "task " << CONFIG::MPI_task_rank << " : added request No" << req.size()-1 << ": Isend #" << iglobal+fny[0] << " to task " << sendto << ", size = " << slicesz<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < nfp[0]; ++i)
|
||||
{
|
||||
size_t iglobal = i + offsetsp_[CONFIG::MPI_task_rank];
|
||||
|
||||
if (iglobal <= fny[0] || iglobal >= 2 * fny[0])
|
||||
{
|
||||
int recvfrom = 0;
|
||||
if (iglobal <= fny[0])
|
||||
recvfrom = get_task(iglobal, offsets_, sizes_, CONFIG::MPI_task_size);
|
||||
else
|
||||
recvfrom = get_task(iglobal - fny[0], offsets_, sizes_, CONFIG::MPI_task_size);
|
||||
|
||||
// std::cout << "task " << CONFIG::MPI_task_rank << " : receive #" << iglobal << " from task "
|
||||
// << recvfrom << ", size = " << slicesz << ", " << crecvbuf_ << ", " << datatype << std::endl;
|
||||
status.MPI_ERROR = MPI_SUCCESS;
|
||||
|
||||
MPI_Recv(&recvbuf_[0], (int)slicesz, datatype, recvfrom, (int)iglobal,
|
||||
MPI_COMM_WORLD, &status);
|
||||
// std::cout << "---> ok! " << (bool)(status.MPI_ERROR==MPI_SUCCESS) << std::endl;
|
||||
|
||||
assert(status.MPI_ERROR == MPI_SUCCESS);
|
||||
|
||||
for (size_t j = 0; j < nf[1]; ++j)
|
||||
{
|
||||
if (j <= fny[1])
|
||||
{
|
||||
size_t jp = j;
|
||||
for (size_t k = 0; k < nf[2]; ++k)
|
||||
{
|
||||
if (typeid(data_t) == typeid(real_t))
|
||||
{
|
||||
fp.kelem(i, jp, k) = crecvbuf_[j * fbuf_->sizes_[3] + k];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (k <= fny[2])
|
||||
fp.kelem(i, jp, k) = crecvbuf_[j * fbuf_->sizes_[3] + k];
|
||||
if (k >= fny[2])
|
||||
fp.kelem(i, jp, k + nf[2] / 2) = crecvbuf_[j * fbuf_->sizes_[3] + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (j >= fny[1])
|
||||
{
|
||||
size_t jp = j + fny[1];
|
||||
for (size_t k = 0; k < nf[2]; ++k)
|
||||
{
|
||||
if (typeid(data_t) == typeid(real_t))
|
||||
{
|
||||
fp.kelem(i, jp, k) = crecvbuf_[j * fbuf_->sizes_[3] + k];
|
||||
}
|
||||
else
|
||||
{
|
||||
if (k <= fny[2])
|
||||
fp.kelem(i, jp, k) = crecvbuf_[j * fbuf_->sizes_[3] + k];
|
||||
if (k >= fny[2])
|
||||
fp.kelem(i, jp, k + fny[2]) = crecvbuf_[j * fbuf_->sizes_[3] + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < req.size(); ++i)
|
||||
{
|
||||
// need to set status as wait does not necessarily modify it
|
||||
// c.f. http://www.open-mpi.org/community/lists/devel/2007/04/1402.php
|
||||
status.MPI_ERROR = MPI_SUCCESS;
|
||||
// std::cout << "task " << CONFIG::MPI_task_rank << " : checking request No" << i << std::endl;
|
||||
MPI_Wait(&req[i], &status);
|
||||
// std::cout << "---> ok!" << std::endl;
|
||||
assert(status.MPI_ERROR == MPI_SUCCESS);
|
||||
}
|
||||
|
||||
// usleep(1000);
|
||||
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
|
||||
// std::cerr << ">>>>> task " << CONFIG::MPI_task_rank << " all transfers completed! <<<<<"
|
||||
// << std::endl; ofs << ">>>>> task " << CONFIG::MPI_task_rank << " all transfers completed!
|
||||
// <<<<<" << std::endl;
|
||||
music::dlog.Print("[MPI] Completed scatter for convolution, took %fs\n",
|
||||
get_wtime() - tstart);
|
||||
|
||||
#endif /// end of ifdef/ifndef USE_MPI ///////////////////////////////////////////////////////////////
|
||||
fbuf_->FourierInterpolateCopyTo( fp );
|
||||
|
||||
#endif //defined(USE_MPI)
|
||||
}
|
||||
|
||||
template <typename operator_t>
|
||||
void unpad(const Grid_FFT<data_t> &fp, operator_t output_op)
|
||||
void unpad( Grid_FFT<data_t> &fp, operator_t output_op)
|
||||
{
|
||||
const real_t rfac = std::sqrt(fp.n_[0] * fp.n_[1] * fp.n_[2]) / std::sqrt(fbuf_->n_[0] * fbuf_->n_[1] * fbuf_->n_[2]);
|
||||
|
||||
|
@ -624,7 +484,7 @@ private:
|
|||
fbuf_->FourierTransformForward(false);
|
||||
size_t nhalf[3] = {fbuf_->n_[0] / 2, fbuf_->n_[1] / 2, fbuf_->n_[2] / 2};
|
||||
|
||||
#pragma omp parallel for
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < fbuf_->size(0); ++i)
|
||||
{
|
||||
size_t ip = (i > nhalf[0]) ? i + nhalf[0] : i;
|
||||
|
@ -643,193 +503,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
//... copy data back
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < fbuf_->ntot_; ++i)
|
||||
{
|
||||
output_op(i, (*fbuf_)[i]);
|
||||
}
|
||||
|
||||
#else /// then USE_MPI is defined //////////////////////////////////////////////////////////////
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
double tstart = get_wtime();
|
||||
|
||||
music::dlog << "[MPI] Started gather for convolution";
|
||||
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
|
||||
size_t nf[3] = {fbuf_->size(0), fbuf_->size(1), fbuf_->size(2)};
|
||||
size_t nfp[4] = {fp.size(0), fp.size(1), fp.size(2), fp.size(3)};
|
||||
size_t fny[3] = {fbuf_->n_[1] / 2, fbuf_->n_[0] / 2, fbuf_->n_[2] / 2};
|
||||
|
||||
size_t slicesz = fp.size(1) * fp.size(3);
|
||||
|
||||
MPI_Datatype datatype =
|
||||
(typeid(data_t) == typeid(float)) ? MPI_C_FLOAT_COMPLEX
|
||||
: (typeid(data_t) == typeid(double)) ? MPI_C_DOUBLE_COMPLEX
|
||||
: (typeid(data_t) == typeid(long double)) ? MPI_C_LONG_DOUBLE_COMPLEX
|
||||
: MPI_BYTE;
|
||||
|
||||
MPI_Status status;
|
||||
|
||||
//... local size must be divisible by 2, otherwise this gets too complicated
|
||||
// assert( tsize%2 == 0 );
|
||||
|
||||
std::vector<MPI_Request> req;
|
||||
MPI_Request temp_req;
|
||||
|
||||
for (size_t i = 0; i < nfp[0]; ++i)
|
||||
{
|
||||
size_t iglobal = i + offsetsp_[CONFIG::MPI_task_rank];
|
||||
|
||||
//... sending
|
||||
if (iglobal <= fny[0])
|
||||
{
|
||||
int sendto = get_task(iglobal, offsets_, sizes_, CONFIG::MPI_task_size);
|
||||
|
||||
MPI_Isend(&fp.kelem(i * slicesz), (int)slicesz, datatype, sendto, (int)iglobal,
|
||||
MPI_COMM_WORLD, &temp_req);
|
||||
req.push_back(temp_req);
|
||||
}
|
||||
else if (iglobal >= 2 * fny[0])
|
||||
{
|
||||
int sendto = get_task(iglobal - fny[0], offsets_, sizes_, CONFIG::MPI_task_size);
|
||||
MPI_Isend(&fp.kelem(i * slicesz), (int)slicesz, datatype, sendto, (int)iglobal,
|
||||
MPI_COMM_WORLD, &temp_req);
|
||||
req.push_back(temp_req);
|
||||
}
|
||||
}
|
||||
|
||||
fbuf_->zero();
|
||||
|
||||
for (size_t i = 0; i < nf[0]; ++i)
|
||||
{
|
||||
size_t iglobal = i + offsets_[CONFIG::MPI_task_rank];
|
||||
int recvfrom = 0;
|
||||
if (iglobal <= fny[0])
|
||||
{
|
||||
real_t wi = (iglobal == fny[0]) ? 0.0 : 1.0;
|
||||
|
||||
recvfrom = get_task(iglobal, offsetsp_, sizesp_, CONFIG::MPI_task_size);
|
||||
MPI_Recv(&recvbuf_[0], (int)slicesz, datatype, recvfrom, (int)iglobal,
|
||||
MPI_COMM_WORLD, &status);
|
||||
|
||||
for (size_t j = 0; j < nf[1]; ++j)
|
||||
{
|
||||
real_t wj = (j == fny[1]) ? 0.0 : 1.0;
|
||||
if (j <= fny[1])
|
||||
{
|
||||
size_t jp = j;
|
||||
for (size_t k = 0; k < nf[2]; ++k)
|
||||
{
|
||||
if (typeid(data_t) == typeid(real_t))
|
||||
{
|
||||
real_t wk = (k == fny[2]) ? 0.0 : 1.0;
|
||||
real_t w = wi * wj * wk;
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k] / rfac;
|
||||
}
|
||||
else
|
||||
{
|
||||
real_t wk = (k == fny[2]) ? 0.0 : 1.0;
|
||||
real_t w = wi * wj * wk;
|
||||
if (k < fny[2])
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k] / rfac;
|
||||
if (k > fny[2])
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k + fny[2]] / rfac;
|
||||
// if (w < 1.0)
|
||||
// {
|
||||
// fbuf_->kelem(i, j, k) = std::real(fbuf_->kelem(i, j, k));
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j >= fny[1])
|
||||
{
|
||||
size_t jp = j + fny[1];
|
||||
for (size_t k = 0; k < nf[2]; ++k)
|
||||
{
|
||||
if (typeid(data_t) == typeid(real_t))
|
||||
{
|
||||
real_t wk = (k == fny[2]) ? 0.0 : 1.0;
|
||||
real_t w = wi * wj * wk;
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k] / rfac;
|
||||
}
|
||||
else
|
||||
{
|
||||
real_t wk = (k == fny[2]) ? 0.0 : 1.0;
|
||||
real_t w = wi * wj * wk;
|
||||
if (k < fny[2])
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k] / rfac;
|
||||
if (k > fny[2])
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k + fny[2]] / rfac;
|
||||
// if (w < 1.0)
|
||||
// {
|
||||
// fbuf_->kelem(i, j, k) = std::real(fbuf_->kelem(i, j, k));
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iglobal >= fny[0])
|
||||
{
|
||||
real_t wi = (iglobal == fny[0]) ? 0.0 : 1.0;
|
||||
|
||||
recvfrom = get_task(iglobal + fny[0], offsetsp_, sizesp_, CONFIG::MPI_task_size);
|
||||
MPI_Recv(&recvbuf_[0], (int)slicesz, datatype, recvfrom,
|
||||
(int)(iglobal + fny[0]), MPI_COMM_WORLD, &status);
|
||||
|
||||
for (size_t j = 0; j < nf[1]; ++j)
|
||||
{
|
||||
real_t wj = (j == fny[1]) ? 0.0 : 1.0;
|
||||
if (j <= fny[1])
|
||||
{
|
||||
size_t jp = j;
|
||||
for (size_t k = 0; k < nf[2]; ++k)
|
||||
{
|
||||
const real_t wk = (k == fny[2]) ? 0.0 : 1.0;
|
||||
const real_t w = wi * wj * wk;
|
||||
if (typeid(data_t) == typeid(real_t))
|
||||
{
|
||||
real_t wk = (k == fny[2]) ? 0.0 : 1.0;
|
||||
real_t w = wi * wj * wk;
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k] / rfac;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (k < fny[2])
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k] / rfac;
|
||||
if (k > fny[2])
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k + fny[2]] / rfac;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (j >= fny[1])
|
||||
{
|
||||
size_t jp = j + fny[1];
|
||||
for (size_t k = 0; k < nf[2]; ++k)
|
||||
{
|
||||
const real_t wk = (k == fny[2]) ? 0.0 : 1.0;
|
||||
const real_t w = wi * wj * wk;
|
||||
if (typeid(data_t) == typeid(real_t))
|
||||
{
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k] / rfac;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (k < fny[2])
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k] / rfac;
|
||||
if (k > fny[2])
|
||||
fbuf_->kelem(i, j, k) += w * crecvbuf_[jp * nfp[3] + k + fny[2]] / rfac;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//... copy data back
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < fbuf_->ntot_; ++i)
|
||||
|
@ -837,21 +510,18 @@ private:
|
|||
output_op(i, (*fbuf_)[i]);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < req.size(); ++i)
|
||||
{
|
||||
// need to preset status as wait does not necessarily modify it to reflect
|
||||
// success c.f.
|
||||
// http://www.open-mpi.org/community/lists/devel/2007/04/1402.php
|
||||
status.MPI_ERROR = MPI_SUCCESS;
|
||||
#else /// then USE_MPI is defined //////////////////////////////////////////////////////////////
|
||||
|
||||
fp.FourierInterpolateCopyTo( *fbuf_ );
|
||||
|
||||
MPI_Wait(&req[i], &status);
|
||||
assert(status.MPI_ERROR == MPI_SUCCESS);
|
||||
//... copy data back
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < fbuf_->ntot_; ++i)
|
||||
{
|
||||
|
||||
output_op(i, (*fbuf_)[i] / rfac);
|
||||
}
|
||||
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
|
||||
music::dlog.Print("[MPI] Completed gather for convolution, took %fs", get_wtime() - tstart);
|
||||
|
||||
#endif /// end of ifdef/ifndef USE_MPI //////////////////////////////////////////////////////////////
|
||||
#endif //defined(USE_MPI)
|
||||
}
|
||||
};
|
||||
|
|
|
@ -38,7 +38,8 @@ namespace cosmology
|
|||
* @brief provides functions to compute cosmological quantities
|
||||
*
|
||||
* This class provides member functions to compute cosmological quantities
|
||||
* related to the Friedmann equations and linear perturbation theory
|
||||
* related to the Friedmann equations and linear perturbation theory, it also
|
||||
* provides the functionality to work with back-scaled cosmological fields
|
||||
*/
|
||||
class calculator
|
||||
{
|
||||
|
@ -54,34 +55,44 @@ private:
|
|||
interpolated_function_1d<true,true,false> D_of_a_, f_of_a_, a_of_D_;
|
||||
double Dnow_, Dplus_start_, Dplus_target_, astart_, atarget_;
|
||||
|
||||
double m_n_s_, m_sqrtpnorm_;
|
||||
|
||||
//! wrapper for GSL adaptive integration routine, do not use if many integrations need to be done as it allocates and deallocates memory
|
||||
//! set to 61-point Gauss-Kronrod and large workspace, used for sigma_8 normalisation
|
||||
real_t integrate(double (*func)(double x, void *params), double a, double b, void *params) const
|
||||
{
|
||||
constexpr size_t wspace_size{100000};
|
||||
|
||||
double result{0.0};
|
||||
double error{0.0};
|
||||
|
||||
gsl_function F;
|
||||
F.function = func;
|
||||
F.params = params;
|
||||
|
||||
double result;
|
||||
double error;
|
||||
|
||||
gsl_set_error_handler_off();
|
||||
gsl_integration_workspace *w = gsl_integration_workspace_alloc(100000);
|
||||
gsl_integration_qag(&F, a, b, 0, REL_PRECISION, 100000, 6, w, &result, &error);
|
||||
|
||||
gsl_integration_workspace_free(w);
|
||||
|
||||
gsl_set_error_handler(NULL);
|
||||
|
||||
auto errh = gsl_set_error_handler_off();
|
||||
gsl_integration_workspace *wspace = gsl_integration_workspace_alloc(wspace_size);
|
||||
gsl_integration_qag(&F, a, b, 0, REL_PRECISION, wspace_size, GSL_INTEG_GAUSS61, wspace, &result, &error);
|
||||
gsl_integration_workspace_free(wspace);
|
||||
gsl_set_error_handler(errh);
|
||||
|
||||
if (error / result > REL_PRECISION)
|
||||
music::wlog << "no convergence in function 'integrate', rel. error=" << error / result << std::endl;
|
||||
|
||||
return (real_t)result;
|
||||
return static_cast<real_t>(result);
|
||||
}
|
||||
|
||||
//! compute the linear theory growth factor D+ by solving the single fluid ODE, returns tables D(a), f(a)
|
||||
/*!
|
||||
* @param tab_a reference to STL vector for values of a at which table entries exist
|
||||
* @param tab_D reference to STL vector for values D(a) with a from tab_a
|
||||
* @param tab_f reference to STL vector for values f(a)=dlog D / dlog a with a from tab_a
|
||||
*/
|
||||
void compute_growth( std::vector<double>& tab_a, std::vector<double>& tab_D, std::vector<double>& tab_f )
|
||||
{
|
||||
using v_t = vec_t<3, double>;
|
||||
|
||||
// set ICs
|
||||
// set ICs, very deep in radiation domination
|
||||
const double a0 = 1e-10;
|
||||
const double D0 = a0;
|
||||
const double Dprime0 = 2.0 * D0 * H_of_a(a0) / std::pow(phys_const::c_SI, 2);
|
||||
|
@ -98,6 +109,8 @@ private:
|
|||
double t = t0;
|
||||
const double eps = 1e-10;
|
||||
|
||||
const double Omega_m( cosmo_param_["Omega_m"] ), H0( cosmo_param_["H0"] );
|
||||
|
||||
while (yy[0] < amax)
|
||||
{
|
||||
// RHS of ODEs
|
||||
|
@ -111,7 +124,7 @@ private:
|
|||
// d D/dtau
|
||||
dy[1] = Dprime;
|
||||
// d^2 D / dtau^2
|
||||
dy[2] = -a * H_of_a(a) * Dprime + 3.0 / 2.0 * cosmo_param_.Omega_m * std::pow(cosmo_param_.H0, 2) * D / a;
|
||||
dy[2] = -a * H_of_a(a) * Dprime + 3.0 / 2.0 * Omega_m * std::pow(H0, 2) * D / a;
|
||||
return dy;
|
||||
};
|
||||
|
||||
|
@ -123,7 +136,7 @@ private:
|
|||
|
||||
tab_a.push_back(yy[0]);
|
||||
tab_D.push_back(yy[1]);
|
||||
tab_f.push_back(yy[2]);
|
||||
tab_f.push_back(yy[2]); // temporarily store D' in table
|
||||
|
||||
dt = dtnext;
|
||||
}
|
||||
|
@ -138,17 +151,19 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
|
||||
calculator() = delete;
|
||||
|
||||
calculator(const calculator& c) = delete;
|
||||
|
||||
//! constructor for a cosmology calculator object
|
||||
/*!
|
||||
* @param acosmo a cosmological parameters structure
|
||||
* @param pTransferFunction pointer to an instance of a transfer function object
|
||||
*/
|
||||
|
||||
explicit calculator(config_file &cf)
|
||||
: cosmo_param_(cf), astart_( 1.0/(1.0+cf.get_value<double>("setup","zstart")) ),
|
||||
atarget_( 1.0/(1.0+cf.get_value_safe<double>("cosmology","ztarget",1./astart_-1.)))
|
||||
atarget_( 1.0/(1.0+cf.get_value_safe<double>("cosmology","ztarget",0.0)) )
|
||||
{
|
||||
// pre-compute growth factors and store for interpolation
|
||||
std::vector<double> tab_a, tab_D, tab_f;
|
||||
|
@ -158,32 +173,33 @@ public:
|
|||
a_of_D_.set_data(tab_D,tab_a);
|
||||
Dnow_ = D_of_a_(1.0);
|
||||
|
||||
Dplus_start_ = D_of_a_( astart_ ) / Dnow_;
|
||||
Dplus_start_ = D_of_a_( astart_ ) / Dnow_;
|
||||
Dplus_target_ = D_of_a_( atarget_ ) / Dnow_;
|
||||
|
||||
music::ilog << "Linear growth factors: D+_target = " << Dplus_target_ << ", D+_start = " << Dplus_start_ << std::endl;
|
||||
|
||||
// set up transfer functions and compute normalisation
|
||||
transfer_function_ = std::move(select_TransferFunction_plugin(cf));
|
||||
transfer_function_ = std::move(select_TransferFunction_plugin(cf, cosmo_param_));
|
||||
transfer_function_->intialise();
|
||||
if( !transfer_function_->tf_isnormalised_ )
|
||||
cosmo_param_.pnorm = this->compute_pnorm_from_sigma8();
|
||||
else{
|
||||
cosmo_param_.pnorm = 1.0/Dplus_target_/Dplus_target_;
|
||||
if( !transfer_function_->tf_isnormalised_ ){
|
||||
cosmo_param_.set("pnorm", this->compute_pnorm_from_sigma8() );
|
||||
}else{
|
||||
cosmo_param_.set("pnorm", 1.0/Dplus_target_/Dplus_target_);
|
||||
auto sigma8 = this->compute_sigma8();
|
||||
music::ilog << "Measured sigma_8 for given PS normalisation is " << sigma8 << std::endl;
|
||||
}
|
||||
cosmo_param_.sqrtpnorm = std::sqrt(cosmo_param_.pnorm);
|
||||
cosmo_param_.set("sqrtpnorm", std::sqrt(cosmo_param_["pnorm"]));
|
||||
|
||||
music::ilog << std::setw(32) << std::left << "TF supports distinct CDM+baryons"
|
||||
<< " : " << (transfer_function_->tf_is_distinct() ? "yes" : "no") << std::endl;
|
||||
music::ilog << std::setw(32) << std::left << "TF maximum wave number"
|
||||
<< " : " << transfer_function_->get_kmax() << " h/Mpc" << std::endl;
|
||||
|
||||
m_n_s_ = cosmo_param_["n_s"];
|
||||
m_sqrtpnorm_ = cosmo_param_["sqrtpnorm"];
|
||||
}
|
||||
|
||||
~calculator()
|
||||
{
|
||||
}
|
||||
~calculator() { }
|
||||
|
||||
//! Write out a correctly scaled power spectrum at time a
|
||||
void write_powerspectrum(real_t a, std::string fname) const
|
||||
|
@ -209,22 +225,23 @@ public:
|
|||
<< std::setw(20) << ("P_dbar(k,a=1)")
|
||||
<< std::setw(20) << ("P_tcdm(k,a=1)")
|
||||
<< std::setw(20) << ("P_tbar(k,a=1)")
|
||||
<< std::setw(20) << ("P_dtot(K,a=1)")
|
||||
<< std::endl;
|
||||
for (double k = kmin; k < transfer_function_->get_kmax(); k *= 1.05)
|
||||
for (double k = kmin; k < transfer_function_->get_kmax(); k *= 1.01)
|
||||
{
|
||||
ofs << std::setw(20) << std::setprecision(10) << k
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, total)*Dplus_start_, 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, cdm)*Dplus_start_, 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, baryon)*Dplus_start_, 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, vcdm)*Dplus_start_, 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, vbaryon)*Dplus_start_, 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, total0), 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, cdm0), 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, baryon0), 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, vcdm0), 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, vbaryon0), 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, vtotal), 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_matter)*Dplus_start_, 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_cdm)*Dplus_start_, 2.0)
|
||||
<< std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_baryon)*Dplus_start_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_matter)*Dplus_start_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_cdm)*Dplus_start_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_baryon)*Dplus_start_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, theta_cdm)*Dplus_start_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, theta_baryon)*Dplus_start_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_matter0)* Dplus_start_ / Dplus_target_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_cdm0)* Dplus_start_ / Dplus_target_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, delta_baryon0)* Dplus_start_ / Dplus_target_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, theta_cdm0)* Dplus_start_ / Dplus_target_, 2.0)
|
||||
// << std::setw(20) << std::setprecision(10) << std::pow(this->get_amplitude(k, theta_baryon0)* Dplus_start_ / Dplus_target_, 2.0)
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -250,18 +267,27 @@ public:
|
|||
<< std::setw(20) << ("delta_m(k,a=ap)")
|
||||
<< std::setw(20) << ("delta_bc(k,a=ap)")
|
||||
<< std::endl;
|
||||
double fb = cosmo_param_.Omega_b / cosmo_param_.Omega_m, fc = 1.0-fb;
|
||||
for (double k = kmin; k < transfer_function_->get_kmax(); k *= 1.05)
|
||||
double fb = cosmo_param_["f_b"], fc = cosmo_param_["f_c"];
|
||||
for (double k = kmin; k < transfer_function_->get_kmax(); k *= 1.01)
|
||||
{
|
||||
double dm = this->get_amplitude(k, total) * Dplus_start_ / Dplus_target_;
|
||||
double dbc = this->get_amplitude(k, baryon) - this->get_amplitude(k, cdm);
|
||||
double db = dm + fc * dbc;
|
||||
double dc = dm - fb * dbc;
|
||||
const double dm = this->get_amplitude(k, delta_matter) * Dplus_start_ / Dplus_target_;
|
||||
const double dbc = this->get_amplitude(k, delta_bc);
|
||||
const double db = dm + fc * dbc;
|
||||
const double dc = dm - fb * dbc;
|
||||
const double tm = this->get_amplitude(k, delta_matter) * Dplus_start_ / Dplus_target_;
|
||||
const double tbc = this->get_amplitude(k, theta_bc);
|
||||
const double tb = dm + fc * dbc;
|
||||
const double tc = dm - fb * dbc;
|
||||
|
||||
ofs << std::setw(20) << std::setprecision(10) << k
|
||||
<< std::setw(20) << std::setprecision(10) << dc
|
||||
<< std::setw(20) << std::setprecision(10) << db
|
||||
<< std::setw(20) << std::setprecision(10) << dm
|
||||
<< std::setw(20) << std::setprecision(10) << dbc
|
||||
<< std::setw(20) << std::setprecision(10) << dbc + 2 * tbc * (std::sqrt( Dplus_target_ / Dplus_start_ ) - 1.0)
|
||||
<< std::setw(20) << std::setprecision(10) << tc / std::pow( Dplus_start_ / Dplus_target_, 0.5 )
|
||||
<< std::setw(20) << std::setprecision(10) << tb / std::pow( Dplus_start_ / Dplus_target_, 0.5 )
|
||||
<< std::setw(20) << std::setprecision(10) << tm / std::pow( Dplus_start_ / Dplus_target_, 0.5 )
|
||||
<< std::setw(20) << std::setprecision(10) << tbc / std::pow( Dplus_start_ / Dplus_target_, 0.5 )
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -277,11 +303,11 @@ public:
|
|||
inline double H_of_a(double a) const noexcept
|
||||
{
|
||||
double HH2 = 0.0;
|
||||
HH2 += cosmo_param_.Omega_r / (a * a * a * a);
|
||||
HH2 += cosmo_param_.Omega_m / (a * a * a);
|
||||
HH2 += cosmo_param_.Omega_k / (a * a);
|
||||
HH2 += cosmo_param_.Omega_DE * std::pow(a, -3. * (1. + cosmo_param_.w_0 + cosmo_param_.w_a)) * exp(-3. * (1.0 - a) * cosmo_param_.w_a);
|
||||
return cosmo_param_.H0 * std::sqrt(HH2);
|
||||
HH2 += cosmo_param_["Omega_r"] / (a * a * a * a);
|
||||
HH2 += cosmo_param_["Omega_m"] / (a * a * a);
|
||||
HH2 += cosmo_param_["Omega_k"] / (a * a);
|
||||
HH2 += cosmo_param_["Omega_DE"] * std::pow(a, -3. * (1. + cosmo_param_["w_0"] + cosmo_param_["w_a"])) * exp(-3. * (1.0 - a) * cosmo_param_["w_a"]);
|
||||
return cosmo_param_["H0"] * std::sqrt(HH2);
|
||||
}
|
||||
|
||||
//! Computes the linear theory growth factor D+, normalised to D+(a=1)=1
|
||||
|
@ -311,7 +337,7 @@ public:
|
|||
*/
|
||||
real_t get_vfact(real_t a) const noexcept
|
||||
{
|
||||
return f_of_a_(a) * a * H_of_a(a) / cosmo_param_.h;
|
||||
return f_of_a_(a) * a * H_of_a(a) / cosmo_param_["h"];
|
||||
}
|
||||
|
||||
//! Integrand for the sigma_8 normalization of the power spectrum
|
||||
|
@ -319,15 +345,13 @@ public:
|
|||
the transfer function and the window function of 8 Mpc/h at wave number k */
|
||||
static double dSigma8(double k, void *pParams)
|
||||
{
|
||||
if (k <= 0.0)
|
||||
return 0.0f;
|
||||
|
||||
cosmology::calculator *pcc = reinterpret_cast<cosmology::calculator *>(pParams);
|
||||
|
||||
double x = k * 8.0;
|
||||
double w = 3.0 * (sin(x) - x * cos(x)) / (x * x * x);
|
||||
static double nspect = (double)pcc->cosmo_param_.nspect;
|
||||
double tf = pcc->transfer_function_->compute(k, total);
|
||||
const double x = k * 8.0;
|
||||
const double w = (x < 0.001)? 1.0-0.1*x*x : 3.0 * (std::sin(x) - x * std::cos(x)) / (x * x * x);
|
||||
|
||||
static double nspect = (double)pcc->cosmo_param_["n_s"];
|
||||
double tf = pcc->transfer_function_->compute(k, delta_matter);
|
||||
|
||||
//... no growth factor since we compute at z=0 and normalize so that D+(z=0)=1
|
||||
return k * k * w * w * pow((double)k, (double)nspect) * tf * tf;
|
||||
|
@ -338,55 +362,48 @@ public:
|
|||
the transfer function and the window function of 8 Mpc/h at wave number k */
|
||||
static double dSigma8_0(double k, void *pParams)
|
||||
{
|
||||
if (k <= 0.0)
|
||||
return 0.0f;
|
||||
|
||||
cosmology::calculator *pcc = reinterpret_cast<cosmology::calculator *>(pParams);
|
||||
|
||||
double x = k * 8.0;
|
||||
double w = 3.0 * (std::sin(x) - x * std::cos(x)) / (x * x * x);
|
||||
static double nspect = static_cast<double>(pcc->cosmo_param_.nspect);
|
||||
double tf = pcc->transfer_function_->compute(k, total0);
|
||||
const double x = k * 8.0;
|
||||
const double w = (x < 0.001)? 1.0-0.1*x*x : 3.0 * (std::sin(x) - x * std::cos(x)) / (x * x * x);
|
||||
|
||||
static double nspect = static_cast<double>(pcc->cosmo_param_["n_s"]);
|
||||
double tf = pcc->transfer_function_->compute(k, delta_matter0);
|
||||
|
||||
//... no growth factor since we compute at z=0 and normalize so that D+(z=0)=1
|
||||
return k * k * w * w * std::pow(k, nspect) * tf * tf;
|
||||
}
|
||||
|
||||
// static double dSigma_bc(double k, void *pParams)
|
||||
// {
|
||||
// if (k <= 0.0)
|
||||
// return 0.0f;
|
||||
|
||||
// cosmology::calculator *pcc = reinterpret_cast<cosmology::calculator *>(pParams);
|
||||
|
||||
// static double nspect = static_cast<double>(pcc->cosmo_param_.nspect);
|
||||
// double tf = pcc->transfer_function_->compute(k, deltabc);
|
||||
|
||||
// //... no growth factor since we compute at z=0 and normalize so that D+(z=0)=1
|
||||
// return k * k * std::pow(k, nspect) * tf * tf; // * cosmo_param_.sqrtpnorm * Dplus_target_;
|
||||
// }
|
||||
|
||||
//! Computes the amplitude of a mode from the power spectrum
|
||||
/*! Function evaluates the supplied transfer function ptransfer_fun_
|
||||
* and returns the amplitude of fluctuations at wave number k at z=0
|
||||
/*! Function evaluates the supplied transfer function transfer_function_
|
||||
* and returns the amplitude of fluctuations at wave number k (in h/Mpc) back-scaled to z=z_start
|
||||
* @param k wave number at which to evaluate
|
||||
* @param type one of the species: {delta,theta}_{matter,cdm,baryon,neutrino}
|
||||
*/
|
||||
inline real_t get_amplitude( const real_t k, const tf_type type) const
|
||||
{
|
||||
return std::pow(k, 0.5 * cosmo_param_.nspect) * transfer_function_->compute(k, type) * cosmo_param_.sqrtpnorm;// * ((type!=deltabc)? 1.0 : 1.0/Dplus_target_);
|
||||
return std::pow(k, 0.5 * m_n_s_) * transfer_function_->compute(k, type) * m_sqrtpnorm_;
|
||||
}
|
||||
|
||||
inline real_t get_amplitude_phibc( const real_t k ) const
|
||||
//! Compute amplitude of the back-scaled delta_bc mode, with decaying velocity v_bc included or not (in which case delta_bc=const)
|
||||
inline real_t get_amplitude_delta_bc( const real_t k, bool withvbc ) const
|
||||
{
|
||||
const real_t Dratio = Dplus_target_ / Dplus_start_;
|
||||
const real_t dbc = transfer_function_->compute(k, delta_bc) + (withvbc? 2 * transfer_function_->compute(k, theta_bc) * (std::sqrt(Dratio) - 1.0) : 0.0);
|
||||
// need to multiply with Dplus_target since sqrtpnorm rescales like that
|
||||
return -std::pow(k, 0.5 * cosmo_param_.nspect-2.0) * transfer_function_->compute(k, deltabc) * cosmo_param_.sqrtpnorm * Dplus_target_;
|
||||
return std::pow(k, 0.5 * m_n_s_) * dbc * (m_sqrtpnorm_ * Dplus_target_);
|
||||
}
|
||||
inline real_t get_amplitude_rhobc( const real_t k ) const
|
||||
|
||||
//! Compute amplitude of the back-scaled relative velocity theta_bc mode if withvbc==true, otherwise return zero
|
||||
inline real_t get_amplitude_theta_bc( const real_t k, bool withvbc ) const
|
||||
{
|
||||
const real_t Dratio = Dplus_target_ / Dplus_start_;
|
||||
const real_t tbc = transfer_function_->compute(k, theta_bc) * std::sqrt(Dratio);
|
||||
// need to multiply with Dplus_target since sqrtpnorm rescales like that
|
||||
return std::pow(k, 0.5 * cosmo_param_.nspect) * transfer_function_->compute(k, deltabc) * cosmo_param_.sqrtpnorm * Dplus_target_;
|
||||
return withvbc ? std::pow(k, 0.5 * m_n_s_) * tbc * (m_sqrtpnorm_ * Dplus_target_) : 0.0;
|
||||
}
|
||||
|
||||
|
||||
//! Computes the normalization for the power spectrum
|
||||
/*!
|
||||
* integrates the power spectrum to fix the normalization to that given
|
||||
|
@ -407,19 +424,6 @@ public:
|
|||
return std::sqrt(sigma0);
|
||||
}
|
||||
|
||||
// real_t compute_sigma_bc( void )
|
||||
// {
|
||||
// real_t sigma0, kmin, kmax;
|
||||
// kmax = 100.0; //transfer_function_->get_kmax();
|
||||
// kmin = transfer_function_->get_kmin();
|
||||
|
||||
// sigma0 = 4.0 * M_PI * integrate(&dSigma_bc, static_cast<double>(kmin), static_cast<double>(kmax), this);
|
||||
// sigma0 = std::sqrt(sigma0);
|
||||
// sigma0 *= cosmo_param_.sqrtpnorm * Dplus_target_;
|
||||
// std::cout << "kmin = " << kmin << ", kmax = " << kmax << ", sigma_bc = " << sigma0 << std::endl;
|
||||
// return sigma0;
|
||||
// }
|
||||
|
||||
//! Computes the normalization for the power spectrum
|
||||
/*!
|
||||
* integrates the power spectrum to fix the normalization to that given
|
||||
|
@ -428,7 +432,7 @@ public:
|
|||
real_t compute_pnorm_from_sigma8(void)
|
||||
{
|
||||
auto measured_sigma8 = this->compute_sigma8();
|
||||
return cosmo_param_.sigma8 * cosmo_param_.sigma8 / (measured_sigma8 * measured_sigma8);
|
||||
return cosmo_param_["sigma_8"] * cosmo_param_["sigma_8"] / (measured_sigma8 * measured_sigma8);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -439,10 +443,10 @@ public:
|
|||
* @param mass mass scale
|
||||
* @returns jeans sound speed
|
||||
*/
|
||||
inline double jeans_sound_speed(double rho, double mass)
|
||||
{
|
||||
const double G = 6.67e-8;
|
||||
return pow(6.0 * mass / M_PI * std::sqrt(rho) * std::pow(G, 1.5), 1.0 / 3.0);
|
||||
}
|
||||
// inline double jeans_sound_speed(double rho, double mass)
|
||||
// {
|
||||
// const double G = 6.67e-8;
|
||||
// return pow(6.0 * mass / M_PI * std::sqrt(rho) * std::pow(G, 1.5), 1.0 / 3.0);
|
||||
// }
|
||||
|
||||
} // namespace cosmology
|
|
@ -1,122 +1,225 @@
|
|||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn
|
||||
//
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include <physical_constants.hh>
|
||||
#include <config_file.hh>
|
||||
#include <general.hh>
|
||||
|
||||
namespace cosmology
|
||||
{
|
||||
//! structure for cosmological parameters
|
||||
struct parameters
|
||||
{
|
||||
|
||||
double
|
||||
Omega_m, //!< baryon+dark matter density
|
||||
Omega_b, //!< baryon matter density
|
||||
Omega_DE, //!< dark energy density (cosmological constant or parameterised)
|
||||
Omega_r, //!< photon + relativistic particle density
|
||||
Omega_k, //!< curvature density
|
||||
f_b, //!< baryon fraction
|
||||
H0, //!< Hubble constant in km/s/Mpc
|
||||
h, //!< hubble parameter
|
||||
nspect, //!< long-wave spectral index (scale free is nspect=1)
|
||||
sigma8, //!< power spectrum normalization
|
||||
Tcmb, //!< CMB temperature (used to set Omega_r)
|
||||
Neff, //!< effective number of neutrino species (used to set Omega_r)
|
||||
w_0, //!< dark energy equation of state parameter 1: w = w0 + a * wa
|
||||
w_a, //!< dark energy equation of state parameter 2: w = w0 + a * wa
|
||||
|
||||
// below are helpers to store additional information
|
||||
dplus, //!< linear perturbation growth factor
|
||||
f, //!< growth factor logarithmic derivative
|
||||
pnorm, //!< actual power spectrum normalisation factor
|
||||
sqrtpnorm, //!< sqrt of power spectrum normalisation factor
|
||||
vfact; //!< velocity<->displacement conversion factor in Zel'dovich approx.
|
||||
|
||||
parameters() = delete;
|
||||
|
||||
parameters( const parameters& ) = default;
|
||||
|
||||
explicit parameters(config_file cf)
|
||||
//! structure for cosmological parameters
|
||||
class parameters
|
||||
{
|
||||
H0 = cf.get_value<double>("cosmology", "H0");
|
||||
h = H0 / 100.0;
|
||||
public:
|
||||
using defaultmmap_t = std::map<std::string,std::map<std::string,real_t>>;
|
||||
|
||||
nspect = cf.get_value<double>("cosmology", "nspec");
|
||||
private:
|
||||
std::map<std::string, double> pmap_; //!< All parameters are stored here as key-value pairs
|
||||
|
||||
Omega_b = cf.get_value<double>("cosmology", "Omega_b");
|
||||
static defaultmmap_t default_pmaps_; //!< Holds pre-defined parameter sets, see src/cosmology_parameters.cc
|
||||
|
||||
Omega_m = cf.get_value<double>("cosmology", "Omega_m");
|
||||
|
||||
Omega_DE = cf.get_value<double>("cosmology", "Omega_L");
|
||||
|
||||
w_0 = cf.get_value_safe<double>("cosmology", "w0", -1.0);
|
||||
|
||||
w_a = cf.get_value_safe<double>("cosmology", "wa", 0.0);
|
||||
|
||||
Tcmb = cf.get_value_safe<double>("cosmology", "Tcmb", 2.7255);
|
||||
|
||||
Neff = cf.get_value_safe<double>("cosmology", "Neff", 3.046);
|
||||
|
||||
sigma8 = cf.get_value_safe<double>("cosmology", "sigma_8",-1.0);
|
||||
|
||||
// calculate energy density in ultrarelativistic species from Tcmb and Neff
|
||||
double Omega_gamma = 4 * phys_const::sigma_SI / std::pow(phys_const::c_SI, 3) * std::pow(Tcmb, 4.0) / phys_const::rhocrit_h2_SI / (h * h);
|
||||
double Omega_nu = Neff * Omega_gamma * 7. / 8. * std::pow(4. / 11., 4. / 3.);
|
||||
Omega_r = Omega_gamma + Omega_nu;
|
||||
|
||||
if (cf.get_value_safe<bool>("cosmology", "ZeroRadiation", false))
|
||||
public:
|
||||
//! get routine for cosmological parameter key-value pairs
|
||||
double get(const std::string &key) const
|
||||
{
|
||||
Omega_r = 0.0;
|
||||
auto it = pmap_.find(key);
|
||||
if (it == pmap_.end())
|
||||
{
|
||||
auto errmsg = std::string("Cosmological parameter \'") + key + std::string("\' does not exist in internal list.");
|
||||
music::elog << errmsg << std::endl;
|
||||
throw std::runtime_error(errmsg.c_str());
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
f_b = Omega_b / Omega_m;
|
||||
//! set routine for cosmological parameter key-value pairs
|
||||
void set(const std::string &key, const double value)
|
||||
{
|
||||
auto it = pmap_.find(key);
|
||||
if (it != pmap_.end())
|
||||
{
|
||||
pmap_[key] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto errmsg = std::string("Cosmological parameter \'") + key + std::string("\' does not exist in internal list. Needs to be defaulted before it can be set!");
|
||||
music::elog << errmsg << std::endl;
|
||||
throw std::runtime_error(errmsg.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//! shortcut get routine for cosmological parameter key-value pairs through bracket operator
|
||||
inline double operator[](const std::string &key) const { return this->get(key); }
|
||||
|
||||
//! default constructor does nothing
|
||||
parameters() {}
|
||||
|
||||
//! default copy constructor
|
||||
parameters(const parameters &) = default;
|
||||
|
||||
//! main constructor for explicit construction from input config file
|
||||
explicit parameters( config_file &cf )
|
||||
{
|
||||
music::ilog << "-------------------------------------------------------------------------------" << std::endl;
|
||||
|
||||
if( cf.get_value_safe<std::string>("cosmology","ParameterSet","none") == std::string("none"))
|
||||
{
|
||||
//-------------------------------------------------------------------------------
|
||||
// read parameters from config file
|
||||
//-------------------------------------------------------------------------------
|
||||
|
||||
auto defaultp = default_pmaps_.find("Planck2018EE+BAO+SN")->second;
|
||||
|
||||
// CMB
|
||||
pmap_["Tcmb"] = cf.get_value_safe<double>("cosmology", "Tcmb", defaultp["Tcmb"]);
|
||||
pmap_["YHe"] = cf.get_value_safe<double>("cosmology", "YHe", defaultp["YHe"]);
|
||||
|
||||
// H0
|
||||
pmap_["h"] = cf.get_value_safe<double>("cosmology", "H0", defaultp["h"]*100.0) / 100.0;
|
||||
|
||||
// primordial and normalisation
|
||||
if(!cf.contains_key("cosmology/n_s"))
|
||||
pmap_["n_s"] = cf.get_value_safe<double>("cosmology", "nspec", defaultp["n_s"]);
|
||||
else
|
||||
pmap_["n_s"] = cf.get_value_safe<double>("cosmology", "n_s", defaultp["n_s"]);
|
||||
|
||||
pmap_["A_s"] = cf.get_value_safe<double>("cosmology", "A_s", cf.contains_key("cosmology/sigma_8")? -1.0 : defaultp["A_s"]);
|
||||
pmap_["k_p"] = cf.get_value_safe<double>("cosmology", "k_p", defaultp["k_p"]);
|
||||
|
||||
pmap_["sigma_8"] = cf.get_value_safe<double>("cosmology", "sigma_8", -1.0);
|
||||
|
||||
// baryon and non-relativistic matter content
|
||||
pmap_["Omega_b"] = cf.get_value_safe<double>("cosmology", "Omega_b", defaultp["Omega_b"]);
|
||||
pmap_["Omega_m"] = cf.get_value_safe<double>("cosmology", "Omega_m", defaultp["Omega_m"]);
|
||||
|
||||
// massive neutrino species
|
||||
pmap_["m_nu1"] = cf.get_value_safe<double>("cosmology", "m_nu1", defaultp["m_nu1"]);
|
||||
pmap_["m_nu2"] = cf.get_value_safe<double>("cosmology", "m_nu2", defaultp["m_nu2"]);
|
||||
pmap_["m_nu3"] = cf.get_value_safe<double>("cosmology", "m_nu3", defaultp["m_nu3"]);
|
||||
int N_nu_massive = int(this->get("m_nu1") > 1e-9) + int(this->get("m_nu2") > 1e-9) + int(this->get("m_nu3") > 1e-9);;
|
||||
|
||||
// number ultrarelativistic neutrinos
|
||||
pmap_["N_ur"] = cf.get_value_safe<double>("cosmology", "N_ur", 3.046 - N_nu_massive);
|
||||
|
||||
// dark energy
|
||||
pmap_["Omega_DE"] = cf.get_value_safe<double>("cosmology", "Omega_L", defaultp["Omega_DE"]);
|
||||
pmap_["w_0"] = cf.get_value_safe<double>("cosmology", "w_0", defaultp["w_0"]);
|
||||
pmap_["w_a"] = cf.get_value_safe<double>("cosmology", "w_a", defaultp["w_a"]);
|
||||
|
||||
}else{
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// load predefined parameter set
|
||||
//-------------------------------------------------------------------------------
|
||||
auto pset_name = cf.get_value<std::string>("cosmology","ParameterSet");
|
||||
auto it = default_pmaps_.find( pset_name );
|
||||
if( it == default_pmaps_.end() ){
|
||||
music::elog << "Unknown cosmology parameter set \'" << pset_name << "\'!" << std::endl;
|
||||
music::ilog << "Valid pre-defined sets are: " << std::endl;
|
||||
for( auto ii : default_pmaps_ ){
|
||||
music::ilog << " " << ii.first << std::endl;
|
||||
}
|
||||
throw std::runtime_error("Invalid value for cosmology/ParameterSet");
|
||||
}else{
|
||||
music::ilog << "Loading cosmological parameter set \'" << it->first << "\'..." << std::endl;
|
||||
}
|
||||
|
||||
// copy pre-defined set in
|
||||
for( auto entry : it->second ){
|
||||
pmap_[entry.first] = entry.second;
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
// derived parameters
|
||||
//-------------------------------------------------------------------------------
|
||||
double h = this->get("h");
|
||||
pmap_["H0"] = 100.0 * h;
|
||||
|
||||
// massive neutrinos
|
||||
pmap_["N_nu_massive"] = int(this->get("m_nu1") > 1e-9) + int(this->get("m_nu2") > 1e-9) + int(this->get("m_nu3") > 1e-9);
|
||||
const double sum_m_nu = this->get("m_nu1") + this->get("m_nu2") + this->get("m_nu3");
|
||||
pmap_["Omega_nu_massive"] = sum_m_nu / (93.14 * h * h); // Omega_nu_m = \sum_i m_i / (93.14 eV h^2)
|
||||
|
||||
// calculate energy density in ultrarelativistic species from Tcmb and Neff
|
||||
// photons
|
||||
pmap_["Omega_gamma"] = 4 * phys_const::sigma_SI / std::pow(phys_const::c_SI, 3) * std::pow(this->get("Tcmb"), 4.0)
|
||||
/ phys_const::rhocrit_h2_SI / (this->get("h") * this->get("h"));
|
||||
// massless neutrinos
|
||||
pmap_["Omega_nu_massless"] = this->get("N_ur") * this->get("Omega_gamma") * 7. / 8. * std::pow(4. / 11., 4. / 3.);
|
||||
// total relativistic
|
||||
pmap_["Omega_r"] = this->get("Omega_gamma") + this->get("Omega_nu_massless");
|
||||
|
||||
// compute amount of cold dark matter as the rest
|
||||
pmap_["Omega_c"] = this->get("Omega_m") - this->get("Omega_b") - this->get("Omega_nu_massive");
|
||||
|
||||
if (cf.get_value_safe<bool>("cosmology", "ZeroRadiation", false))
|
||||
{
|
||||
pmap_["Omega_r"] = 0.0;
|
||||
}
|
||||
|
||||
pmap_["f_b"] = this->get("Omega_b") / this->get("Omega_m");
|
||||
pmap_["f_c"] = 1.0 - this->get("f_b"); // this means we add massive neutrinos to CDM here
|
||||
|
||||
#if 1
|
||||
// assume zero curvature, take difference from dark energy
|
||||
Omega_DE += 1.0 - Omega_m - Omega_DE - Omega_r;
|
||||
Omega_k = 0.0;
|
||||
// assume zero curvature, take difference from dark energy
|
||||
pmap_["Omega_DE"] += 1.0 - this->get("Omega_m") - this->get("Omega_DE") - this->get("Omega_r");
|
||||
// Omega_DE += 1.0 - Omega_m - Omega_DE - Omega_r;
|
||||
pmap_["Omega_k"] = 0.0;
|
||||
#else
|
||||
// allow for curvature
|
||||
Omega_k = 1.0 - Omega_m - Omega_DE - Omega_r;
|
||||
// allow for curvature
|
||||
Omega_k = 1.0 - Omega_m - Omega_DE - Omega_r;
|
||||
#endif
|
||||
|
||||
dplus = 0.0;
|
||||
pnorm = 0.0;
|
||||
vfact = 0.0;
|
||||
pmap_["dplus"] = 0.0;
|
||||
pmap_["pnorm"] = 0.0;
|
||||
pmap_["sqrtpnorm"] = 0.0;
|
||||
pmap_["vfact"] = 0.0;
|
||||
|
||||
music::ilog << "-------------------------------------------------------------------------------" << std::endl;
|
||||
music::ilog << "Cosmological parameters are: " << std::endl;
|
||||
music::ilog << " H0 = " << std::setw(16) << H0 << "sigma_8 = " << std::setw(16) << sigma8 << std::endl;
|
||||
music::ilog << " Omega_c = " << std::setw(16) << Omega_m-Omega_b << "Omega_b = " << std::setw(16) << Omega_b << std::endl;
|
||||
if (!cf.get_value_safe<bool>("cosmology", "ZeroRadiation", false)){
|
||||
music::ilog << " Omega_g = " << std::setw(16) << Omega_gamma << "Omega_nu = " << std::setw(16) << Omega_nu << std::endl;
|
||||
}else{
|
||||
music::ilog << " Omega_r = " << std::setw(16) << Omega_r << std::endl;
|
||||
music::ilog << "Cosmological parameters are: " << std::endl;
|
||||
music::ilog << " h = " << std::setw(16) << this->get("h");
|
||||
if( this->get("A_s") > 0.0 )
|
||||
music::ilog << "A_s = " << std::setw(16) << this->get("A_s");
|
||||
else
|
||||
music::ilog << "sigma_8 = " << std::setw(16) << this->get("sigma_8");
|
||||
music::ilog << "n_s = " << std::setw(16) << this->get("n_s") << std::endl;
|
||||
music::ilog << " Omega_c = " << std::setw(16) << this->get("Omega_c") << "Omega_b = " << std::setw(16) << this->get("Omega_b") << "Omega_m = " << std::setw(16) << this->get("Omega_m") << std::endl;
|
||||
music::ilog << " Omega_r = " << std::setw(16) << this->get("Omega_r") << "Omega_nu = " << std::setw(16) << this->get("Omega_nu_massive") << "∑m_nu = " << sum_m_nu << "eV" << std::endl;
|
||||
music::ilog << " Omega_DE = " << std::setw(16) << this->get("Omega_DE") << "w_0 = " << std::setw(16) << this->get("w_0") << "w_a = " << std::setw(16) << this->get("w_a") << std::endl;
|
||||
//music::ilog << " Omega_k = " << 1.0 - this->get("Omega_m") - this->get("Omega_r") - this->get("Omega_DE") << std::endl;
|
||||
if (this->get("Omega_r") > 0.0)
|
||||
{
|
||||
music::wlog << " Radiation enabled, using Omega_r=" << this->get("Omega_r") << " internally for backscaling." << std::endl;
|
||||
music::wlog << " Make sure your sim code supports this, otherwise set [cosmology] / ZeroRadiation=true." << std::endl;
|
||||
}
|
||||
}
|
||||
music::ilog << " Omega_DE = " << std::setw(16) << Omega_DE << "nspect = " << std::setw(16) << nspect << std::endl;
|
||||
music::ilog << " w0 = " << std::setw(16) << w_0 << "w_a = " << std::setw(16) << w_a << std::endl;
|
||||
|
||||
if( Omega_r > 0.0 )
|
||||
//! print the names of all pre-defined parameter sets
|
||||
void print_available_sets( void ) const
|
||||
{
|
||||
music::wlog << "Radiation enabled, using Omega_r=" << Omega_r << " internally."<< std::endl;
|
||||
music::wlog << "Make sure your sim code supports this..." << std::endl;
|
||||
for( auto ii : default_pmaps_ ){
|
||||
music::ilog << "\t\'" << ii.first << "\'" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
void print_ParameterSets( void );
|
||||
} // namespace cosmology
|
|
@ -30,8 +30,15 @@
|
|||
|
||||
#include "config_file.hh"
|
||||
|
||||
//! use to suppress warnings of unused variables
|
||||
#define _unused(x) ((void)(x))
|
||||
|
||||
//! assert on all elements of a brace enclosed initializer list (useful for variadic templates)
|
||||
inline void list_assert_all( const std::initializer_list<bool>& t )
|
||||
{
|
||||
for( auto b : t ) {assert(b);_unused(b);}
|
||||
}
|
||||
|
||||
// include CMake controlled configuration settings
|
||||
#include "cmake_config.hh"
|
||||
|
||||
|
|
|
@ -84,9 +84,9 @@ public:
|
|||
|
||||
void reset()
|
||||
{
|
||||
if (data_ != nullptr) { fftw_free(data_); data_ = nullptr; }
|
||||
if (plan_ != nullptr) { fftw_destroy_plan(plan_); plan_ = nullptr; }
|
||||
if (iplan_ != nullptr) { fftw_destroy_plan(iplan_); iplan_ = nullptr; }
|
||||
if (data_ != nullptr) { FFTW_API(free)(data_); data_ = nullptr; }
|
||||
if (plan_ != nullptr) { FFTW_API(destroy_plan)(plan_); plan_ = nullptr; }
|
||||
if (iplan_ != nullptr) { FFTW_API(destroy_plan)(iplan_); iplan_ = nullptr; }
|
||||
ballocated_ = false;
|
||||
}
|
||||
|
||||
|
@ -134,7 +134,7 @@ public:
|
|||
//! set all field elements to zero
|
||||
void zero() noexcept
|
||||
{
|
||||
#pragma omp parallel for
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < ntot_; ++i)
|
||||
data_[i] = 0.0;
|
||||
}
|
||||
|
@ -155,8 +155,8 @@ public:
|
|||
assert(this->n_[1] == g.n_[1]);
|
||||
assert(this->n_[2] == g.n_[2]);
|
||||
|
||||
// now we can copy all the data over
|
||||
#pragma omp parallel for
|
||||
// now we can copy all the data over
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < ntot_; ++i)
|
||||
data_[i] = g.data_[i];
|
||||
}
|
||||
|
@ -305,9 +305,9 @@ public:
|
|||
data_t get_cic( const vec3_t<real_t>& v ) const noexcept
|
||||
{
|
||||
// warning! this doesn't work with MPI
|
||||
vec3_t<real_t> x({std::fmod(v.x/length_[0]+1.0,1.0)*n_[0],
|
||||
std::fmod(v.y/length_[1]+1.0,1.0)*n_[1],
|
||||
std::fmod(v.z/length_[2]+1.0,1.0)*n_[2] });
|
||||
vec3_t<real_t> x({real_t(std::fmod(v.x/length_[0]+1.0,1.0)*n_[0]),
|
||||
real_t(std::fmod(v.y/length_[1]+1.0,1.0)*n_[1]),
|
||||
real_t(std::fmod(v.z/length_[2]+1.0,1.0)*n_[2]) });
|
||||
size_t ix = static_cast<size_t>(x.x);
|
||||
size_t iy = static_cast<size_t>(x.y);
|
||||
size_t iz = static_cast<size_t>(x.z);
|
||||
|
@ -357,6 +357,7 @@ public:
|
|||
return val;
|
||||
}
|
||||
|
||||
|
||||
inline ccomplex_t gradient( const int idim, std::array<size_t,3> ijk ) const
|
||||
{
|
||||
if( bdistributed ){
|
||||
|
@ -677,10 +678,12 @@ public:
|
|||
return real_t(locmin);
|
||||
}
|
||||
*/
|
||||
template <typename functional, typename grid_t>
|
||||
void assign_function_of_grids_r(const functional &f, const grid_t &g)
|
||||
|
||||
//! In real space, assigns the value of a functional of arbitrarily many grids, i.e. f(x) = f(g1(x),g2(x),...)
|
||||
template <typename functional, typename... Grids>
|
||||
void assign_function_of_grids_r(const functional &f, Grids&... grids)
|
||||
{
|
||||
assert(g.size(0) == size(0) && g.size(1) == size(1));
|
||||
list_assert_all( { ((grids.size(0)==this->size(0))&&(grids.size(1)==this->size(1))&&(grids.size(2)==this->size(2)))... } );
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < sizes_[0]; ++i)
|
||||
|
@ -689,20 +692,17 @@ public:
|
|||
{
|
||||
for (size_t k = 0; k < sizes_[2]; ++k)
|
||||
{
|
||||
auto &elem = this->relem(i, j, k);
|
||||
const auto &elemg = g.relem(i, j, k);
|
||||
|
||||
elem = f(elemg);
|
||||
this->relem(i, j, k) = f((grids.relem(i, j, k))...);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename functional, typename grid1_t, typename grid2_t>
|
||||
void assign_function_of_grids_r(const functional &f, const grid1_t &g1, const grid2_t &g2)
|
||||
//! In Fourier space, assigns the value of a functional of arbitrarily many grids, i.e. f(k) = f(g1(k),g2(k),...)
|
||||
template <typename functional, typename... Grids>
|
||||
void assign_function_of_grids_k(const functional &f, Grids&... grids)
|
||||
{
|
||||
assert(g1.size(0) == size(0) && g1.size(1) == size(1));
|
||||
assert(g2.size(0) == size(0) && g2.size(1) == size(1));
|
||||
list_assert_all( { ((grids.size(0)==this->size(0))&&(grids.size(1)==this->size(1))&&(grids.size(2)==this->size(2)))... } );
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < sizes_[0]; ++i)
|
||||
|
@ -711,24 +711,18 @@ public:
|
|||
{
|
||||
for (size_t k = 0; k < sizes_[2]; ++k)
|
||||
{
|
||||
//auto idx = this->get_idx(i,j,k);
|
||||
auto &elem = this->relem(i, j, k);
|
||||
|
||||
const auto &elemg1 = g1.relem(i, j, k);
|
||||
const auto &elemg2 = g2.relem(i, j, k);
|
||||
|
||||
elem = f(elemg1, elemg2);
|
||||
this->kelem(i, j, k) = f((grids.kelem(i, j, k))...);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename functional, typename grid1_t, typename grid2_t, typename grid3_t>
|
||||
void assign_function_of_grids_r(const functional &f, const grid1_t &g1, const grid2_t &g2, const grid3_t &g3)
|
||||
//! In Fourier space, assigns the value of a functional of arbitrarily many grids where first argument is the 3d array index
|
||||
//! i.e. f[ijk] = f({ijk}, g1[ijk], g2[ijk], ...)
|
||||
template <typename functional, typename... Grids>
|
||||
void assign_function_of_grids_ijk(const functional &f, Grids&... grids)
|
||||
{
|
||||
assert(g1.size(0) == size(0) && g1.size(1) == size(1)); // && g1.size(2) == size(2));
|
||||
assert(g2.size(0) == size(0) && g2.size(1) == size(1)); // && g2.size(2) == size(2));
|
||||
assert(g3.size(0) == size(0) && g3.size(1) == size(1)); // && g3.size(2) == size(2));
|
||||
list_assert_all( { ((grids.size(0)==this->size(0))&&(grids.size(1)==this->size(1))&&(grids.size(2)==this->size(2)))... } );
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < sizes_[0]; ++i)
|
||||
|
@ -737,23 +731,19 @@ public:
|
|||
{
|
||||
for (size_t k = 0; k < sizes_[2]; ++k)
|
||||
{
|
||||
//auto idx = this->get_idx(i,j,k);
|
||||
auto &elem = this->relem(i, j, k);
|
||||
|
||||
const auto &elemg1 = g1.relem(i, j, k);
|
||||
const auto &elemg2 = g2.relem(i, j, k);
|
||||
const auto &elemg3 = g3.relem(i, j, k);
|
||||
|
||||
elem = f(elemg1, elemg2, elemg3);
|
||||
this->kelem(i, j, k) = f({i, j, k}, (grids.kelem(i, j, k))...);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename functional, typename grid_t>
|
||||
void assign_function_of_grids_k(const functional &f, const grid_t &g)
|
||||
//! In Fourier space, assigns the value of a functional of arbitrarily many grids where first argument is the k vector
|
||||
//! i.e. f(k) = f(k, g1(k), g2(k), ...)
|
||||
template <typename functional, typename... Grids>
|
||||
void assign_function_of_grids_kdep(const functional &f, Grids&... grids)
|
||||
{
|
||||
assert(g.size(0) == size(0) && g.size(1) == size(1)); // && g.size(2) == size(2) );
|
||||
// check that all grids are same size
|
||||
list_assert_all( { ((grids.size(0)==this->size(0))&&(grids.size(1)==this->size(1))&&(grids.size(2)==this->size(2)))... } );
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < sizes_[0]; ++i)
|
||||
|
@ -762,77 +752,7 @@ public:
|
|||
{
|
||||
for (size_t k = 0; k < sizes_[2]; ++k)
|
||||
{
|
||||
auto &elem = this->kelem(i, j, k);
|
||||
const auto &elemg = g.kelem(i, j, k);
|
||||
|
||||
elem = f(elemg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename functional, typename grid1_t, typename grid2_t>
|
||||
void assign_function_of_grids_k(const functional &f, const grid1_t &g1, const grid2_t &g2)
|
||||
{
|
||||
assert(g1.size(0) == size(0) && g1.size(1) == size(1)); // && g.size(2) == size(2) );
|
||||
assert(g2.size(0) == size(0) && g2.size(1) == size(1)); // && g.size(2) == size(2) );
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < sizes_[0]; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < sizes_[1]; ++j)
|
||||
{
|
||||
for (size_t k = 0; k < sizes_[2]; ++k)
|
||||
{
|
||||
auto &elem = this->kelem(i, j, k);
|
||||
const auto &elemg1 = g1.kelem(i, j, k);
|
||||
const auto &elemg2 = g2.kelem(i, j, k);
|
||||
|
||||
elem = f(elemg1, elemg2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename functional, typename grid_t>
|
||||
void assign_function_of_grids_kdep(const functional &f, const grid_t &g)
|
||||
{
|
||||
assert(g.size(0) == size(0) && g.size(1) == size(1)); // && g.size(2) == size(2) );
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < sizes_[0]; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < sizes_[1]; ++j)
|
||||
{
|
||||
for (size_t k = 0; k < sizes_[2]; ++k)
|
||||
{
|
||||
auto &elem = this->kelem(i, j, k);
|
||||
const auto &elemg = g.kelem(i, j, k);
|
||||
|
||||
elem = f(this->get_k<real_t>(i, j, k), elemg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename functional, typename grid1_t, typename grid2_t>
|
||||
void assign_function_of_grids_kdep(const functional &f, const grid1_t &g1, const grid2_t &g2)
|
||||
{
|
||||
assert(g1.size(0) == size(0) && g1.size(1) == size(1) && g1.size(2) == size(2) );
|
||||
assert(g2.size(0) == size(0) && g2.size(1) == size(1) && g2.size(2) == size(2) );
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < size(0); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < size(1); ++j)
|
||||
{
|
||||
for (size_t k = 0; k < size(2); ++k)
|
||||
{
|
||||
auto &elem = this->kelem(i, j, k);
|
||||
const auto &elemg1 = g1.kelem(i, j, k);
|
||||
const auto &elemg2 = g2.kelem(i, j, k);
|
||||
|
||||
elem = f(this->get_k<real_t>(i, j, k), elemg1, elemg2);
|
||||
this->kelem(i, j, k) = f(this->get_k<real_t>(i, j, k), (grids.kelem(i, j, k))...);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -872,13 +792,17 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
//! perform a backwards Fourier transform
|
||||
void FourierTransformBackward(bool do_transform = true);
|
||||
|
||||
//! perform a forwards Fourier transform
|
||||
void FourierTransformForward(bool do_transform = true);
|
||||
|
||||
void ApplyNorm(void);
|
||||
//! perform a copy operation between to FFT grids that might not be of the same size
|
||||
void FourierInterpolateCopyTo( grid_fft_t &grid_to );
|
||||
|
||||
void FillRandomReal(unsigned long int seed = 123456ul);
|
||||
//! normalise field
|
||||
void ApplyNorm(void);
|
||||
|
||||
void Write_to_HDF5(std::string fname, std::string datasetname) const;
|
||||
|
||||
|
@ -894,7 +818,7 @@ public:
|
|||
{
|
||||
FourierTransformForward();
|
||||
apply_function_k_dep([&](auto x, auto k) -> ccomplex_t {
|
||||
real_t shift = s.x * k[0] * get_dx()[0] + s.y * k[1] * get_dx()[1] + s.z * k[2] * get_dx()[2];
|
||||
real_t shift = s.x * k[0] * this->get_dx()[0] + s.y * k[1] * this->get_dx()[1] + s.z * k[2] * this->get_dx()[2];
|
||||
return x * std::exp(ccomplex_t(0.0, shift));
|
||||
});
|
||||
if( transform_back ){
|
||||
|
|
|
@ -162,12 +162,12 @@ struct grid_interpolate
|
|||
if (is_distributed_trait)
|
||||
{
|
||||
#if defined(USE_MPI)
|
||||
std::sort(pos.begin(), pos.end(), [&](auto x1, auto x2) { return get_task(x1) < get_task(x2); });
|
||||
std::sort(pos.begin(), pos.end(), [&](auto x1, auto x2) { return this->get_task(x1) < this->get_task(x2); });
|
||||
std::vector<int> sendcounts(MPI::get_size(), 0), sendoffsets(MPI::get_size(), 0);
|
||||
std::vector<int> recvcounts(MPI::get_size(), 0), recvoffsets(MPI::get_size(), 0);
|
||||
for (auto x : pos)
|
||||
{
|
||||
sendcounts[get_task(x)] += 3;
|
||||
sendcounts[this->get_task(x)] += 3;
|
||||
}
|
||||
|
||||
MPI_Alltoall(&sendcounts[0], 1, MPI_INT, &recvcounts[0], 1, MPI_INT, MPI_COMM_WORLD);
|
||||
|
@ -204,4 +204,4 @@ struct grid_interpolate
|
|||
return std::exp(ccomplex_t(0.0, shift)) / del;
|
||||
}
|
||||
|
||||
};
|
||||
};
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
|
||||
namespace ic_generator{
|
||||
|
||||
int Run( config_file& the_config );
|
||||
int run( config_file& the_config );
|
||||
|
||||
int Initialise( config_file& the_config );
|
||||
int initialise( config_file& the_config );
|
||||
|
||||
void reset();
|
||||
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
@ -29,6 +46,7 @@ public:
|
|||
interpolated_function_1d(const std::vector<double> &data_x, const std::vector<double> &data_y)
|
||||
: isinit_(false)
|
||||
{
|
||||
static_assert(!(logx & periodic),"Class \'interpolated_function_1d\' cannot both be periodic and logarithmic in x!");
|
||||
this->set_data( data_x, data_y );
|
||||
}
|
||||
|
||||
|
@ -44,7 +62,6 @@ public:
|
|||
|
||||
assert(data_x_.size() == data_y_.size());
|
||||
assert(data_x_.size() > 5);
|
||||
assert(!(logx & periodic));
|
||||
|
||||
if (logx) for (auto &d : data_x_) d = std::log(d);
|
||||
if (logy) for (auto &d : data_y_) d = std::log(d);
|
||||
|
@ -61,8 +78,8 @@ public:
|
|||
double operator()(double x) const noexcept
|
||||
{
|
||||
assert( isinit_ && !(logx&&x<=0.0) );
|
||||
double xa = logx ? std::log(x) : x;
|
||||
double y(gsl_spline_eval(gsl_sp_, xa, gsl_ia_));
|
||||
const double xa = logx ? std::log(x) : x;
|
||||
const double y(gsl_spline_eval(gsl_sp_, xa, gsl_ia_));
|
||||
return logy ? std::exp(y) : y;
|
||||
}
|
||||
};
|
|
@ -1,12 +1,33 @@
|
|||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gsl/gsl_math.h>
|
||||
#include <gsl/gsl_eigen.h>
|
||||
|
||||
#include <math/vec3.hh>
|
||||
|
||||
//! class for 3x3 matrix calculations
|
||||
template<typename T>
|
||||
class mat3_t{
|
||||
protected:
|
||||
std::array<T,9> data_;
|
||||
std::array<double,9> data_double_;
|
||||
gsl_matrix_view m_;
|
||||
gsl_vector *eval_;
|
||||
gsl_matrix *evec_;
|
||||
|
@ -17,12 +38,20 @@ protected:
|
|||
// allocate memory for GSL operations if we haven't done so yet
|
||||
if( !bdid_alloc_gsl_ )
|
||||
{
|
||||
m_ = gsl_matrix_view_array (&data_[0], 3, 3);
|
||||
if( typeid(T)!=typeid(double) ){
|
||||
m_ = gsl_matrix_view_array ( &data_double_[0], 3, 3);
|
||||
}else{
|
||||
m_ = gsl_matrix_view_array ( (double*)(&data_[0]), 3, 3); // this should only ever be called for T==double so cast is to avoid constexpr ifs from C++17
|
||||
}
|
||||
eval_ = gsl_vector_alloc (3);
|
||||
evec_ = gsl_matrix_alloc (3, 3);
|
||||
wsp_ = gsl_eigen_symmv_alloc (3);
|
||||
bdid_alloc_gsl_ = true;
|
||||
}
|
||||
|
||||
if( typeid(T)!=typeid(double) ){
|
||||
for( int i=0; i<9; ++i ) data_double_[i] = double(data_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void free_gsl(){
|
||||
|
|
|
@ -1,12 +1,23 @@
|
|||
#pragma once
|
||||
/*******************************************************************************\
|
||||
odetools.hh - This file is part of MUSIC2 -
|
||||
a code to generate initial conditions for cosmological simulations
|
||||
|
||||
CHANGELOG (only majors, for details see repo):
|
||||
06/2019 - Oliver Hahn - first implementation
|
||||
\*******************************************************************************/
|
||||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
//! ODE integration namespace
|
||||
namespace ode_integrate
|
||||
{
|
||||
|
||||
|
|
|
@ -1,10 +1,20 @@
|
|||
/*******************************************************************\
|
||||
vec3_t.hh - This file is part of MUSIC2 -
|
||||
a code to generate initial conditions for cosmological simulations
|
||||
|
||||
CHANGELOG (only majors, for details see repo):
|
||||
06/2019 - Oliver Hahn - first implementation
|
||||
\*******************************************************************/
|
||||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
//! implements a simple class of 3-vectors of arbitrary scalar type
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <general.hh>
|
||||
#include <grid_fft.hh>
|
||||
#include <config_file.hh>
|
||||
#include <cosmology_calculator.hh>
|
||||
|
||||
enum class output_type {particles,field_lagrangian,field_eulerian};
|
||||
|
||||
|
@ -35,6 +36,9 @@ protected:
|
|||
//! reference to the config_file object that holds all configuration options
|
||||
config_file &cf_;
|
||||
|
||||
//! reference to the cosmology calculator object that does all things cosmological
|
||||
std::unique_ptr<cosmology::calculator> &pcc_;
|
||||
|
||||
//! output file or directory name
|
||||
std::string fname_;
|
||||
|
||||
|
@ -42,8 +46,8 @@ protected:
|
|||
std::string interface_name_;
|
||||
public:
|
||||
//! constructor
|
||||
output_plugin(config_file &cf, std::string interface_name )
|
||||
: cf_(cf), interface_name_(interface_name)
|
||||
output_plugin(config_file &cf, std::unique_ptr<cosmology::calculator>& pcc, std::string interface_name )
|
||||
: cf_(cf), pcc_(pcc), interface_name_(interface_name)
|
||||
{
|
||||
fname_ = cf_.get_value<std::string>("output", "filename");
|
||||
}
|
||||
|
@ -88,7 +92,7 @@ public:
|
|||
struct output_plugin_creator
|
||||
{
|
||||
//! create an instance of a plug-in
|
||||
virtual std::unique_ptr<output_plugin> create(config_file &cf) const = 0;
|
||||
virtual std::unique_ptr<output_plugin> create(config_file &cf, std::unique_ptr<cosmology::calculator>& pcc) const = 0;
|
||||
|
||||
//! destroy an instance of a plug-in
|
||||
virtual ~output_plugin_creator() {}
|
||||
|
@ -113,12 +117,12 @@ struct output_plugin_creator_concrete : public output_plugin_creator
|
|||
}
|
||||
|
||||
//! create an instance of the plug-in
|
||||
std::unique_ptr<output_plugin> create(config_file &cf) const
|
||||
std::unique_ptr<output_plugin> create(config_file &cf, std::unique_ptr<cosmology::calculator>& pcc) const
|
||||
{
|
||||
return std::make_unique<Derived>(cf); // Derived( cf );
|
||||
return std::make_unique<Derived>(cf,pcc); // Derived( cf );
|
||||
}
|
||||
};
|
||||
|
||||
//! failsafe version to select the output plug-in
|
||||
std::unique_ptr<output_plugin> select_output_plugin(config_file &cf);
|
||||
std::unique_ptr<output_plugin> select_output_plugin(config_file &cf, std::unique_ptr<cosmology::calculator>& pcc);
|
||||
|
||||
|
|
|
@ -39,19 +39,19 @@ namespace particle
|
|||
const std::vector<std::vector<vec3_t<real_t>>> lattice_shifts =
|
||||
{
|
||||
// first shift must always be zero! (otherwise set_positions and set_velocities break)
|
||||
/* SC : */ {{0.0, 0.0, 0.0}},
|
||||
/* BCC: */ {{0.0, 0.0, 0.0}, {0.5, 0.5, 0.5}},
|
||||
/* FCC: */ {{0.0, 0.0, 0.0}, {0.0, 0.5, 0.5}, {0.5, 0.0, 0.5}, {0.5, 0.5, 0.0}},
|
||||
/* RSC: */ {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.5}, {0.0, 0.5, 0.0}, {0.0, 0.5, 0.5}, {0.5, 0.0, 0.0}, {0.5, 0.0, 0.5}, {0.5, 0.5, 0.0}, {0.5, 0.5, 0.5}},
|
||||
/* SC : */ {{real_t{0.0}, real_t{0.0}, real_t{0.0}}},
|
||||
/* BCC: */ {{real_t{0.0}, real_t{0.0}, real_t{0.0}}, {real_t{0.5}, real_t{0.5}, real_t{0.5}}},
|
||||
/* FCC: */ {{real_t{0.0}, real_t{0.0}, real_t{0.0}}, {real_t{0.0}, real_t{0.5}, real_t{0.5}}, {real_t{0.5}, real_t{0.0}, real_t{0.5}}, {real_t{0.5}, real_t{0.5}, real_t{0.0}}},
|
||||
/* RSC: */ {{real_t{0.0}, real_t{0.0}, real_t{0.0}}, {real_t{0.0}, real_t{0.0}, real_t{0.5}}, {real_t{0.0}, real_t{0.5}, real_t{0.0}}, {real_t{0.0}, real_t{0.5}, real_t{0.5}}, {real_t{0.5}, real_t{0.0}, real_t{0.0}}, {real_t{0.5}, real_t{0.0}, real_t{0.5}}, {real_t{0.5}, real_t{0.5}, real_t{0.0}}, {real_t{0.5}, real_t{0.5}, real_t{0.5}}},
|
||||
};
|
||||
|
||||
const std::vector<vec3_t<real_t>> second_lattice_shift =
|
||||
{
|
||||
/* SC : */ {0.5, 0.5, 0.5}, // this corresponds to CsCl lattice
|
||||
/* BCC: */ {0.5, 0.5, 0.0}, // is there a diatomic lattice with BCC base?!?
|
||||
/* FCC: */ {0.5, 0.5, 0.5}, // this corresponds to NaCl lattice
|
||||
// /* FCC: */ {0.25, 0.25, 0.25}, // this corresponds to Zincblende/GaAs lattice
|
||||
/* RSC: */ {0.25, 0.25, 0.25},
|
||||
/* SC : */ {real_t{0.5}, real_t{0.5}, real_t{0.5}}, // this corresponds to CsCl lattice
|
||||
/* BCC: */ {real_t{0.5}, real_t{0.5}, real_t{0.0}}, // is there a diatomic lattice with BCC base?!?
|
||||
/* FCC: */ {real_t{0.5}, real_t{0.5}, real_t{0.5}}, // this corresponds to NaCl lattice
|
||||
// /* FCC: */ {real_t{0.25}, real_t{0.25}, real_t{0.25}}, // this corresponds to Zincblende/GaAs lattice
|
||||
/* RSC: */ {real_t{0.25}, real_t{0.25}, real_t{0.25}},
|
||||
};
|
||||
|
||||
template <typename field_t>
|
||||
|
@ -283,7 +283,7 @@ namespace particle
|
|||
{
|
||||
for (size_t k = 0; k < field.size(2); ++k)
|
||||
{
|
||||
auto pos = field.template get_unit_r_shifted<real_t>(i, j, k, lattice_shifts[lattice_type][ishift] + (is_second_lattice ? second_lattice_shift[lattice_type] : vec3_t<real_t>{0., 0., 0.}));
|
||||
auto pos = field.template get_unit_r_shifted<real_t>(i, j, k, lattice_shifts[lattice_type][ishift] + (is_second_lattice ? second_lattice_shift[lattice_type] : vec3_t<real_t>{real_t(0.), real_t(0.), real_t(0.)}));
|
||||
if (b64reals)
|
||||
{
|
||||
particles_.set_pos64(ipcount++, idim, pos[idim] * lunit + field.relem(i, j, k));
|
||||
|
|
|
@ -51,7 +51,7 @@ class lattice_gradient{
|
|||
private:
|
||||
const real_t boxlen_, aini_;
|
||||
const size_t ngmapto_, ngrid_, ngrid32_;
|
||||
const real_t mapratio_, XmL_;
|
||||
const real_t mapratio_;//, XmL_;
|
||||
Grid_FFT<real_t,false> D_xx_, D_xy_, D_xz_, D_yy_, D_yz_, D_zz_;
|
||||
Grid_FFT<real_t,false> grad_x_, grad_y_, grad_z_;
|
||||
std::vector<vec3_t<real_t>> vectk_;
|
||||
|
@ -76,14 +76,14 @@ private:
|
|||
//! === vectors, reciprocals and normals for the SC lattice ===
|
||||
const int charge_fac_sc = 1;
|
||||
const mat3_t<real_t> mat_bravais_sc{
|
||||
1.0, 0.0, 0.0,
|
||||
0.0, 1.0, 0.0,
|
||||
0.0, 0.0, 1.0,
|
||||
real_t{1.0}, real_t{0.0}, real_t{0.0},
|
||||
real_t{0.0}, real_t{1.0}, real_t{0.0},
|
||||
real_t{0.0}, real_t{0.0}, real_t{1.0},
|
||||
};
|
||||
const mat3_t<real_t> mat_reciprocal_sc{
|
||||
twopi, 0.0, 0.0,
|
||||
0.0, twopi, 0.0,
|
||||
0.0, 0.0, twopi,
|
||||
twopi, real_t{0.0}, real_t{0.0},
|
||||
real_t{0.0}, twopi, real_t{0.0},
|
||||
real_t{0.0}, real_t{0.0}, twopi,
|
||||
};
|
||||
const mat3_t<int> mat_invrecip_sc{
|
||||
2, 0, 0,
|
||||
|
@ -91,22 +91,22 @@ private:
|
|||
0, 0, 2,
|
||||
};
|
||||
const std::vector<vec3_t<real_t>> normals_sc{
|
||||
{pi,0.,0.},{-pi,0.,0.},
|
||||
{0.,pi,0.},{0.,-pi,0.},
|
||||
{0.,0.,pi},{0.,0.,-pi},
|
||||
{pi,real_t{0.},real_t{0.}},{-pi,real_t{0.},real_t{0.}},
|
||||
{real_t{0.},pi,real_t{0.}},{real_t{0.},-pi,real_t{0.}},
|
||||
{real_t{0.},real_t{0.},pi},{real_t{0.},real_t{0.},-pi},
|
||||
};
|
||||
|
||||
|
||||
//! === vectors, reciprocals and normals for the BCC lattice ===
|
||||
const int charge_fac_bcc = 2;
|
||||
const mat3_t<real_t> mat_bravais_bcc{
|
||||
1.0, 0.0, 0.5,
|
||||
0.0, 1.0, 0.5,
|
||||
0.0, 0.0, 0.5,
|
||||
real_t{1.0}, real_t{0.0}, real_t{0.5},
|
||||
real_t{0.0}, real_t{1.0}, real_t{0.5},
|
||||
real_t{0.0}, real_t{0.0}, real_t{0.5},
|
||||
};
|
||||
const mat3_t<real_t> mat_reciprocal_bcc{
|
||||
twopi, 0.0, 0.0,
|
||||
0.0, twopi, 0.0,
|
||||
twopi, real_t{0.0}, real_t{0.0},
|
||||
real_t{0.0}, twopi, real_t{0.0},
|
||||
-twopi, -twopi, fourpi,
|
||||
};
|
||||
const mat3_t<int> mat_invrecip_bcc{
|
||||
|
@ -115,23 +115,23 @@ private:
|
|||
1, 1, 1,
|
||||
};
|
||||
const std::vector<vec3_t<real_t>> normals_bcc{
|
||||
{0.,pi,pi},{0.,-pi,pi},{0.,pi,-pi},{0.,-pi,-pi},
|
||||
{pi,0.,pi},{-pi,0.,pi},{pi,0.,-pi},{-pi,0.,-pi},
|
||||
{pi,pi,0.},{-pi,pi,0.},{pi,-pi,0.},{-pi,-pi,0.}
|
||||
{real_t{0.0},pi,pi},{real_t{0.0},-pi,pi},{real_t{0.0},pi,-pi},{real_t{0.0},-pi,-pi},
|
||||
{pi,real_t{0.0},pi},{-pi,real_t{0.0},pi},{pi,real_t{0.0},-pi},{-pi,real_t{0.0},-pi},
|
||||
{pi,pi,real_t{0.0}},{-pi,pi,real_t{0.0}},{pi,-pi,real_t{0.0}},{-pi,-pi,real_t{0.0}}
|
||||
};
|
||||
|
||||
|
||||
//! === vectors, reciprocals and normals for the FCC lattice ===
|
||||
const int charge_fac_fcc = 4;
|
||||
const mat3_t<real_t> mat_bravais_fcc{
|
||||
0.0, 0.5, 0.0,
|
||||
0.5, 0.0, 1.0,
|
||||
0.5, 0.5, 0.0,
|
||||
real_t{0.0}, real_t{0.5}, real_t{0.0},
|
||||
real_t{0.5}, real_t{0.0}, real_t{1.0},
|
||||
real_t{0.5}, real_t{0.5}, real_t{0.0},
|
||||
};
|
||||
const mat3_t<real_t> mat_reciprocal_fcc{
|
||||
-fourpi, fourpi, twopi,
|
||||
0.0, 0.0, twopi,
|
||||
fourpi, 0.0, -twopi,
|
||||
real_t{0.0}, real_t{0.0}, twopi,
|
||||
fourpi, real_t{0.0}, -twopi,
|
||||
};
|
||||
const mat3_t<int> mat_invrecip_fcc{
|
||||
0, 1, 1,
|
||||
|
@ -139,9 +139,9 @@ private:
|
|||
0, 2, 0,
|
||||
};
|
||||
const std::vector<vec3_t<real_t>> normals_fcc{
|
||||
{twopi,0.,0.},{-twopi,0.,0.},
|
||||
{0.,twopi,0.},{0.,-twopi,0.},
|
||||
{0.,0.,twopi},{0.,0.,-twopi},
|
||||
{twopi,real_t{0.0},real_t{0.0}},{-twopi,real_t{0.0},real_t{0.0}},
|
||||
{real_t{0.0},twopi,real_t{0.0}},{real_t{0.0},-twopi,real_t{0.0}},
|
||||
{real_t{0.0},real_t{0.0},twopi},{real_t{0.0},real_t{0.0},-twopi},
|
||||
{+pi,+pi,+pi},{+pi,+pi,-pi},
|
||||
{+pi,-pi,+pi},{+pi,-pi,-pi},
|
||||
{-pi,+pi,+pi},{-pi,+pi,-pi},
|
||||
|
@ -223,7 +223,7 @@ private:
|
|||
#pragma omp parallel
|
||||
{
|
||||
//... temporary to hold values of the dynamical matrix
|
||||
mat3_t<real_t> matD(0.0);
|
||||
mat3_t<real_t> matD(real_t(0.0));
|
||||
|
||||
#pragma omp for
|
||||
for( ptrdiff_t i=0; i<nlattice; ++i ){
|
||||
|
@ -421,7 +421,7 @@ private:
|
|||
|
||||
if( !is_in(i,j,k,mat_invrecip) ){
|
||||
auto average_lv = [&]( const auto& t1, const auto& t2, const auto& t3, vec3_t<real_t>& v, vec3_t<real_t>& l ) {
|
||||
v = 0.0; l = 0.0;
|
||||
v = real_t(0.0); l = real_t(0.0);
|
||||
int count(0);
|
||||
|
||||
auto add_lv = [&]( auto it ) -> void {
|
||||
|
@ -476,9 +476,9 @@ private:
|
|||
// ///////////////////////////////////
|
||||
// // project onto spherical coordinate vectors
|
||||
|
||||
real_t kr = kv.norm(), kphi = kr>0.0? std::atan2(kv.y,kv.x) : 0.0, ktheta = kr>0.0? std::acos( kv.z / kr ): 0.0;
|
||||
real_t kr = kv.norm(), kphi = kr>0.0? std::atan2(kv.y,kv.x) : real_t(0.0), ktheta = kr>0.0? std::acos( kv.z / kr ): real_t(0.0);
|
||||
real_t st = std::sin(ktheta), ct = std::cos(ktheta), sp = std::sin(kphi), cp = std::cos(kphi);
|
||||
vec3_t<real_t> e_r( st*cp, st*sp, ct), e_theta( ct*cp, ct*sp, -st), e_phi( -sp, cp, 0.0 );
|
||||
vec3_t<real_t> e_r( st*cp, st*sp, ct), e_theta( ct*cp, ct*sp, -st), e_phi( -sp, cp, real_t(0.0) );
|
||||
|
||||
// re-normalise to that longitudinal amplitude is exact
|
||||
double renorm = evec1.dot( e_r ); if( renorm < 0.01 ) renorm = 1.0;
|
||||
|
@ -522,7 +522,7 @@ public:
|
|||
aini_ ( 1.0/(1.0+the_config.get_value<double>("setup", "zstart")) ),
|
||||
ngmapto_( the_config.get_value<size_t>("setup", "GridRes") ),
|
||||
ngrid_( ngridself ), ngrid32_( std::pow(ngrid_, 1.5) ), mapratio_(real_t(ngrid_)/real_t(ngmapto_)),
|
||||
XmL_ ( the_config.get_value<double>("cosmology", "Omega_L") / the_config.get_value<double>("cosmology", "Omega_m") ),
|
||||
//XmL_ ( the_config.get_value<double>("cosmology", "Omega_L") / the_config.get_value<double>("cosmology", "Omega_m") ),
|
||||
D_xx_({ngrid_, ngrid_, ngrid_}, {1.0,1.0,1.0}), D_xy_({ngrid_, ngrid_, ngrid_}, {1.0,1.0,1.0}),
|
||||
D_xz_({ngrid_, ngrid_, ngrid_}, {1.0,1.0,1.0}), D_yy_({ngrid_, ngrid_, ngrid_}, {1.0,1.0,1.0}),
|
||||
D_yz_({ngrid_, ngrid_, ngrid_}, {1.0,1.0,1.0}), D_zz_({ngrid_, ngrid_, ngrid_}, {1.0,1.0,1.0}),
|
||||
|
|
|
@ -69,4 +69,7 @@ static constexpr double u_SI = 1.660539040e-27;
|
|||
// critical density of the Universe in h^2 kg/m^3
|
||||
static constexpr double rhocrit_h2_SI = 3 * 1e10 / (8 * pi_ * G_SI) / Mpc_SI / Mpc_SI;
|
||||
|
||||
// solar mass in kg
|
||||
static constexpr double Msun_SI = 1.98847e30;
|
||||
|
||||
} // namespace phys_const
|
|
@ -21,29 +21,31 @@
|
|||
#include <memory>
|
||||
#include <general.hh>
|
||||
#include <config_file.hh>
|
||||
#include <cosmology_parameters.hh>
|
||||
|
||||
enum tf_type
|
||||
{
|
||||
total,
|
||||
cdm,
|
||||
baryon,
|
||||
vtotal,
|
||||
vcdm,
|
||||
vbaryon,
|
||||
deltabc,
|
||||
total0,
|
||||
cdm0,
|
||||
baryon0,
|
||||
vtotal0,
|
||||
vcdm0,
|
||||
vbaryon0,
|
||||
delta_matter,
|
||||
delta_cdm,
|
||||
delta_baryon,
|
||||
theta_matter,
|
||||
theta_cdm,
|
||||
theta_baryon,
|
||||
delta_bc,
|
||||
theta_bc,
|
||||
delta_matter0,
|
||||
delta_cdm0,
|
||||
delta_baryon0,
|
||||
theta_matter0,
|
||||
theta_cdm0,
|
||||
theta_baryon0,
|
||||
};
|
||||
|
||||
class TransferFunction_plugin
|
||||
{
|
||||
public:
|
||||
// Cosmology cosmo_; //!< cosmological parameter, read from config_file
|
||||
config_file *pcf_; //!< pointer to config_file from which to read parameters
|
||||
const cosmology::parameters& cosmo_params_; //!< cosmological parameters are stored here
|
||||
bool tf_distinct_; //!< bool if density transfer function is distinct for baryons and DM
|
||||
bool tf_withvel_; //!< bool if also have velocity transfer functions
|
||||
bool tf_withtotal0_; //!< have the z=0 spectrum for normalisation purposes
|
||||
|
@ -52,8 +54,9 @@ class TransferFunction_plugin
|
|||
|
||||
public:
|
||||
//! constructor
|
||||
TransferFunction_plugin(config_file &cf)
|
||||
: pcf_(&cf), tf_distinct_(false), tf_withvel_(false), tf_withtotal0_(false), tf_velunits_(false), tf_isnormalised_(false)
|
||||
TransferFunction_plugin(config_file &cf, const cosmology::parameters& cosmo_params)
|
||||
: pcf_(&cf), cosmo_params_( cosmo_params ), tf_distinct_(false), tf_withvel_(false),
|
||||
tf_withtotal0_(false), tf_velunits_(false), tf_isnormalised_(false)
|
||||
{ }
|
||||
|
||||
//! destructor
|
||||
|
@ -100,7 +103,7 @@ class TransferFunction_plugin
|
|||
struct TransferFunction_plugin_creator
|
||||
{
|
||||
//! create an instance of a transfer function plug-in
|
||||
virtual std::unique_ptr<TransferFunction_plugin> create(config_file &cf) const = 0;
|
||||
virtual std::unique_ptr<TransferFunction_plugin> create(config_file &cf, const cosmology::parameters& cp) const = 0;
|
||||
|
||||
//! destroy an instance of a plug-in
|
||||
virtual ~TransferFunction_plugin_creator() {}
|
||||
|
@ -121,12 +124,12 @@ struct TransferFunction_plugin_creator_concrete : public TransferFunction_plugin
|
|||
}
|
||||
|
||||
//! create an instance of the plug-in
|
||||
std::unique_ptr<TransferFunction_plugin> create(config_file &cf) const
|
||||
std::unique_ptr<TransferFunction_plugin> create(config_file &cf, const cosmology::parameters& cp) const
|
||||
{
|
||||
return std::make_unique<Derived>(cf);
|
||||
return std::make_unique<Derived>(cf,cp);
|
||||
}
|
||||
};
|
||||
|
||||
// typedef TransferFunction_plugin TransferFunction;
|
||||
|
||||
std::unique_ptr<TransferFunction_plugin> select_TransferFunction_plugin(config_file &cf);
|
||||
std::unique_ptr<TransferFunction_plugin> select_TransferFunction_plugin(config_file &cf, const cosmology::parameters& cp);
|
||||
|
|
111
src/cosmology_parameters.cc
Normal file
111
src/cosmology_parameters.cc
Normal file
|
@ -0,0 +1,111 @@
|
|||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <cosmology_parameters.hh>
|
||||
|
||||
namespace cosmology{
|
||||
|
||||
//! we store here the preset cosmological paramters
|
||||
parameters::defaultmmap_t parameters::default_pmaps_
|
||||
{
|
||||
//=============================================================================
|
||||
// Planck 2018 baseline cosmologies
|
||||
// cf. https://wiki.cosmos.esa.int/planck-legacy-archive/images/b/be/Baseline_params_table_2018_68pc.pdf
|
||||
//=============================================================================
|
||||
|
||||
// baseline 2.17 base_plikHM_TTTEEE_lowl_lowE_lensing
|
||||
{"Planck2018EE", {
|
||||
{"h", 0.67321},
|
||||
{"Omega_m", 0.3158},
|
||||
{"Omega_b", 0.04938898},
|
||||
{"Omega_DE", 0.6842},
|
||||
{"w_0", -1.0},
|
||||
{"w_a", 0.0},
|
||||
{"n_s", 0.96605},
|
||||
{"A_s", 2.1005e-9},
|
||||
{"k_p", 0.05},
|
||||
{"YHe", 0.245401},
|
||||
{"N_ur", 2.046},
|
||||
{"m_nu1", 0.06},
|
||||
{"m_nu2", 0.0},
|
||||
{"m_nu3", 0.0},
|
||||
{"Tcmb", 2.7255}}},
|
||||
|
||||
// baseline 2.18 base_plikHM_TTTEEE_lowl_lowE_lensing_post_BAO
|
||||
{"Planck2018EE+BAO", {
|
||||
{"h", 0.67702},
|
||||
{"Omega_m", 0.3106},
|
||||
{"Omega_b", 0.04897284},
|
||||
{"Omega_DE", 0.6894},
|
||||
{"w_0", -1.0},
|
||||
{"w_a", 0.0},
|
||||
{"n_s", 0.96824},
|
||||
{"A_s", 2.1073e-9},
|
||||
{"k_p", 0.05},
|
||||
{"YHe", 0.245425},
|
||||
{"N_ur", 2.046},
|
||||
{"m_nu1", 0.06},
|
||||
{"m_nu2", 0.0},
|
||||
{"m_nu3", 0.0},
|
||||
{"Tcmb", 2.7255}}},
|
||||
|
||||
// baseline 2.19 base_plikHM_TTTEEE_lowl_lowE_lensing_post_Pantheon
|
||||
{"Planck2018EE+SN", {
|
||||
{"h", 0.6749},
|
||||
{"Omega_m", 0.3134},
|
||||
{"Omega_b", 0.04919537},
|
||||
{"Omega_DE", 0.6866},
|
||||
{"w_0", -1.0},
|
||||
{"w_a", 0.0},
|
||||
{"n_s", 0.96654},
|
||||
{"A_s", 2.1020e-9},
|
||||
{"k_p", 0.05},
|
||||
{"YHe", 0.245411},
|
||||
{"N_ur", 2.046},
|
||||
{"m_nu1", 0.06},
|
||||
{"m_nu2", 0.0},
|
||||
{"m_nu3", 0.0},
|
||||
{"Tcmb", 2.7255}}},
|
||||
|
||||
// baseline 2.20 base_plikHM_TTTEEE_lowl_lowE_lensing_post_BAO_Pantheon
|
||||
{"Planck2018EE+BAO+SN", {
|
||||
{"h", 0.67742},
|
||||
{"Omega_m", 0.3099},
|
||||
{"Omega_b", 0.048891054},
|
||||
{"Omega_DE", 0.6901},
|
||||
{"w_0", -1.0},
|
||||
{"w_a", 0.0},
|
||||
{"n_s", 0.96822},
|
||||
{"A_s", 2.1064e-9},
|
||||
{"k_p", 0.05},
|
||||
{"YHe", 0.245421},
|
||||
{"N_ur", 2.046},
|
||||
{"m_nu1", 0.06},
|
||||
{"m_nu2", 0.0},
|
||||
{"m_nu3", 0.0},
|
||||
{"Tcmb", 2.7255}}}
|
||||
};
|
||||
|
||||
|
||||
void print_ParameterSets( void ){
|
||||
music::ilog << "Available cosmology parameter sets:" << std::endl;
|
||||
cosmology::parameters p;
|
||||
p.print_available_sets();
|
||||
music::ilog << std::endl;
|
||||
}
|
||||
|
||||
}// end namespace cosmology
|
271
src/grid_fft.cc
271
src/grid_fft.cc
|
@ -29,7 +29,7 @@ void Grid_FFT<data_t, bdistributed>::allocate(void)
|
|||
music::dlog.Print("[FFT] Setting up a shared memory field %lux%lux%lu\n", n_[0], n_[1], n_[2]);
|
||||
if (typeid(data_t) == typeid(real_t))
|
||||
{
|
||||
data_ = reinterpret_cast<data_t *>(fftw_malloc(ntot_ * sizeof(real_t)));
|
||||
data_ = reinterpret_cast<data_t *>(FFTW_API(malloc)(ntot_ * sizeof(real_t)));
|
||||
cdata_ = reinterpret_cast<ccomplex_t *>(data_);
|
||||
|
||||
plan_ = FFTW_API(plan_dft_r2c_3d)(n_[0], n_[1], n_[2], (real_t *)data_, (complex_t *)data_, FFTW_RUNMODE);
|
||||
|
@ -37,7 +37,7 @@ void Grid_FFT<data_t, bdistributed>::allocate(void)
|
|||
}
|
||||
else if (typeid(data_t) == typeid(ccomplex_t))
|
||||
{
|
||||
data_ = reinterpret_cast<data_t *>(fftw_malloc(ntot_ * sizeof(ccomplex_t)));
|
||||
data_ = reinterpret_cast<data_t *>(FFTW_API(malloc)(ntot_ * sizeof(ccomplex_t)));
|
||||
cdata_ = reinterpret_cast<ccomplex_t *>(data_);
|
||||
|
||||
plan_ = FFTW_API(plan_dft_3d)(n_[0], n_[1], n_[2], (complex_t *)data_, (complex_t *)data_, FFTW_FORWARD, FFTW_RUNMODE);
|
||||
|
@ -99,10 +99,10 @@ void Grid_FFT<data_t, bdistributed>::allocate(void)
|
|||
|
||||
if (typeid(data_t) == typeid(real_t))
|
||||
{
|
||||
cmplxsz = FFTW_API(mpi_local_size_3d_transposed)(n_[0], n_[1], n_[2] / 2 + 1, MPI_COMM_WORLD,
|
||||
cmplxsz = FFTW_API(mpi_local_size_3d_transposed)(n_[0], n_[1], n_[2], MPI_COMM_WORLD,
|
||||
&local_0_size_, &local_0_start_, &local_1_size_, &local_1_start_);
|
||||
ntot_ = 2 * cmplxsz;
|
||||
data_ = (data_t *)fftw_malloc(ntot_ * sizeof(real_t));
|
||||
ntot_ = local_0_size_ * n_[1] * (n_[2]+2);
|
||||
data_ = (data_t *)FFTW_API(malloc)(ntot_ * sizeof(real_t));
|
||||
cdata_ = reinterpret_cast<ccomplex_t *>(data_);
|
||||
plan_ = FFTW_API(mpi_plan_dft_r2c_3d)(n_[0], n_[1], n_[2], (real_t *)data_, (complex_t *)data_,
|
||||
MPI_COMM_WORLD, FFTW_RUNMODE | FFTW_MPI_TRANSPOSED_OUT);
|
||||
|
@ -114,7 +114,7 @@ void Grid_FFT<data_t, bdistributed>::allocate(void)
|
|||
cmplxsz = FFTW_API(mpi_local_size_3d_transposed)(n_[0], n_[1], n_[2], MPI_COMM_WORLD,
|
||||
&local_0_size_, &local_0_start_, &local_1_size_, &local_1_start_);
|
||||
ntot_ = cmplxsz;
|
||||
data_ = (data_t *)fftw_malloc(ntot_ * sizeof(ccomplex_t));
|
||||
data_ = (data_t *)FFTW_API(malloc)(ntot_ * sizeof(ccomplex_t));
|
||||
cdata_ = reinterpret_cast<ccomplex_t *>(data_);
|
||||
plan_ = FFTW_API(mpi_plan_dft_3d)(n_[0], n_[1], n_[2], (complex_t *)data_, (complex_t *)data_,
|
||||
MPI_COMM_WORLD, FFTW_FORWARD, FFTW_RUNMODE | FFTW_MPI_TRANSPOSED_OUT);
|
||||
|
@ -185,6 +185,7 @@ void Grid_FFT<data_t, bdistributed>::ApplyNorm(void)
|
|||
data_[i] *= fft_norm_fac_;
|
||||
}
|
||||
|
||||
//! Perform a backwards Fourier transformation
|
||||
template <typename data_t, bool bdistributed>
|
||||
void Grid_FFT<data_t, bdistributed>::FourierTransformForward(bool do_transform)
|
||||
{
|
||||
|
@ -217,6 +218,7 @@ void Grid_FFT<data_t, bdistributed>::FourierTransformForward(bool do_transform)
|
|||
}
|
||||
}
|
||||
|
||||
//! Perform a forward Fourier transformation
|
||||
template <typename data_t, bool bdistributed>
|
||||
void Grid_FFT<data_t, bdistributed>::FourierTransformBackward(bool do_transform)
|
||||
{
|
||||
|
@ -248,6 +250,229 @@ void Grid_FFT<data_t, bdistributed>::FourierTransformBackward(bool do_transform)
|
|||
}
|
||||
}
|
||||
|
||||
//! Perform a copy to another field, not necessarily the same size, using Fourier interpolation
|
||||
template <typename data_t, bool bdistributed>
|
||||
void Grid_FFT<data_t, bdistributed>::FourierInterpolateCopyTo( grid_fft_t &grid_to )
|
||||
{
|
||||
grid_fft_t &grid_from = *this;
|
||||
|
||||
//... transform both grids to Fourier space
|
||||
grid_from.FourierTransformForward(true);
|
||||
grid_to.FourierTransformForward(false);
|
||||
|
||||
// if grids are same size, we directly copy without the need for interpolation
|
||||
if( grid_from.n_[0] == grid_to.n_[0]
|
||||
&& grid_from.n_[1] == grid_to.n_[1]
|
||||
&& grid_from.n_[2] == grid_to.n_[2] )
|
||||
{
|
||||
grid_to.copy_from( grid_from );
|
||||
return;
|
||||
}
|
||||
|
||||
// set to zero so that regions without data are zeroed
|
||||
grid_to.zero();
|
||||
|
||||
// if not running MPI, then can do without sending and receiving
|
||||
#if !defined(USE_MPI)
|
||||
|
||||
// determine effective Nyquist modes representable by both fields and their locations in array
|
||||
size_t fny0_left = std::min(grid_from.n_[0] / 2, grid_to.n_[0] / 2);
|
||||
size_t fny0_right = std::max(grid_from.n_[0] - grid_to.n_[0] / 2, grid_from.n_[0] / 2);
|
||||
size_t fny1_left = std::min(grid_from.n_[1] / 2, grid_to.n_[1] / 2);
|
||||
size_t fny1_right = std::max(grid_from.n_[1] - grid_to.n_[1] / 2, grid_from.n_[1] / 2);
|
||||
size_t fny2_left = std::min(grid_from.n_[2] / 2, grid_to.n_[2] / 2);
|
||||
// size_t fny2_right = std::max(grid_from.n_[2] - grid_to.n_[2] / 2, grid_from.n_[2] / 2);
|
||||
|
||||
const size_t fny0_left_recv = fny0_left;
|
||||
const size_t fny0_right_recv = (fny0_right + grid_to.n_[0]) - grid_from.n_[0];
|
||||
const size_t fny1_left_recv = fny1_left;
|
||||
const size_t fny1_right_recv = (fny1_right + grid_to.n_[1]) - grid_from.n_[1];
|
||||
const size_t fny2_left_recv = fny2_left;
|
||||
// const size_t fny2_right_recv = (fny2_right + grid_to.n_[2]) - grid_from.n_[2];
|
||||
|
||||
#pragma omp parallel for
|
||||
for( size_t i=0; i<grid_to.size(0); ++i )
|
||||
{
|
||||
if (i < fny0_left_recv || i > fny0_right_recv)
|
||||
{
|
||||
size_t isend = (i < fny0_left_recv)? i : (i + grid_from.n_[0]) - grid_to.n_[0];
|
||||
|
||||
// copy data slice into new grid, avoiding modes that do not exist in both
|
||||
for( size_t j=0; j<grid_to.size(1); ++j )
|
||||
{
|
||||
if( j < fny1_left_recv || j > fny1_right_recv )
|
||||
{
|
||||
const size_t jsend = (j < fny1_left_recv)? j : (j + grid_from.n_[1]) - grid_to.n_[1];
|
||||
|
||||
for( size_t k=0; k<fny2_left_recv; ++k )
|
||||
{
|
||||
grid_to.kelem(i,j,k) = grid_from.kelem(isend,jsend,k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
// if they are not the same size, we use Fourier interpolation to upscale/downscale
|
||||
double tstart = get_wtime();
|
||||
music::dlog << "[MPI] Started scatter for Fourier interpolation/copy" << std::endl;
|
||||
|
||||
//... determine communication offsets
|
||||
std::vector<ptrdiff_t> offsets_send, offsets_recv, sizes_send, sizes_recv;
|
||||
|
||||
// this should use bisection, not linear search
|
||||
auto get_task = [](ptrdiff_t index, const std::vector<ptrdiff_t> &offsets, const int ntasks) -> int
|
||||
{
|
||||
int itask = 0;
|
||||
while (itask < ntasks - 1 && offsets[itask + 1] <= index)
|
||||
++itask;
|
||||
return itask;
|
||||
};
|
||||
|
||||
int ntasks(MPI::get_size());
|
||||
|
||||
offsets_send.assign(ntasks+1, 0);
|
||||
sizes_send.assign(ntasks, 0);
|
||||
offsets_recv.assign(ntasks+1, 0);
|
||||
sizes_recv.assign(ntasks, 0);
|
||||
|
||||
MPI_Allgather(&grid_from.local_1_size_, 1, MPI_LONG_LONG, &sizes_send[0], 1,
|
||||
MPI_LONG_LONG, MPI_COMM_WORLD);
|
||||
MPI_Allgather(&grid_to.local_1_size_, 1, MPI_LONG_LONG, &sizes_recv[0], 1,
|
||||
MPI_LONG_LONG, MPI_COMM_WORLD);
|
||||
MPI_Allgather(&grid_from.local_1_start_, 1, MPI_LONG_LONG, &offsets_send[0], 1,
|
||||
MPI_LONG_LONG, MPI_COMM_WORLD);
|
||||
MPI_Allgather(&grid_to.local_1_start_, 1, MPI_LONG_LONG, &offsets_recv[0], 1,
|
||||
MPI_LONG_LONG, MPI_COMM_WORLD);
|
||||
|
||||
for( int i=0; i< CONFIG::MPI_task_size; i++ ){
|
||||
if( offsets_send[i+1] < offsets_send[i] + sizes_send[i] ) offsets_send[i+1] = offsets_send[i] + sizes_send[i];
|
||||
if( offsets_recv[i+1] < offsets_recv[i] + sizes_recv[i] ) offsets_recv[i+1] = offsets_recv[i] + sizes_recv[i];
|
||||
}
|
||||
|
||||
const MPI_Datatype datatype =
|
||||
(typeid(data_t) == typeid(float)) ? MPI_C_FLOAT_COMPLEX
|
||||
: (typeid(data_t) == typeid(double)) ? MPI_C_DOUBLE_COMPLEX
|
||||
: (typeid(data_t) == typeid(long double)) ? MPI_C_LONG_DOUBLE_COMPLEX
|
||||
: MPI_BYTE;
|
||||
|
||||
const size_t slicesz = grid_from.size(1) * grid_from.size(3);
|
||||
|
||||
// determine effective Nyquist modes representable by both fields and their locations in array
|
||||
const size_t fny0_left = std::min(grid_from.n_[1] / 2, grid_to.n_[1] / 2);
|
||||
const size_t fny0_right = std::max(grid_from.n_[1] - grid_to.n_[1] / 2, grid_from.n_[1] / 2);
|
||||
const size_t fny1_left = std::min(grid_from.n_[0] / 2, grid_to.n_[0] / 2);
|
||||
const size_t fny1_right = std::max(grid_from.n_[0] - grid_to.n_[0] / 2, grid_from.n_[0] / 2);
|
||||
const size_t fny2_left = std::min(grid_from.n_[2] / 2, grid_to.n_[2] / 2);
|
||||
// size_t fny2_right = std::max(grid_from.n_[2] - grid_to.n_[2] / 2, grid_from.n_[2] / 2);
|
||||
|
||||
const size_t fny0_left_recv = fny0_left;
|
||||
const size_t fny0_right_recv = (fny0_right + grid_to.n_[1]) - grid_from.n_[1];
|
||||
const size_t fny1_left_recv = fny1_left;
|
||||
const size_t fny1_right_recv = (fny1_right + grid_to.n_[0]) - grid_from.n_[0];
|
||||
const size_t fny2_left_recv = fny2_left;
|
||||
// const size_t fny2_right_recv = (fny2_right + grid_to.n_[2]) - grid_from.n_[2];
|
||||
|
||||
//--- send data from buffer ---------------------------------------------------
|
||||
|
||||
std::vector<MPI_Request> req;
|
||||
MPI_Request temp_req;
|
||||
|
||||
for (size_t i = 0; i < grid_from.size(0); ++i)
|
||||
{
|
||||
size_t iglobal_send = i + offsets_send[CONFIG::MPI_task_rank];
|
||||
|
||||
if (iglobal_send < fny0_left)
|
||||
{
|
||||
size_t iglobal_recv = iglobal_send;
|
||||
int sendto = get_task(iglobal_recv, offsets_recv, CONFIG::MPI_task_size);
|
||||
MPI_Isend(&grid_from.kelem(i * slicesz), (int)slicesz, datatype, sendto,
|
||||
(int)iglobal_recv, MPI_COMM_WORLD, &temp_req);
|
||||
req.push_back(temp_req);
|
||||
// std::cout << "task " << CONFIG::MPI_task_rank << " : added request No" << req.size()-1 << ": Isend #" << iglobal_send << " to task " << sendto << ", size = " << slicesz << std::endl;
|
||||
}
|
||||
if (iglobal_send > fny0_right)
|
||||
{
|
||||
size_t iglobal_recv = (iglobal_send + grid_to.n_[1]) - grid_from.n_[1];
|
||||
int sendto = get_task(iglobal_recv, offsets_recv, CONFIG::MPI_task_size);
|
||||
MPI_Isend(&grid_from.kelem(i * slicesz), (int)slicesz, datatype, sendto,
|
||||
(int)iglobal_recv, MPI_COMM_WORLD, &temp_req);
|
||||
req.push_back(temp_req);
|
||||
// std::cout << "task " << CONFIG::MPI_task_rank << " : added request No" << req.size()-1 << ": Isend #" << iglobal_send << " to task " << sendto << ", size = " << slicesz<< std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
//--- receive data ------------------------------------------------------------
|
||||
#pragma omp parallel if(CONFIG::MPI_threads_ok)
|
||||
{
|
||||
MPI_Status status;
|
||||
ccomplex_t * recvbuf = new ccomplex_t[ slicesz ];
|
||||
|
||||
#pragma omp for schedule(dynamic)
|
||||
for( size_t i=0; i<grid_to.size(0); ++i )
|
||||
{
|
||||
size_t iglobal_recv = i + offsets_recv[CONFIG::MPI_task_rank];
|
||||
|
||||
if (iglobal_recv < fny0_left_recv || iglobal_recv > fny0_right_recv)
|
||||
{
|
||||
size_t iglobal_send = (iglobal_recv < fny0_left_recv)? iglobal_recv : (iglobal_recv + grid_from.n_[1]) - grid_to.n_[1];
|
||||
|
||||
int recvfrom = get_task(iglobal_send, offsets_send, CONFIG::MPI_task_size);
|
||||
|
||||
//#pragma omp critical // need critical region here if we do "MPI_THREAD_FUNNELED",
|
||||
{
|
||||
// receive data slice and check for MPI errors when in debug mode
|
||||
status.MPI_ERROR = MPI_SUCCESS;
|
||||
MPI_Recv(&recvbuf[0], (int)slicesz, datatype, recvfrom, (int)iglobal_recv, MPI_COMM_WORLD, &status);
|
||||
assert(status.MPI_ERROR == MPI_SUCCESS);
|
||||
}
|
||||
|
||||
// copy data slice into new grid, avoiding modes that do not exist in both
|
||||
for( size_t j=0; j<grid_to.size(1); ++j )
|
||||
{
|
||||
if( j < fny1_left_recv || j > fny1_right_recv )
|
||||
{
|
||||
const size_t jsend = (j < fny1_left_recv)? j : (j + grid_from.n_[0]) - grid_to.n_[0];
|
||||
|
||||
for( size_t k=0; k<fny2_left_recv; ++k )
|
||||
{
|
||||
grid_to.kelem(i,j,k) = recvbuf[jsend * grid_from.sizes_[3] + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete[] recvbuf;
|
||||
}
|
||||
MPI_Barrier( MPI_COMM_WORLD );
|
||||
|
||||
MPI_Status status;
|
||||
for (size_t i = 0; i < req.size(); ++i)
|
||||
{
|
||||
// need to set status as wait does not necessarily modify it
|
||||
// c.f. http://www.open-mpi.org/community/lists/devel/2007/04/1402.php
|
||||
status.MPI_ERROR = MPI_SUCCESS;
|
||||
// std::cout << "task " << CONFIG::MPI_task_rank << " : checking request No" << i << std::endl;
|
||||
int flag(1);
|
||||
MPI_Test(&req[i], &flag, &status);
|
||||
if( !flag ){
|
||||
std::cout << "task " << CONFIG::MPI_task_rank << " : request No" << i << " unsuccessful" << std::endl;
|
||||
}
|
||||
|
||||
MPI_Wait(&req[i], &status);
|
||||
// std::cout << "---> ok!" << std::endl;
|
||||
assert(status.MPI_ERROR == MPI_SUCCESS);
|
||||
}
|
||||
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
|
||||
music::dlog.Print("[MPI] Completed scatter for Fourier interpolation/copy, took %fs\n",
|
||||
get_wtime() - tstart);
|
||||
#endif //defined(USE_MPI)
|
||||
}
|
||||
|
||||
|
||||
#define H5_USE_16_API
|
||||
#include <hdf5.h>
|
||||
|
||||
|
@ -586,7 +811,29 @@ void Grid_FFT<data_t, bdistributed>::Write_to_HDF5(std::string fname, std::strin
|
|||
|
||||
#endif
|
||||
|
||||
#if defined(USE_MPI)
|
||||
std::vector<size_t> sizes0(MPI::get_size(), 0);
|
||||
std::vector<size_t> offsets0(MPI::get_size()+1, 0);
|
||||
|
||||
MPI_Allgather((this->space_==kspace_id)? &this->local_1_start_ : &this->local_0_start_, 1,
|
||||
MPI_UNSIGNED_LONG_LONG, &offsets0[0], 1, MPI_UNSIGNED_LONG_LONG, MPI_COMM_WORLD);
|
||||
|
||||
MPI_Allgather((this->space_==kspace_id)? &this->local_1_size_ : &this->local_0_size_, 1,
|
||||
MPI_UNSIGNED_LONG_LONG, &sizes0[0], 1, MPI_UNSIGNED_LONG_LONG, MPI_COMM_WORLD);
|
||||
|
||||
for( int i=0; i< CONFIG::MPI_task_size; i++ ){
|
||||
if( offsets0[i+1] < offsets0[i] + sizes0[i] ) offsets0[i+1] = offsets0[i] + sizes0[i];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(USE_MPI)
|
||||
auto loc_count = size(0), glob_count = size(0);
|
||||
MPI_Allreduce( &loc_count, &glob_count, 1, MPI_UNSIGNED_LONG_LONG, MPI_SUM, MPI_COMM_WORLD );
|
||||
#endif
|
||||
|
||||
#if defined(USE_MPI) && !defined(USE_MPI_IO)
|
||||
|
||||
for (int itask = 0; itask < mpi_size; ++itask)
|
||||
{
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
|
@ -603,7 +850,7 @@ void Grid_FFT<data_t, bdistributed>::Write_to_HDF5(std::string fname, std::strin
|
|||
count[i] = size(i);
|
||||
|
||||
#if defined(USE_MPI)
|
||||
count[0] *= mpi_size;
|
||||
count[0] = glob_count;
|
||||
#endif
|
||||
|
||||
if (typeid(data_t) == typeid(float))
|
||||
|
@ -654,7 +901,7 @@ void Grid_FFT<data_t, bdistributed>::Write_to_HDF5(std::string fname, std::strin
|
|||
plist_id = H5Pcreate(H5P_DATASET_XFER);
|
||||
H5Pset_dxpl_mpio(plist_id, H5FD_MPIO_COLLECTIVE);
|
||||
#else
|
||||
plist_id = H5P_DEFAULT;
|
||||
plist_id = H5P_DEFAULT;
|
||||
#endif
|
||||
|
||||
memspace = H5Screate_simple(3, count, NULL);
|
||||
|
@ -663,9 +910,9 @@ void Grid_FFT<data_t, bdistributed>::Write_to_HDF5(std::string fname, std::strin
|
|||
for (size_t i = 0; i < size(0); ++i)
|
||||
{
|
||||
#if defined(USE_MPI)
|
||||
offset[0] = mpi_rank * size(0) + i;
|
||||
offset[0] = offsets0[mpi_rank] + i;
|
||||
#else
|
||||
offset[0] = i;
|
||||
offset[0] = i;
|
||||
#endif
|
||||
|
||||
for (size_t j = 0; j < size(1); ++j)
|
||||
|
@ -703,7 +950,7 @@ void Grid_FFT<data_t, bdistributed>::Write_to_HDF5(std::string fname, std::strin
|
|||
for (int i = 0; i < 3; ++i)
|
||||
count[i] = size(i);
|
||||
#if defined(USE_MPI)
|
||||
count[0] *= mpi_size;
|
||||
count[0] = glob_count;
|
||||
#endif
|
||||
|
||||
#if defined(USE_MPI) && !defined(USE_MPI_IO)
|
||||
|
@ -738,7 +985,7 @@ void Grid_FFT<data_t, bdistributed>::Write_to_HDF5(std::string fname, std::strin
|
|||
for (size_t i = 0; i < size(0); ++i)
|
||||
{
|
||||
#if defined(USE_MPI)
|
||||
offset[0] = mpi_rank * size(0) + i;
|
||||
offset[0] = offsets0[mpi_rank] + i;//mpi_rank * size(0) + i;
|
||||
#else
|
||||
offset[0] = i;
|
||||
#endif
|
||||
|
|
|
@ -40,12 +40,12 @@ std::unique_ptr<RNG_plugin> the_random_number_generator;
|
|||
std::unique_ptr<output_plugin> the_output_plugin;
|
||||
std::unique_ptr<cosmology::calculator> the_cosmo_calc;
|
||||
|
||||
int Initialise( config_file& the_config )
|
||||
int initialise( config_file& the_config )
|
||||
{
|
||||
the_random_number_generator = std::move(select_RNG_plugin(the_config));
|
||||
the_output_plugin = std::move(select_output_plugin(the_config));
|
||||
the_cosmo_calc = std::make_unique<cosmology::calculator>(the_config);
|
||||
|
||||
the_output_plugin = std::move(select_output_plugin(the_config, the_cosmo_calc));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ void reset () {
|
|||
the_cosmo_calc.reset();
|
||||
}
|
||||
|
||||
int Run( config_file& the_config )
|
||||
int run( config_file& the_config )
|
||||
{
|
||||
//--------------------------------------------------------------------------------------------------------
|
||||
// Read run parameters
|
||||
|
@ -96,14 +96,17 @@ int Run( config_file& the_config )
|
|||
//--------------------------------------------------------------------------------------------------------
|
||||
//! do baryon ICs?
|
||||
const bool bDoBaryons = the_config.get_value_safe<bool>("setup", "DoBaryons", false );
|
||||
//! enable also back-scaled decaying relative velocity mode? only first order!
|
||||
const bool bDoLinearBCcorr = the_config.get_value_safe<bool>("cosmology", "DoBaryonVrel", false);
|
||||
// compute mass fractions
|
||||
std::map< cosmo_species, double > Omega;
|
||||
if( bDoBaryons ){
|
||||
double Om = the_config.get_value<double>("cosmology", "Omega_m");
|
||||
double Ob = the_config.get_value<double>("cosmology", "Omega_b");
|
||||
double Om = the_cosmo_calc->cosmo_param_["Omega_m"];
|
||||
double Ob = the_cosmo_calc->cosmo_param_["Omega_b"];
|
||||
Omega[cosmo_species::dm] = Om-Ob;
|
||||
Omega[cosmo_species::baryon] = Ob;
|
||||
}else{
|
||||
double Om = the_config.get_value<double>("cosmology", "Omega_m");
|
||||
double Om = the_cosmo_calc->cosmo_param_["Omega_m"];
|
||||
Omega[cosmo_species::dm] = Om;
|
||||
Omega[cosmo_species::baryon] = 0.0;
|
||||
}
|
||||
|
@ -137,9 +140,9 @@ int Run( config_file& the_config )
|
|||
|
||||
// Anisotropy parameters for beyond box tidal field
|
||||
const std::array<real_t,3> lss_aniso_lambda = {
|
||||
the_config.get_value_safe<double>("cosmology", "LSS_aniso_lx", 0.0),
|
||||
the_config.get_value_safe<double>("cosmology", "LSS_aniso_ly", 0.0),
|
||||
the_config.get_value_safe<double>("cosmology", "LSS_aniso_lz", 0.0),
|
||||
real_t(the_config.get_value_safe<double>("cosmology", "LSS_aniso_lx", 0.0)),
|
||||
real_t(the_config.get_value_safe<double>("cosmology", "LSS_aniso_ly", 0.0)),
|
||||
real_t(the_config.get_value_safe<double>("cosmology", "LSS_aniso_lz", 0.0)),
|
||||
};
|
||||
|
||||
const real_t lss_aniso_sum_lambda = lss_aniso_lambda[0]+lss_aniso_lambda[1]+lss_aniso_lambda[2];
|
||||
|
@ -161,31 +164,42 @@ int Run( config_file& the_config )
|
|||
const real_t Dplus0 = the_cosmo_calc->get_growth_factor(astart);
|
||||
const real_t vfac = the_cosmo_calc->get_vfact(astart);
|
||||
|
||||
const double g1 = -Dplus0;
|
||||
const double g2 = ((LPTorder>1)? -3.0/7.0*Dplus0*Dplus0 : 0.0);
|
||||
const double g3 = ((LPTorder>2)? 1.0/3.0*Dplus0*Dplus0*Dplus0 : 0.0);
|
||||
// const double g3a = ((LPTorder>2)? 1.0/3.0*Dplus0*Dplus0*Dplus0 : 0.0);
|
||||
// const double g3b = ((LPTorder>2)? -10.0/21.*Dplus0*Dplus0*Dplus0 : 0.0);
|
||||
const double g3c = ((LPTorder>2)? 1.0/7.0*Dplus0*Dplus0*Dplus0 : 0.0);
|
||||
const real_t g1 = -Dplus0;
|
||||
const real_t g2 = ((LPTorder>1)? -3.0/7.0*Dplus0*Dplus0 : 0.0);
|
||||
const real_t g3 = ((LPTorder>2)? 1.0/3.0*Dplus0*Dplus0*Dplus0 : 0.0);
|
||||
const real_t g3c = ((LPTorder>2)? 1.0/7.0*Dplus0*Dplus0*Dplus0 : 0.0);
|
||||
|
||||
// vfac = d log D+ / dt
|
||||
// d(D+^2)/dt = 2*D+ * d D+/dt = 2 * D+^2 * vfac
|
||||
// d(D+^3)/dt = 3*D+^2* d D+/dt = 3 * D+^3 * vfac
|
||||
const double vfac1 = vfac;
|
||||
const double vfac2 = 2*vfac;
|
||||
const double vfac3 = 3*vfac;
|
||||
const real_t vfac1 = vfac;
|
||||
const real_t vfac2 = 2*vfac;
|
||||
const real_t vfac3 = 3*vfac;
|
||||
|
||||
// anisotropic velocity growth factor for external tides
|
||||
// cf. eq. (5) of Stuecker et al. 2020 (https://arxiv.org/abs/2003.06427)
|
||||
const std::array<real_t,3> lss_aniso_alpha = {
|
||||
1.0 - Dplus0 * lss_aniso_lambda[0],
|
||||
1.0 - Dplus0 * lss_aniso_lambda[1],
|
||||
1.0 - Dplus0 * lss_aniso_lambda[2],
|
||||
real_t(1.0) - Dplus0 * lss_aniso_lambda[0],
|
||||
real_t(1.0) - Dplus0 * lss_aniso_lambda[1],
|
||||
real_t(1.0) - Dplus0 * lss_aniso_lambda[2],
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Create arrays
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
// white noise field
|
||||
Grid_FFT<real_t> wnoise({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen});
|
||||
|
||||
//... Fill the wnoise grid with a Gaussian white noise field, we do this first since the RNG might need extra memory
|
||||
music::ilog << "-------------------------------------------------------------------------------" << std::endl;
|
||||
music::ilog << "Generating white noise field...." << std::endl;
|
||||
|
||||
the_random_number_generator->Fill_Grid(wnoise);
|
||||
|
||||
wnoise.FourierTransformForward();
|
||||
|
||||
//... Next, declare LPT related arrays, allocated only as needed by order
|
||||
Grid_FFT<real_t> phi({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen});
|
||||
Grid_FFT<real_t> phi2({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen}, false); // do not allocate these unless needed
|
||||
Grid_FFT<real_t> phi3({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen}, false); // ..
|
||||
|
@ -196,24 +210,12 @@ int Run( config_file& the_config )
|
|||
//... array [.] access to components of A3:
|
||||
std::array<Grid_FFT<real_t> *, 3> A3({&A3x, &A3y, &A3z});
|
||||
|
||||
// white noise field
|
||||
Grid_FFT<real_t> wnoise({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen});
|
||||
|
||||
// temporary storage of additional data
|
||||
Grid_FFT<real_t> tmp({ngrid, ngrid, ngrid}, {boxlen, boxlen, boxlen});
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Fill the grid with a Gaussian white noise field
|
||||
//--------------------------------------------------------------------
|
||||
music::ilog << "-------------------------------------------------------------------------------" << std::endl;
|
||||
music::ilog << "Generating white noise field...." << std::endl;
|
||||
|
||||
the_random_number_generator->Fill_Grid(wnoise);
|
||||
|
||||
wnoise.FourierTransformForward();
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Use externally specified large scale modes from constraints in case
|
||||
// TODO: move to separate routine
|
||||
//--------------------------------------------------------------------
|
||||
if( bAddConstrainedModes ){
|
||||
Grid_FFT<real_t,false> cwnoise({8,8,8}, {boxlen,boxlen,boxlen});
|
||||
|
@ -328,7 +330,7 @@ int Run( config_file& the_config )
|
|||
phi.FourierTransformForward(false);
|
||||
phi.assign_function_of_grids_kdep([&](auto k, auto wn) {
|
||||
real_t kmod = k.norm();
|
||||
ccomplex_t delta = wn * the_cosmo_calc->get_amplitude(kmod, total);
|
||||
ccomplex_t delta = wn * the_cosmo_calc->get_amplitude(kmod, delta_matter);
|
||||
return -delta / (kmod * kmod);
|
||||
}, wnoise);
|
||||
|
||||
|
@ -359,7 +361,7 @@ int Run( config_file& the_config )
|
|||
phi2.assign_function_of_grids_kdep([&](vec3_t<real_t> kvec, ccomplex_t pphi, ccomplex_t pphi2) {
|
||||
real_t k2 = kvec.norm_squared();
|
||||
real_t fac_aniso = (kvec[0] * kvec[0] * lss_aniso_lambda[0] + kvec[1] * kvec[1] * lss_aniso_lambda[1] + kvec[2] * kvec[2] * lss_aniso_lambda[2]);
|
||||
return pphi2 - (lss_aniso_sum_lambda * k2 + 4.0/3.0 * fac_aniso ) * pphi;
|
||||
return pphi2 - (lss_aniso_sum_lambda * k2 + real_t(4.0/3.0) * fac_aniso ) * pphi;
|
||||
}, phi, phi2);
|
||||
}
|
||||
|
||||
|
@ -490,7 +492,7 @@ int Run( config_file& the_config )
|
|||
music::ilog << std::endl
|
||||
<< ">>> Computing ICs for species \'" << cosmo_species_name[this_species] << "\' <<<\n" << std::endl;
|
||||
|
||||
const real_t C_species = (this_species == cosmo_species::baryon)? (1.0-the_cosmo_calc->cosmo_param_.f_b) : -the_cosmo_calc->cosmo_param_.f_b;
|
||||
const real_t C_species = (this_species == cosmo_species::baryon)? (1.0-the_cosmo_calc->cosmo_param_["f_b"]) : -the_cosmo_calc->cosmo_param_["f_b"];
|
||||
|
||||
// main loop block
|
||||
{
|
||||
|
@ -525,7 +527,7 @@ int Run( config_file& the_config )
|
|||
wnoise.FourierTransformForward();
|
||||
rho.FourierTransformForward(false);
|
||||
rho.assign_function_of_grids_kdep( [&]( auto k, auto wn ){
|
||||
return wn * the_cosmo_calc->get_amplitude_rhobc(k.norm());;
|
||||
return wn * the_cosmo_calc->get_amplitude_delta_bc(k.norm(),bDoLinearBCcorr);
|
||||
}, wnoise );
|
||||
rho.zero_DC_mode();
|
||||
rho.FourierTransformBackward();
|
||||
|
@ -556,7 +558,7 @@ int Run( config_file& the_config )
|
|||
wnoise.FourierTransformForward();
|
||||
rho.FourierTransformForward(false);
|
||||
rho.assign_function_of_grids_kdep( [&]( auto k, auto wn ){
|
||||
return wn * the_cosmo_calc->get_amplitude_rhobc(k.norm());;
|
||||
return wn * the_cosmo_calc->get_amplitude_delta_bc(k.norm(), false);
|
||||
}, wnoise );
|
||||
rho.zero_DC_mode();
|
||||
rho.FourierTransformBackward();
|
||||
|
@ -650,7 +652,7 @@ int Run( config_file& the_config )
|
|||
|
||||
tmp.FourierTransformBackward(false);
|
||||
tmp.assign_function_of_grids_r([&](auto ppsi, auto pgrad_psi, auto prho) {
|
||||
return vunit * std::real((std::conj(ppsi) * pgrad_psi - ppsi * std::conj(pgrad_psi)) / ccomplex_t(0.0, 2.0 / hbar)/(1.0+prho));
|
||||
return vunit * std::real((std::conj(ppsi) * pgrad_psi - ppsi * std::conj(pgrad_psi)) / ccomplex_t(0.0, 2.0 / hbar)/real_t(1.0+prho));
|
||||
}, psi, grad_psi, rho);
|
||||
|
||||
fluid_component fc = (idim==0)? fluid_component::vx : ((idim==1)? fluid_component::vy : fluid_component::vz );
|
||||
|
@ -682,6 +684,7 @@ int Run( config_file& the_config )
|
|||
A3[1]->FourierTransformForward();
|
||||
A3[2]->FourierTransformForward();
|
||||
}
|
||||
wnoise.FourierTransformForward();
|
||||
|
||||
// write out positions
|
||||
for( int idim=0; idim<3; ++idim ){
|
||||
|
@ -769,6 +772,12 @@ int Run( config_file& the_config )
|
|||
tmp.kelem(idx) += vfac3 * (lg.gradient(idimp,tmp.get_k3(i,j,k)) * A3[idimpp]->kelem(idx) - lg.gradient(idimpp,tmp.get_k3(i,j,k)) * A3[idimp]->kelem(idx));
|
||||
}
|
||||
|
||||
// if multi-species, then add vbc component backwards
|
||||
if( bDoBaryons & bDoLinearBCcorr ){
|
||||
real_t knorm = wnoise.get_k<real_t>(i,j,k).norm();
|
||||
tmp.kelem(idx) -= vfac1 * C_species * the_cosmo_calc->get_amplitude_theta_bc(knorm, bDoLinearBCcorr) * wnoise.kelem(i,j,k) * lg.gradient(idim,tmp.get_k3(i,j,k)) / (knorm*knorm);
|
||||
}
|
||||
|
||||
// correct with interpolation kernel if we used interpolation to read out the positions (for glasses)
|
||||
if( the_output_plugin->write_species_as( this_species ) == output_type::particles && lattice_type == particle::lattice_glass){
|
||||
tmp.kelem(idx) *= interp.compensation_kernel( tmp.get_k<real_t>(i,j,k) );
|
||||
|
|
28
src/main.cc
28
src/main.cc
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <general.hh>
|
||||
#include <ic_generator.hh>
|
||||
#include <cosmology_parameters.hh>
|
||||
#include <particle_plt.hh>
|
||||
|
||||
|
||||
|
@ -73,8 +74,9 @@ int main( int argc, char** argv )
|
|||
//------------------------------------------------------------------------------
|
||||
|
||||
#if defined(USE_MPI)
|
||||
MPI_Init_thread(&argc, &argv, MPI_THREAD_FUNNELED, &CONFIG::MPI_thread_support);
|
||||
CONFIG::MPI_threads_ok = CONFIG::MPI_thread_support >= MPI_THREAD_FUNNELED;
|
||||
int thread_wanted = MPI_THREAD_MULTIPLE; // MPI_THREAD_FUNNELED
|
||||
MPI_Init_thread(&argc, &argv, thread_wanted, &CONFIG::MPI_thread_support);
|
||||
CONFIG::MPI_threads_ok = CONFIG::MPI_thread_support >= thread_wanted;
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &CONFIG::MPI_task_rank);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &CONFIG::MPI_task_size);
|
||||
CONFIG::MPI_ok = true;
|
||||
|
@ -123,6 +125,7 @@ int main( int argc, char** argv )
|
|||
if (argc != 2)
|
||||
{
|
||||
// print_region_generator_plugins();
|
||||
cosmology::print_ParameterSets();
|
||||
print_TransferFunction_plugins();
|
||||
print_RNG_plugins();
|
||||
print_output_plugins();
|
||||
|
@ -166,7 +169,7 @@ int main( int argc, char** argv )
|
|||
omp_set_num_threads(CONFIG::num_threads);
|
||||
#endif
|
||||
|
||||
// std::feclearexcept(FE_ALL_EXCEPT);
|
||||
std::feclearexcept(FE_ALL_EXCEPT);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Write code configuration to screen
|
||||
|
@ -211,7 +214,7 @@ int main( int argc, char** argv )
|
|||
music::ilog << std::setw(32) << std::left << "OS/Kernel version" << " : " << kinfo.kernel << " version " << kinfo.major << "." << kinfo.minor << " build " << kinfo.build_number << std::endl;
|
||||
|
||||
// FFTW related infos
|
||||
music::ilog << std::setw(32) << std::left << "FFTW version" << " : " << fftw_version << std::endl;
|
||||
music::ilog << std::setw(32) << std::left << "FFTW version" << " : " << FFTW_API(version) << std::endl;
|
||||
music::ilog << std::setw(32) << std::left << "FFTW supports multi-threading" << " : " << (CONFIG::FFTW_threads_ok? "yes" : "no") << std::endl;
|
||||
music::ilog << std::setw(32) << std::left << "FFTW mode" << " : ";
|
||||
#if defined(FFTW_MODE_PATIENT)
|
||||
|
@ -221,12 +224,12 @@ int main( int argc, char** argv )
|
|||
#else
|
||||
music::ilog << "FFTW_ESTIMATE" << std::endl;
|
||||
#endif
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Initialise plug-ins
|
||||
//--------------------------------------------------------------------
|
||||
try
|
||||
{
|
||||
ic_generator::Initialise( the_config );
|
||||
ic_generator::initialise( the_config );
|
||||
}catch(...){
|
||||
handle_eptr( std::current_exception() );
|
||||
music::elog << "Problem during initialisation. See error(s) above. Exiting..." << std::endl;
|
||||
|
@ -235,17 +238,20 @@ int main( int argc, char** argv )
|
|||
#endif
|
||||
return 1;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// do the job...
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
ic_generator::Run( the_config );
|
||||
|
||||
// particle::test_plt();
|
||||
ic_generator::run( the_config );
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// call the destructor of plugins before tearing down MPI
|
||||
ic_generator::reset();
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
#if defined(USE_MPI)
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
|
|
|
@ -40,12 +40,11 @@ void print_output_plugins()
|
|||
music::ilog << std::endl;
|
||||
}
|
||||
|
||||
std::unique_ptr<output_plugin> select_output_plugin( config_file& cf )
|
||||
std::unique_ptr<output_plugin> select_output_plugin( config_file& cf, std::unique_ptr<cosmology::calculator>& pcc )
|
||||
{
|
||||
std::string formatname = cf.get_value<std::string>( "output", "format" );
|
||||
|
||||
output_plugin_creator *the_output_plugin_creator
|
||||
= get_output_plugin_map()[ formatname ];
|
||||
output_plugin_creator *the_output_plugin_creator = get_output_plugin_map()[ formatname ];
|
||||
|
||||
if( !the_output_plugin_creator )
|
||||
{
|
||||
|
@ -58,7 +57,7 @@ std::unique_ptr<output_plugin> select_output_plugin( config_file& cf )
|
|||
music::ilog << std::setw(32) << std::left << "Output plugin" << " : " << formatname << std::endl;
|
||||
}
|
||||
|
||||
return std::move(the_output_plugin_creator->create( cf ));
|
||||
return std::move(the_output_plugin_creator->create( cf, pcc ));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -73,8 +73,8 @@ protected:
|
|||
|
||||
public:
|
||||
//! constructor
|
||||
explicit gadget_hdf5_output_plugin(config_file &cf)
|
||||
: output_plugin(cf, "GADGET-HDF5")
|
||||
explicit gadget_hdf5_output_plugin(config_file &cf, std::unique_ptr<cosmology::calculator>& pcc)
|
||||
: output_plugin(cf, pcc, "AREPO-HDF5")
|
||||
{
|
||||
num_files_ = 1;
|
||||
#ifdef USE_MPI
|
||||
|
@ -106,19 +106,19 @@ public:
|
|||
header_.flag_cooling = 0;
|
||||
header_.num_files = num_files_;
|
||||
header_.BoxSize = lunit_;
|
||||
header_.Omega0 = cf_.get_value<double>("cosmology", "Omega_m");
|
||||
header_.OmegaLambda = cf_.get_value<double>("cosmology", "Omega_L");
|
||||
header_.OmegaBaryon = cf_.get_value<double>("cosmology", "Omega_b");
|
||||
header_.HubbleParam = cf_.get_value<double>("cosmology", "H0") / 100.0;
|
||||
header_.Omega0 = pcc->cosmo_param_["Omega_m"];
|
||||
header_.OmegaLambda = pcc->cosmo_param_["Omega_DE"];
|
||||
header_.OmegaBaryon = pcc->cosmo_param_["Omega_b"];
|
||||
header_.HubbleParam = pcc->cosmo_param_["h"];
|
||||
header_.flag_stellarage = 0;
|
||||
header_.flag_metals = 0;
|
||||
header_.flag_entropy_instead_u = 0;
|
||||
header_.flag_doubleprecision = (typeid(write_real_t) == typeid(double)) ? true : false;
|
||||
|
||||
// initial gas temperature
|
||||
double Tcmb0 = 2.726;
|
||||
double Omegab = cf_.get_value<double>("cosmology", "Omega_b");
|
||||
double h = cf_.get_value<double>("cosmology", "H0") / 100.0, h2 = h*h;
|
||||
double Tcmb0 = pcc->cosmo_param_["Tcmb"];
|
||||
double Omegab = pcc->cosmo_param_["Omega_b"];
|
||||
double h = pcc->cosmo_param_["h"], h2 = h*h;
|
||||
double adec = 1.0 / (160.0 * pow(Omegab * h2 / 0.022, 2.0 / 5.0));
|
||||
Tini_ = astart < adec ? Tcmb0 / astart : Tcmb0 / astart / astart * adec;
|
||||
|
||||
|
@ -179,7 +179,7 @@ public:
|
|||
HDFWriteGroupAttribute(this_fname_, "Header", "suggested_highressoft", from_value<double>(softening_));
|
||||
HDFWriteGroupAttribute(this_fname_, "Header", "suggested_gas_Tinit", from_value<double>(Tini_));
|
||||
|
||||
music::ilog << "Wrote" << std::endl;
|
||||
music::ilog << this->interface_name_ << " output plugin wrote to \'" << this_fname_ << "\'" << std::endl;
|
||||
}
|
||||
|
||||
output_type write_species_as(const cosmo_species &) const { return output_type::particles; }
|
||||
|
|
|
@ -1,209 +0,0 @@
|
|||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include <fstream>
|
||||
#include <output_plugin.hh>
|
||||
|
||||
constexpr int empty_fill_bytes{56};
|
||||
|
||||
template <typename write_real_t>
|
||||
class gadget2_output_plugin : public output_plugin
|
||||
{
|
||||
public:
|
||||
struct header
|
||||
{
|
||||
int npart[6];
|
||||
double mass[6];
|
||||
double time;
|
||||
double redshift;
|
||||
int flag_sfr;
|
||||
int flag_feedback;
|
||||
unsigned int npartTotal[6];
|
||||
int flag_cooling;
|
||||
int num_files;
|
||||
double BoxSize;
|
||||
double Omega0;
|
||||
double OmegaLambda;
|
||||
double HubbleParam;
|
||||
int flag_stellarage;
|
||||
int flag_metals;
|
||||
unsigned int npartTotalHighWord[6];
|
||||
int flag_entropy_instead_u;
|
||||
int flag_doubleprecision;
|
||||
char fill[empty_fill_bytes];
|
||||
};
|
||||
|
||||
protected:
|
||||
int num_files_;
|
||||
header this_header_;
|
||||
real_t lunit_, vunit_, munit_;
|
||||
bool blongids_;
|
||||
|
||||
public:
|
||||
//! constructor
|
||||
explicit gadget2_output_plugin(config_file &cf)
|
||||
: output_plugin(cf, "GADGET-2")
|
||||
{
|
||||
num_files_ = 1;
|
||||
#ifdef USE_MPI
|
||||
// use as many output files as we have MPI tasks
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_files_);
|
||||
#endif
|
||||
const double rhoc = 27.7519737; // in h^2 1e10 M_sol / Mpc^3
|
||||
real_t astart = 1.0 / (1.0 + cf_.get_value<double>("setup", "zstart"));
|
||||
lunit_ = cf_.get_value<double>("setup", "BoxLength");
|
||||
vunit_ = lunit_ / std::sqrt(astart);
|
||||
munit_ = rhoc * std::pow(cf_.get_value<double>("setup", "BoxLength"), 3);
|
||||
blongids_ = cf_.get_value_safe<bool>("output", "UseLongids", false);
|
||||
}
|
||||
|
||||
output_type write_species_as(const cosmo_species &) const { return output_type::particles; }
|
||||
|
||||
real_t position_unit() const { return lunit_; }
|
||||
|
||||
real_t velocity_unit() const { return vunit_; }
|
||||
|
||||
real_t mass_unit() const { return munit_; }
|
||||
|
||||
bool has_64bit_reals() const
|
||||
{
|
||||
if (typeid(write_real_t) == typeid(double))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_64bit_ids() const
|
||||
{
|
||||
if (blongids_)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void write_particle_data(const particle::container &pc, const cosmo_species &s, double Omega_species)
|
||||
{
|
||||
// fill the Gadget-2 header
|
||||
memset(reinterpret_cast<void *>(&this_header_), 0, sizeof(header));
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
this_header_.npart[i] = 0;
|
||||
this_header_.npartTotal[i] = 0;
|
||||
this_header_.npartTotalHighWord[i] = 0;
|
||||
}
|
||||
|
||||
this_header_.npart[1] = (pc.get_local_num_particles());
|
||||
this_header_.npartTotal[1] = (uint32_t)(pc.get_global_num_particles());
|
||||
this_header_.npartTotalHighWord[1] = (uint32_t)((pc.get_global_num_particles()) >> 32);
|
||||
|
||||
/////
|
||||
//... set time ......................................................
|
||||
this_header_.redshift = cf_.get_value<double>("setup", "zstart");
|
||||
this_header_.time = 1.0 / (1.0 + this_header_.redshift);
|
||||
|
||||
//... SF flags
|
||||
this_header_.flag_sfr = 0;
|
||||
this_header_.flag_feedback = 0;
|
||||
this_header_.flag_cooling = 0;
|
||||
|
||||
//...
|
||||
this_header_.num_files = num_files_; //1;
|
||||
this_header_.BoxSize = cf_.get_value<double>("setup", "BoxLength");
|
||||
this_header_.Omega0 = cf_.get_value<double>("cosmology", "Omega_m");
|
||||
this_header_.OmegaLambda = cf_.get_value<double>("cosmology", "Omega_L");
|
||||
this_header_.HubbleParam = cf_.get_value<double>("cosmology", "H0") / 100.0;
|
||||
|
||||
this_header_.flag_stellarage = 0;
|
||||
this_header_.flag_metals = 0;
|
||||
|
||||
this_header_.flag_entropy_instead_u = 0;
|
||||
|
||||
// default units are in Mpc/h
|
||||
//if( kpcunits_ )
|
||||
// this_header_.BoxSize *= 1000.0;
|
||||
// this_header_.BoxSize /= unit_length_chosen_;
|
||||
|
||||
//... set masses
|
||||
double rhoc = 27.7519737; // in h^2 1e10 M_sol / Mpc^3
|
||||
double boxmass = Omega_species * rhoc * std::pow(this_header_.BoxSize, 3);
|
||||
this_header_.mass[1] = boxmass / pc.get_global_num_particles();
|
||||
|
||||
std::string fname = fname_;
|
||||
int thisrank = 0;
|
||||
|
||||
#ifdef USE_MPI
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &thisrank);
|
||||
if (num_files_ > 1)
|
||||
fname += "." + std::to_string(thisrank);
|
||||
#endif
|
||||
uint32_t blocksz;
|
||||
std::ofstream ofs(fname.c_str(), std::ios::binary);
|
||||
|
||||
music::ilog << "Writer \'" << this->interface_name_ << "\' : Writing data for " << pc.get_global_num_particles() << " particles." << std::endl;
|
||||
|
||||
blocksz = sizeof(header);
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
ofs.write(reinterpret_cast<char *>(&this_header_), sizeof(header));
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
|
||||
// we write double precision
|
||||
if (this->has_64bit_reals())
|
||||
{
|
||||
blocksz = 3 * sizeof(double) * pc.get_local_num_particles();
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
ofs.write(reinterpret_cast<const char *>(pc.get_pos64_ptr()), blocksz);
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
ofs.write(reinterpret_cast<const char *>(pc.get_vel64_ptr()), blocksz);
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
blocksz = 3 * sizeof(float) * pc.get_local_num_particles();
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
ofs.write(reinterpret_cast<const char *>(pc.get_pos32_ptr()), blocksz);
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
ofs.write(reinterpret_cast<const char *>(pc.get_vel32_ptr()), blocksz);
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
}
|
||||
|
||||
// we write long IDs
|
||||
if (this->has_64bit_ids())
|
||||
{
|
||||
blocksz = sizeof(uint64_t) * pc.get_local_num_particles();
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
ofs.write(reinterpret_cast<const char *>(pc.get_ids64_ptr()), blocksz);
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
}
|
||||
else
|
||||
{
|
||||
blocksz = sizeof(uint32_t) * pc.get_local_num_particles();
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
ofs.write(reinterpret_cast<const char *>(pc.get_ids32_ptr()), blocksz);
|
||||
ofs.write(reinterpret_cast<char *>(&blocksz), sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
output_plugin_creator_concrete<gadget2_output_plugin<float>> creator1("gadget2");
|
||||
#if !defined(USE_SINGLEPRECISION)
|
||||
output_plugin_creator_concrete<gadget2_output_plugin<double>> creator3("gadget2_double");
|
||||
#endif
|
||||
} // namespace
|
|
@ -66,8 +66,8 @@ protected:
|
|||
|
||||
public:
|
||||
//! constructor
|
||||
explicit gadget_hdf5_output_plugin(config_file &cf)
|
||||
: output_plugin(cf, "GADGET-HDF5")
|
||||
explicit gadget_hdf5_output_plugin(config_file &cf, std::unique_ptr<cosmology::calculator> &pcc)
|
||||
: output_plugin(cf, pcc, "GADGET-HDF5")
|
||||
{
|
||||
num_files_ = 1;
|
||||
#ifdef USE_MPI
|
||||
|
@ -99,9 +99,9 @@ public:
|
|||
header_.flag_cooling = 0;
|
||||
header_.num_files = num_files_;
|
||||
header_.BoxSize = lunit_;
|
||||
header_.Omega0 = cf_.get_value<double>("cosmology", "Omega_m");
|
||||
header_.OmegaLambda = cf_.get_value<double>("cosmology", "Omega_L");
|
||||
header_.HubbleParam = cf_.get_value<double>("cosmology", "H0") / 100.0;
|
||||
header_.Omega0 = pcc->cosmo_param_["Omega_m"];
|
||||
header_.OmegaLambda = pcc->cosmo_param_["Omega_DE"];
|
||||
header_.HubbleParam = pcc->cosmo_param_["h"];
|
||||
header_.flag_stellarage = 0;
|
||||
header_.flag_metals = 0;
|
||||
header_.flag_entropy_instead_u = 0;
|
||||
|
|
|
@ -30,14 +30,14 @@ protected:
|
|||
bool out_eulerian_;
|
||||
public:
|
||||
//! constructor
|
||||
explicit generic_output_plugin(config_file &cf )
|
||||
: output_plugin(cf, "Generic HDF5")
|
||||
explicit generic_output_plugin(config_file &cf, std::unique_ptr<cosmology::calculator> &pcc )
|
||||
: output_plugin(cf, pcc, "Generic HDF5")
|
||||
{
|
||||
real_t astart = 1.0/(1.0+cf_.get_value<double>("setup", "zstart"));
|
||||
real_t boxsize = cf_.get_value<double>("setup", "BoxLength");
|
||||
real_t omegab = cf_.get_value<double>("cosmology", "Omega_b");
|
||||
real_t omegam = cf_.get_value<double>("cosmology", "Omega_m");
|
||||
real_t omegal = cf_.get_value<double>("cosmology", "Omega_L");
|
||||
real_t omegab = pcc->cosmo_param_["Omega_b"];
|
||||
real_t omegam = pcc->cosmo_param_["Omega_m"];
|
||||
real_t omegal = pcc->cosmo_param_["Omega_DE"];
|
||||
|
||||
|
||||
out_eulerian_ = cf_.get_value_safe<bool>("output", "generic_out_eulerian",false);
|
||||
|
|
|
@ -20,8 +20,8 @@ protected:
|
|||
|
||||
public:
|
||||
//! constructor
|
||||
explicit genericio_output_plugin(config_file &cf)
|
||||
: output_plugin(cf, "GenericIO")
|
||||
explicit genericio_output_plugin(config_file &cf, cosmology::calculator &cc)
|
||||
: output_plugin(cf, cc, "GenericIO")
|
||||
{
|
||||
real_t astart = 1.0 / (1.0 + cf_.get_value<double>("setup", "zstart"));
|
||||
lunit_ = cf_.get_value<double>("setup", "BoxLength");
|
||||
|
@ -34,7 +34,7 @@ public:
|
|||
mu_value_ = 4.0 / (1.0 + 3.0*primordial_x);
|
||||
|
||||
double rhoc = 27.7519737 * 1e10; // in h^2 M_sol / Mpc^3
|
||||
rho_value_ = cf_.get_value<double>("cosmology", "Omega_b") * rhoc;
|
||||
rho_value_ = cc_.cosmo_param_["Omega_b"] * rhoc;
|
||||
munit_ = rhoc * std::pow(cf_.get_value<double>("setup", "BoxLength"), 3);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ private:
|
|||
|
||||
protected:
|
||||
header header_;
|
||||
real_t lunit_, vunit_, munit_;
|
||||
real_t lunit_, vunit_, munit_, omegab_;
|
||||
uint32_t levelmin_;
|
||||
bool bhavebaryons_;
|
||||
std::vector<float> data_buf_;
|
||||
|
@ -57,19 +57,22 @@ protected:
|
|||
|
||||
public:
|
||||
//! constructor
|
||||
explicit grafic2_output_plugin(config_file &cf)
|
||||
: output_plugin(cf, "GRAFIC2/RAMSES")
|
||||
explicit grafic2_output_plugin(config_file &cf, std::unique_ptr<cosmology::calculator> &pcc)
|
||||
: output_plugin(cf, pcc, "GRAFIC2/RAMSES")
|
||||
{
|
||||
lunit_ = 1.0;
|
||||
vunit_ = 1.0;
|
||||
|
||||
double
|
||||
boxlength = cf_.get_value<double>("setup", "BoxLength"),
|
||||
H0 = cf_.get_value<double>("cosmology", "H0"),
|
||||
zstart = cf_.get_value<double>("setup", "zstart"),
|
||||
astart = 1.0 / (1.0 + zstart),
|
||||
omegam = cf_.get_value<double>("cosmology", "Omega_m"),
|
||||
omegaL = cf_.get_value<double>("cosmology", "Omega_L");
|
||||
H0 = pcc->cosmo_param_["H0"],
|
||||
omegam = pcc->cosmo_param_["Omega_m"],
|
||||
omegaL = pcc->cosmo_param_["Omega_DE"];
|
||||
|
||||
omegab_ = pcc->cosmo_param_["Omega_b"];
|
||||
|
||||
uint32_t ngrid = cf_.get_value<int>("setup", "GridRes");
|
||||
|
||||
bUseSPT_ = cf_.get_value_safe<bool>("output", "grafic_use_SPT", false);
|
||||
|
@ -286,6 +289,7 @@ void grafic2_output_plugin::write_ramses_namelist(void) const
|
|||
ofst
|
||||
<< "&INIT_PARAMS\n"
|
||||
<< "filetype=\'grafic\'\n"
|
||||
<< "omega_b=" << omegab_ << "\n"
|
||||
<< "initfile(1)=\'" << dirname_ << "\'\n"
|
||||
<< "/\n\n";
|
||||
|
||||
|
|
251
src/plugins/output_swift.cc
Normal file
251
src/plugins/output_swift.cc
Normal file
|
@ -0,0 +1,251 @@
|
|||
|
||||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn & Michael Buehlmann (this file)
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifdef USE_HDF5
|
||||
#include <unistd.h> // for unlink
|
||||
#include <array>
|
||||
#include <output_plugin.hh>
|
||||
#include "HDF_IO.hh"
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> from_6array(const std::array<T,6>& a)
|
||||
{
|
||||
return std::vector<T>{{a[0], a[1], a[2], a[3], a[4], a[5]}};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::vector<T> from_value(const T a)
|
||||
{
|
||||
return std::vector<T>{{a}};
|
||||
}
|
||||
|
||||
template <typename write_real_t>
|
||||
class swift_output_plugin : public output_plugin
|
||||
{
|
||||
|
||||
protected:
|
||||
int num_files_, num_simultaneous_writers_;
|
||||
|
||||
real_t lunit_, vunit_, munit_;
|
||||
real_t boxsize_, hubble_param_, astart_;
|
||||
bool blongids_, bdobaryons_;
|
||||
std::string this_fname_;
|
||||
|
||||
std::array<uint32_t,6> npart_, npartTotal_, npartTotalHighWord_;
|
||||
std::array<double,6> mass_;
|
||||
double time_;
|
||||
|
||||
public:
|
||||
//! constructor
|
||||
explicit swift_output_plugin(config_file &cf, std::unique_ptr<cosmology::calculator> &pcc)
|
||||
: output_plugin(cf, pcc, "SWIFT")
|
||||
{
|
||||
num_files_ = 1;
|
||||
#ifdef USE_MPI
|
||||
// use as many output files as we have MPI tasks
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_files_);
|
||||
#endif
|
||||
real_t astart = 1.0 / (1.0 + cf_.get_value<double>("setup", "zstart"));
|
||||
const double rhoc = 27.7519737; // in h^2 1e10 M_sol / Mpc^3
|
||||
|
||||
hubble_param_ = pcc->cosmo_param_["h"];
|
||||
astart_ = 1.0/(1.0+cf_.get_value<double>("setup","zstart"));
|
||||
boxsize_ = cf_.get_value<double>("setup", "BoxLength");
|
||||
|
||||
lunit_ = boxsize_ / hubble_param_; // final units will be in Mpc (without h)
|
||||
vunit_ = boxsize_; // final units will be in km/s
|
||||
munit_ = rhoc * std::pow(boxsize_, 3) / hubble_param_; // final units will be in 1e10 M_sol
|
||||
|
||||
blongids_ = cf_.get_value_safe<bool>("output", "UseLongids", false);
|
||||
bdobaryons_ = cf_.get_value<bool>("setup","DoBaryons");
|
||||
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
npart_[i] = 0;
|
||||
npartTotal_[i] = 0;
|
||||
npartTotalHighWord_[i] = 0;
|
||||
mass_[i] = 0.0;
|
||||
}
|
||||
|
||||
time_ = astart;
|
||||
|
||||
this_fname_ = fname_;
|
||||
#ifdef USE_MPI
|
||||
int thisrank = 0;
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &thisrank);
|
||||
if (num_files_ > 1)
|
||||
this_fname_ += "." + std::to_string(thisrank);
|
||||
#endif
|
||||
|
||||
// delete output file if it exists
|
||||
unlink(this_fname_.c_str());
|
||||
|
||||
// create output HDF5 file
|
||||
HDFCreateFile(this_fname_);
|
||||
|
||||
// Write UNITS header
|
||||
HDFCreateGroup(this_fname_, "Units");
|
||||
HDFWriteGroupAttribute(this_fname_, "Units", "Unit mass in cgs (U_M)", 1.98848e43); // 10^10 Msun in grams
|
||||
HDFWriteGroupAttribute(this_fname_, "Units", "Unit length in cgs (U_L)", 3.08567758e24); // 1 Mpc in cm
|
||||
HDFWriteGroupAttribute(this_fname_, "Units", "Unit time in cgs (U_t)", 3.08567758e19); // so that unit vel is 1 km/s
|
||||
HDFWriteGroupAttribute(this_fname_, "Units", "Unit current in cgs (U_I)", 1.0); // 1 Ampere
|
||||
HDFWriteGroupAttribute(this_fname_, "Units", "Unit temperature in cgs (U_T)", 1.0); // 1 Kelvin
|
||||
|
||||
// TODO: Write MUSIC configuration header
|
||||
HDFCreateGroup(fname_, "ICs_parameters");
|
||||
// ...
|
||||
}
|
||||
|
||||
// use destructor to write header post factum
|
||||
~swift_output_plugin()
|
||||
{
|
||||
if (!std::uncaught_exception())
|
||||
{
|
||||
HDFCreateGroup(this_fname_, "Header");
|
||||
HDFWriteGroupAttribute(fname_, "Header", "Dimension", 3);
|
||||
HDFWriteGroupAttribute(fname_, "Header", "BoxSize", lunit_); // in Mpc, not Mpc/h
|
||||
|
||||
HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_Total", from_6array<unsigned>(npartTotal_));
|
||||
HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_Total_HighWord", from_6array<unsigned>(npartTotalHighWord_));
|
||||
HDFWriteGroupAttribute(this_fname_, "Header", "NumPart_ThisFile", from_6array<unsigned>(npart_));
|
||||
HDFWriteGroupAttribute(this_fname_, "Header", "MassTable", from_6array<double>(mass_));
|
||||
|
||||
HDFWriteGroupAttribute(this_fname_, "Header", "Time", from_value<double>(time_));
|
||||
HDFWriteGroupAttribute(this_fname_, "Header", "Flag_Entropy_ICs", from_value<int>(0));
|
||||
|
||||
HDFWriteGroupAttribute(this_fname_, "Header", "NumFilesPerSnapshot", from_value<int>(num_files_));
|
||||
|
||||
// write GAS internal energy if baryons are enabled
|
||||
if( bdobaryons_ )
|
||||
{
|
||||
const double gamma = cf_.get_value_safe<double>("cosmology", "gamma", 5.0 / 3.0);
|
||||
const double YHe = pcc_->cosmo_param_["YHe"];
|
||||
//const double Omega0 = cf_.get_value<double>("cosmology", "Omega_m");
|
||||
const double omegab = pcc_->cosmo_param_["Omega_b"];
|
||||
const double Tcmb0 = pcc_->cosmo_param_["Tcmb"];
|
||||
|
||||
|
||||
// compute gas internal energy
|
||||
const double npol = (fabs(1.0 - gamma) > 1e-7) ? 1.0 / (gamma - 1.) : 1.0;
|
||||
const double unitv = 1e5;
|
||||
const double adec = 1.0 / (160. * std::pow(omegab * hubble_param_ * hubble_param_ / 0.022, 2.0 / 5.0));
|
||||
const double Tini = astart_ < adec ? Tcmb0 / astart_ : Tcmb0 / astart_ / astart_ * adec;
|
||||
const double mu = (Tini > 1.e4) ? 4.0 / (8. - 5. * YHe) : 4.0 / (1. + 3. * (1. - YHe));
|
||||
const double ceint = 1.3806e-16 / 1.6726e-24 * Tini * npol / mu / unitv / unitv;
|
||||
|
||||
music::ilog.Print("Swift : set initial gas temperature to %.2f K/mu", Tini / mu);
|
||||
|
||||
std::vector<write_real_t> data( npart_[0], ceint );
|
||||
HDFWriteDataset(this_fname_, "PartType0/InternalEnergy", data);
|
||||
|
||||
data.assign( npart_[0], boxsize_ / cf_.get_value<double>("setup","GridRes") );
|
||||
HDFWriteDataset(this_fname_, "PartType0/SmoothingLength", data);
|
||||
|
||||
}
|
||||
|
||||
music::ilog << "Wrote SWIFT IC file(s) to " << this_fname_ << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
output_type write_species_as(const cosmo_species &) const { return output_type::particles; }
|
||||
|
||||
real_t position_unit() const { return lunit_; }
|
||||
|
||||
real_t velocity_unit() const { return vunit_; }
|
||||
|
||||
real_t mass_unit() const { return munit_; }
|
||||
|
||||
bool has_64bit_reals() const
|
||||
{
|
||||
if (typeid(write_real_t) == typeid(double))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool has_64bit_ids() const
|
||||
{
|
||||
if (blongids_)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
int get_species_idx(const cosmo_species &s) const
|
||||
{
|
||||
switch (s)
|
||||
{
|
||||
case cosmo_species::dm:
|
||||
return 1;
|
||||
case cosmo_species::baryon:
|
||||
return 0;
|
||||
case cosmo_species::neutrino:
|
||||
return 3;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void write_particle_data(const particle::container &pc, const cosmo_species &s, double Omega_species)
|
||||
{
|
||||
int sid = get_species_idx(s);
|
||||
|
||||
assert(sid != -1);
|
||||
|
||||
npart_[sid] = (pc.get_local_num_particles());
|
||||
npartTotal_[sid] = (uint32_t)(pc.get_global_num_particles());
|
||||
npartTotalHighWord_[sid] = (uint32_t)((pc.get_global_num_particles()) >> 32);
|
||||
|
||||
if( pc.bhas_individual_masses_ )
|
||||
mass_[sid] = 0.0;
|
||||
else
|
||||
mass_[sid] = Omega_species * munit_ / pc.get_global_num_particles();
|
||||
|
||||
HDFCreateGroup(this_fname_, std::string("PartType") + std::to_string(sid));
|
||||
|
||||
//... write positions and velocities.....
|
||||
if (this->has_64bit_reals())
|
||||
{
|
||||
HDFWriteDatasetVector(this_fname_, std::string("PartType") + std::to_string(sid) + std::string("/Coordinates"), pc.positions64_);
|
||||
HDFWriteDatasetVector(this_fname_, std::string("PartType") + std::to_string(sid) + std::string("/Velocities"), pc.velocities64_);
|
||||
}
|
||||
else
|
||||
{
|
||||
HDFWriteDatasetVector(this_fname_, std::string("PartType") + std::to_string(sid) + std::string("/Coordinates"), pc.positions32_);
|
||||
HDFWriteDatasetVector(this_fname_, std::string("PartType") + std::to_string(sid) + std::string("/Velocities"), pc.velocities32_);
|
||||
}
|
||||
|
||||
//... write ids.....
|
||||
if (this->has_64bit_ids())
|
||||
HDFWriteDataset(this_fname_, std::string("PartType") + std::to_string(sid) + std::string("/ParticleIDs"), pc.ids64_);
|
||||
else
|
||||
HDFWriteDataset(this_fname_, std::string("PartType") + std::to_string(sid) + std::string("/ParticleIDs"), pc.ids32_);
|
||||
|
||||
//... write masses.....
|
||||
if( pc.bhas_individual_masses_ ){
|
||||
if (this->has_64bit_reals()){
|
||||
HDFWriteDataset(this_fname_, std::string("PartType") + std::to_string(sid) + std::string("/Masses"), pc.mass64_);
|
||||
}else{
|
||||
HDFWriteDataset(this_fname_, std::string("PartType") + std::to_string(sid) + std::string("/Masses"), pc.mass32_);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
output_plugin_creator_concrete<swift_output_plugin<float>> creator1("SWIFT");
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -300,21 +300,15 @@ music_wnoise_generator<T>::music_wnoise_generator(/*const*/ music_wnoise_generat
|
|||
*rfine = new real_t[(size_t)rc.res_ * (size_t)rc.res_ * 2 * ((size_t)rc.res_ / 2 + 1)],
|
||||
*rcoarse = new real_t[(size_t)res_ * (size_t)res_ * 2 * ((size_t)res_ / 2 + 1)];
|
||||
|
||||
fftw_complex
|
||||
*ccoarse = reinterpret_cast<fftw_complex *>(rcoarse),
|
||||
*cfine = reinterpret_cast<fftw_complex *>(rfine);
|
||||
complex_t
|
||||
*ccoarse = reinterpret_cast<complex_t *>(rcoarse),
|
||||
*cfine = reinterpret_cast<complex_t *>(rfine);
|
||||
|
||||
int nx(rc.res_), ny(rc.res_), nz(rc.res_), nxc(res_), nyc(res_), nzc(res_);
|
||||
|
||||
#ifdef USE_SINGLEPRECISION
|
||||
fftwf_plan
|
||||
pf = fftwf_plan_dft_r2c_3d(nx, ny, nz, rfine, cfine, FFTW_ESTIMATE),
|
||||
ipc = fftwf_plan_dft_c2r_3d(nxc, nyc, nzc, ccoarse, rcoarse, FFTW_ESTIMATE);
|
||||
#else
|
||||
fftw_plan
|
||||
pf = fftw_plan_dft_r2c_3d(nx, ny, nz, rfine, cfine, FFTW_ESTIMATE),
|
||||
ipc = fftw_plan_dft_c2r_3d(nxc, nyc, nzc, ccoarse, rcoarse, FFTW_ESTIMATE);
|
||||
#endif
|
||||
FFTW_API(plan)
|
||||
pf = FFTW_API(plan_dft_r2c_3d)(nx, ny, nz, rfine, cfine, FFTW_ESTIMATE),
|
||||
ipc = FFTW_API(plan_dft_c2r_3d)(nxc, nyc, nzc, ccoarse, rcoarse, FFTW_ESTIMATE);
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < nx; i++)
|
||||
|
@ -429,19 +423,11 @@ music_wnoise_generator<T>::music_wnoise_generator(music_wnoise_generator<T> &rc,
|
|||
nxc = lx[0] / 2, nyc = lx[1] / 2, nzc = lx[2] / 2;
|
||||
|
||||
real_t *rfine = new real_t[nx * ny * (nz + 2l)];
|
||||
fftw_complex *cfine = reinterpret_cast<fftw_complex *>(rfine);
|
||||
|
||||
|
||||
#ifdef USE_SINGLEPRECISION
|
||||
fftwf_plan
|
||||
pf = fftwf_plan_dft_r2c_3d(nx, ny, nz, rfine, cfine, FFTW_ESTIMATE),
|
||||
ipf = fftwf_plan_dft_c2r_3d(nx, ny, nz, cfine, rfine, FFTW_ESTIMATE);
|
||||
#else
|
||||
fftw_plan
|
||||
pf = fftw_plan_dft_r2c_3d(nx, ny, nz, rfine, cfine, FFTW_ESTIMATE),
|
||||
ipf = fftw_plan_dft_c2r_3d(nx, ny, nz, cfine, rfine, FFTW_ESTIMATE);
|
||||
#endif
|
||||
complex_t *cfine = reinterpret_cast<complex_t *>(rfine);
|
||||
|
||||
FFTW_API(plan)
|
||||
pf = FFTW_API(plan_dft_r2c_3d)(nx, ny, nz, rfine, cfine, FFTW_ESTIMATE),
|
||||
ipf = FFTW_API(plan_dft_c2r_3d)(nx, ny, nz, cfine, rfine, FFTW_ESTIMATE);
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < (int)nx; i++)
|
||||
|
@ -454,14 +440,10 @@ music_wnoise_generator<T>::music_wnoise_generator(music_wnoise_generator<T> &rc,
|
|||
//this->free_all_mem(); // temporarily free memory, allocate again later
|
||||
|
||||
real_t *rcoarse = new real_t[nxc * nyc * (nzc + 2)];
|
||||
fftw_complex *ccoarse = reinterpret_cast<fftw_complex *>(rcoarse);
|
||||
complex_t *ccoarse = reinterpret_cast<complex_t *>(rcoarse);
|
||||
|
||||
|
||||
#ifdef USE_SINGLEPRECISION
|
||||
fftwf_plan pc = fftwf_plan_dft_r2c_3d(nxc, nyc, nzc, rcoarse, ccoarse, FFTW_ESTIMATE);
|
||||
#else
|
||||
fftw_plan pc = fftw_plan_dft_r2c_3d(nxc, nyc, nzc, rcoarse, ccoarse, FFTW_ESTIMATE);
|
||||
#endif
|
||||
FFTW_API(plan) pc = FFTW_API(plan_dft_r2c_3d)(nxc, nyc, nzc, rcoarse, ccoarse, FFTW_ESTIMATE);
|
||||
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < (int)nxc; i++)
|
||||
|
@ -824,5 +806,10 @@ void music_wnoise_generator<T>::print_allocated(void)
|
|||
music::ilog.Print(" -> %d of %d random number cubes currently allocated", ncount, ntot);
|
||||
}
|
||||
|
||||
#if defined(USE_PRECISION_FLOAT)
|
||||
template class music_wnoise_generator<float>;
|
||||
#elif defined(USE_PRECISION_DOUBLE)
|
||||
template class music_wnoise_generator<double>;
|
||||
#elif defined(USE_PRECISION_LONGDOUBLE)
|
||||
template class music_wnoise_generator<long double>;
|
||||
#endif
|
||||
|
|
|
@ -148,13 +148,12 @@ private:
|
|||
protected:
|
||||
std::string descriptor_string_;
|
||||
int num_threads_;
|
||||
int levelmin_, levelmin_final_, levelmax_, ngrid_;
|
||||
int levelmin_, levelmin_final_, levelmax_, ngrid_, ngrid_panphasia_;
|
||||
bool incongruent_fields_;
|
||||
double inter_grid_phase_adjustment_;
|
||||
// double translation_phase_;
|
||||
pan_state_ *lstate;
|
||||
int grid_p_, grid_m_;
|
||||
double grid_rescale_fac_;
|
||||
int grid_p_;
|
||||
int coordinate_system_shift_[3];
|
||||
int ix_abs_[3], ix_per_[3], ix_rel_[3], level_p_, lextra_;
|
||||
|
||||
|
@ -170,32 +169,29 @@ protected:
|
|||
|
||||
void initialize_for_grid_structure(void)
|
||||
{
|
||||
clear_panphasia_thread_states();
|
||||
music::ilog.Print("PANPHASIA: running with %d threads", num_threads_);
|
||||
|
||||
// if ngrid is not a multiple of i_base, then we need to enlarge and then sample down
|
||||
ngrid_ = pcf_->get_value<size_t>("setup", "GridRes");
|
||||
|
||||
grid_p_ = pdescriptor_->i_base;
|
||||
grid_m_ = largest_power_two_lte(grid_p_);
|
||||
|
||||
lextra_ = (log10((double)ngrid_ / (double)grid_p_) + 0.001) / log10(2.0);
|
||||
|
||||
lextra_ = (log10((double)ngrid_ / (double)pdescriptor_->i_base) + 0.001) / log10(2.0);
|
||||
int ratio = 1 << lextra_;
|
||||
grid_rescale_fac_ = 1.0;
|
||||
ngrid_panphasia_ = (1 << lextra_) * grid_p_;
|
||||
|
||||
if( ngrid_panphasia_ < ngrid_ ){
|
||||
lextra_++;
|
||||
ngrid_panphasia_*=2;
|
||||
}
|
||||
assert( ngrid_panphasia_ >= ngrid_ );
|
||||
|
||||
clear_panphasia_thread_states();
|
||||
|
||||
music::ilog.Print("PANPHASIA: using grid size %lld (level=%d)",ngrid_panphasia_, lextra_);
|
||||
music::ilog.Print("PANPHASIA: running with %d threads", num_threads_, ngrid_panphasia_ );
|
||||
|
||||
coordinate_system_shift_[0] = -pcf_->get_value_safe<int>("setup", "shift_x", 0);
|
||||
coordinate_system_shift_[1] = -pcf_->get_value_safe<int>("setup", "shift_y", 0);
|
||||
coordinate_system_shift_[2] = -pcf_->get_value_safe<int>("setup", "shift_z", 0);
|
||||
|
||||
incongruent_fields_ = false;
|
||||
if (ngrid_ != ratio * pdescriptor_->i_base)
|
||||
{
|
||||
incongruent_fields_ = true;
|
||||
ngrid_ = 2 * ratio * pdescriptor_->i_base;
|
||||
grid_rescale_fac_ = (double)ngrid_ / (1 << levelmin_);
|
||||
music::ilog << "PANPHASIA: will use a higher resolution (using Fourier interpolation)" << std::endl;
|
||||
music::ilog << " (" << grid_m_ << " -> " << grid_p_ << ") * 2**ref to be compatible with PANPHASIA" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<panphasia_descriptor> pdescriptor_;
|
||||
|
@ -243,28 +239,17 @@ public:
|
|||
auto dsinc = [](real_t x) { return (std::fabs(x) > 1e-16) ? (x * std::cos(x) - std::sin(x)) / (x * x) : 0.0; };
|
||||
const real_t sqrt3{std::sqrt(3.0)}, sqrt27{std::sqrt(27.0)};
|
||||
|
||||
// make sure we're in the right space
|
||||
Grid_FFT<real_t> &g0 = g;
|
||||
g0.FourierTransformBackward(false);
|
||||
|
||||
// temporaries
|
||||
Grid_FFT<real_t> g1(g.n_, g.length_);
|
||||
Grid_FFT<real_t> g2(g.n_, g.length_);
|
||||
Grid_FFT<real_t> g3(g.n_, g.length_);
|
||||
Grid_FFT<real_t> g4(g.n_, g.length_);
|
||||
// we will overwrite 'g', we can deallocate it while we prepare the panphasia field
|
||||
g.reset();
|
||||
|
||||
clear_panphasia_thread_states();
|
||||
music::ilog.Print("PANPHASIA: running with %d threads", num_threads_);
|
||||
|
||||
ngrid_ = pcf_->get_value<size_t>("setup", "GridRes");
|
||||
|
||||
grid_p_ = pdescriptor_->i_base;
|
||||
// grid_m_ = largest_power_two_lte(grid_p_);
|
||||
if (ngrid_ % grid_p_ != 0)
|
||||
{
|
||||
music::elog << "Grid resolution " << ngrid_ << " is not divisible by PANPHASIA descriptor length " << grid_p_ << std::endl;
|
||||
throw std::runtime_error("Chosen [setup] / GridRes is not compatible with PANPHASIA descriptor length!");
|
||||
}
|
||||
|
||||
// temporaries
|
||||
Grid_FFT<real_t> g0({size_t(ngrid_panphasia_),size_t(ngrid_panphasia_),size_t(ngrid_panphasia_)}, g.length_);
|
||||
Grid_FFT<real_t> g1({size_t(ngrid_panphasia_),size_t(ngrid_panphasia_),size_t(ngrid_panphasia_)}, g.length_);
|
||||
Grid_FFT<real_t> g2({size_t(ngrid_panphasia_),size_t(ngrid_panphasia_),size_t(ngrid_panphasia_)}, g.length_);
|
||||
Grid_FFT<real_t> g3({size_t(ngrid_panphasia_),size_t(ngrid_panphasia_),size_t(ngrid_panphasia_)}, g.length_);
|
||||
Grid_FFT<real_t> g4({size_t(ngrid_panphasia_),size_t(ngrid_panphasia_),size_t(ngrid_panphasia_)}, g.length_);
|
||||
|
||||
double t1 = get_wtime();
|
||||
// double tp = t1;
|
||||
|
@ -285,22 +270,17 @@ public:
|
|||
std::memset(descriptor, 0, 100);
|
||||
std::memcpy(descriptor, descriptor_string_.c_str(), descriptor_string_.size());
|
||||
|
||||
start_panphasia_(&lstate[mythread], descriptor, &ngrid_, &verbosity);
|
||||
start_panphasia_(&lstate[mythread], descriptor, &ngrid_panphasia_, &verbosity);
|
||||
|
||||
{
|
||||
panphasia_descriptor d(descriptor_string_);
|
||||
|
||||
const int lextra = (log10((double)ngrid_ / (double)d.i_base) + 0.001) / log10(2.0);
|
||||
int level_p = d.wn_level_base + lextra;
|
||||
const int ratio = 1 << lextra;
|
||||
int level_p = d.wn_level_base + lextra_;
|
||||
|
||||
lstate[mythread].layer_min = 0;
|
||||
lstate[mythread].layer_max = level_p;
|
||||
lstate[mythread].indep_field = 1;
|
||||
|
||||
_unused(ratio);
|
||||
assert(ngrid_ == ratio * d.i_base);
|
||||
|
||||
long long ix_rel[3];
|
||||
ix_rel[0] = 0; //ileft_corner_p[0];
|
||||
ix_rel[1] = 0; //ileft_corner_p[1];
|
||||
|
@ -317,26 +297,28 @@ public:
|
|||
pan_state_ *ps = &lstate[mythread];
|
||||
|
||||
#pragma omp for //nowait
|
||||
for (size_t i = 0; i < g.size(0); i += 2)
|
||||
for (size_t i = 0; i < g0.size(0); i += 2)
|
||||
{
|
||||
for (size_t j = 0; j < g.size(1); j += 2)
|
||||
const int ixmax(std::min<int>(2,g0.size(0)-i));
|
||||
for (size_t j = 0; j < g0.size(1); j += 2)
|
||||
{
|
||||
for (size_t k = 0; k < g.size(2); k += 2)
|
||||
const int iymax(std::min<int>(2,g0.size(1)-j));
|
||||
for (size_t k = 0; k < g0.size(2); k += 2)
|
||||
{
|
||||
const int izmax(std::min<int>(2,g0.size(2)-k));
|
||||
|
||||
// ARJ - added inner set of loops to speed up evaluation of Panphasia
|
||||
|
||||
for (int ix = 0; ix < 2; ++ix)
|
||||
for (int ix = 0; ix < ixmax; ++ix)
|
||||
{
|
||||
for (int iy = 0; iy < 2; ++iy)
|
||||
{
|
||||
for (int iz = 0; iz < 2; ++iz)
|
||||
for (int iy = 0; iy < iymax; ++iy)
|
||||
{
|
||||
for (int iz = 0; iz < izmax; ++iz)
|
||||
{
|
||||
int ilocal = i + ix;
|
||||
int jlocal = j + iy;
|
||||
int klocal = k + iz;
|
||||
|
||||
int iglobal = ilocal + g.local_0_start_;
|
||||
int iglobal = ilocal + g0.local_0_start_;
|
||||
int jglobal = jlocal;
|
||||
int kglobal = klocal;
|
||||
|
||||
|
@ -373,19 +355,19 @@ public:
|
|||
{
|
||||
auto kvec = g0.get_k<real_t>(i, j, k);
|
||||
|
||||
auto argx = 0.5 * M_PI * kvec[0] / g.kny_[0];
|
||||
auto argy = 0.5 * M_PI * kvec[1] / g.kny_[1];
|
||||
auto argz = 0.5 * M_PI * kvec[2] / g.kny_[2];
|
||||
auto argx = 0.5 * M_PI * kvec[0] / g0.kny_[0];
|
||||
auto argy = 0.5 * M_PI * kvec[1] / g0.kny_[1];
|
||||
auto argz = 0.5 * M_PI * kvec[2] / g0.kny_[2];
|
||||
|
||||
auto fx = sinc(argx);
|
||||
auto fx = real_t(sinc(argx));
|
||||
auto gx = ccomplex_t(0.0, dsinc(argx));
|
||||
auto fy = sinc(argy);
|
||||
auto fy = real_t(sinc(argy));
|
||||
auto gy = ccomplex_t(0.0, dsinc(argy));
|
||||
auto fz = sinc(argz);
|
||||
auto fz = real_t(sinc(argz));
|
||||
auto gz = ccomplex_t(0.0, dsinc(argz));
|
||||
|
||||
auto temp = (fx + sqrt3 * gx) * (fy + sqrt3 * gy) * (fz + sqrt3 * gz);
|
||||
auto magnitude = std::sqrt(1.0 - std::fabs(temp * temp));
|
||||
auto magnitude = real_t(std::sqrt(1.0 - std::fabs(temp * temp)));
|
||||
|
||||
auto y0(g0.kelem(i, j, k)), y1(g1.kelem(i, j, k)), y2(g2.kelem(i, j, k)), y3(g3.kelem(i, j, k)), y4(g4.kelem(i, j, k));
|
||||
|
||||
|
@ -423,22 +405,17 @@ public:
|
|||
std::memset(descriptor, 0, 100);
|
||||
std::memcpy(descriptor, descriptor_string_.c_str(), descriptor_string_.size());
|
||||
|
||||
start_panphasia_(&lstate[mythread], descriptor, &ngrid_, &verbosity);
|
||||
start_panphasia_(&lstate[mythread], descriptor, &ngrid_panphasia_, &verbosity);
|
||||
|
||||
{
|
||||
panphasia_descriptor d(descriptor_string_);
|
||||
|
||||
const int lextra = (log10((double)ngrid_ / (double)d.i_base) + 0.001) / log10(2.0);
|
||||
int level_p = d.wn_level_base + lextra;
|
||||
const int ratio = 1 << lextra;
|
||||
int level_p = d.wn_level_base + lextra_;
|
||||
|
||||
lstate[mythread].layer_min = 0;
|
||||
lstate[mythread].layer_max = level_p;
|
||||
lstate[mythread].indep_field = 1;
|
||||
|
||||
_unused(ratio);
|
||||
assert(ngrid_ == ratio * d.i_base);
|
||||
|
||||
long long ix_rel[3];
|
||||
ix_rel[0] = 0; //ileft_corner_p[0];
|
||||
ix_rel[1] = 0; //ileft_corner_p[1];
|
||||
|
@ -460,22 +437,26 @@ public:
|
|||
#pragma omp for //nowait
|
||||
for (size_t i = 0; i < g1.size(0); i += 2)
|
||||
{
|
||||
const int ixmax(std::min<int>(2,g1.size(0)-i));
|
||||
for (size_t j = 0; j < g1.size(1); j += 2)
|
||||
{
|
||||
const int iymax(std::min<int>(2,g1.size(1)-j));
|
||||
for (size_t k = 0; k < g1.size(2); k += 2)
|
||||
{
|
||||
const int izmax(std::min<int>(2,g1.size(2)-k));
|
||||
|
||||
// ARJ - added inner set of loops to speed up evaluation of Panphasia
|
||||
for (int ix = 0; ix < 2; ++ix)
|
||||
for (int ix = 0; ix < ixmax; ++ix)
|
||||
{
|
||||
for (int iy = 0; iy < 2; ++iy)
|
||||
{
|
||||
for (int iz = 0; iz < 2; ++iz)
|
||||
for (int iy = 0; iy < iymax; ++iy)
|
||||
{
|
||||
for (int iz = 0; iz < izmax; ++iz)
|
||||
{
|
||||
int ilocal = i + ix;
|
||||
int jlocal = j + iy;
|
||||
int klocal = k + iz;
|
||||
|
||||
int iglobal = ilocal + g.local_0_start_;
|
||||
int iglobal = ilocal + g1.local_0_start_;
|
||||
int jglobal = jlocal;
|
||||
int kglobal = klocal;
|
||||
|
||||
|
@ -505,43 +486,52 @@ public:
|
|||
g4.FourierTransformForward();
|
||||
|
||||
#pragma omp parallel for
|
||||
for (size_t i = 0; i < g1.size(0); i++)
|
||||
for (size_t i = 0; i < g0.size(0); i++)
|
||||
{
|
||||
for (size_t j = 0; j < g1.size(1); j++)
|
||||
for (size_t j = 0; j < g0.size(1); j++)
|
||||
{
|
||||
for (size_t k = 0; k < g1.size(2); k++)
|
||||
for (size_t k = 0; k < g0.size(2); k++)
|
||||
{
|
||||
if (!g1.is_nyquist_mode(i, j, k))
|
||||
if (!g0.is_nyquist_mode(i, j, k))
|
||||
{
|
||||
auto kvec = g1.get_k<real_t>(i, j, k);
|
||||
auto kvec = g0.get_k<real_t>(i, j, k);
|
||||
|
||||
auto argx = 0.5 * M_PI * kvec[0] / g.kny_[0];
|
||||
auto argy = 0.5 * M_PI * kvec[1] / g.kny_[1];
|
||||
auto argz = 0.5 * M_PI * kvec[2] / g.kny_[2];
|
||||
auto argx = 0.5 * M_PI * kvec[0] / g0.kny_[0];
|
||||
auto argy = 0.5 * M_PI * kvec[1] / g0.kny_[1];
|
||||
auto argz = 0.5 * M_PI * kvec[2] / g0.kny_[2];
|
||||
|
||||
auto fx = sinc(argx);
|
||||
auto fx = real_t(sinc(argx));
|
||||
auto gx = ccomplex_t(0.0, dsinc(argx));
|
||||
auto fy = sinc(argy);
|
||||
auto fy = real_t(sinc(argy));
|
||||
auto gy = ccomplex_t(0.0, dsinc(argy));
|
||||
auto fz = sinc(argz);
|
||||
auto fz = real_t(sinc(argz));
|
||||
auto gz = ccomplex_t(0.0, dsinc(argz));
|
||||
|
||||
auto y1(g1.kelem(i, j, k)), y2(g2.kelem(i, j, k)), y3(g3.kelem(i, j, k)), y4(g4.kelem(i, j, k));
|
||||
|
||||
g0.kelem(i, j, k) += 3.0 * (y1 * gx * gy * fz + y2 * fx * gy * gz + y3 * gx * fy * gz) + sqrt27 * y4 * gx * gy * gz;
|
||||
g0.kelem(i, j, k) += real_t(3.0) * (y1 * gx * gy * fz + y2 * fx * gy * gz + y3 * gx * fy * gz) + sqrt27 * y4 * gx * gy * gz;
|
||||
|
||||
// fix the overall minus w.r.t. the monofonic noise definition
|
||||
g0.kelem(i, j, k ) *= -1.0;
|
||||
// do final phase shift to account for corner centered coordinates vs. cell centers
|
||||
auto phase_shift = - 0.5 * M_PI * ( kvec[0] / g0.kny_[0]
|
||||
+ kvec[1] /g0.kny_[1] + kvec[2] / g0.kny_[2]);
|
||||
|
||||
g0.kelem(i, j, k) *= std::exp( ccomplex_t(0,phase_shift) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// music::ilog.Print("\033[31mtiming [build panphasia field2]: %f s\033[0m", get_wtime() - tp);
|
||||
// tp = get_wtime();
|
||||
g1.reset();
|
||||
g2.reset();
|
||||
g3.reset();
|
||||
g4.reset();
|
||||
|
||||
g.allocate();
|
||||
g0.FourierInterpolateCopyTo( g );
|
||||
|
||||
music::ilog.Print("time for calculating PANPHASIA field : %f s, %f µs/cell", get_wtime() - t1,
|
||||
1e6 * (get_wtime() - t1) / g.global_size(0) / g.global_size(1) / g.global_size(2));
|
||||
music::ilog.Print("PANPHASIA k-space statistices: mean Re = %f, std = %f", g0.mean(), g0.std());
|
||||
music::ilog.Print("PANPHASIA k-space statistices: mean Re = %f, std = %f", g.mean(), g.std());
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,76 +1,56 @@
|
|||
// This file is part of monofonIC (MUSIC2)
|
||||
// A software package to generate ICs for cosmological simulations
|
||||
// Copyright (C) 2020 by Oliver Hahn
|
||||
//
|
||||
//
|
||||
// monofonIC 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.
|
||||
//
|
||||
//
|
||||
// monofonIC is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include <gsl/gsl_errno.h>
|
||||
#include <gsl/gsl_spline.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "transfer_function_plugin.hh"
|
||||
|
||||
const double tiny = 1e-30;
|
||||
#include <transfer_function_plugin.hh>
|
||||
#include <math/interpolate.hh>
|
||||
|
||||
class transfer_CAMB_file_plugin : public TransferFunction_plugin
|
||||
{
|
||||
|
||||
private:
|
||||
std::string m_filename_Pk, m_filename_Tk;
|
||||
std::vector<double> m_tab_k, m_tab_Tk_tot, m_tab_Tk_cdm, m_tab_Tk_baryon;
|
||||
std::vector<double> m_tab_Tvk_tot, m_tab_Tvk_cdm, m_tab_Tvk_baryon;
|
||||
gsl_interp_accel *acc_tot, *acc_cdm, *acc_baryon;
|
||||
gsl_interp_accel *acc_vtot, *acc_vcdm, *acc_vbaryon;
|
||||
gsl_spline *spline_tot, *spline_cdm, *spline_baryon;
|
||||
gsl_spline *spline_vtot, *spline_vcdm, *spline_vbaryon;
|
||||
|
||||
double m_kmin, m_kmax, m_Omega_b, m_Omega_m, m_zstart;
|
||||
unsigned m_nlines;
|
||||
using TransferFunction_plugin::cosmo_params_;
|
||||
|
||||
bool m_linbaryoninterp;
|
||||
interpolated_function_1d<true, true, false> delta_c_, delta_b_, delta_n_, delta_m_, theta_c_, theta_b_, theta_n_, theta_m_;
|
||||
|
||||
void read_table(void)
|
||||
double m_kmin, m_kmax;
|
||||
|
||||
// bool m_linbaryoninterp;
|
||||
|
||||
void read_table( const std::string& filename )
|
||||
{
|
||||
|
||||
m_nlines = 0;
|
||||
m_linbaryoninterp = false;
|
||||
size_t nlines{0};
|
||||
// m_linbaryoninterp = false;
|
||||
|
||||
#ifdef WITH_MPI
|
||||
if (MPI::COMM_WORLD.Get_rank() == 0)
|
||||
std::vector<double> k, dc, tc, db, tb, dn, tn, dm, tm;
|
||||
|
||||
if( CONFIG::MPI_task_rank == 0 )
|
||||
{
|
||||
#endif
|
||||
music::ilog.Print("Reading tabulated transfer function data from file \n \'%s\'", m_filename_Tk.c_str());
|
||||
music::ilog << "Reading tabulated transfer function data from file:" << std::endl
|
||||
<< " \'" << filename << "\'" << std::endl;
|
||||
|
||||
std::string line;
|
||||
std::ifstream ifs(m_filename_Tk.c_str());
|
||||
std::ifstream ifs(filename.c_str());
|
||||
|
||||
if (!ifs.good())
|
||||
throw std::runtime_error("Could not find transfer function file \'" + m_filename_Tk + "\'");
|
||||
|
||||
m_tab_k.clear();
|
||||
m_tab_Tk_tot.clear();
|
||||
m_tab_Tk_cdm.clear();
|
||||
m_tab_Tk_baryon.clear();
|
||||
m_tab_Tvk_tot.clear();
|
||||
m_tab_Tvk_cdm.clear(); //>[150609SH: add]
|
||||
m_tab_Tvk_baryon.clear(); //>[150609SH: add]
|
||||
|
||||
m_kmin = 1e30;
|
||||
m_kmax = -1e30;
|
||||
std::ofstream ofs("dump_transfer.txt");
|
||||
|
||||
throw std::runtime_error("Could not find transfer function file \'" + filename + "\'");
|
||||
|
||||
while (!ifs.eof())
|
||||
{
|
||||
getline(ifs, line);
|
||||
|
@ -83,285 +63,169 @@ private:
|
|||
|
||||
std::stringstream ss(line);
|
||||
|
||||
double k, Tkc, Tkb, Tktot, Tkvtot, Tkvc, Tkvb, dummy;
|
||||
double Tk, Tdc, Tdb, Tdn, Tdm, Tvb, Tvc, dummy;
|
||||
|
||||
ss >> k;
|
||||
ss >> Tkc; // cdm
|
||||
ss >> Tkb; // baryon
|
||||
ss >> Tk; // k
|
||||
ss >> Tdc; // cdm
|
||||
ss >> Tdb; // baryon
|
||||
ss >> dummy; // photon
|
||||
ss >> dummy; // nu
|
||||
ss >> dummy; // mass_nu
|
||||
ss >> Tktot; // total
|
||||
ss >> Tdn; // mass_nu
|
||||
ss >> Tdm; // total
|
||||
ss >> dummy; // no_nu
|
||||
ss >> dummy; // total_de
|
||||
ss >> dummy; // Weyl
|
||||
ss >> Tkvc; // v_cdm
|
||||
ss >> Tkvb; // v_b
|
||||
ss >> Tvc; // v_cdm
|
||||
ss >> Tvb; // v_b
|
||||
ss >> dummy; // v_b-v_cdm
|
||||
|
||||
if (ss.bad() || ss.fail())
|
||||
{
|
||||
music::elog.Print("error reading the transfer function file (corrupt or not in expected format)!");
|
||||
throw std::runtime_error("error reading transfer function file \'" +
|
||||
m_filename_Tk + "\'");
|
||||
throw std::runtime_error("error reading transfer function file \'" + filename + "\'");
|
||||
}
|
||||
|
||||
if (m_Omega_b < 1e-6)
|
||||
Tkvtot = Tktot;
|
||||
else
|
||||
Tkvtot = ((m_Omega_m - m_Omega_b) * Tkvc + m_Omega_b * Tkvb) / m_Omega_m; //MvD
|
||||
// if (cosmo_params_["Omega_b"] < 1e-6)
|
||||
// Tkvtot = Tktot;
|
||||
// else
|
||||
// Tkvtot = cosmo_params_["f_c"] * Tkvc + cosmo_params_["f_b"]* Tkvb;
|
||||
|
||||
m_linbaryoninterp |= Tkb < 0.0 || Tkvb < 0.0;
|
||||
// m_linbaryoninterp |= Tkb < 0.0 || Tkvb < 0.0;
|
||||
|
||||
m_tab_k.push_back(log10(k));
|
||||
|
||||
m_tab_Tk_tot.push_back(Tktot);
|
||||
m_tab_Tk_baryon.push_back(Tkb);
|
||||
m_tab_Tk_cdm.push_back(Tkc);
|
||||
m_tab_Tvk_tot.push_back(Tkvtot);
|
||||
m_tab_Tvk_baryon.push_back(Tkvb);
|
||||
m_tab_Tvk_cdm.push_back(Tkvc);
|
||||
|
||||
++m_nlines;
|
||||
|
||||
if (k < m_kmin)
|
||||
m_kmin = k;
|
||||
if (k > m_kmax)
|
||||
m_kmax = k;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < m_tab_k.size(); ++i)
|
||||
{
|
||||
m_tab_Tk_tot[i] = log10(m_tab_Tk_tot[i]);
|
||||
m_tab_Tk_cdm[i] = log10(m_tab_Tk_cdm[i]);
|
||||
m_tab_Tvk_cdm[i] = log10(m_tab_Tvk_cdm[i]);
|
||||
m_tab_Tvk_tot[i] = log10(m_tab_Tvk_tot[i]);
|
||||
|
||||
if (!m_linbaryoninterp)
|
||||
{
|
||||
m_tab_Tk_baryon[i] = log10(m_tab_Tk_baryon[i]);
|
||||
m_tab_Tvk_baryon[i] = log10(m_tab_Tvk_baryon[i]);
|
||||
}
|
||||
k.push_back(Tk);
|
||||
dc.push_back(Tdc);
|
||||
db.push_back(Tdb);
|
||||
dn.push_back(Tdn);
|
||||
dm.push_back(Tdm);
|
||||
tc.push_back(Tvc);
|
||||
tb.push_back(Tvb);
|
||||
tn.push_back(Tdm);
|
||||
tm.push_back(Tdm);
|
||||
++nlines;
|
||||
}
|
||||
|
||||
ifs.close();
|
||||
music::ilog.Print("Read CAMB transfer function table with %d rows", nlines);
|
||||
|
||||
music::ilog.Print("Read CAMB transfer function table with %d rows", m_nlines);
|
||||
// if (m_linbaryoninterp)
|
||||
// music::ilog.Print("Using log-lin interpolation for baryons\n (TF is not positive definite)");
|
||||
|
||||
if (m_linbaryoninterp)
|
||||
music::ilog.Print("Using log-lin interpolation for baryons\n (TF is not "
|
||||
"positive definite)");
|
||||
|
||||
#ifdef WITH_MPI
|
||||
}
|
||||
|
||||
unsigned n = m_tab_k.size();
|
||||
MPI::COMM_WORLD.Bcast(&n, 1, MPI_UNSIGNED, 0);
|
||||
#if defined(USE_MPI)
|
||||
unsigned n = k.size();
|
||||
MPI_Bcast(&n, 1, MPI_UNSIGNED, 0, MPI_COMM_WORLD);
|
||||
|
||||
if (MPI::COMM_WORLD.Get_rank() > 0)
|
||||
if (CONFIG::MPI_task_rank > 0)
|
||||
{
|
||||
m_tab_k.assign(n, 0);
|
||||
m_tab_Tk_tot.assign(n, 0);
|
||||
m_tab_Tk_cdm.assign(n, 0);
|
||||
m_tab_Tk_baryon.assign(n, 0);
|
||||
m_tab_Tvk_tot.assign(n, 0);
|
||||
m_tab_Tvk_cdm.assign(n, 0);
|
||||
m_tab_Tvk_baryon.assign(n, 0);
|
||||
k.assign(n, 0);
|
||||
dc.assign(n, 0);
|
||||
tc.assign(n, 0);
|
||||
db.assign(n, 0);
|
||||
tb.assign(n, 0);
|
||||
dn.assign(n, 0);
|
||||
tn.assign(n, 0);
|
||||
dm.assign(n, 0);
|
||||
tm.assign(n, 0);
|
||||
}
|
||||
|
||||
MPI::COMM_WORLD.Bcast(&m_tab_k[0], n, MPI_DOUBLE, 0);
|
||||
MPI::COMM_WORLD.Bcast(&m_tab_Tk_tot[0], n, MPI_DOUBLE, 0);
|
||||
MPI::COMM_WORLD.Bcast(&m_tab_Tk_cdm[0], n, MPI_DOUBLE, 0);
|
||||
MPI::COMM_WORLD.Bcast(&m_tab_Tk_baryon[0], n, MPI_DOUBLE, 0);
|
||||
MPI::COMM_WORLD.Bcast(&m_tab_Tvk_tot[0], n, MPI_DOUBLE, 0);
|
||||
MPI::COMM_WORLD.Bcast(&m_tab_Tvk_cdm[0], n, MPI_DOUBLE, 0);
|
||||
MPI::COMM_WORLD.Bcast(&m_tab_Tvk_baryon[0], n, MPI_DOUBLE, 0);
|
||||
|
||||
MPI_Bcast(&k[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
MPI_Bcast(&dc[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
MPI_Bcast(&tc[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
MPI_Bcast(&db[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
MPI_Bcast(&tb[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
MPI_Bcast(&dn[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
MPI_Bcast(&tn[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
MPI_Bcast(&dm[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
MPI_Bcast(&tm[0], n, MPI_DOUBLE, 0, MPI_COMM_WORLD);
|
||||
#endif
|
||||
|
||||
delta_c_.set_data(k, dc);
|
||||
theta_c_.set_data(k, tc);
|
||||
delta_b_.set_data(k, db);
|
||||
theta_b_.set_data(k, tb);
|
||||
delta_n_.set_data(k, dn);
|
||||
theta_n_.set_data(k, tn);
|
||||
delta_m_.set_data(k, dm);
|
||||
theta_m_.set_data(k, tm);
|
||||
|
||||
// do not use first and last value since interpolation becomes lower order
|
||||
m_kmin = k[1];
|
||||
m_kmax = k[k.size()-2];
|
||||
}
|
||||
|
||||
public:
|
||||
transfer_CAMB_file_plugin(config_file &cf)
|
||||
: TransferFunction_plugin(cf)
|
||||
transfer_CAMB_file_plugin(config_file &cf, const cosmology::parameters& cosmo_params)
|
||||
: TransferFunction_plugin(cf, cosmo_params)
|
||||
{
|
||||
music::wlog << "The CAMB file plugin is not well tested! Proceed with checks of correctness of output before running a simulation!" << std::endl;
|
||||
|
||||
m_filename_Tk = pcf_->get_value<std::string>("cosmology", "transfer_file");
|
||||
m_Omega_m = cf.get_value<double>("cosmology", "Omega_m"); //MvD
|
||||
m_Omega_b = cf.get_value<double>("cosmology", "Omega_b"); //MvD
|
||||
m_zstart = cf.get_value<double>("setup", "zstart"); //MvD
|
||||
std::string filename = pcf_->get_value<std::string>("cosmology", "transfer_file");
|
||||
|
||||
read_table();
|
||||
|
||||
acc_tot = gsl_interp_accel_alloc();
|
||||
acc_cdm = gsl_interp_accel_alloc();
|
||||
acc_baryon = gsl_interp_accel_alloc();
|
||||
acc_vtot = gsl_interp_accel_alloc();
|
||||
acc_vcdm = gsl_interp_accel_alloc();
|
||||
acc_vbaryon = gsl_interp_accel_alloc();
|
||||
|
||||
spline_tot = gsl_spline_alloc(gsl_interp_cspline, m_tab_k.size());
|
||||
spline_cdm = gsl_spline_alloc(gsl_interp_cspline, m_tab_k.size());
|
||||
spline_baryon = gsl_spline_alloc(gsl_interp_cspline, m_tab_k.size());
|
||||
spline_vtot = gsl_spline_alloc(gsl_interp_cspline, m_tab_k.size());
|
||||
spline_vcdm =
|
||||
gsl_spline_alloc(gsl_interp_cspline, m_tab_k.size());
|
||||
spline_vbaryon =
|
||||
gsl_spline_alloc(gsl_interp_cspline, m_tab_k.size());
|
||||
|
||||
gsl_spline_init(spline_tot, &m_tab_k[0], &m_tab_Tk_tot[0], m_tab_k.size());
|
||||
gsl_spline_init(spline_cdm, &m_tab_k[0], &m_tab_Tk_cdm[0], m_tab_k.size());
|
||||
gsl_spline_init(spline_baryon, &m_tab_k[0], &m_tab_Tk_baryon[0],
|
||||
m_tab_k.size());
|
||||
gsl_spline_init(spline_vtot, &m_tab_k[0], &m_tab_Tvk_tot[0],
|
||||
m_tab_k.size());
|
||||
gsl_spline_init(spline_vcdm, &m_tab_k[0], &m_tab_Tvk_cdm[0],
|
||||
m_tab_k.size());
|
||||
gsl_spline_init(spline_vbaryon, &m_tab_k[0], &m_tab_Tvk_baryon[0],
|
||||
m_tab_k.size());
|
||||
this->read_table( filename );
|
||||
|
||||
// set properties of this transfer function plugin:
|
||||
tf_distinct_ = true; // different density between CDM v.s. Baryon
|
||||
tf_withvel_ = true; // using velocity transfer function
|
||||
tf_withtotal0_ = false; // only have 1 file for the moment
|
||||
}
|
||||
|
||||
~transfer_CAMB_file_plugin()
|
||||
{
|
||||
gsl_spline_free(spline_tot);
|
||||
gsl_spline_free(spline_cdm);
|
||||
gsl_spline_free(spline_baryon);
|
||||
gsl_spline_free(spline_vtot);
|
||||
gsl_spline_free(spline_vcdm);
|
||||
gsl_spline_free(spline_vbaryon);
|
||||
|
||||
gsl_interp_accel_free(acc_tot);
|
||||
gsl_interp_accel_free(acc_cdm);
|
||||
gsl_interp_accel_free(acc_baryon);
|
||||
gsl_interp_accel_free(acc_vtot);
|
||||
gsl_interp_accel_free(acc_vcdm);
|
||||
gsl_interp_accel_free(acc_vbaryon);
|
||||
}
|
||||
|
||||
// linear interpolation in log-log
|
||||
inline double extrap_right(double k, const tf_type &type) const
|
||||
{
|
||||
int n = m_tab_k.size() - 1, n1 = n - 1;
|
||||
|
||||
double v1(1.0), v2(1.0);
|
||||
|
||||
double lk = log10(k);
|
||||
double dk = m_tab_k[n] - m_tab_k[n1];
|
||||
double delk = lk - m_tab_k[n];
|
||||
double dc{0.0}, db{0.0};
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case cdm:
|
||||
v1 = m_tab_Tk_cdm[n1];
|
||||
v2 = m_tab_Tk_cdm[n];
|
||||
return pow(10.0, (v2 - v1) / dk * (delk) + v2);
|
||||
case baryon:
|
||||
v1 = m_tab_Tk_baryon[n1];
|
||||
v2 = m_tab_Tk_baryon[n];
|
||||
if (m_linbaryoninterp)
|
||||
return std::max((v2 - v1) / dk * (delk) + v2, tiny);
|
||||
return pow(10.0, (v2 - v1) / dk * (delk) + v2);
|
||||
case vtotal: //>[150609SH: add]
|
||||
v1 = m_tab_Tvk_tot[n1];
|
||||
v2 = m_tab_Tvk_tot[n];
|
||||
return pow(10.0, (v2 - v1) / dk * (delk) + v2);
|
||||
case vcdm: //>[150609SH: add]
|
||||
v1 = m_tab_Tvk_cdm[n1];
|
||||
v2 = m_tab_Tvk_cdm[n];
|
||||
return pow(10.0, (v2 - v1) / dk * (delk) + v2);
|
||||
case vbaryon: //>[150609SH: add]
|
||||
v1 = m_tab_Tvk_baryon[n1];
|
||||
v2 = m_tab_Tvk_baryon[n];
|
||||
if (m_linbaryoninterp)
|
||||
return std::max((v2 - v1) / dk * (delk) + v2, tiny);
|
||||
return pow(10.0, (v2 - v1) / dk * (delk) + v2);
|
||||
case total:
|
||||
v1 = m_tab_Tk_tot[n1];
|
||||
v2 = m_tab_Tk_tot[n];
|
||||
return pow(10.0, (v2 - v1) / dk * (delk) + v2);
|
||||
case deltabc:
|
||||
v1 = m_tab_Tk_cdm[n1];
|
||||
v2 = m_tab_Tk_cdm[n];
|
||||
dc = pow(10.0, (v2 - v1) / dk * (delk) + v2);
|
||||
v1 = m_tab_Tk_baryon[n1];
|
||||
v2 = m_tab_Tk_baryon[n];
|
||||
db = pow(10.0, (v2 - v1) / dk * (delk) + v2);
|
||||
return db-dc;
|
||||
default:
|
||||
throw std::runtime_error(
|
||||
"Invalid type requested in transfer function evaluation");
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//!< return log-log interpolated values for transfer funtion 'type'
|
||||
inline double compute(double k, tf_type type) const
|
||||
{
|
||||
// use constant interpolation on the left side of the tabulated values
|
||||
if (k < m_kmin)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case cdm:
|
||||
return pow(10.0, m_tab_Tk_cdm[0]);
|
||||
case baryon:
|
||||
if (m_linbaryoninterp)
|
||||
return m_tab_Tk_baryon[0];
|
||||
return pow(10.0, m_tab_Tk_baryon[0]);
|
||||
case vtotal:
|
||||
return pow(10.0, m_tab_Tvk_tot[0]);
|
||||
case vcdm:
|
||||
return pow(10.0, m_tab_Tvk_cdm[0]);
|
||||
case vbaryon:
|
||||
if (m_linbaryoninterp)
|
||||
return m_tab_Tvk_baryon[0];
|
||||
return pow(10.0, m_tab_Tvk_baryon[0]);
|
||||
case total:
|
||||
return pow(10.0, m_tab_Tk_tot[0]);
|
||||
default:
|
||||
throw std::runtime_error(
|
||||
"Invalid type requested in transfer function evaluation");
|
||||
}
|
||||
}
|
||||
// use linear interpolation on the right side of the tabulated values
|
||||
else if (k > m_kmax)
|
||||
return extrap_right(k, type);
|
||||
// use constant interpolation on the left side of the tabulated values, i.e.
|
||||
// set values k<k_min to value at k_min! (since transfer functions asymptote to constant)
|
||||
k = std::max(k,m_kmin);
|
||||
|
||||
double lk = log10(k);
|
||||
switch (type)
|
||||
{
|
||||
case cdm:
|
||||
return pow(10.0, gsl_spline_eval(spline_cdm, lk, acc_cdm));
|
||||
case baryon:
|
||||
if (m_linbaryoninterp)
|
||||
return gsl_spline_eval(spline_baryon, lk, acc_baryon);
|
||||
return pow(10.0, gsl_spline_eval(spline_baryon, lk, acc_baryon));
|
||||
case vtotal:
|
||||
return pow(10.0, gsl_spline_eval(spline_vtot, lk, acc_vtot)); //MvD
|
||||
case vcdm:
|
||||
return pow(10.0, gsl_spline_eval(spline_vcdm, lk, acc_vcdm));
|
||||
case vbaryon:
|
||||
if (m_linbaryoninterp)
|
||||
return gsl_spline_eval(spline_vbaryon, lk, acc_vbaryon);
|
||||
return pow(10.0, gsl_spline_eval(spline_vbaryon, lk, acc_vbaryon));
|
||||
case total:
|
||||
return pow(10.0, gsl_spline_eval(spline_tot, lk, acc_tot));
|
||||
case delta_matter0:
|
||||
case delta_matter:
|
||||
return delta_m_(k);
|
||||
|
||||
case delta_cdm0:
|
||||
case delta_cdm:
|
||||
return delta_c_(k);
|
||||
|
||||
case delta_baryon0:
|
||||
case delta_baryon:
|
||||
return delta_b_(k);
|
||||
|
||||
case theta_matter0:
|
||||
case theta_matter:
|
||||
return theta_m_(k);
|
||||
|
||||
case theta_cdm0:
|
||||
case theta_cdm:
|
||||
return theta_c_(k);
|
||||
|
||||
case theta_baryon0:
|
||||
case theta_baryon:
|
||||
return theta_b_(k);
|
||||
|
||||
case delta_bc:
|
||||
return delta_b_(k)-delta_c_(k);
|
||||
|
||||
case theta_bc:
|
||||
return theta_b_(k)-theta_c_(k);
|
||||
|
||||
default:
|
||||
throw std::runtime_error(
|
||||
"Invalid type requested in transfer function evaluation");
|
||||
throw std::runtime_error("Invalid type requested in transfer function evaluation");
|
||||
}
|
||||
}
|
||||
|
||||
inline double get_kmin(void) const { return pow(10.0, m_tab_k[1]); }
|
||||
//!< Return minimum k for which we can interpolate
|
||||
inline double get_kmin(void) const { return m_kmin; }
|
||||
|
||||
inline double get_kmax(void) const { return pow(10.0, m_tab_k[m_tab_k.size() - 2]); }
|
||||
//!< Return maximum k for which we can interpolate
|
||||
inline double get_kmax(void) const { return m_kmax; }
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
TransferFunction_plugin_creator_concrete<transfer_CAMB_file_plugin> creator("CAMB_file");
|
||||
TransferFunction_plugin_creator_concrete<transfer_CAMB_file_plugin> creator("CAMB_file");
|
||||
}
|
||||
|
|
|
@ -28,21 +28,20 @@
|
|||
#include <general.hh>
|
||||
#include <config_file.hh>
|
||||
#include <transfer_function_plugin.hh>
|
||||
#include <ic_generator.hh>
|
||||
|
||||
#include <math/interpolate.hh>
|
||||
|
||||
class transfer_CLASS_plugin : public TransferFunction_plugin
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
using TransferFunction_plugin::cosmo_params_;
|
||||
|
||||
interpolated_function_1d<true, true, false> delta_c_, delta_b_, delta_n_, delta_m_, theta_c_, theta_b_, theta_n_, theta_m_;
|
||||
interpolated_function_1d<true, true, false> delta_c0_, delta_b0_, delta_n0_, delta_m0_, theta_c0_, theta_b0_, theta_n0_, theta_m0_;
|
||||
|
||||
// single fluid growing/decaying mode decomposition
|
||||
// gsl_interp_accel *gsl_ia_Cplus_, *gsl_ia_Cminus_;
|
||||
// gsl_spline *gsl_sp_Cplus_, *gsl_sp_Cminus_;
|
||||
// std::vector<double> tab_Cplus_, tab_Cminus_;
|
||||
|
||||
double Omega_m_, Omega_b_, N_ur_, zstart_, ztarget_, kmax_, kmin_, h_, astart_, atarget_, A_s_, n_s_, sigma8_, Tcmb_, tnorm_;
|
||||
double zstart_, ztarget_, astart_, atarget_, kmax_, kmin_, h_, tnorm_;
|
||||
|
||||
ClassParams pars_;
|
||||
std::unique_ptr<ClassEngine> the_ClassEngine_;
|
||||
|
@ -60,7 +59,7 @@ private:
|
|||
{
|
||||
//--- general parameters ------------------------------------------
|
||||
add_class_parameter("z_max_pk", std::max(std::max(zstart_, ztarget_),199.0)); // use 1.2 as safety
|
||||
add_class_parameter("P_k_max_h/Mpc", kmax_);
|
||||
add_class_parameter("P_k_max_h/Mpc", std::max(2.0,kmax_));
|
||||
add_class_parameter("output", "dTk,vTk");
|
||||
add_class_parameter("extra metric transfer functions","yes");
|
||||
// add_class_parameter("lensing", "no");
|
||||
|
@ -70,46 +69,60 @@ private:
|
|||
add_class_parameter("gauge", "synchronous");
|
||||
|
||||
//--- cosmological parameters, densities --------------------------
|
||||
add_class_parameter("h", h_);
|
||||
add_class_parameter("h", cosmo_params_.get("h"));
|
||||
|
||||
add_class_parameter("Omega_b", Omega_b_);
|
||||
add_class_parameter("Omega_cdm", Omega_m_ - Omega_b_);
|
||||
add_class_parameter("Omega_k", 0.0);
|
||||
// add_class_parameter("Omega_Lambda",1.0-Omega_m_);
|
||||
add_class_parameter("Omega_b", cosmo_params_.get("Omega_b"));
|
||||
add_class_parameter("Omega_cdm", cosmo_params_.get("Omega_c"));
|
||||
add_class_parameter("Omega_k", cosmo_params_.get("Omega_k"));
|
||||
add_class_parameter("Omega_fld", 0.0);
|
||||
add_class_parameter("Omega_scf", 0.0);
|
||||
|
||||
|
||||
// add_class_parameter("fluid_equation_of_state","CLP");
|
||||
// add_class_parameter("w0_fld", -1 );
|
||||
// add_class_parameter("wa_fld", 0. );
|
||||
// add_class_parameter("cs2_fld", 1);
|
||||
|
||||
//--- massive neutrinos -------------------------------------------
|
||||
#if 1
|
||||
#if 0
|
||||
//default off
|
||||
// add_class_parameter("Omega_ur",0.0);
|
||||
add_class_parameter("N_ur", N_ur_);
|
||||
add_class_parameter("N_ur", cosmo_params_.get("N_ur"));
|
||||
add_class_parameter("N_ncdm", 0);
|
||||
|
||||
#else
|
||||
|
||||
add_class_parameter("N_ur", cosmo_params_.get("N_ur"));
|
||||
add_class_parameter("N_ncdm", cosmo_params_.get("N_nu_massive"));
|
||||
if( cosmo_params_.get("N_nu_massive") > 0 ){
|
||||
std::stringstream sstr;
|
||||
if( cosmo_params_.get("m_nu1") > 1e-9 ) sstr << cosmo_params_.get("m_nu1");
|
||||
if( cosmo_params_.get("m_nu2") > 1e-9 ) sstr << ", " << cosmo_params_.get("m_nu2");
|
||||
if( cosmo_params_.get("m_nu3") > 1e-9 ) sstr << ", " << cosmo_params_.get("m_nu3");
|
||||
add_class_parameter("m_ncdm", sstr.str().c_str());
|
||||
}
|
||||
|
||||
// change above to enable
|
||||
add_class_parameter("N_ur", 0);
|
||||
add_class_parameter("N_ncdm", 1);
|
||||
add_class_parameter("m_ncdm", "0.4");
|
||||
add_class_parameter("T_ncdm", 0.71611);
|
||||
//add_class_parameter("omega_ncdm", 0.0006451439);
|
||||
//add_class_parameter("m_ncdm", "0.4");
|
||||
//add_class_parameter("T_ncdm", 0.71611);
|
||||
#endif
|
||||
|
||||
//--- cosmological parameters, primordial -------------------------
|
||||
add_class_parameter("P_k_ini type", "analytic_Pk");
|
||||
|
||||
if( A_s_ > 0.0 ){
|
||||
add_class_parameter("A_s", A_s_);
|
||||
if( cosmo_params_.get("A_s") > 0.0 ){
|
||||
add_class_parameter("A_s", cosmo_params_.get("A_s"));
|
||||
}else{
|
||||
add_class_parameter("sigma8", sigma8_);
|
||||
add_class_parameter("sigma8", cosmo_params_.get("sigma_8"));
|
||||
}
|
||||
add_class_parameter("n_s", n_s_);
|
||||
add_class_parameter("n_s", cosmo_params_.get("n_s"));
|
||||
add_class_parameter("alpha_s", 0.0);
|
||||
add_class_parameter("T_cmb", Tcmb_);
|
||||
add_class_parameter("YHe", 0.248);
|
||||
add_class_parameter("T_cmb", cosmo_params_.get("Tcmb"));
|
||||
add_class_parameter("YHe", cosmo_params_.get("YHe"));
|
||||
|
||||
// additional parameters
|
||||
add_class_parameter("reio_parametrization", "reio_none");
|
||||
|
||||
// precision parameters
|
||||
add_class_parameter("k_per_decade_for_pk", 100);
|
||||
|
@ -166,53 +179,49 @@ private:
|
|||
|
||||
the_ClassEngine_->getTk(z, k, dc, db, dn, dm, tc, tb, tn, tm);
|
||||
|
||||
real_t fc = (Omega_m_ - Omega_b_) / Omega_m_;
|
||||
real_t fb = Omega_b_ / Omega_m_;
|
||||
const double h = cosmo_params_.get("h");
|
||||
|
||||
for (size_t i = 0; i < k.size(); ++i)
|
||||
{
|
||||
// convert to 'CAMB' format, since we interpolate loglog and
|
||||
// don't want negative numbers...
|
||||
auto ik2 = 1.0 / (k[i] * k[i]) * h_ * h_;
|
||||
auto ik2 = 1.0 / (k[i] * k[i]) * h * h;
|
||||
dc[i] = -dc[i] * ik2;
|
||||
db[i] = -db[i] * ik2;
|
||||
dn[i] = -dn[i] * ik2;
|
||||
dm[i] = fc * dc[i] + fb * db[i];
|
||||
dm[i] = -dm[i] * ik2;
|
||||
tc[i] = -tc[i] * ik2;
|
||||
tb[i] = -tb[i] * ik2;
|
||||
tn[i] = -tn[i] * ik2;
|
||||
tm[i] = fc * tc[i] + fb * tb[i];
|
||||
tm[i] = -tm[i] * ik2;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
explicit transfer_CLASS_plugin(config_file &cf)
|
||||
: TransferFunction_plugin(cf)
|
||||
explicit transfer_CLASS_plugin(config_file &cf, const cosmology::parameters& cosmo_params)
|
||||
: TransferFunction_plugin(cf,cosmo_params)
|
||||
{
|
||||
this->tf_isnormalised_ = true;
|
||||
|
||||
ofs_class_input_.open("input_class_parameters.ini", std::ios::trunc);
|
||||
|
||||
h_ = pcf_->get_value<double>("cosmology", "H0") / 100.0;
|
||||
Omega_m_ = pcf_->get_value<double>("cosmology", "Omega_m");
|
||||
Omega_b_ = pcf_->get_value<double>("cosmology", "Omega_b");
|
||||
N_ur_ = pcf_->get_value_safe<double>("cosmology", "Neff", 3.046);
|
||||
// all cosmological parameters need to be passed through the_cosmo_calc
|
||||
|
||||
ztarget_ = pcf_->get_value_safe<double>("cosmology", "ztarget", 0.0);
|
||||
atarget_ = 1.0 / (1.0 + ztarget_);
|
||||
zstart_ = pcf_->get_value<double>("setup", "zstart");
|
||||
astart_ = 1.0 / (1.0 + zstart_);
|
||||
A_s_ = pcf_->get_value_safe<double>("cosmology", "A_s", -1.0);
|
||||
n_s_ = pcf_->get_value<double>("cosmology", "nspec");
|
||||
Tcmb_ = cf.get_value_safe<double>("cosmology", "Tcmb", 2.7255);
|
||||
|
||||
if (A_s_ > 0) {
|
||||
music::ilog << "CLASS: Using A_s=" << A_s_<< " to normalise the transfer function." << std::endl;
|
||||
h_ = cosmo_params_["h"];
|
||||
|
||||
if (cosmo_params_["A_s"] > 0.0) {
|
||||
music::ilog << "CLASS: Using A_s=" << cosmo_params_["A_s"] << " to normalise the transfer function." << std::endl;
|
||||
}else{
|
||||
sigma8_ = pcf_->get_value_safe<double>("cosmology", "sigma_8", -1.0);
|
||||
if( sigma8_ < 0 ){
|
||||
double sigma8 = cosmo_params_["sigma_8"];
|
||||
if( sigma8 < 0 ){
|
||||
throw std::runtime_error("Need to specify either A_s or sigma_8 for CLASS plugin...");
|
||||
}
|
||||
music::ilog << "CLASS: Using sigma8_ =" << sigma8_<< " to normalise the transfer function." << std::endl;
|
||||
music::ilog << "CLASS: Using sigma8_ =" << sigma8<< " to normalise the transfer function." << std::endl;
|
||||
}
|
||||
|
||||
// determine highest k we will need for the resolution selected
|
||||
|
@ -222,11 +231,11 @@ public:
|
|||
|
||||
// initialise CLASS and get the normalisation
|
||||
this->init_ClassEngine();
|
||||
A_s_ = the_ClassEngine_->get_A_s(); // this either the input one, or the one computed from sigma8
|
||||
double A_s_ = the_ClassEngine_->get_A_s(); // this either the input one, or the one computed from sigma8
|
||||
|
||||
// compute the normalisation to interface with MUSIC
|
||||
double k_p = pcf_->get_value_safe<double>("cosmology", "k_p", 0.05);
|
||||
tnorm_ = std::sqrt(2.0 * M_PI * M_PI * A_s_ * std::pow(1.0 / k_p * h_, n_s_ - 1) / std::pow(2.0 * M_PI, 3.0));
|
||||
double k_p = cosmo_params["k_p"] / cosmo_params["h"];
|
||||
tnorm_ = std::sqrt(2.0 * M_PI * M_PI * A_s_ * std::pow(1.0 / k_p, cosmo_params["n_s"] - 1) / std::pow(2.0 * M_PI, 3.0));
|
||||
|
||||
// compute the transfer function at z=0 using CLASS engine
|
||||
std::vector<double> k, dc, tc, db, tb, dn, tn, dm, tm;
|
||||
|
@ -257,32 +266,6 @@ public:
|
|||
|
||||
music::ilog << "CLASS table contains k = " << this->get_kmin() << " to " << this->get_kmax() << " h Mpc-1." << std::endl;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// single fluid growing/decaying mode decomposition
|
||||
//--------------------------------------------------------------------------
|
||||
/*gsl_ia_Cplus_ = gsl_interp_accel_alloc();
|
||||
gsl_ia_Cminus_ = gsl_interp_accel_alloc();
|
||||
|
||||
gsl_sp_Cplus_ = gsl_spline_alloc(gsl_interp_cspline, tab_lnk_.size());
|
||||
gsl_sp_Cminus_ = gsl_spline_alloc(gsl_interp_cspline, tab_lnk_.size());
|
||||
|
||||
tab_Cplus_.assign(tab_lnk_.size(), 0);
|
||||
tab_Cminus_.assign(tab_lnk_.size(), 0);
|
||||
|
||||
std::ofstream ofs("grow_decay.txt");
|
||||
|
||||
for (size_t i = 0; i < tab_lnk_.size(); ++i)
|
||||
{
|
||||
tab_Cplus_[i] = (3.0 / 5.0 * tab_dtot_[i] / atarget_ - 2.0 / 5.0 * tab_ttot_[i] / atarget_);
|
||||
tab_Cminus_[i] = (2.0 / 5.0 * std::pow(atarget_, 1.5) * (tab_dtot_[i] + tab_ttot_[i]));
|
||||
|
||||
ofs << std::exp(tab_lnk_[i]) << " " << tab_Cplus_[i] << " " << tab_Cminus_[i] << " " << tab_dtot_[i] << " " << tab_ttot_[i] << std::endl;
|
||||
}
|
||||
|
||||
gsl_spline_init(gsl_sp_Cplus_, &tab_lnk_[0], &tab_Cplus_[0], tab_lnk_.size());
|
||||
gsl_spline_init(gsl_sp_Cminus_, &tab_lnk_[0], &tab_Cminus_[0], tab_lnk_.size());*/
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
tf_distinct_ = true;
|
||||
tf_withvel_ = true;
|
||||
tf_withtotal0_ = true;
|
||||
|
@ -305,33 +288,35 @@ public:
|
|||
switch (type)
|
||||
{
|
||||
// values at ztarget:
|
||||
case total:
|
||||
case delta_matter:
|
||||
val = delta_m_(k); break;
|
||||
case cdm:
|
||||
case delta_cdm:
|
||||
val = delta_c_(k); break;
|
||||
case baryon:
|
||||
case delta_baryon:
|
||||
val = delta_b_(k); break;
|
||||
case vtotal:
|
||||
case theta_matter:
|
||||
val = theta_m_(k); break;
|
||||
case vcdm:
|
||||
case theta_cdm:
|
||||
val = theta_c_(k); break;
|
||||
case vbaryon:
|
||||
case theta_baryon:
|
||||
val = theta_b_(k); break;
|
||||
case deltabc:
|
||||
case delta_bc:
|
||||
val = delta_b_(k)-delta_c_(k); break;
|
||||
case theta_bc:
|
||||
val = theta_b_(k)-theta_c_(k); break;
|
||||
|
||||
// values at zstart:
|
||||
case total0:
|
||||
case delta_matter0:
|
||||
val = delta_m0_(k); break;
|
||||
case cdm0:
|
||||
case delta_cdm0:
|
||||
val = delta_c0_(k); break;
|
||||
case baryon0:
|
||||
case delta_baryon0:
|
||||
val = delta_b0_(k); break;
|
||||
case vtotal0:
|
||||
case theta_matter0:
|
||||
val = theta_m0_(k); break;
|
||||
case vcdm0:
|
||||
case theta_cdm0:
|
||||
val = theta_c0_(k); break;
|
||||
case vbaryon0:
|
||||
case theta_baryon0:
|
||||
val = theta_b0_(k); break;
|
||||
default:
|
||||
throw std::runtime_error("Invalid type requested in transfer function evaluation");
|
||||
|
|
|
@ -208,6 +208,8 @@ struct eisenstein_transfer
|
|||
*/
|
||||
class transfer_eisenstein_plugin : public TransferFunction_plugin
|
||||
{
|
||||
using TransferFunction_plugin::cosmo_params_;
|
||||
|
||||
protected:
|
||||
eisenstein_transfer etf_;
|
||||
|
||||
|
@ -218,13 +220,13 @@ public:
|
|||
\param Tcmb mean temperature of the CMB fluctuations (defaults to
|
||||
Tcmb = 2.726 if not specified)
|
||||
*/
|
||||
transfer_eisenstein_plugin(config_file &cf)
|
||||
: TransferFunction_plugin(cf)
|
||||
transfer_eisenstein_plugin(config_file &cf, const cosmology::parameters& cp)
|
||||
: TransferFunction_plugin(cf, cp)
|
||||
{
|
||||
double Tcmb = pcf_->get_value_safe<double>("cosmology", "Tcmb", 2.726);
|
||||
double H0 = pcf_->get_value<double>("cosmology", "H0");
|
||||
double Omega_m = pcf_->get_value<double>("cosmology", "Omega_m");
|
||||
double Omega_b = pcf_->get_value<double>("cosmology", "Omega_b");
|
||||
double Tcmb = cosmo_params_["Tcmb"];
|
||||
double H0 = cosmo_params_["H0"];
|
||||
double Omega_m = cosmo_params_["Omega_m"];
|
||||
double Omega_b = cosmo_params_["Omega_b"];
|
||||
|
||||
etf_.set_parameters(H0, Omega_m, Omega_b, Tcmb);
|
||||
|
||||
|
@ -235,7 +237,8 @@ public:
|
|||
//! Computes the transfer function for k in Mpc/h by calling TFfit_onek
|
||||
inline double compute(double k, tf_type type) const
|
||||
{
|
||||
return (type!=deltabc)? etf_.at_k(k) : 0.0;
|
||||
if( type == theta_bc || type == delta_bc ) return 0.0;
|
||||
return etf_.at_k(k);
|
||||
}
|
||||
|
||||
inline double get_kmin(void) const
|
||||
|
@ -252,6 +255,8 @@ public:
|
|||
#include <map>
|
||||
class transfer_eisenstein_wdm_plugin : public TransferFunction_plugin
|
||||
{
|
||||
using TransferFunction_plugin::cosmo_params_;
|
||||
|
||||
protected:
|
||||
real_t m_WDMalpha, m_h0;
|
||||
double omegam_, wdmm_, wdmgx_, wdmnu_, H0_, omegab_;
|
||||
|
@ -268,13 +273,13 @@ protected:
|
|||
};
|
||||
|
||||
public:
|
||||
transfer_eisenstein_wdm_plugin(config_file &cf)
|
||||
: TransferFunction_plugin(cf)
|
||||
transfer_eisenstein_wdm_plugin(config_file &cf, const cosmology::parameters& cp)
|
||||
: TransferFunction_plugin(cf, cp)
|
||||
{
|
||||
double Tcmb = pcf_->get_value_safe("cosmology", "Tcmb", 2.726);
|
||||
omegam_ = pcf_->get_value<double>("cosmology", "Omega_m");
|
||||
omegab_ = pcf_->get_value<double>("cosmology", "Omega_b");
|
||||
H0_ = pcf_->get_value<double>("cosmology", "H0");
|
||||
double Tcmb = cosmo_params_["Tcmb"];
|
||||
H0_ = cosmo_params_["H0"];
|
||||
omegam_ = cosmo_params_["Omega_m"];
|
||||
omegab_ = cosmo_params_["Omega_b"];
|
||||
m_h0 = H0_ / 100.0;
|
||||
wdmm_ = pcf_->get_value<double>("cosmology", "WDMmass");
|
||||
|
||||
|
@ -328,6 +333,7 @@ public:
|
|||
|
||||
inline double compute(double k, tf_type type) const
|
||||
{
|
||||
if( type == theta_bc || type == delta_bc ) return 0.0;
|
||||
return etf_.at_k(k) * pow(1.0 + pow(m_WDMalpha * k, 2.0 * wdmnu_), -5.0 / wdmnu_);
|
||||
}
|
||||
|
||||
|
@ -345,20 +351,22 @@ public:
|
|||
// CDM Bino type WIMP small-scale damped spectrum from Green, Hofmann & Schwarz (2004)
|
||||
class transfer_eisenstein_cdmbino_plugin : public TransferFunction_plugin
|
||||
{
|
||||
using TransferFunction_plugin::cosmo_params_;
|
||||
|
||||
protected:
|
||||
|
||||
real_t m_h0;
|
||||
double omegam_, H0_, omegab_, mcdm_, Tkd_, kfs_, kd_;
|
||||
eisenstein_transfer etf_;
|
||||
|
||||
public:
|
||||
transfer_eisenstein_cdmbino_plugin(config_file &cf)
|
||||
: TransferFunction_plugin(cf)
|
||||
transfer_eisenstein_cdmbino_plugin(config_file &cf, const cosmology::parameters& cp)
|
||||
: TransferFunction_plugin(cf, cp)
|
||||
{
|
||||
double Tcmb = pcf_->get_value_safe("cosmology", "Tcmb", 2.726);
|
||||
|
||||
omegam_ = pcf_->get_value<double>("cosmology", "Omega_m");
|
||||
omegab_ = pcf_->get_value<double>("cosmology", "Omega_b");
|
||||
H0_ = pcf_->get_value<double>("cosmology", "H0");
|
||||
double Tcmb = cosmo_params_["Tcmb"];
|
||||
H0_ = cosmo_params_["H0"];
|
||||
omegam_ = cosmo_params_["Omega_m"];
|
||||
omegab_ = cosmo_params_["Omega_b"];
|
||||
m_h0 = H0_ / 100.0;
|
||||
|
||||
etf_.set_parameters(H0_, omegam_, omegab_, Tcmb);
|
||||
|
@ -378,6 +386,8 @@ public:
|
|||
double kkfs2 = kkfs * kkfs;
|
||||
double kkd2 = (k / kd_) * (k / kd_);
|
||||
|
||||
if( type == theta_bc || type == delta_bc ) return 0.0;
|
||||
|
||||
// in principle the Green et al. (2004) works only up to k/k_fs < 1
|
||||
// the fit crosses zero at (k/k_fs)**2 = 3/2, we just zero it there...
|
||||
if (kkfs2 < 1.5)
|
||||
|
@ -397,53 +407,10 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class transfer_eisenstein_cutoff_plugin : public TransferFunction_plugin
|
||||
{
|
||||
protected:
|
||||
real_t m_h0;
|
||||
double omegam_, H0_, omegab_, mcdm_, Tkd_, kfs_, kd_;
|
||||
double Rcut_;
|
||||
eisenstein_transfer etf_;
|
||||
|
||||
public:
|
||||
transfer_eisenstein_cutoff_plugin(config_file &cf)
|
||||
: TransferFunction_plugin(cf)
|
||||
{
|
||||
double Tcmb = pcf_->get_value_safe("cosmology", "Tcmb", 2.726);
|
||||
|
||||
omegam_ = pcf_->get_value<double>("cosmology", "Omega_m");
|
||||
omegab_ = pcf_->get_value<double>("cosmology", "Omega_b");
|
||||
H0_ = pcf_->get_value<double>("cosmology", "H0");
|
||||
m_h0 = H0_ / 100.0;
|
||||
|
||||
etf_.set_parameters(H0_, omegam_, omegab_, Tcmb);
|
||||
|
||||
Rcut_ = pcf_->get_value_safe<double>("cosmology", "Rcut", 1.0);
|
||||
}
|
||||
|
||||
inline double compute(double k, tf_type type) const
|
||||
{
|
||||
//std::cerr << k << " " << Rcut_ << " " << std::exp(-k*k*Rcut_*Rcut_) << std::endl;
|
||||
double cut = std::exp(-k*k*Rcut_*Rcut_);
|
||||
// std::cerr << k << " " << cut << ", " << std::endl;
|
||||
return etf_.at_k(k) * cut;
|
||||
}
|
||||
|
||||
inline double get_kmin(void) const
|
||||
{
|
||||
return 1e-4;
|
||||
}
|
||||
|
||||
inline double get_kmax(void) const
|
||||
{
|
||||
return 1.e4;
|
||||
}
|
||||
};
|
||||
|
||||
namespace
|
||||
{
|
||||
TransferFunction_plugin_creator_concrete<transfer_eisenstein_plugin> creator("eisenstein");
|
||||
TransferFunction_plugin_creator_concrete<transfer_eisenstein_wdm_plugin> creator2("eisenstein_wdm");
|
||||
TransferFunction_plugin_creator_concrete<transfer_eisenstein_cdmbino_plugin> creator3("eisenstein_cdmbino");
|
||||
// TransferFunction_plugin_creator_concrete<transfer_eisenstein_cutoff_plugin> creator4("eisenstein_cutoff");
|
||||
} // namespace
|
||||
|
|
|
@ -295,7 +295,7 @@ void output_convergence(
|
|||
for (std::size_t k = 0; k < phi_code.size(2); ++k) {
|
||||
std::size_t idx = phi_code.get_idx(i, j, k);
|
||||
auto kk = phi_code.get_k<real_t>(i, j, k);
|
||||
nabla_vini_mn.kelem(idx) = phi_code.kelem(idx) * (kk[m] * kk[n]);
|
||||
nabla_vini_mn.kelem(idx) = phi_code.kelem(idx) * real_t(kk[m] * kk[n]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -379,12 +379,12 @@ void output_convergence(
|
|||
for (std::size_t k = 0; k < phi.size(2); ++k) {
|
||||
auto kk = phi.get_k<real_t>(i, j, k);
|
||||
std::size_t idx = phi.get_idx(i, j, k);
|
||||
psi_1_tmp.kelem(idx) = ccomplex_t(0.0, 1.0) * (kk[idim] * phi.kelem(idx));
|
||||
psi_2_tmp.kelem(idx) = ccomplex_t(0.0, 1.0) * (kk[idim] * phi2.kelem(idx));
|
||||
psi_1_tmp.kelem(idx) = ccomplex_t(0.0, 1.0) * (real_t(kk[idim]) * phi.kelem(idx));
|
||||
psi_2_tmp.kelem(idx) = ccomplex_t(0.0, 1.0) * (real_t(kk[idim]) * phi2.kelem(idx));
|
||||
psi_3_tmp.kelem(idx) = ccomplex_t(0.0, 1.0) * (
|
||||
kk[idim] * phi3.kelem(idx) +
|
||||
kk[idimp] * A3[idimpp]->kelem(idx) -
|
||||
kk[idimpp] * A3[idimp]->kelem(idx)
|
||||
real_t(kk[idim]) * phi3.kelem(idx) +
|
||||
real_t(kk[idimp]) * A3[idimpp]->kelem(idx) -
|
||||
real_t(kk[idimpp]) * A3[idimp]->kelem(idx)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ void print_TransferFunction_plugins()
|
|||
music::ilog << std::endl;
|
||||
}
|
||||
|
||||
std::unique_ptr<TransferFunction_plugin> select_TransferFunction_plugin(config_file &cf)
|
||||
std::unique_ptr<TransferFunction_plugin> select_TransferFunction_plugin(config_file &cf, const cosmology::parameters& cosmo_param)
|
||||
{
|
||||
std::string tfname = cf.get_value<std::string>("cosmology", "transfer");
|
||||
|
||||
|
@ -57,5 +57,5 @@ std::unique_ptr<TransferFunction_plugin> select_TransferFunction_plugin(config_f
|
|||
music::ilog << std::setw(32) << std::left << "Transfer function plugin" << " : " << tfname << std::endl;
|
||||
}
|
||||
|
||||
return std::move(the_TransferFunction_plugin_creator->create(cf));
|
||||
return std::move(the_TransferFunction_plugin_creator->create(cf, cosmo_param));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue