Initial import
This commit is contained in:
commit
56a50eead3
820 changed files with 192077 additions and 0 deletions
42
libLSS/samplers/ares/ares_bias.hpp
Normal file
42
libLSS/samplers/ares/ares_bias.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/ares_bias.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_ARES_BIAS_HPP
|
||||
#define __LIBLSS_ARES_BIAS_HPP
|
||||
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/samplers/core/types_samplers.hpp"
|
||||
#include "libLSS/mcmc/global_state.hpp"
|
||||
#include <boost/format.hpp>
|
||||
|
||||
namespace LibLSS {
|
||||
namespace ARES {
|
||||
inline double& extract_bias(MarkovState& state, int c)
|
||||
{
|
||||
using boost::format;
|
||||
return (*state.get<ArrayType1d>(format("galaxy_bias_%d") % c)->array)[0];
|
||||
}
|
||||
|
||||
template<typename InitializerArray>
|
||||
void ensure_bias_size(MarkovState& state, unsigned int c, const InitializerArray& init_a)
|
||||
{
|
||||
using boost::format;
|
||||
auto& a = (*state.get<ArrayType1d>(format("galaxy_bias_%d") % c)->array);
|
||||
size_t old_sz = a.size();
|
||||
if (old_sz < init_a.size()) {
|
||||
a.resize(boost::extents[init_a.size()]);
|
||||
for (size_t i = old_sz; i < init_a.size(); i++)
|
||||
a[i] = init_a[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
536
libLSS/samplers/ares/gibbs_messenger.cpp
Normal file
536
libLSS/samplers/ares/gibbs_messenger.cpp
Normal file
|
@ -0,0 +1,536 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/gibbs_messenger.cpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include <Eigen/Core>
|
||||
#include <cmath>
|
||||
#include <boost/format.hpp>
|
||||
#include <CosmoTool/fourier/fft/fftw_calls.hpp>
|
||||
#include "libLSS/samplers/core/random_number.hpp"
|
||||
#include "libLSS/samplers/ares/gibbs_messenger.hpp"
|
||||
#include "libLSS/tools/mpi_fftw_helper.hpp"
|
||||
#include "libLSS/samplers/ares/ares_bias.hpp"
|
||||
#include "libLSS/tools/fused_array.hpp"
|
||||
#include "libLSS/tools/fused_assign.hpp"
|
||||
#include "libLSS/tools/array_tools.hpp"
|
||||
|
||||
using namespace LibLSS;
|
||||
using boost::format;
|
||||
using boost::extents;
|
||||
using LibLSS::ARES::extract_bias;
|
||||
|
||||
typedef boost::multi_array_types::extent_range range;
|
||||
|
||||
typedef Eigen::Map<Eigen::ArrayXd, Eigen::Aligned> MappedArray;
|
||||
|
||||
/* (data,s) -> t sampler
|
||||
*/
|
||||
|
||||
MessengerSampler::MessengerSampler(MPI_Communication * comm_)
|
||||
: comm(comm_), constrainedGeneration(true), mgr(0)
|
||||
{
|
||||
}
|
||||
|
||||
MessengerSampler::~MessengerSampler()
|
||||
{
|
||||
if (mgr != 0)
|
||||
delete mgr;
|
||||
}
|
||||
|
||||
void MessengerSampler::restore(MarkovState& state)
|
||||
{
|
||||
initialize(state);
|
||||
}
|
||||
|
||||
void MessengerSampler::initialize(MarkovState& state)
|
||||
{
|
||||
ArrayType *messenger;
|
||||
Console& cons = Console::instance();
|
||||
|
||||
cons.print<LOG_INFO>("Initialize Messenger sampler");
|
||||
cons.indent();
|
||||
|
||||
N0 = state.get<SLong>("N0")->value;
|
||||
N1 = state.get<SLong>("N1")->value;
|
||||
N2 = state.get<SLong>("N2")->value;
|
||||
|
||||
mgr = new FFTMgr(N0, N1, N2, comm);
|
||||
|
||||
startN0 = mgr->startN0;
|
||||
localN0 = mgr->localN0;
|
||||
|
||||
Ntot = N0*N1*N2;
|
||||
localNtot = localN0*N1*N2;
|
||||
|
||||
N_k = state.get<SLong>("NUM_MODES")->value;
|
||||
|
||||
rng = state.get<RandomGen>("random_generator");
|
||||
|
||||
cons.print<LOG_DEBUG>("Allocating messenger field");
|
||||
messenger = new ArrayType(extents[range(startN0,startN0+localN0)][N1][N2]);
|
||||
messenger->setRealDims(ArrayDimension(N0, N1, N2));
|
||||
cons.print<LOG_DEBUG>(format("Allocated messenger_field %p") % messenger->array->data());
|
||||
cons.print<LOG_DEBUG>("Allocating messenger field");
|
||||
messenger_mask = new ArrayType(extents[range(startN0,startN0+localN0)][N1][N2]);
|
||||
messenger_mask->setRealDims(ArrayDimension(N0, N1, N2));
|
||||
cons.print<LOG_DEBUG>("Allocating mixed data field");
|
||||
data_field = new ArrayType(extents[range(startN0,startN0+localN0)][N1][N2]);
|
||||
data_field->setRealDims(ArrayDimension(N0, N1, N2));
|
||||
|
||||
state.newElement("messenger_field", messenger);
|
||||
state.newElement("messenger_mask", messenger_mask);
|
||||
state.newElement("messenger_tau", messenger_tau = new SDouble());
|
||||
state.newElement("data_field", data_field);
|
||||
|
||||
cons.unindent();
|
||||
cons.print<LOG_INFO>("Done");
|
||||
}
|
||||
|
||||
void MessengerSampler::sample(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("MessengerSampler::sample");
|
||||
ArrayType& s_field = static_cast<ArrayType&>(state["s_field"]);
|
||||
ArrayType::ArrayType& m_field = *state.get<ArrayType>("messenger_field")->array;
|
||||
ArrayType& data_field = static_cast<ArrayType&>(state["data_field"]);
|
||||
// We need the 3d messenger mask/window
|
||||
ArrayType& W = *messenger_mask;
|
||||
// We need the random generator
|
||||
SDouble& tau = *messenger_tau;
|
||||
double sqrt_tau = std::sqrt(tau);
|
||||
|
||||
if (constrainedGeneration) {
|
||||
#pragma omp parallel
|
||||
{
|
||||
auto &rng_g = rng->get();
|
||||
const auto &W_tmp = W.array->data();
|
||||
const auto &s_tmp = s_field.array->data();
|
||||
const auto &d_tmp = data_field.array->data();
|
||||
const auto &m_tmp = m_field.data();
|
||||
#pragma omp for schedule(static)
|
||||
for (long i = 0; i < localNtot; i++) {
|
||||
double A = rng_g.gaussian();
|
||||
double Wi = W_tmp[i];
|
||||
double si = s_tmp[i];
|
||||
double di = d_tmp[i];
|
||||
double mu, sigma;
|
||||
|
||||
if (Wi > 0) {
|
||||
mu = (si * Wi + tau * di) / (Wi + tau);
|
||||
sigma = std::sqrt( (Wi*tau) / (Wi + tau) );
|
||||
} else if (Wi < 0){
|
||||
mu = si;
|
||||
sigma = sqrt_tau;
|
||||
} else {
|
||||
mu = di;
|
||||
sigma = 0;
|
||||
}
|
||||
|
||||
m_tmp[i] = mu + sigma * A;
|
||||
}
|
||||
} // end of parallel region
|
||||
} else {
|
||||
for (long i = 0; i < localNtot; i++) {
|
||||
double A = rng->get().gaussian();
|
||||
double Wi = W.array->data()[i];
|
||||
double m_i = m_field.data()[i];
|
||||
double& di = data_field.array->data()[i];
|
||||
|
||||
if (Wi > 0)
|
||||
di = m_i + std::sqrt(Wi)*A;
|
||||
else
|
||||
di = 0;
|
||||
Console::instance().c_assert(!std::isnan(di), "Data is a NaN");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* t-> s sampler
|
||||
*/
|
||||
|
||||
MessengerSignalSampler::MessengerSignalSampler(MPI_Communication* comm)
|
||||
: flat_key(0), tmp_fourier(0), tmp_fourier_m(0), tmp_m_field(0), tmp_real_field(0), analysis_plan(0), synthesis_plan(0),
|
||||
constrainedGeneration(true), comm(comm), mgr(0)
|
||||
{
|
||||
}
|
||||
|
||||
void MessengerSignalSampler::restore(MarkovState& state)
|
||||
{
|
||||
initialize(state);
|
||||
}
|
||||
|
||||
void MessengerSignalSampler::initialize(MarkovState& state)
|
||||
{
|
||||
Console& cons = Console::instance();
|
||||
ConsoleContext<LOG_INFO> ctx("Messenger-Signal sampler");
|
||||
|
||||
N0 = static_cast<SLong&>(state["N0"]);
|
||||
N1 = static_cast<SLong&>(state["N1"]);
|
||||
N2 = static_cast<SLong&>(state["N2"]);
|
||||
|
||||
mgr = new FFTMgr(N0, N1, N2, comm);
|
||||
|
||||
// This for MPI support
|
||||
startN0 = mgr->startN0;
|
||||
localN0 = mgr->localN0;
|
||||
fourierLocalSize = mgr->allocator_real.minAllocSize;
|
||||
|
||||
N_k = state.get<SLong>("NUM_MODES")->value;
|
||||
|
||||
L0 = static_cast<SDouble&>(state["L0"]);
|
||||
L1 = static_cast<SDouble&>(state["L1"]);
|
||||
L2 = static_cast<SDouble&>(state["L2"]);
|
||||
|
||||
if (tmp_fourier) {
|
||||
error_helper<ErrorBadState>("MessengerSignalSampler has already been initialized.");
|
||||
}
|
||||
|
||||
|
||||
cons.print<LOG_DEBUG>("Allocating x field");
|
||||
x_field = new ArrayType(extents[range(startN0,startN0+localN0)][N1][N2]);
|
||||
x_field->setRealDims(ArrayDimension(N0, N1, N2));
|
||||
cons.print<LOG_DEBUG>("Allocating s field");
|
||||
s_field = new ArrayType(extents[range(startN0,startN0+localN0)][N1][N2]);
|
||||
s_field->setRealDims(ArrayDimension(N0, N1, N2));
|
||||
state.newElement("x_field", x_field);
|
||||
state.newElement("s_field", s_field, true);
|
||||
|
||||
s_field->eigen().fill(0);
|
||||
x_field->eigen().fill(0);
|
||||
|
||||
Ntot = N0*N1*N2;
|
||||
Ntot_k = N0*N1*(N2/2+1);
|
||||
|
||||
localNtot = localN0*N1*N2;
|
||||
localNtot_k = localN0*N1*(N2/2+1);
|
||||
|
||||
volume = L0*L1*L2;
|
||||
volNorm = volume/Ntot;
|
||||
|
||||
ctx.print(format("fourierLocalSize = %d") % fourierLocalSize);
|
||||
tmp_fourier = MFCalls::alloc_complex(fourierLocalSize);
|
||||
tmp_fourier_m = MFCalls::alloc_complex(fourierLocalSize);
|
||||
|
||||
|
||||
#ifndef ARES_MPI_FFTW
|
||||
ctx.print("Creating FFTW plans for Messenger-Signal");
|
||||
tmp_m_field = new ArrayType(boost::extents[range(startN0,startN0+localN0)][N1][N2]);
|
||||
ctx.print(format("Allocated tmp_m_field %p") % tmp_m_field->array->origin());
|
||||
analysis_plan = MFCalls::plan_dft_r2c_3d(
|
||||
N0, N1, N2,
|
||||
x_field->array->data(),
|
||||
tmp_fourier,
|
||||
FFTW_DESTROY_INPUT|FFTW_MEASURE);
|
||||
synthesis_plan = MFCalls::plan_dft_c2r_3d(
|
||||
N0, N1, N2,
|
||||
tmp_fourier,
|
||||
x_field->array->data(),
|
||||
FFTW_DESTROY_INPUT|FFTW_MEASURE);
|
||||
#else
|
||||
ctx.print("Creating MPI/FFTW plans for Messenger-Signal");
|
||||
tmp_real_field = MFCalls::alloc_real(fourierLocalSize*2);
|
||||
analysis_plan = MFCalls::plan_dft_r2c_3d(
|
||||
N0, N1, N2,
|
||||
tmp_real_field,
|
||||
tmp_fourier,
|
||||
comm->comm(),
|
||||
// FFTW_MPI_TRANSPOSED_OUT|
|
||||
FFTW_DESTROY_INPUT|FFTW_MEASURE);
|
||||
synthesis_plan = MFCalls::plan_dft_c2r_3d(
|
||||
N0, N1, N2,
|
||||
tmp_fourier,
|
||||
tmp_real_field,
|
||||
comm->comm(),
|
||||
//FFTW_MPI_TRANSPOSED_IN|
|
||||
FFTW_DESTROY_INPUT|FFTW_MEASURE);
|
||||
#endif
|
||||
ctx.print(format("allocated tmp_fourier(%p) tmp_fourier_m(%p) and tmp_real_field(%p)") % tmp_fourier % tmp_fourier_m% tmp_real_field);
|
||||
ctx.print("Done creating FFTW plans for Messenger-Signal");
|
||||
}
|
||||
|
||||
|
||||
MessengerSignalSampler::~MessengerSignalSampler()
|
||||
{
|
||||
if (tmp_fourier) {
|
||||
Console::instance().print<LOG_INFO>("Cleaning up Messenger-Signal");
|
||||
|
||||
#ifdef ARES_MPI_FFTW
|
||||
delete tmp_m_field;
|
||||
#endif
|
||||
if (flat_key)
|
||||
delete flat_key;
|
||||
if (tmp_fourier)
|
||||
MFCalls::free(tmp_fourier);
|
||||
if (tmp_fourier_m)
|
||||
MFCalls::free(tmp_fourier_m);
|
||||
if (tmp_real_field)
|
||||
MFCalls::free(tmp_real_field);
|
||||
if (analysis_plan)
|
||||
MFCalls::destroy_plan(analysis_plan);
|
||||
if (synthesis_plan)
|
||||
MFCalls::destroy_plan(synthesis_plan);
|
||||
|
||||
if (mgr)
|
||||
delete mgr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MessengerSignalSampler::sample(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("MessengerSignalSampler::sample");
|
||||
RandomGen& rng = static_cast<RandomGen&>(state["random_generator"]);
|
||||
ArrayType& m_field = *state.get<ArrayType>("messenger_field");
|
||||
ArrayType1d::ArrayType& P_info = *state.get<ArrayType1d>("powerspectrum")->array;
|
||||
SDouble& tau = static_cast<SDouble&>(state["messenger_tau"]);
|
||||
IArrayType::ArrayType& P_key = *state.get<IArrayType>("k_keys")->array; // Built by powerspec_tools
|
||||
|
||||
ArrayType& x = *x_field;
|
||||
ArrayType& s = *s_field;
|
||||
double alpha = 1/std::sqrt(double(Ntot));
|
||||
Console& cons = Console::instance();
|
||||
|
||||
ctx.print("Sample messenger-signal");
|
||||
|
||||
if (state.get<SBool>("messenger_signal_blocked")->value && constrainedGeneration)
|
||||
return;
|
||||
|
||||
// We have to initialize this lazily. k_keys is created by powerspectrum samplers.
|
||||
if (flat_key == 0) {
|
||||
IArrayType *keys = state.get<IArrayType>("k_keys");
|
||||
flat_key = new FlatIntType( keys->array->data(), boost::extents[keys->array->num_elements()] );
|
||||
}
|
||||
|
||||
#pragma omp parallel
|
||||
{
|
||||
auto &rng_g = rng.get();
|
||||
const auto &data = x.array->data();
|
||||
#pragma omp for schedule(static)
|
||||
for (long i = 0; i < localNtot; i++) {
|
||||
data[i] = rng_g.gaussian()*alpha;
|
||||
}
|
||||
}
|
||||
copy_padded_data(*x.array, tmp_real_field, true);
|
||||
// This destroy the x_field. Not a problem. synthesis is regenerating it
|
||||
MFCalls::execute(analysis_plan);
|
||||
#ifdef ARES_MPI_FFTW
|
||||
copy_padded_data(*m_field.array, tmp_real_field);
|
||||
MFCalls::execute_r2c(analysis_plan, tmp_real_field, tmp_fourier_m);
|
||||
#else
|
||||
// This destroy the m_field. Could be annoying.
|
||||
tmp_m_field->eigen() = m_field.eigen();
|
||||
FCalls::execute_r2c(analysis_plan, m_field.array->data(), tmp_fourier_m);
|
||||
#endif
|
||||
|
||||
if (constrainedGeneration) {
|
||||
double scaler = 1/volNorm;
|
||||
double T = tau * volume;
|
||||
|
||||
boost::multi_array<double, 1> sqrtP(boost::extents[N_k]);
|
||||
boost::multi_array<double, 1> A1(boost::extents[N_k]);
|
||||
boost::multi_array<double, 1> A2(boost::extents[N_k]);
|
||||
|
||||
LibLSS::copy_array(sqrtP,
|
||||
b_fused<double>(P_info,
|
||||
[this,scaler](double x)->double const { return x < 0 ? 0 : std::sqrt(x*volume);}
|
||||
)
|
||||
);
|
||||
LibLSS::copy_array(A1,
|
||||
b_fused<double>(P_info, sqrtP,
|
||||
[this,scaler,T](double x,double y)->double const { return x < 0 ? 0 : y/(T+x*volume*scaler); })
|
||||
);
|
||||
LibLSS::copy_array(A2,
|
||||
b_fused<double>(P_info,
|
||||
[this,scaler,T](double x)->double const { return x < 0 ? 0 : std::sqrt(T/(T+x*volume*scaler)); })
|
||||
);
|
||||
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (long i = 0; i < localNtot_k; i++) {
|
||||
long key = (*flat_key)[i];
|
||||
double color_P = sqrtP[key];
|
||||
double aux1 = A1[key];
|
||||
double aux2 = A2[key];
|
||||
MFCalls::complex_type& white_phase = tmp_fourier_m[i];
|
||||
MFCalls::complex_type& random_phase = tmp_fourier[i];
|
||||
MFCalls::complex_type& colored_phase = tmp_fourier_m[i];
|
||||
|
||||
random_phase[0] = aux1 * white_phase[0] + aux2 * random_phase[0];
|
||||
random_phase[1] = aux1 * white_phase[1] + aux2 * random_phase[1];
|
||||
|
||||
colored_phase[0] = color_P * random_phase[0];
|
||||
colored_phase[1] = color_P * random_phase[1];
|
||||
}
|
||||
if (startN0 == 0 && localN0 > 1) {
|
||||
tmp_fourier[0][0] = 0;
|
||||
tmp_fourier[0][1] = 0;
|
||||
tmp_fourier_m[0][0] = 0;
|
||||
tmp_fourier_m[0][1] = 0;
|
||||
}
|
||||
} else {
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (long i = 0; i < localNtot_k; i++) {
|
||||
double P = P_info[(*flat_key)[i]] * volume;
|
||||
double color_P = std::sqrt(P);
|
||||
MFCalls::complex_type& white_phase = tmp_fourier_m[i];
|
||||
MFCalls::complex_type& random_phase = tmp_fourier[i];
|
||||
MFCalls::complex_type& colored_phase = tmp_fourier_m[i];
|
||||
|
||||
colored_phase[0] = color_P * random_phase[0];
|
||||
colored_phase[1] = color_P * random_phase[1];
|
||||
}
|
||||
}
|
||||
|
||||
ctx.print("Fourier synthesis of phases");
|
||||
// Regenerate a correct x_field
|
||||
MFCalls::execute(synthesis_plan);
|
||||
copy_unpadded_data(tmp_real_field, *x.array, true);
|
||||
|
||||
ctx.print("Fourier synthesis of signal");
|
||||
// Generate the colored s field
|
||||
#ifdef ARES_MPI_FFTW
|
||||
MFCalls::execute_c2r(synthesis_plan, tmp_fourier_m, tmp_real_field);
|
||||
copy_unpadded_data(tmp_real_field, *s.array);
|
||||
#else
|
||||
FCalls::execute_c2r(synthesis_plan, tmp_fourier_m, s.array->data());
|
||||
if (constrainedGeneration) {
|
||||
// Restore m_field
|
||||
m_field.eigen() = tmp_m_field->eigen();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Just renormalize
|
||||
array::scaleArray3d(*s.array, 1.0/volume);
|
||||
array::scaleArray3d(*x.array, 1.0/volume);
|
||||
|
||||
// Generate m_field in mock mode
|
||||
if (!constrainedGeneration) {
|
||||
double sq_tau = sqrt(tau);
|
||||
|
||||
// Populate m_field
|
||||
for (long i = 0; i < localNtot; i++)
|
||||
m_field.array->data()[i] = s.array->data()[i] + rng.get().gaussian()*sq_tau;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* (catalog,meta) -> data
|
||||
*/
|
||||
|
||||
|
||||
void CatalogProjectorSampler::initialize(MarkovState& state)
|
||||
{
|
||||
Ncat = static_cast<SLong&>(state["NCAT"]);
|
||||
}
|
||||
|
||||
void CatalogProjectorSampler::restore(MarkovState& state)
|
||||
{
|
||||
Ncat = static_cast<SLong&>(state["NCAT"]);
|
||||
}
|
||||
|
||||
void CatalogProjectorSampler::sample(MarkovState& state)
|
||||
{
|
||||
RandomGen& rng = static_cast<RandomGen&>(state["random_generator"]);
|
||||
ArrayType& W = *state.get<ArrayType>("messenger_mask");
|
||||
SDouble *messenger_tau = state.get<SDouble>("messenger_tau");
|
||||
ArrayType& G = *state.get<ArrayType>("growth_factor");
|
||||
ArrayType& data_field = *state.get<ArrayType>("data_field");
|
||||
// Just do vectorized operation here
|
||||
MappedArray map_W = W.eigen();
|
||||
MappedArray growth = G.eigen();
|
||||
MappedArray map_data = data_field.eigen();
|
||||
ConsoleContext<LOG_DEBUG> ctx("regenerate_W");
|
||||
double heat = state.getScalar<double>("ares_heat");
|
||||
|
||||
ctx.print("Rebuild the projected data and covariance matrix");
|
||||
// Clear up W first
|
||||
map_W.fill(0);
|
||||
if (!mockGeneration)
|
||||
map_data.fill(0);
|
||||
for (int c = 0; c < Ncat; c++) {
|
||||
ctx.print(format("Looking at catalog %d") % c);
|
||||
|
||||
SelArrayType& sel_field = *state.get<SelArrayType>(format("galaxy_synthetic_sel_window_%d") % c);
|
||||
ArrayType& g_field = *state.get<ArrayType>(format("galaxy_data_%d") % c);
|
||||
double& bias = extract_bias(state, c);
|
||||
double nmean = state.get<SDouble>(format("galaxy_nmean_%d") % c)->value;
|
||||
MappedArray g_data = g_field.eigen();
|
||||
MappedArray map_sel = sel_field.eigen();
|
||||
|
||||
if (!mockGeneration)
|
||||
map_data += (g_data - nmean * map_sel) * bias * growth;
|
||||
|
||||
map_W += map_sel * nmean * bias*bias * growth * growth;
|
||||
}
|
||||
map_W /= heat;
|
||||
|
||||
ctx.print("Finish weights");
|
||||
|
||||
// Hmm... I cannot use the vectorized instruction here as it depends on the positivity of map_W[i]. Just do a loop
|
||||
double tau_inverse = 0; // This is the inverse of minimum covariance
|
||||
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (long n = 0; n < map_W.size(); n++) {
|
||||
double& val = map_W[n];
|
||||
|
||||
if (val > 0) {
|
||||
if (val > tau_inverse)
|
||||
tau_inverse = val;
|
||||
val = 1/val;
|
||||
} else
|
||||
val = 0;
|
||||
}
|
||||
ctx.print(format("Got partial_tau = %lg") % (1/tau_inverse));
|
||||
|
||||
comm->all_reduce(MPI_IN_PLACE, &tau_inverse, 1, translateMPIType<double>(), MPI_MAX);
|
||||
double tau = 1/tau_inverse;
|
||||
|
||||
messenger_tau->value = tau;
|
||||
|
||||
if (!mockGeneration)
|
||||
map_data *= map_W;
|
||||
else {
|
||||
for (int c = 0; c < Ncat; c++) {
|
||||
SelArrayType& sel_field = *state.get<SelArrayType>(format("galaxy_synthetic_sel_window_%d") % c);
|
||||
double& bias = extract_bias(state, c);
|
||||
double nmean = state.get<SDouble>(format("galaxy_nmean_%d") % c)->value;
|
||||
MappedArray map_sel = sel_field.eigen();
|
||||
ArrayType& s_field = *state.get<ArrayType>("s_field");
|
||||
ArrayType& g_field = *state.get<ArrayType>(format("galaxy_data_%d") % c);
|
||||
MappedArray s_data = s_field.eigen();
|
||||
MappedArray g_data = g_field.eigen();
|
||||
Eigen::ArrayXd err(map_sel.size());
|
||||
|
||||
ctx.print(format("Catalog %d: Generate mock data with nmean = %lg, bias = %lg") % c % nmean % bias);
|
||||
|
||||
err = map_sel * nmean;
|
||||
|
||||
g_data = err*(1+bias*growth*s_data);
|
||||
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (long i = 0; i < err.size(); i++) {
|
||||
double E = err[i];
|
||||
if (E > 0) {
|
||||
g_data[i] += rng.get().gaussian() * sqrt(E);
|
||||
} else {
|
||||
g_data[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (long n = 0; n < map_W.size(); n++) {
|
||||
if (map_W[n] > 0)
|
||||
map_W[n] = std::max(double(0), map_W[n] - tau);
|
||||
else
|
||||
map_W[n] = -1;
|
||||
}
|
||||
ctx.print(format("Got tau = %lg") % tau );
|
||||
}
|
102
libLSS/samplers/ares/gibbs_messenger.hpp
Normal file
102
libLSS/samplers/ares/gibbs_messenger.hpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/gibbs_messenger.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_GIBBS_MESSENGER_HPP
|
||||
#define __LIBLSS_GIBBS_MESSENGER_HPP
|
||||
|
||||
#include <CosmoTool/fourier/fft/fftw_calls.hpp>
|
||||
#include "libLSS/mpi/generic_mpi.hpp"
|
||||
#include "libLSS/mcmc/global_state.hpp"
|
||||
#include "libLSS/tools/fftw_allocator.hpp"
|
||||
#include "libLSS/samplers/core/markov.hpp"
|
||||
#include "libLSS/samplers/core/random_number.hpp"
|
||||
#include "libLSS/samplers/core/types_samplers.hpp"
|
||||
#include "libLSS/tools/mpi_fftw_helper.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
namespace GibbsMessenger {
|
||||
|
||||
namespace details {
|
||||
|
||||
typedef FFTW_Manager_3d<double> FFTMgr;
|
||||
|
||||
class MessengerSampler: public MarkovSampler {
|
||||
protected:
|
||||
long N0, N1, N2, Ntot, N_k;
|
||||
long localN0, startN0, localNtot;
|
||||
ArrayType *messenger_mask, *data_field;
|
||||
SDouble *messenger_tau;
|
||||
RandomGen *rng;
|
||||
bool constrainedGeneration;
|
||||
MPI_Communication *comm;
|
||||
FFTMgr *mgr;
|
||||
public:
|
||||
MessengerSampler(MPI_Communication *comm);
|
||||
virtual ~MessengerSampler();
|
||||
|
||||
virtual void restore(MarkovState& state);
|
||||
virtual void initialize(MarkovState& state);
|
||||
virtual void sample(MarkovState& state);
|
||||
|
||||
void setMockGeneration(bool b) { constrainedGeneration = !b; }
|
||||
|
||||
};
|
||||
|
||||
class MessengerSignalSampler: public MarkovSampler {
|
||||
protected:
|
||||
typedef boost::multi_array_ref< IArrayType::ArrayType::element, 1> FlatIntType;
|
||||
long fourierLocalSize;
|
||||
FCalls::plan_type analysis_plan, synthesis_plan;
|
||||
FCalls::complex_type *tmp_fourier, *tmp_fourier_m;
|
||||
FlatIntType *flat_key;
|
||||
double volNorm;
|
||||
long N0, N1, N2, Ntot, Ntot_k, N_k;
|
||||
long startN0, localN0, localNtot, localNtot_k;
|
||||
double L0, L1, L2, volume;
|
||||
ArrayType *tmp_m_field, *x_field, *s_field;
|
||||
bool constrainedGeneration;
|
||||
MPI_Communication *comm;
|
||||
FCalls::real_type *tmp_real_field;
|
||||
FFTMgr *mgr;
|
||||
public:
|
||||
MessengerSignalSampler(MPI_Communication* comm);
|
||||
virtual ~MessengerSignalSampler();
|
||||
|
||||
virtual void restore(MarkovState& state);
|
||||
virtual void initialize(MarkovState& state);
|
||||
virtual void sample(MarkovState& state);
|
||||
|
||||
void setMockGeneration(bool b) { constrainedGeneration = !b; }
|
||||
|
||||
};
|
||||
|
||||
class CatalogProjectorSampler: public MarkovSampler {
|
||||
protected:
|
||||
int Ncat;
|
||||
MPI_Communication *comm;
|
||||
bool mockGeneration;
|
||||
public:
|
||||
CatalogProjectorSampler(MPI_Communication *comm0): comm(comm0), mockGeneration(false) {}
|
||||
|
||||
virtual void restore(MarkovState& state);
|
||||
virtual void initialize(MarkovState& state);
|
||||
virtual void sample(MarkovState& state);
|
||||
|
||||
void setMockGeneration(bool b) { mockGeneration = b; }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
using GibbsMessenger::details::MessengerSampler;
|
||||
using GibbsMessenger::details::MessengerSignalSampler;
|
||||
using GibbsMessenger::details::CatalogProjectorSampler;
|
||||
}
|
||||
|
||||
#endif
|
266
libLSS/samplers/ares/linbias_sampler.cpp
Normal file
266
libLSS/samplers/ares/linbias_sampler.cpp
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/linbias_sampler.cpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include <boost/format.hpp>
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
#include <CosmoTool/algo.hpp>
|
||||
#include "libLSS/tools/errors.hpp"
|
||||
#include "libLSS/samplers/core/gig_sampler.hpp"
|
||||
#include "libLSS/samplers/ares/linbias_sampler.hpp"
|
||||
#include "libLSS/samplers/rgen/slice_sweep.hpp"
|
||||
#include "libLSS/samplers/ares/ares_bias.hpp"
|
||||
#include "libLSS/tools/array_tools.hpp"
|
||||
#include "boost/lambda/lambda.hpp"
|
||||
|
||||
using namespace LibLSS;
|
||||
using boost::format;
|
||||
using LibLSS::ARES::extract_bias;
|
||||
using LibLSS::ARES::ensure_bias_size;
|
||||
namespace ph = std::placeholders;
|
||||
|
||||
void LinearBiasSampler::initialize(MarkovState& state)
|
||||
{
|
||||
long N0, N1, N2;
|
||||
long localN0, startN0;
|
||||
|
||||
ConsoleContext<LOG_DEBUG> ctx("initialization of LinearBiasSampler");
|
||||
// This sampler depends heavily on the rest of the model.
|
||||
// First grab the number of catalogs available in the markov chain
|
||||
|
||||
Ncat = static_cast<SLong&>(state["NCAT"]);
|
||||
|
||||
N0 = static_cast<SLong&>(state["N0"]);
|
||||
localN0 = static_cast<SLong&>(state["localN0"]);
|
||||
startN0 = static_cast<SLong&>(state["startN0"]);
|
||||
N1 = static_cast<SLong&>(state["N1"]);
|
||||
N2 = static_cast<SLong&>(state["N2"]);
|
||||
|
||||
Ntot = N0*N1*N2;
|
||||
localNtot = localN0*N1*N2;
|
||||
// Ensure that the bias is at least size 1
|
||||
for (unsigned int c = 0; c < Ncat; c++)
|
||||
ensure_bias_size(state, c, boost::array<double,1>({1}));
|
||||
}
|
||||
|
||||
void LinearBiasSampler::restore(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("restoration of LinearBiasSampler");
|
||||
initialize(state);
|
||||
}
|
||||
|
||||
|
||||
static inline double logPosteriorBias(double b, double mean, double dev, double heat)
|
||||
{
|
||||
if (b < 0)
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
|
||||
double delta = (b-mean)/dev;
|
||||
|
||||
return -0.5*delta*delta*heat;
|
||||
}
|
||||
|
||||
void LinearBiasSampler::sample(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("sampling of mean and bias");
|
||||
ArrayType& data_field = *state.get<ArrayType>("data_field");
|
||||
ArrayType& W = *state.get<ArrayType>("messenger_mask");
|
||||
double *G = state.get<ArrayType>("growth_factor")->array->data();
|
||||
double *s_field = state.get<ArrayType>("s_field")->array->data();
|
||||
RandomGen *rng = state.get<RandomGen>("random_generator");
|
||||
double heat = state.getScalar<double>("ares_heat");
|
||||
using boost::extents;
|
||||
using CosmoTool::square;
|
||||
|
||||
if (state.get<SBool>("bias_sampler_blocked")->value)
|
||||
return;
|
||||
|
||||
auto ext_Ncat = extents[Ncat];
|
||||
boost::multi_array<double, 1>
|
||||
alphas(ext_Ncat), betas(ext_Ncat),
|
||||
chis(ext_Ncat), psis(ext_Ncat), Npixs(ext_Ncat);
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// Time consuming part, do data reduction per sub-catalog
|
||||
// We are only computing alphas and betas here.
|
||||
for (int c = 0; c < Ncat; c++) {
|
||||
SelArrayType& sel_field = *state.get<SelArrayType>(format("galaxy_synthetic_sel_window_%d") % c);
|
||||
double *g_field = state.get<ArrayType>(format("galaxy_data_%d") % c)->array->data();
|
||||
double& bias = extract_bias(state, c);
|
||||
SDouble *g_nmean = state.get<SDouble>(format("galaxy_nmean_%d") % c);
|
||||
double nmean = g_nmean->value;
|
||||
|
||||
const auto &sel_array = sel_field.array->data();
|
||||
double loc_alpha = 0, loc_beta = 0, loc_psi = 0, loc_chi = 0, loc_Npix = 0, alpha = 0, beta = 0;
|
||||
|
||||
#pragma omp parallel for schedule(dynamic, 1024) reduction(+:loc_alpha,loc_beta,loc_chi,loc_psi,loc_Npix)
|
||||
for (long i = 0; i < localNtot; i++) {
|
||||
double selection = sel_array[i];
|
||||
if (selection > 0) {
|
||||
double Nobs = g_field[i];
|
||||
double Dplus = G[i];
|
||||
double density = s_field[i];
|
||||
double aux_gamma = 1 + bias * Dplus * density;
|
||||
|
||||
loc_beta += selection * nmean * Dplus * Dplus * density * density;
|
||||
loc_alpha += (Nobs - selection*nmean) * Dplus * density;
|
||||
loc_chi += Nobs*Nobs/selection;
|
||||
loc_psi += selection * aux_gamma * aux_gamma;
|
||||
loc_Npix++;
|
||||
}
|
||||
}
|
||||
|
||||
// Store the partial result and continue
|
||||
alphas[c] = loc_alpha;
|
||||
betas[c] = loc_beta;
|
||||
chis[c] = loc_chi;
|
||||
psis[c] = loc_psi;
|
||||
Npixs[c] = loc_Npix;
|
||||
}
|
||||
|
||||
// Final reduction
|
||||
ctx.print("Reducing result");
|
||||
comm->all_reduce_t(MPI_IN_PLACE, alphas.data(), Ncat, MPI_SUM);
|
||||
comm->all_reduce_t(MPI_IN_PLACE, betas.data(), Ncat, MPI_SUM);
|
||||
comm->all_reduce_t(MPI_IN_PLACE, chis.data(), Ncat, MPI_SUM);
|
||||
comm->all_reduce_t(MPI_IN_PLACE, psis.data(), Ncat, MPI_SUM);
|
||||
comm->all_reduce_t(MPI_IN_PLACE, Npixs.data(), Ncat, MPI_SUM);
|
||||
ctx.print("Done");
|
||||
|
||||
for (int c = 0; c < Ncat; c++) {
|
||||
double& bias = extract_bias(state, c);
|
||||
double& nmean = state.get<SDouble>(format("galaxy_nmean_%d") % c)->value;
|
||||
|
||||
double alpha = alphas[c], beta = betas[c];
|
||||
bool biasRef = state.get<SBool>(format("galaxy_bias_ref_%d") % c )->value;
|
||||
|
||||
if (comm->rank() == 0 ) {// || comm->size() == 1 ) { // Use another node */
|
||||
double lambda = 1 - 0.5*Npixs[c];
|
||||
|
||||
nmean = GIG_sampler_3params(heat*psis[c],heat*chis[c],lambda,
|
||||
rng->get());
|
||||
|
||||
ctx.print(format("Npix = %d, chi = %lg, psi = %lg") % Npixs[c] % chis[c] % psis[c]);
|
||||
ctx.print(format("Broadcast value -> nmean = %lg") % nmean);
|
||||
}
|
||||
|
||||
if (!biasRef && comm->rank() == 0) {
|
||||
double mean_bias = alpha/beta;
|
||||
double dev_bias = sqrt(1/beta);
|
||||
|
||||
Console::instance().c_assert(!std::isinf(mean_bias) && !std::isnan(mean_bias), "Mean is NaN or infinite");
|
||||
ctx.print(format("bias = %lg, mean_bias = %lg, dev_bias = %lg") % bias % mean_bias % dev_bias);
|
||||
bias = slice_sweep(rng->get(), std::bind(logPosteriorBias, ph::_1, mean_bias, dev_bias, heat), bias, dev_bias);
|
||||
|
||||
Console::instance().c_assert(bias > 0, "Negative bias (0). Ouch!");
|
||||
}
|
||||
|
||||
ctx.print("Sync bias");
|
||||
// Synchronize all nodes with the new bias value
|
||||
comm->broadcast_t(&bias, 1, 0);
|
||||
|
||||
ctx.print("Sync nmean");
|
||||
// Synchronize all nodes with the new mean value
|
||||
comm->broadcast_t(&nmean, 1, 0 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
///now improve sampling efficiency by performing a joint step in s,P(k) and biases
|
||||
///NOTE: the following algorithm MUST be executed in sequence
|
||||
///get RNG
|
||||
|
||||
//only update if power-spectrum is sampled
|
||||
if (state.getScalar<bool>("power_sampler_a_blocked") &&
|
||||
state.getScalar<bool>("power_sampler_b_blocked") &&
|
||||
state.getScalar<bool>("power_sampler_c_blocked"))
|
||||
return;
|
||||
|
||||
RandomGen *rgen = state.get<RandomGen>("random_generator");
|
||||
double factor = 1.;
|
||||
|
||||
if (comm->rank() == 0) {
|
||||
for (int c = 0; c < Ncat; c++) {
|
||||
bool biasRef = state.get<SBool>(format("galaxy_bias_ref_%d") % c )->value;
|
||||
|
||||
//Don't sample the reference bias
|
||||
if (biasRef)
|
||||
continue;
|
||||
|
||||
//1) draw random bias realization (b1) for the first catalog
|
||||
double mean_bias = alphas[c]/betas[c];
|
||||
double dev_bias = sqrt(1./betas[c]);
|
||||
double& b0 = extract_bias(state, c);
|
||||
double b1=b0;
|
||||
|
||||
ctx.print(boost::format("Slice sweeping[%d]: mean_bias = %lg, dev_bias = %lg") % c % mean_bias % dev_bias);
|
||||
b1 = slice_sweep(rng->get(), std::bind(logPosteriorBias, ph::_1, mean_bias, dev_bias, heat), b1, dev_bias);
|
||||
|
||||
double fact_virt = b0/b1;
|
||||
|
||||
//Now calculate hastings value for the all catalogs but the current one (this sum can be done in parallel)
|
||||
double dH=0.;
|
||||
for (int cc = 0; cc < Ncat; cc++) {
|
||||
|
||||
if(c!=cc) {
|
||||
double bb = extract_bias(state, cc);
|
||||
|
||||
//Note that we need to operate with the updated density field
|
||||
//we calculate the metropolis factor of remaining likelihoods with respect to jumps in bias and density field
|
||||
dH += 2 * (1-fact_virt) * alphas[cc] * factor * bb -
|
||||
(1-fact_virt*fact_virt) * betas[cc]*square(factor*bb);
|
||||
}
|
||||
}
|
||||
|
||||
dH *= 0.5*heat;
|
||||
|
||||
//now do Metropolis step
|
||||
double log_u = log(rgen->get().uniform());
|
||||
if (log_u <= -dH) {
|
||||
//update accepted bias
|
||||
b0 = b1;
|
||||
//also update the density factor
|
||||
//this accounts for updating the density and power-spectrum fields deterministically
|
||||
factor *= fact_virt;
|
||||
|
||||
// ctx.print(format("Sample accepted for catalog nr. %lg! New bias = %lg , New density factor = %lg") %c % b0 % factor);
|
||||
}
|
||||
//if sample is rejected then simply continue
|
||||
comm->broadcast_t(&b0, 1, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// We are not root, just gather the biases as they are updated
|
||||
for (int c = 0; c < Ncat; c++) {
|
||||
bool biasRef = state.get<SBool>(format("galaxy_bias_ref_%d") % c )->value;
|
||||
|
||||
//Don't sample the reference bias
|
||||
if (!biasRef) {
|
||||
double& b0 = extract_bias(state, c);
|
||||
|
||||
// Update from Root rank the value of bias
|
||||
comm->broadcast_t(&b0, 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Broadcast and gather the scaling factor
|
||||
comm->broadcast_t(&factor, 1, 0);
|
||||
|
||||
//Finally we just need to rescale the density and power-spectrum fields by "factor"
|
||||
|
||||
//1) scale density field in real and Fourier space
|
||||
array::scaleArray3d(*state.get<ArrayType>("s_field")->array, factor);
|
||||
|
||||
//2) scale power-spectrum
|
||||
ArrayType1d::ArrayType& P_info = *state.get<ArrayType1d>("powerspectrum")->array;
|
||||
LibLSS::copy_array(P_info, b_fused<double>(P_info, (factor*factor)*boost::lambda::_1));
|
||||
}
|
36
libLSS/samplers/ares/linbias_sampler.hpp
Normal file
36
libLSS/samplers/ares/linbias_sampler.hpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/linbias_sampler.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_LINEAR_BIAS_SAMPLER_HPP
|
||||
#define __LIBLSS_LINEAR_BIAS_SAMPLER_HPP
|
||||
|
||||
#include <boost/multi_array.hpp>
|
||||
#include "libLSS/samplers/core/markov.hpp"
|
||||
#include "libLSS/samplers/core/types_samplers.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class LinearBiasSampler: public MarkovSampler {
|
||||
protected:
|
||||
int Ncat;
|
||||
long Ntot, localNtot;
|
||||
boost::multi_array<SDouble *, 1> biases;
|
||||
MPI_Communication *comm;
|
||||
public:
|
||||
LinearBiasSampler(MPI_Communication *comm0) : comm(comm0) {}
|
||||
virtual ~LinearBiasSampler() {}
|
||||
|
||||
virtual void initialize(MarkovState& state);
|
||||
virtual void restore(MarkovState& state);
|
||||
virtual void sample(MarkovState& state);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
142
libLSS/samplers/ares/powerspectrum_a_sampler.cpp
Normal file
142
libLSS/samplers/ares/powerspectrum_a_sampler.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/powerspectrum_a_sampler.cpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include <cmath>
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/samplers/ares/powerspectrum_a_sampler.hpp"
|
||||
#include "libLSS/mcmc/state_element.hpp"
|
||||
#include "libLSS/samplers/core/powerspec_tools.hpp"
|
||||
#include "libLSS/tools/mpi_fftw_helper.hpp"
|
||||
|
||||
using namespace LibLSS;
|
||||
|
||||
void PowerSpectrumSampler_a::base_init()
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("base_init");
|
||||
|
||||
ctx.print(boost::format("Allocating Fourier buffer %dx%dx%d") % N0 % N1 % N2_HC);
|
||||
tmp_fourier = MFCalls::alloc_complex(fourierLocalSize);
|
||||
tmp_s = MFCalls::alloc_real(2*fourierLocalSize);
|
||||
assert(tmp_fourier != 0);
|
||||
|
||||
ctx.print(boost::format("Fourier buffer %p") % tmp_fourier);
|
||||
ctx.print(boost::format("Allocating plan %dx%dx%d") % N0 % N1 % N2);
|
||||
analysis_plan = MFCalls::plan_dft_r2c_3d(
|
||||
N0, N1, N2,
|
||||
tmp_s,
|
||||
(FCalls::complex_type *)tmp_fourier,
|
||||
#ifdef ARES_MPI_FFTW
|
||||
comm->comm(),
|
||||
#endif
|
||||
//FFTW_MPI_TRANSPOSED_OUT|
|
||||
FFTW_DESTROY_INPUT|FFTW_MEASURE);
|
||||
|
||||
flat_keys = new FlatIntType(keys->array->data(), boost::extents[keys->array->num_elements()] );
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_a::restore(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_INFO> ctx("restoration of power spectrum sampler (a)");
|
||||
|
||||
restore_base(state);
|
||||
|
||||
base_init();
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_a::initialize(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_INFO> ctx("initialization of power spectrum sampler (a)");
|
||||
|
||||
initialize_base(state);
|
||||
|
||||
base_init();
|
||||
}
|
||||
|
||||
PowerSpectrumSampler_a::PowerSpectrumSampler_a(MPI_Communication *comm0)
|
||||
: PowerSpectrumSampler_Base(comm0), tmp_fourier(0), flat_keys(0), tmp_s(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
PowerSpectrumSampler_a::~PowerSpectrumSampler_a()
|
||||
{
|
||||
if (tmp_fourier) {
|
||||
Console::instance().print<LOG_INFO>("Cleaning up Powerspectrum sampler (a)");
|
||||
|
||||
MFCalls::free(tmp_fourier);
|
||||
MFCalls::destroy_plan(analysis_plan);
|
||||
delete flat_keys;
|
||||
}
|
||||
if (tmp_s)
|
||||
MFCalls::free(tmp_s);
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_a::sample(MarkovState& state)
|
||||
{
|
||||
// Grab the messenger field
|
||||
ConsoleContext<LOG_DEBUG> ctx("PowerSpectrumSampler_a::sample");
|
||||
Console& cons = Console::instance();
|
||||
ArrayType& s_field = static_cast<ArrayType&>(state["s_field"]);
|
||||
|
||||
//return;
|
||||
IArrayType1d::ArrayType& nmode_array = *nmode->array;
|
||||
ArrayType1d::ArrayType& P_array = *P->array;
|
||||
|
||||
|
||||
if (state.get<SBool>("power_sampler_a_blocked")->value)
|
||||
return;
|
||||
|
||||
copy_padded_data(*s_field.array, tmp_s);
|
||||
MFCalls::execute(analysis_plan);
|
||||
|
||||
ctx.print("Compute inverse-gamma parameter");
|
||||
|
||||
std::fill(P_array.begin(), P_array.end(), 0);
|
||||
|
||||
ctx.print(boost::format("N_fourier_elements = %d") % N_fourier_elements);
|
||||
int *adjust = adjustMul->array->data();
|
||||
//#pragma omp parallel for schedule(static)
|
||||
for (long i = 0; i < local_fourier_elements; i++) {
|
||||
FCalls::complex_type& m_hat = tmp_fourier[i];
|
||||
double Pelt = m_hat[0]*m_hat[0] + m_hat[1]*m_hat[1];
|
||||
|
||||
// adjust increase memory bandwidth consumption. Not great...
|
||||
// OTOH it is very convenient and this loop is not the most time consuming aspect
|
||||
P_array[ (*flat_keys)[i] ] += adjust[i] * Pelt;
|
||||
}
|
||||
P_sync.mpiAllSum(*comm);
|
||||
|
||||
ctx.print("Sample new power spectrum");
|
||||
|
||||
const int alpha=1; ///Jeffreys prior
|
||||
|
||||
// Only compute random numbers on rank==0, broadcast after
|
||||
if (comm->rank() == 0) {
|
||||
#pragma omp parallel for schedule(static)
|
||||
for(long l = 0; l < N_k; l++) {
|
||||
if(nmode_array[l] > 0) {
|
||||
int beta = (2*alpha-2) + nmode_array[l];
|
||||
|
||||
///generate CHi-SQUARE sample
|
||||
double z2 = 0.;
|
||||
for(int j = 0; j < beta; j++) {
|
||||
double aux=rgen->get().gaussian();
|
||||
|
||||
z2 += aux*aux;
|
||||
}
|
||||
///calculate power-spectrum sample
|
||||
P_array[l] = (P_array[l]/z2) * volNorm / Ntot;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
P_sync.mpiBroadcast(*comm);
|
||||
}
|
||||
|
41
libLSS/samplers/ares/powerspectrum_a_sampler.hpp
Normal file
41
libLSS/samplers/ares/powerspectrum_a_sampler.hpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/powerspectrum_a_sampler.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_POWERSPECTRUM_A_SAMPLER_HPP
|
||||
#define __LIBLSS_POWERSPECTRUM_A_SAMPLER_HPP
|
||||
|
||||
#include "libLSS/mpi/generic_mpi.hpp"
|
||||
#include "libLSS/samplers/core/markov.hpp"
|
||||
#include "libLSS/samplers/core/types_samplers.hpp"
|
||||
#include "libLSS/samplers/core/powerspec_tools.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class PowerSpectrumSampler_a: public PowerSpectrumSampler_Base {
|
||||
protected:
|
||||
typedef boost::multi_array_ref< IArrayType::ArrayType::element, 1> FlatIntType;
|
||||
|
||||
FCalls::complex_type *tmp_fourier;
|
||||
FCalls::plan_type analysis_plan;
|
||||
FlatIntType *flat_keys;
|
||||
MFCalls::real_type *tmp_s;
|
||||
|
||||
void base_init();
|
||||
public:
|
||||
PowerSpectrumSampler_a(MPI_Communication *comm);
|
||||
virtual ~PowerSpectrumSampler_a();
|
||||
|
||||
virtual void restore(MarkovState& state);
|
||||
virtual void initialize(MarkovState& state);
|
||||
virtual void sample(MarkovState& state);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
217
libLSS/samplers/ares/powerspectrum_b_sampler.cpp
Normal file
217
libLSS/samplers/ares/powerspectrum_b_sampler.cpp
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/powerspectrum_b_sampler.cpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include <CosmoTool/algo.hpp>
|
||||
#include <cmath>
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/mcmc/state_element.hpp"
|
||||
#include "libLSS/samplers/core/powerspec_tools.hpp"
|
||||
#include "libLSS/samplers/ares/powerspectrum_b_sampler.hpp"
|
||||
#include "libLSS/tools/mpi_fftw_helper.hpp"
|
||||
|
||||
using boost::format;
|
||||
using namespace LibLSS;
|
||||
|
||||
PowerSpectrumSampler_b::PowerSpectrumSampler_b(MPI_Communication *comm0)
|
||||
: PowerSpectrumSampler_Coloring(comm0),
|
||||
tmp_fourier(0), P0_array(boost::extents[0]), P1_array(boost::extents[0]),
|
||||
tmp_x(0), tmp_t(0), total_accepted(0), total_tried(0), flat_keys(0)
|
||||
{
|
||||
}
|
||||
|
||||
PowerSpectrumSampler_b::~PowerSpectrumSampler_b()
|
||||
{
|
||||
if (tmp_fourier) {
|
||||
Console::instance().print<LOG_INFO>("Cleaning up Powerspectrum sampler (b)");
|
||||
Console::instance().print<LOG_DEBUG>(format("tmp_fourier=%p tmp_fourier=%p") % tmp_fourier % tmp_fourier_t);
|
||||
|
||||
FCalls::free(tmp_fourier);
|
||||
FCalls::free(tmp_fourier_t);
|
||||
FCalls::destroy_plan(analysis_plan);
|
||||
}
|
||||
if (tmp_x)
|
||||
MFCalls::free(tmp_x);
|
||||
if (tmp_t)
|
||||
MFCalls::free(tmp_t);
|
||||
if (flat_keys)
|
||||
delete flat_keys;
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_b::base_init(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("base init");
|
||||
|
||||
ctx.print(boost::format("Allocating Fourier buffer %dx%dx%d (sz=%d)") % localN0 % N1 % N2_HC % fourierLocalSize);
|
||||
tmp_fourier = MFCalls::alloc_complex(fourierLocalSize);
|
||||
tmp_fourier_t = MFCalls::alloc_complex(fourierLocalSize);
|
||||
tmp_x = MFCalls::alloc_real(2*fourierLocalSize);
|
||||
tmp_t = MFCalls::alloc_real(2*fourierLocalSize);
|
||||
P0_array.resize(boost::extents[N_k]);
|
||||
P1_array.resize(boost::extents[N_k]);
|
||||
|
||||
ctx.print(boost::format("Fourier buffer %p") % tmp_fourier);
|
||||
ctx.print(boost::format("Allocating plan %dx%dx%d") % N0 % N1 % N2);
|
||||
analysis_plan = MFCalls::plan_dft_r2c_3d(
|
||||
N0, N1, N2,
|
||||
tmp_x,
|
||||
tmp_fourier,
|
||||
#ifdef ARES_MPI_FFTW
|
||||
comm->comm(),
|
||||
#endif
|
||||
//FFTW_MPI_TRANSPOSED_OUT|
|
||||
FFTW_DESTROY_INPUT|FFTW_MEASURE);
|
||||
|
||||
flat_keys = new FlatIntType(keys->array->data(), boost::extents[keys->array->num_elements()] );
|
||||
|
||||
state.newElement("sampler_b_accepted", new SLong());
|
||||
state.newElement("sampler_b_tried", new SLong());
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_b::restore(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_INFO> ctx("restoration of power spectrum sampler (b)");
|
||||
|
||||
ctx.print("Restoring power spectrum sampler (b)");
|
||||
|
||||
restore_base(state);
|
||||
restore_coloring(state);
|
||||
|
||||
base_init(state);
|
||||
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_b::initialize(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_INFO> ctx("initialization of power spectrum sampler (b)");
|
||||
Console& cons = Console::instance();
|
||||
|
||||
initialize_base(state);
|
||||
initialize_coloring(state);
|
||||
base_init(state);
|
||||
|
||||
state.get<SLong>("sampler_b_accepted")->value = 0;
|
||||
state.get<SLong>("sampler_b_tried")->value = 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PowerSpectrumSampler_b::sample(MarkovState& state)
|
||||
{
|
||||
// Grab the messenger field
|
||||
ConsoleContext<LOG_DEBUG> ctx("sampling of power spectrum (b)");
|
||||
Console& cons = Console::instance();
|
||||
ArrayType& x_field = static_cast<ArrayType&>(state["x_field"]);
|
||||
ArrayType& t_field = static_cast<ArrayType&>(state["messenger_field"]);
|
||||
RandomGen *rng = state.get<RandomGen>("random_generator");
|
||||
IArrayType1d::ArrayType& nmode_array = *nmode->array;
|
||||
ArrayType1d::ArrayType& P_array = *P->array;
|
||||
SDouble *messenger_tau = state.get<SDouble>("messenger_tau");
|
||||
double tau = messenger_tau->value;
|
||||
long localNtot = localN0*N1*N2;
|
||||
|
||||
if (state.get<SBool>("power_sampler_b_blocked")->value)
|
||||
return;
|
||||
|
||||
#ifdef ARES_MPI_FFTW
|
||||
copy_padded_data(*x_field.array, tmp_x);
|
||||
copy_padded_data(*t_field.array, tmp_t);
|
||||
#else
|
||||
::memcpy(tmp_x, x_field.array->data(), Ntot * sizeof(MFCalls::real_type));
|
||||
::memcpy(tmp_t, t_field.array->data(), Ntot * sizeof(MFCalls::real_type));
|
||||
#endif
|
||||
|
||||
ctx.print("Fourier analysis (1)");
|
||||
MFCalls::execute(analysis_plan);
|
||||
ctx.print("Fourier analysis (2)");
|
||||
MFCalls::execute_r2c(analysis_plan, tmp_t, tmp_fourier_t);
|
||||
|
||||
ctx.print("Compute inverse-gamma parameter");
|
||||
|
||||
ctx.print(boost::format("local_fourier_elements = %d") % local_fourier_elements);
|
||||
int *adjust = adjustMul->array->data();
|
||||
|
||||
std::fill(P0_array.begin(), P0_array.end(), 0);
|
||||
std::fill(P1_array.begin(), P1_array.end(), 0);
|
||||
|
||||
//#pragma omp parallel for schedule(static)
|
||||
for (long i = 0; i < local_fourier_elements; i++) {
|
||||
FCalls::complex_type& x_hat = tmp_fourier[i];
|
||||
FCalls::complex_type& t_hat = tmp_fourier_t[i];
|
||||
double Pelt_cross = x_hat[0]*t_hat[0] + x_hat[1]*t_hat[1];
|
||||
double Pelt_auto = x_hat[0]*x_hat[0] + x_hat[1]*x_hat[1];
|
||||
|
||||
// adjust increase memory bandwidth consumption. Not great...
|
||||
// OTOH it is very convenient and this loop is not the most time consuming aspect
|
||||
P0_array[ (*flat_keys)[i] ] += adjust[i] * Pelt_cross;
|
||||
P1_array[ (*flat_keys)[i] ] += adjust[i] * Pelt_auto;
|
||||
}
|
||||
|
||||
// No helper function written here. Ask MPI to reduce the arrays in-place.
|
||||
comm->all_reduce_t(MPI_IN_PLACE, P0_array.data(), P0_array.num_elements(),
|
||||
MPI_SUM);
|
||||
comm->all_reduce_t(MPI_IN_PLACE, P1_array.data(), P1_array.num_elements(),
|
||||
MPI_SUM);
|
||||
|
||||
int accepted = 0, tried = 0;
|
||||
double normalization = tau * Ntot;
|
||||
|
||||
if (comm->rank() == 0) {
|
||||
ctx.print("Accumulated, now create plausible sample");
|
||||
#pragma omp parallel for schedule(static) reduction(+:accepted,tried)
|
||||
for (int i = 0; i < N_k; i++) {
|
||||
if (P1_array[i] > 0) {
|
||||
double s = 1/P1_array[i];
|
||||
P0_array[i] *= s;
|
||||
P1_array[i] = sqrt(s * normalization);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
double u0 = sqrt(P_array[i] * volume);
|
||||
double u1 = -1;
|
||||
double mean = P0_array[i];
|
||||
double sigma = P1_array[i];
|
||||
assert(!std::isnan(u0));
|
||||
assert(!std::isnan(mean));
|
||||
assert(!std::isnan(sigma));
|
||||
ctx.print(format(" k = %lg, mean = %lg, sigma = %lg") % (*k->array)[i]% mean % sigma);
|
||||
if (mean < 0) mean = 0;
|
||||
while(u1 < 0)
|
||||
u1 = mean + sigma*rng->get().gaussian(); ///NOTE: sample from truncated Gaussian
|
||||
|
||||
double PA = u1/u0;
|
||||
if(PA>1.)
|
||||
PA=1.;
|
||||
|
||||
double u = rng->get().uniform();
|
||||
if (u < PA) {
|
||||
P_array[i] = u1*u1 / volume;
|
||||
accepted++;
|
||||
}
|
||||
tried++;
|
||||
}
|
||||
}
|
||||
|
||||
ctx.print("Broadcast data");
|
||||
P_sync.mpiBroadcast(*comm);
|
||||
|
||||
total_accepted += accepted;
|
||||
total_tried += tried;
|
||||
|
||||
// Force update s_field with the new P
|
||||
update_s_field_from_x(state);
|
||||
|
||||
state.get<SLong>("sampler_b_accepted")->value = total_accepted;
|
||||
state.get<SLong>("sampler_b_tried")->value = total_tried;
|
||||
|
||||
if (comm->rank() == 0)
|
||||
Console::instance().print<LOG_VERBOSE>(format("PSpec sampler (b) total acceptance ratio: %2.0f %%") % (double(total_accepted)*100/total_tried));
|
||||
}
|
||||
|
||||
|
44
libLSS/samplers/ares/powerspectrum_b_sampler.hpp
Normal file
44
libLSS/samplers/ares/powerspectrum_b_sampler.hpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/powerspectrum_b_sampler.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_POWERSPECTRUM_B_SAMPLER_HPP
|
||||
#define __LIBLSS_POWERSPECTRUM_B_SAMPLER_HPP
|
||||
|
||||
#include "libLSS/mpi/generic_mpi.hpp"
|
||||
#include "libLSS/samplers/core/markov.hpp"
|
||||
#include "libLSS/samplers/core/types_samplers.hpp"
|
||||
#include "libLSS/samplers/core/powerspec_tools.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class PowerSpectrumSampler_b: public PowerSpectrumSampler_Coloring {
|
||||
protected:
|
||||
typedef boost::multi_array_ref< IArrayType::ArrayType::element, 1> FlatIntType;
|
||||
|
||||
MFCalls::complex_type *tmp_fourier, *tmp_fourier_t;
|
||||
MFCalls::real_type *tmp_x, *tmp_t;
|
||||
MFCalls::plan_type analysis_plan;
|
||||
FlatIntType *flat_keys;
|
||||
int total_accepted, total_tried;
|
||||
|
||||
ArrayType1d::ArrayType P0_array, P1_array;
|
||||
|
||||
void base_init(MarkovState& state);
|
||||
public:
|
||||
PowerSpectrumSampler_b(MPI_Communication *comm);
|
||||
virtual ~PowerSpectrumSampler_b();
|
||||
|
||||
virtual void restore(MarkovState& state);
|
||||
virtual void initialize(MarkovState& state);
|
||||
virtual void sample(MarkovState& state);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
196
libLSS/samplers/ares/powerspectrum_c_sampler.cpp
Normal file
196
libLSS/samplers/ares/powerspectrum_c_sampler.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/powerspectrum_c_sampler.cpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <CosmoTool/algo.hpp>
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/mcmc/state_element.hpp"
|
||||
#include "libLSS/samplers/core/powerspec_tools.hpp"
|
||||
#include "libLSS/samplers/ares/powerspectrum_c_sampler.hpp"
|
||||
#include "libLSS/tools/mpi_fftw_helper.hpp"
|
||||
#include "libLSS/samplers/rgen/slice_sweep.hpp"
|
||||
#include "libLSS/samplers/ares/ares_bias.hpp"
|
||||
|
||||
static const int ROOT = 0;
|
||||
static const size_t LARGE_SCALE_MODE_COUNT=14;
|
||||
|
||||
using boost::format;
|
||||
using namespace LibLSS;
|
||||
using LibLSS::ARES::extract_bias;
|
||||
namespace ph = std::placeholders;
|
||||
|
||||
PowerSpectrumSampler_c::PowerSpectrumSampler_c(MPI_Communication *comm0)
|
||||
: PowerSpectrumSampler_Coloring(comm0), counter_evaluations(0)
|
||||
{
|
||||
}
|
||||
|
||||
PowerSpectrumSampler_c::~PowerSpectrumSampler_c()
|
||||
{
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_c::base_init(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("base init");
|
||||
|
||||
Ncatalog = state.get<SLong>("NCAT")->value;
|
||||
localNtot = localN0 * N1 * N2;
|
||||
|
||||
// Create a counter reinitialized at each save that look at the number of posterior evaluation
|
||||
// required for each mode
|
||||
counter_evaluations = new IArrayType1d(boost::extents[P->array->num_elements()]);
|
||||
state.newElement("spectrum_c_eval_counter", counter_evaluations, true);
|
||||
counter_evaluations->setResetOnSave(0);
|
||||
counter_evaluations->fill(0);
|
||||
|
||||
sigma_init = new ArrayType1d(boost::extents[P->array->num_elements()]);
|
||||
state.newElement("spectrum_c_init_sigma", sigma_init);
|
||||
sigma_init->fill(0);
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_c::restore(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_INFO> ctx("restoration of power spectrum sampler (b)");
|
||||
|
||||
ctx.print("Restoring power spectrum sampler (b)");
|
||||
|
||||
restore_base(state);
|
||||
restore_coloring(state);
|
||||
|
||||
base_init(state);
|
||||
|
||||
init_sampler = false;
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_c::initialize(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_INFO> ctx("initialization of power spectrum sampler (c)");
|
||||
Console& cons = Console::instance();
|
||||
|
||||
initialize_base(state);
|
||||
initialize_coloring(state);
|
||||
base_init(state);
|
||||
|
||||
init_sampler = true;
|
||||
}
|
||||
|
||||
|
||||
double PowerSpectrumSampler_c::log_likelihood(MarkovState& state, int k, double P_trial)
|
||||
{
|
||||
// Reuse system power spectrum
|
||||
//
|
||||
if (P_trial < 0)
|
||||
return -std::numeric_limits<double>::infinity();
|
||||
|
||||
(*P->array)[k] = P_trial;
|
||||
update_s_field_from_x(state, (*P));
|
||||
|
||||
// Now compute full likelihood
|
||||
double *s = state.get<ArrayType>("s_field")->array->data();
|
||||
double heat = state.getScalar<double>("ares_heat");
|
||||
|
||||
double L = 0, loc_L = 0;
|
||||
for (int c = 0; c < Ncatalog; c++) {
|
||||
double Lc = 0;
|
||||
SelArrayType& sel_field = *state.get<SelArrayType>(format("galaxy_synthetic_sel_window_%d") % c);
|
||||
ArrayType& g_field = *state.get<ArrayType>(format("galaxy_data_%d") % c);
|
||||
double bias = extract_bias(state, c);
|
||||
double nmean = state.get<SDouble>(format("galaxy_nmean_%d") % c)->value;
|
||||
double *R = sel_field.array->data();
|
||||
double *gdata = g_field.array->data();
|
||||
|
||||
//#pragma omp simd aligned(s,R,gdata)
|
||||
#pragma omp parallel for schedule(static) reduction(+:Lc)
|
||||
for (long i = 0; i < localNtot; i++) {
|
||||
if (R[i] <= 0)
|
||||
continue;
|
||||
Lc += CosmoTool::square(gdata[i] - nmean * R[i] * (1 + bias * s[i])) / (R[i]*nmean);
|
||||
}
|
||||
|
||||
loc_L += Lc;
|
||||
}
|
||||
|
||||
comm->reduce_t(&loc_L, &L, 1, MPI_SUM, ROOT);
|
||||
// if (comm->rank() == 0)
|
||||
// Console::instance().print<LOG_INFO>(format("Likelihood(P=%lg) = %lg") % P_trial % L);
|
||||
|
||||
// o << format("%15.15lg %15.15lg")%P_trial %L<< std::endl;
|
||||
|
||||
(*counter_evaluations->array)[k]++;
|
||||
return -0.5*heat*L - std::log(P_trial);
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_c::sample(MarkovState& state)
|
||||
{
|
||||
// Grab the messenger field
|
||||
ConsoleContext<LOG_INFO_SINGLE> ctx("sampling of power spectrum (c)");
|
||||
Console& cons = Console::instance();
|
||||
ArrayType& x_field = static_cast<ArrayType&>(state["x_field"]);
|
||||
RandomGen *rng = state.get<RandomGen>("random_generator");
|
||||
IArrayType1d::ArrayType& nmode_array = *nmode->array;
|
||||
ArrayType1d::ArrayType& P_array = *P->array;
|
||||
long localNtot = localN0*N1*N2;
|
||||
long step = state.get<SLong>("MCMC_STEP")->value;
|
||||
|
||||
if (state.get<SBool>("power_sampler_c_blocked")->value)
|
||||
return;
|
||||
if ((step % 10) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx.print("Fourier analysis (1)");
|
||||
copy_padded_data(*x_field.array, tmp_real);
|
||||
|
||||
MFCalls::execute_r2c(analysis_plan, tmp_real, tmp_fourier);
|
||||
|
||||
int *counts = key_counts->array->data();
|
||||
|
||||
ArrayType1d::ArrayType& sigma_init_array = *sigma_init->array;
|
||||
if (init_sampler) {
|
||||
ctx.print("initial guess for the step for slice sampler...");
|
||||
for (long i = 0 ; i < P_array.size() ; i++) {
|
||||
if (counts[i] == 0)
|
||||
sigma_init_array[i] = 0;
|
||||
else
|
||||
sigma_init_array[i] = (P_array[i]) / std::sqrt(double(counts[i]));
|
||||
}
|
||||
init_sampler = false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < std::min(LARGE_SCALE_MODE_COUNT, P_array.size()); i++) {
|
||||
// std::string fname = str(format("P_k_%d.txt") % i);
|
||||
// std::ofstream f(fname.c_str());
|
||||
// Skip zero mode
|
||||
if (counts[i] == 0)
|
||||
continue;
|
||||
|
||||
double cosmic_var = sigma_init_array[i];
|
||||
ctx.print(format("Finding P_array(k=%d / %d) cvar=%g") % i % P_array.size() % cosmic_var);
|
||||
|
||||
auto posterior_fun =
|
||||
std::bind(&PowerSpectrumSampler_c::log_likelihood,
|
||||
this, boost::ref(state), i, ph::_1);
|
||||
|
||||
// We need the slice_sweep_double algo here. Cosmic var tends to quite underestimate
|
||||
// the width of the posterior
|
||||
if (cosmic_var >0)
|
||||
P_array[i] =
|
||||
slice_sweep_double(comm, rng->get(),
|
||||
posterior_fun,
|
||||
P_array[i], cosmic_var);
|
||||
|
||||
comm->broadcast_t(&P_array[i], 1, ROOT);
|
||||
}
|
||||
|
||||
update_s_field_from_x(state);
|
||||
|
||||
}
|
47
libLSS/samplers/ares/powerspectrum_c_sampler.hpp
Normal file
47
libLSS/samplers/ares/powerspectrum_c_sampler.hpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/powerspectrum_c_sampler.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_POWERSPECTRUM_C_SAMPLER_HPP
|
||||
#define __LIBLSS_POWERSPECTRUM_C_SAMPLER_HPP
|
||||
|
||||
#include <iostream>
|
||||
#include "libLSS/mpi/generic_mpi.hpp"
|
||||
#include "libLSS/samplers/core/markov.hpp"
|
||||
#include "libLSS/samplers/core/types_samplers.hpp"
|
||||
#include "libLSS/samplers/core/powerspec_tools.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class PowerSpectrumSampler_c: public PowerSpectrumSampler_Coloring {
|
||||
protected:
|
||||
typedef boost::multi_array_ref< IArrayType::ArrayType::element, 1> FlatIntType;
|
||||
|
||||
long localNtot;
|
||||
int total_accepted, total_tried;
|
||||
|
||||
bool init_sampler;
|
||||
IArrayType1d *counter_evaluations;
|
||||
ArrayType1d *sigma_init;
|
||||
|
||||
void base_init(MarkovState& state);
|
||||
|
||||
double log_likelihood(MarkovState& state, int k, double P_trial);
|
||||
|
||||
public:
|
||||
PowerSpectrumSampler_c(MPI_Communication *comm);
|
||||
virtual ~PowerSpectrumSampler_c();
|
||||
|
||||
virtual void restore(MarkovState& state);
|
||||
virtual void initialize(MarkovState& state);
|
||||
virtual void sample(MarkovState& state);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
102
libLSS/samplers/ares/synthetic_selection.cpp
Normal file
102
libLSS/samplers/ares/synthetic_selection.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/synthetic_selection.cpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include <boost/format.hpp>
|
||||
#include "libLSS/tools/errors.hpp"
|
||||
#include "libLSS/samplers/core/gig_sampler.hpp"
|
||||
#include "libLSS/samplers/ares/synthetic_selection.hpp"
|
||||
#include "libLSS/tools/fused_array.hpp"
|
||||
#include "libLSS/tools/fused_assign.hpp"
|
||||
|
||||
using namespace LibLSS;
|
||||
using boost::format;
|
||||
|
||||
using boost::extents;
|
||||
|
||||
typedef boost::multi_array_types::extent_range range;
|
||||
|
||||
|
||||
void SyntheticSelectionUpdater::initialize(MarkovState& state)
|
||||
{
|
||||
long N0, N1, N2;
|
||||
long localN0, startN0;
|
||||
long localNdata[6], Ndata[3];
|
||||
|
||||
ConsoleContext<LOG_DEBUG> ctx("initialization of Selection updater");
|
||||
|
||||
Ncat = static_cast<SLong&>(state["NCAT"]);
|
||||
|
||||
N0 = static_cast<SLong&>(state["N0"]);
|
||||
localN0 = static_cast<SLong&>(state["localN0"]);
|
||||
startN0 = static_cast<SLong&>(state["startN0"]);
|
||||
N1 = static_cast<SLong&>(state["N1"]);
|
||||
N2 = static_cast<SLong&>(state["N2"]);
|
||||
state.getScalarArray<long,3>("Ndata", Ndata);
|
||||
state.getScalarArray<long,6>("localNdata", localNdata);
|
||||
|
||||
Ntot = N0*N1*N2;
|
||||
localNtot = localN0*N1*N2;
|
||||
|
||||
for (int c = 0; c < Ncat; c++) {
|
||||
SelArrayType *sel_window;
|
||||
state.newElement(format("galaxy_synthetic_sel_window_%d") % c,
|
||||
sel_window = new SelArrayType(extents[range(localNdata[0],localNdata[1])][range(localNdata[2],localNdata[3])][range(localNdata[4],localNdata[5])]));
|
||||
|
||||
sel_window->setRealDims(ArrayDimension(Ndata[0], Ndata[1], Ndata[2]));
|
||||
}
|
||||
}
|
||||
|
||||
void SyntheticSelectionUpdater::restore(MarkovState& state)
|
||||
{
|
||||
initialize(state);
|
||||
}
|
||||
|
||||
void SyntheticSelectionUpdater::sample(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_VERBOSE> ctx("processing of 3d selection (including foregrounds)");
|
||||
|
||||
for (int c = 0; c < Ncat; c++) {
|
||||
SelArrayType *original_selection_grid = state.get<SelArrayType>(format("galaxy_sel_window_%d") % c);
|
||||
SelArrayType *sel_grid = state.get<SelArrayType>(format("galaxy_synthetic_sel_window_%d") % c);
|
||||
IArrayType1d *fgmap = state.get<IArrayType1d>(format("catalog_foreground_maps_%d") % c);
|
||||
ArrayType1d *fgvals = state.get<ArrayType1d>(format("catalog_foreground_coefficient_%d") % c);
|
||||
int NcatForegrounds = fgmap->array->num_elements();
|
||||
|
||||
ctx.format("Copy initial selection for catalog %d", c);
|
||||
sel_grid->eigen() = original_selection_grid->eigen();
|
||||
|
||||
for (int f = 0; f < NcatForegrounds; f++) {
|
||||
int c = (*fgmap->array)[f];
|
||||
double val = (*fgvals->array)[f];
|
||||
|
||||
ctx.print(format("Applying foreground %d (value %lg) to selection of catalog %d") % f % val % c);
|
||||
|
||||
ArrayType *fgField = state.get<ArrayType>(format("foreground_3d_%d") % (c));
|
||||
|
||||
auto mergingFunction = [val](double s,double f) { return s*(1 - f * val); };
|
||||
|
||||
// copy_array is parallelized, hopefully later vectorized
|
||||
if (f == 0) {
|
||||
LibLSS::copy_array(*sel_grid->array,
|
||||
b_fused<double>(*original_selection_grid->array,
|
||||
*fgField->array,
|
||||
mergingFunction
|
||||
)
|
||||
);
|
||||
} else {
|
||||
LibLSS::copy_array(*sel_grid->array,
|
||||
b_fused<double>(*sel_grid->array,
|
||||
*fgField->array,
|
||||
mergingFunction
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
33
libLSS/samplers/ares/synthetic_selection.hpp
Normal file
33
libLSS/samplers/ares/synthetic_selection.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/ares/synthetic_selection.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_SYNTHETIC_SELECTION_UPDATER_HPP
|
||||
#define __LIBLSS_SYNTHETIC_SELECTION_UPDATER_HPP
|
||||
|
||||
#include <boost/multi_array.hpp>
|
||||
#include "libLSS/samplers/core/markov.hpp"
|
||||
#include "libLSS/samplers/core/types_samplers.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class SyntheticSelectionUpdater: public MarkovSampler {
|
||||
protected:
|
||||
int Ncat;
|
||||
long Ntot, localNtot;
|
||||
public:
|
||||
|
||||
virtual void initialize(MarkovState& state);
|
||||
virtual void restore(MarkovState& state);
|
||||
virtual void sample(MarkovState& state);
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif
|
25
libLSS/samplers/core/gaussian_ratio.tcc
Normal file
25
libLSS/samplers/core/gaussian_ratio.tcc
Normal file
|
@ -0,0 +1,25 @@
|
|||
inline double RandomNumber::gaussian_ratio()
|
||||
{
|
||||
double u, v, x, y, Q;
|
||||
const double s = 0.449871; /* Constants from Leva */
|
||||
const double t = -0.386595;
|
||||
const double a = 0.19600;
|
||||
const double b = 0.25472;
|
||||
const double r1 = 0.27597;
|
||||
const double r2 = 0.27846;
|
||||
|
||||
do {
|
||||
u = 1 - uniform();
|
||||
v = uniform() - 0.5;
|
||||
|
||||
v *= 1.7156;
|
||||
|
||||
x = u - s;
|
||||
y = std::abs(v) - t;
|
||||
Q = x * x + y * (a * y - b * x);
|
||||
}
|
||||
while (Q >= r1 && (Q > r2 || (v*v) > (-4*u*u*log(u)) ) );
|
||||
|
||||
return v/u;
|
||||
}
|
||||
|
105
libLSS/samplers/core/gig_sampler.cc
Normal file
105
libLSS/samplers/core/gig_sampler.cc
Normal file
|
@ -0,0 +1,105 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <iomanip>
|
||||
#include <math.h>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cfloat>
|
||||
#include <string>
|
||||
#include <gsl/gsl_rng.h>
|
||||
#include <gsl/gsl_randist.h>
|
||||
#include "gig_sampler.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
using namespace LibLSS;
|
||||
|
||||
static double psi(double x, double alpha, double lambd)
|
||||
{
|
||||
return (-alpha*(cosh(x) -1.)-lambd*(exp(x)-x-1.));
|
||||
}
|
||||
|
||||
static double psi_prime(double x, double alpha,double lambd)
|
||||
{
|
||||
return (-alpha*sinh(x)-lambd*(exp(x)-1.));
|
||||
}
|
||||
|
||||
static double GIG_sampler_Devroy(double lambd, double omega, RandomNumber& rng)
|
||||
{
|
||||
double alpha=sqrt(omega*omega+lambd*lambd)-lambd;
|
||||
|
||||
double psi0=psi(1.,alpha,lambd);
|
||||
double psi1=psi(-1.,alpha,lambd);
|
||||
|
||||
double rho=4.;
|
||||
double t=sqrt(2.*rho/(alpha+lambd));
|
||||
rho=psi(t,alpha,lambd);
|
||||
|
||||
double taux=t;
|
||||
taux=(-taux+(rho-psi(-taux,alpha,lambd))/psi_prime(-taux,alpha,lambd))*(-1.);
|
||||
taux=(-taux+(rho-psi(-taux,alpha,lambd))/psi_prime(-taux,alpha,lambd))*(-1.);
|
||||
taux=(-taux+(rho-psi(-taux,alpha,lambd))/psi_prime(-taux,alpha,lambd))*(-1.);
|
||||
taux=(-taux+(rho-psi(-taux,alpha,lambd))/psi_prime(-taux,alpha,lambd))*(-1.);
|
||||
double s=(-taux+(rho-psi(-taux,alpha,lambd))/psi_prime(-taux,alpha,lambd))*(-1.);
|
||||
|
||||
double eta = -psi(t,alpha,lambd);
|
||||
double theta = -psi_prime(t,alpha,lambd);
|
||||
double phi = -psi(-s,alpha,lambd);
|
||||
double xi = psi_prime(-s,alpha,lambd);
|
||||
|
||||
double p = 1./xi;
|
||||
double r = 1./theta;
|
||||
|
||||
double t_prime = t-r*eta;
|
||||
double s_prime = s-p*phi;
|
||||
double q = t_prime+s_prime;
|
||||
|
||||
double X=0.;
|
||||
double chi=0.;
|
||||
|
||||
while(true)
|
||||
{
|
||||
double U=rng.uniform();
|
||||
double V=rng.uniform();
|
||||
double W=rng.uniform();
|
||||
|
||||
if(U<q/(p+q+r))
|
||||
{
|
||||
X=-s_prime+q*V;
|
||||
chi=0.;
|
||||
}
|
||||
else if (U<(q+r)/(p+q+r))
|
||||
{
|
||||
X=t_prime+r*log(1./V);
|
||||
chi=(-eta-theta*(X-t));
|
||||
}
|
||||
else
|
||||
{
|
||||
X=-s_prime-p*log(1./V);
|
||||
chi=(-phi+xi*(X+s));
|
||||
}
|
||||
if (log(W)+chi <= (psi(X,alpha,lambd))) break;
|
||||
}
|
||||
return ((lambd/omega+sqrt(1.+lambd*lambd/omega/omega))*exp(X));
|
||||
}
|
||||
|
||||
double LibLSS::GIG_sampler_3params(double a,double b,double p, RandomNumber& rng)
|
||||
{
|
||||
///this routine provides samples of the three parameter Generalized Inverse Gaussian (GIG) distribution
|
||||
/// log(P)=-1./2.*(x*a+b*power(x,-1.)) + (p-1.)*log(x)
|
||||
|
||||
double lambd=p;
|
||||
double omega=sqrt(b*a);
|
||||
|
||||
//one only needs to draw for lambda>0 see Devroy 2014
|
||||
double X=0.;
|
||||
|
||||
if(lambd>0.)
|
||||
X=GIG_sampler_Devroy(lambd,omega,rng);
|
||||
else
|
||||
X=1./GIG_sampler_Devroy(-lambd,omega,rng);
|
||||
|
||||
return sqrt(b/a)*X;
|
||||
}
|
19
libLSS/samplers/core/gig_sampler.hpp
Normal file
19
libLSS/samplers/core/gig_sampler.hpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/gig_sampler.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LSS_GIG_SAMPLER_HPP
|
||||
#define __LSS_GIG_SAMPLER_HPP
|
||||
|
||||
#include "random_number.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
double GIG_sampler_3params(double a,double b,double p, RandomNumber& rng);
|
||||
}
|
||||
|
||||
#endif
|
122
libLSS/samplers/core/main_loop.cpp
Normal file
122
libLSS/samplers/core/main_loop.cpp
Normal file
|
@ -0,0 +1,122 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/main_loop.cpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/samplers/core/main_loop.hpp"
|
||||
#include "libLSS/tools/timing_db.hpp"
|
||||
|
||||
using namespace LibLSS;
|
||||
using std::string;
|
||||
|
||||
MainLoop::MainLoop() {
|
||||
show_splash();
|
||||
mcmc_id = 0;
|
||||
}
|
||||
|
||||
MainLoop::~MainLoop() {}
|
||||
|
||||
void MainLoop::show_splash() {}
|
||||
|
||||
void MainLoop::initialize() {
|
||||
Console &cons = Console::instance();
|
||||
|
||||
cons.print<LOG_STD>("Initializing samplers");
|
||||
cons.indent();
|
||||
|
||||
for (MCList::iterator i = mclist.begin(); i != mclist.end(); ++i) {
|
||||
i->first->init_markov(state);
|
||||
}
|
||||
cons.unindent();
|
||||
cons.print<LOG_STD>("Done");
|
||||
}
|
||||
|
||||
void MainLoop::snap() {
|
||||
using boost::format;
|
||||
using boost::str;
|
||||
MPI_Communication *comm = MPI_Communication::instance();
|
||||
std::shared_ptr<H5::H5File> f;
|
||||
|
||||
if (comm->rank() == 0) {
|
||||
f = std::make_shared<H5::H5File>(
|
||||
str(format("mcmc_%d.h5") % mcmc_id), H5F_ACC_TRUNC);
|
||||
}
|
||||
|
||||
state.mpiSaveState(f, comm, false, true);
|
||||
mcmc_id++;
|
||||
}
|
||||
|
||||
void MainLoop::save() {
|
||||
using boost::format;
|
||||
using boost::str;
|
||||
MPI_Communication *comm = MPI_Communication::instance();
|
||||
string fname_final = str(format("restart.h5_%d") % comm->rank());
|
||||
string fname_build = fname_final + "_build";
|
||||
|
||||
{
|
||||
H5::H5File f(fname_build, H5F_ACC_TRUNC);
|
||||
state.saveState(f);
|
||||
timings::save(f);
|
||||
}
|
||||
comm->barrier();
|
||||
|
||||
rename(fname_build.c_str(), fname_final.c_str());
|
||||
}
|
||||
|
||||
void MainLoop::save_crash() {
|
||||
using boost::format;
|
||||
using boost::str;
|
||||
MPI_Communication *comm = MPI_Communication::instance();
|
||||
string fname_final = str(format("crash_file.h5_%d") % comm->rank());
|
||||
string fname_build = fname_final + "_build";
|
||||
|
||||
{
|
||||
H5::H5File f(fname_build, H5F_ACC_TRUNC);
|
||||
state.saveState(f);
|
||||
}
|
||||
|
||||
rename(fname_build.c_str(), fname_final.c_str());
|
||||
}
|
||||
|
||||
void MainLoop::run() {
|
||||
ConsoleContext<LOG_STD> ctx("MainLoop::run");
|
||||
int count = 0;
|
||||
Progress<LOG_STD> progress = Console::instance().start_progress<LOG_STD>(
|
||||
"Main loop iteration", mclist.size(), 30);
|
||||
for (MCList::iterator i = mclist.begin(); i != mclist.end(); ++i) {
|
||||
int looping = i->second;
|
||||
for (int j = 0; j < looping; j++)
|
||||
i->first->sample(state);
|
||||
count++;
|
||||
progress.update(count);
|
||||
}
|
||||
progress.destroy();
|
||||
}
|
||||
|
||||
void MainLoop::restore(const std::string &fname, bool flexible) {
|
||||
Console &cons = Console::instance();
|
||||
MPI_Communication *comm = MPI_Communication::instance();
|
||||
string fname_full =
|
||||
flexible ? fname
|
||||
: (boost::str(boost::format("%s_%d") % fname % comm->rank()));
|
||||
H5::H5File f(fname_full, 0);
|
||||
ConsoleContext<LOG_INFO> ctx("restoration of MCMC state");
|
||||
|
||||
if (flexible)
|
||||
Console::instance().print<LOG_WARNING>("Using flexible mechanism");
|
||||
|
||||
ctx.print("Initialize variables");
|
||||
for (MCList::iterator i = mclist.begin(); i != mclist.end(); ++i) {
|
||||
i->first->restore_markov(state);
|
||||
}
|
||||
|
||||
ctx.print("Load markov state from file");
|
||||
{ state.restoreState(f, flexible); }
|
||||
|
||||
timings::load(f);
|
||||
}
|
109
libLSS/samplers/core/main_loop.hpp
Normal file
109
libLSS/samplers/core/main_loop.hpp
Normal file
|
@ -0,0 +1,109 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/main_loop.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_SAMPLERS_MAINLOOP_HPP
|
||||
#define __LIBLSS_SAMPLERS_MAINLOOP_HPP
|
||||
|
||||
#include <utility>
|
||||
#include <list>
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/samplers/core/markov.hpp"
|
||||
#include "libLSS/mcmc/global_state.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class BlockLoop;
|
||||
class BlockSampler {
|
||||
public:
|
||||
typedef std::list<std::pair<std::shared_ptr<MarkovSampler>,int> > MCList;
|
||||
protected:
|
||||
MCList mclist;
|
||||
friend class BlockLoop;
|
||||
public:
|
||||
virtual void adder(BlockSampler& s) const {
|
||||
ConsoleContext<LOG_DEBUG> ctx("adder classic");
|
||||
s.mclist.insert(s.mclist.end(), mclist.begin(), mclist.end());
|
||||
}
|
||||
|
||||
BlockSampler& operator<<(std::shared_ptr<MarkovSampler>&& s) {
|
||||
ConsoleContext<LOG_DEBUG> ctx("inserter shared_ptr");
|
||||
mclist.push_back(std::make_pair(s,1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BlockSampler& operator<<(std::shared_ptr<MarkovSampler>& s) {
|
||||
ConsoleContext<LOG_DEBUG> ctx("inserter shared_ptr");
|
||||
mclist.push_back(std::make_pair(s,1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BlockSampler& operator<<(MarkovSampler& s) {
|
||||
ConsoleContext<LOG_DEBUG> ctx("inserter");
|
||||
mclist.push_back(std::make_pair(std::shared_ptr<MarkovSampler>(&s, [](void *) {}), 1));
|
||||
return *this;
|
||||
}
|
||||
|
||||
BlockSampler& operator<<(const BlockSampler& l) {
|
||||
ConsoleContext<LOG_DEBUG> ctx("adding block");
|
||||
l.adder(*this);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class BlockLoop: public BlockSampler {
|
||||
private:
|
||||
int num_loop;
|
||||
protected:
|
||||
friend class BlockSampler;
|
||||
// Prevent any copy.
|
||||
BlockLoop(const BlockLoop& l) {
|
||||
num_loop = l.num_loop;
|
||||
}
|
||||
BlockLoop& operator=(const BlockLoop& l) { return *this; }
|
||||
public:
|
||||
BlockLoop(int loop = 1) : num_loop(loop) {}
|
||||
|
||||
void setLoop(int loop) { num_loop = loop; }
|
||||
|
||||
virtual void adder(BlockSampler& s) const {
|
||||
ConsoleContext<LOG_DEBUG> ctx("adder blockloop");
|
||||
ctx.print(boost::format("num_loop = %d") % num_loop);
|
||||
for (int l = 0; l < num_loop; l++)
|
||||
s.mclist.insert(s.mclist.end(), mclist.begin(), mclist.end());
|
||||
}
|
||||
|
||||
~BlockLoop() {}
|
||||
};
|
||||
|
||||
class MainLoop: public BlockSampler {
|
||||
protected:
|
||||
MarkovState state;
|
||||
int mcmc_id;
|
||||
|
||||
void show_splash();
|
||||
public:
|
||||
MainLoop();
|
||||
~MainLoop();
|
||||
|
||||
void initialize();
|
||||
void restore(const std::string& fname, bool flexible = false);
|
||||
void run();
|
||||
void save();
|
||||
void save_crash();
|
||||
void snap();
|
||||
|
||||
MarkovState& get_state() { return state; }
|
||||
const MarkovState& get_state() const { return state; }
|
||||
|
||||
void setStepID(int i) { mcmc_id = i; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
48
libLSS/samplers/core/markov.hpp
Normal file
48
libLSS/samplers/core/markov.hpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/markov.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_MARKOV_SAMPLER_HPP
|
||||
#define __LIBLSS_MARKOV_SAMPLER_HPP
|
||||
|
||||
#include "libLSS/mcmc/global_state.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class MarkovSampler {
|
||||
protected:
|
||||
virtual void initialize(MarkovState& state) = 0;
|
||||
virtual void restore(MarkovState& state) = 0;
|
||||
private:
|
||||
bool yet_init;
|
||||
public:
|
||||
MarkovSampler() : yet_init(false) {}
|
||||
virtual ~MarkovSampler() {}
|
||||
|
||||
virtual void sample(MarkovState& state) = 0;
|
||||
|
||||
void init_markov(MarkovState& state) {
|
||||
if (!yet_init) {
|
||||
yet_init = true;
|
||||
initialize(state);
|
||||
}
|
||||
}
|
||||
|
||||
void restore_markov(MarkovState& state) {
|
||||
if (!yet_init) {
|
||||
yet_init = true;
|
||||
restore(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
241
libLSS/samplers/core/powerspec_tools.cpp
Normal file
241
libLSS/samplers/core/powerspec_tools.cpp
Normal file
|
@ -0,0 +1,241 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/powerspec_tools.cpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/samplers/core/powerspec_tools.hpp"
|
||||
|
||||
using namespace LibLSS;
|
||||
using boost::format;
|
||||
typedef boost::multi_array_types::extent_range range;
|
||||
|
||||
|
||||
PowerSpectrumSampler_Base::~PowerSpectrumSampler_Base()
|
||||
{
|
||||
if (mgr != 0)
|
||||
delete mgr;
|
||||
}
|
||||
|
||||
bool PowerSpectrumSampler_Base::restore_base(MarkovState& state)
|
||||
{
|
||||
Console& cons = Console::instance();
|
||||
ConsoleContext<LOG_INFO> ctx("power spectrum sampler (common)");
|
||||
bool build_keys;
|
||||
|
||||
L0 = *state.get<SDouble>("L0");
|
||||
L1 = *state.get<SDouble>("L1");
|
||||
L2 = *state.get<SDouble>("L2");
|
||||
|
||||
N0 = *state.get<SLong>("N0");
|
||||
N1 = *state.get<SLong>("N1");
|
||||
N2 = *state.get<SLong>("N2");
|
||||
N2_HC = *state.get<SLong>("N2_HC");
|
||||
|
||||
// Creates a manager. Then we get access to all derived quantities
|
||||
// for parallelism.
|
||||
mgr = new FFTMgr(N0, N1, N2, comm);
|
||||
|
||||
|
||||
Ntot = N0*N1*N2;
|
||||
volNorm = L0*L1*L2/Ntot;
|
||||
volume = L0*L1*L2;
|
||||
|
||||
ctx.print(format("Power spectrum (%dx%dx%d), box (%gx%gx%g)") % N0 % N1 % N2 % L0 % L1 % L2);
|
||||
|
||||
N_k = *state.get<SLong>("NUM_MODES");
|
||||
kmin = *state.get<SDouble>("K_MIN");
|
||||
kmax = *state.get<SDouble>("K_MAX");
|
||||
|
||||
startN0 = mgr->startN0;
|
||||
localN0 = mgr->localN0;
|
||||
fourierLocalSize = mgr->allocator_real.minAllocSize;
|
||||
|
||||
ctx.print(format("Num modes = %d, kmin = %lg, kmax = %lg") % N_k % kmin % kmax);
|
||||
|
||||
rgen = state.get<RandomGen>("random_generator");
|
||||
|
||||
if (state.exists("powerspectrum")) {
|
||||
k = state.get<ArrayType1d>("k_modes");
|
||||
keys = state.get<IArrayType>("k_keys");
|
||||
nmode = state.get<IArrayType1d>("k_nmodes");
|
||||
key_counts = state.get<IArrayType1d>("key_counts");
|
||||
P_sync += (P = state.get<ArrayType1d>("powerspectrum"));
|
||||
adjustMul = state.get<IArrayType>("adjust_mode_multiplier");
|
||||
|
||||
build_keys = false;
|
||||
} else {
|
||||
cons.print<LOG_DEBUG>("Allocating power spectrum array");
|
||||
P = new ArrayType1d(boost::extents[N_k]);
|
||||
cons.print<LOG_DEBUG>("Allocating number of stacked modes array");
|
||||
nmode = new IArrayType1d(boost::extents[N_k]);
|
||||
cons.print<LOG_DEBUG>("Allocating key counts array");
|
||||
key_counts = new IArrayType1d(boost::extents[N_k]);
|
||||
cons.print<LOG_DEBUG>("Allocating mode list");
|
||||
k = new ArrayType1d(boost::extents[N_k]);
|
||||
|
||||
cons.print<LOG_DEBUG>("Allocating mode keys array");
|
||||
keys = new IArrayType(mgr->extents_complex());
|
||||
keys->setRealDims(ArrayDimension(N0, N1, N2_HC));
|
||||
cons.print<LOG_DEBUG>("Mode multiplier adjustment");
|
||||
adjustMul = new IArrayType(mgr->extents_complex());
|
||||
adjustMul->setRealDims(ArrayDimension(N0, N1, N2_HC));
|
||||
|
||||
state.newElement("k_modes", k);
|
||||
state.newElement("k_keys", keys);
|
||||
state.newElement("k_nmodes", nmode);
|
||||
state.newElement("key_counts", key_counts);
|
||||
P_sync += state.newElement("powerspectrum", P, true);
|
||||
state.newElement("adjust_mode_multiplier", adjustMul);
|
||||
|
||||
build_keys = true;
|
||||
}
|
||||
|
||||
{
|
||||
ArrayType1d::ArrayType& P_array = *P->array;
|
||||
|
||||
for (long i = 0; i < N_k; i++)
|
||||
P_array[i] = 1e6;
|
||||
}
|
||||
|
||||
N_fourier_elements = N0*N1*N2_HC;
|
||||
local_fourier_elements = localN0*N1*N2_HC;
|
||||
ctx.print(boost::format("N0 = %d, N1 = %d, N2 = %d, N2_HC=%d, localN0=%d, startN0=%d") % N0 % N1 % N2 % N2_HC % localN0 % startN0);
|
||||
|
||||
|
||||
|
||||
return build_keys;
|
||||
}
|
||||
|
||||
|
||||
void PowerSpectrumSampler_Base::initialize_base(MarkovState& state)
|
||||
{
|
||||
Console& cons = Console::instance();
|
||||
bool build_keys;
|
||||
|
||||
build_keys = restore_base(state);
|
||||
|
||||
if (!build_keys) {
|
||||
cons.print<LOG_INFO>("Keys already built. Returning.");
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
ArrayType1d::ArrayType& k_array = *k->array;
|
||||
ArrayType1d::ArrayType& P_array = *P->array;
|
||||
|
||||
for (long i = 0; i < N_k; i++) {
|
||||
k_array[i] = (kmax-kmin)/N_k * double(i);
|
||||
P_array[i] = 1e-6;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Build the powerspectrum keys
|
||||
cons.print<LOG_INFO>("Building keys");
|
||||
IArrayType::ArrayType& array_key = *keys->array;
|
||||
IArrayType1d::ArrayType& nmode_array = *nmode->array;
|
||||
IArrayType1d::ArrayType& array_key_counts = *key_counts->array;
|
||||
IArrayType::ArrayType& adjust = *adjustMul->array;
|
||||
|
||||
boost::array<double, 3> L = { L0, L1, L2 };
|
||||
|
||||
init_helpers::initialize_powerspectrum_keys(
|
||||
*mgr, array_key, array_key_counts, adjust, nmode_array,
|
||||
L, kmin, kmax, N_k);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PowerSpectrumSampler_Coloring::~PowerSpectrumSampler_Coloring()
|
||||
{
|
||||
if (tmp_fourier != 0) {
|
||||
MFCalls::free(tmp_fourier);
|
||||
MFCalls::free(tmp_real);
|
||||
MFCalls::destroy_plan(analysis_plan);
|
||||
MFCalls::destroy_plan(synthesis_plan);
|
||||
}
|
||||
}
|
||||
|
||||
bool PowerSpectrumSampler_Coloring::initialize_coloring(MarkovState& state)
|
||||
{
|
||||
ConsoleContext<LOG_INFO> ctx("coloring initialization");
|
||||
tmp_fourier = MFCalls::alloc_complex(fourierLocalSize);
|
||||
tmp_real = MFCalls::alloc_real(fourierLocalSize*2);
|
||||
|
||||
ctx.print("Creating MPI/FFTW plans for Messenger-Signal");
|
||||
analysis_plan = MFCalls::plan_dft_r2c_3d(
|
||||
N0, N1, N2,
|
||||
tmp_real,
|
||||
tmp_fourier,
|
||||
#ifdef ARES_MPI_FFTW
|
||||
comm->comm(),
|
||||
#endif
|
||||
// FFTW_MPI_TRANSPOSED_OUT|
|
||||
FFTW_DESTROY_INPUT|FFTW_MEASURE);
|
||||
synthesis_plan = MFCalls::plan_dft_c2r_3d(
|
||||
N0, N1, N2,
|
||||
tmp_fourier,
|
||||
tmp_real,
|
||||
#ifdef ARES_MPI_FFTW
|
||||
comm->comm(),
|
||||
#endif
|
||||
//FFTW_MPI_TRANSPOSED_IN|
|
||||
FFTW_DESTROY_INPUT|FFTW_MEASURE);
|
||||
|
||||
sqrt_P_info.array->resize(boost::extents[P->array->num_elements()]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PowerSpectrumSampler_Coloring::restore_coloring(MarkovState& state)
|
||||
{
|
||||
return initialize_coloring(state);
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_Coloring::update_s_field_from_x(MarkovState& state, const ArrayType1d& powerSpec)
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("update of s_field from x_field");
|
||||
ArrayType& x_field = *state.get<ArrayType>("x_field");
|
||||
ArrayType& s_field = *state.get<ArrayType>("s_field");
|
||||
|
||||
ctx.print(format("%p") % P);
|
||||
Console::instance().c_assert(powerSpec.array->num_elements() == P->array->size(), "coloring works only on similar powerspectrum as the system one");
|
||||
|
||||
// Overwrite s
|
||||
ctx.print("Copying x_field");
|
||||
copy_padded_data(*x_field.array, tmp_real);
|
||||
ctx.print("Analyzing");
|
||||
MFCalls::execute_r2c(analysis_plan, tmp_real, tmp_fourier);
|
||||
|
||||
long P_size = powerSpec.array->num_elements();
|
||||
for (long i = 0; i < P_size; i++) {
|
||||
(*sqrt_P_info.array)[i] = std::sqrt((*powerSpec.array)[i] * volume) / (Ntot);
|
||||
}
|
||||
|
||||
|
||||
int *flat_keys = keys->array->data();
|
||||
|
||||
ctx.print("Coloring");
|
||||
#pragma omp parallel for schedule(static)
|
||||
for (long i = 0; i < local_fourier_elements; i++) {
|
||||
double sqrt_P = (*sqrt_P_info.array)[flat_keys[i]];
|
||||
|
||||
tmp_fourier[i][0] *= sqrt_P;
|
||||
tmp_fourier[i][1] *= sqrt_P;
|
||||
}
|
||||
|
||||
ctx.print("Synthesis");
|
||||
MFCalls::execute_c2r(synthesis_plan, tmp_fourier, tmp_real);
|
||||
copy_unpadded_data(tmp_real, *s_field.array);
|
||||
}
|
||||
|
||||
void PowerSpectrumSampler_Coloring::update_s_field_from_x(MarkovState& state)
|
||||
{
|
||||
update_s_field_from_x(state, *P);
|
||||
}
|
206
libLSS/samplers/core/powerspec_tools.hpp
Normal file
206
libLSS/samplers/core/powerspec_tools.hpp
Normal file
|
@ -0,0 +1,206 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/powerspec_tools.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_POWER_SPECTRUM_TOOLS_HPP
|
||||
#define __LIBLSS_POWER_SPECTRUM_TOOLS_HPP
|
||||
|
||||
#include "libLSS/samplers/core/markov.hpp"
|
||||
#include "libLSS/mcmc/state_sync.hpp"
|
||||
#include "libLSS/samplers/core/types_samplers.hpp"
|
||||
#include "libLSS/tools/mpi_fftw_helper.hpp"
|
||||
#include "libLSS/tools/array_tools.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
template <typename ArrayType>
|
||||
typename ArrayType::value_type norm_v(const ArrayType &x) {
|
||||
typename ArrayType::value_type ret = 0;
|
||||
|
||||
for (size_t i = 0; i < x.size(); i++)
|
||||
ret += x[i] * x[i];
|
||||
|
||||
return std::sqrt(ret);
|
||||
}
|
||||
|
||||
static inline int ifftfreq(int i, int N) {
|
||||
return ((i > N / 2) ? (i - N) : i);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T kmode(int i, int N, T L) {
|
||||
return 2 * M_PI / L * ifftfreq(i, N);
|
||||
}
|
||||
|
||||
template <typename IKArray, typename LArray>
|
||||
int power_key(
|
||||
const IKArray &N, const IKArray &ik, const LArray &L, double kmin,
|
||||
double dk, int Nbin) {
|
||||
///calculate kmodes
|
||||
boost::array<double, 3> k;
|
||||
double kmod;
|
||||
|
||||
// 0 mode is specific
|
||||
if (ik[0] == 0 && ik[1] == 0 && ik[2] == 0)
|
||||
return 0;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
k[i] = kmode(ik[i], N[i], L[i]);
|
||||
|
||||
kmod = norm_v(k); /// units k [h/Mpc]
|
||||
|
||||
int ll = 1 + int(std::floor((kmod - kmin) / dk));
|
||||
|
||||
Console::instance().c_assert(
|
||||
(ll >= 0) && (ll < Nbin), "Over/Underflow binning in powerspectrum");
|
||||
return ll;
|
||||
}
|
||||
|
||||
namespace init_helpers {
|
||||
|
||||
template <
|
||||
typename Manager, typename ArrayKey, typename ArrayKeyCounts,
|
||||
typename ArrayAdjust, typename ArrayNmode>
|
||||
void initialize_powerspectrum_keys(
|
||||
Manager &manager, ArrayKey &array_key, ArrayKeyCounts &array_key_counts,
|
||||
ArrayAdjust &adjust, ArrayNmode &nmode_array,
|
||||
boost::array<double, 3> const &L, double kmin, double kmax,
|
||||
size_t N_k) {
|
||||
using boost::format;
|
||||
Console &cons = Console::instance();
|
||||
size_t N0 = manager.N0;
|
||||
size_t startN0 = manager.startN0;
|
||||
size_t localN0 = manager.localN0;
|
||||
size_t N1 = manager.N1;
|
||||
size_t N2_HC = manager.N2_HC;
|
||||
|
||||
// FIX: Manager sizes should size_t.
|
||||
boost::array<size_t, 3> iN{N0, N1, size_t(manager.N2)};
|
||||
|
||||
array::fill(nmode_array, 0);
|
||||
array::fill(array_key_counts, 0);
|
||||
|
||||
for (size_t ikx = startN0; ikx < startN0 + localN0; ikx++) {
|
||||
for (size_t iky = 0; iky < N1; iky++) {
|
||||
for (size_t ikz = 0; ikz < N2_HC; ikz++) {
|
||||
boost::array<size_t, 3> ik{ikx, iky, ikz};
|
||||
int p_key = power_key(iN, ik, L, kmin, (kmax - kmin) / N_k, N_k);
|
||||
|
||||
array_key_counts[p_key]++;
|
||||
array_key[ikx][iky][ikz] = p_key;
|
||||
assert(p_key < N_k);
|
||||
nmode_array[p_key] +=
|
||||
2; // Put everybody at 2. There will be a fix after the loop.
|
||||
adjust[ikx][iky][ikz] = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only one mode and it is not sampling.
|
||||
array_key_counts[0] = 0;
|
||||
|
||||
if (startN0 == 0 && localN0 > 0) {
|
||||
adjust[0][0][0] = 0;
|
||||
adjust[0][N1 / 2][0] = 1;
|
||||
adjust[0][0][N2_HC - 1] = 1;
|
||||
adjust[0][N1 / 2][N2_HC - 1] = 1;
|
||||
|
||||
nmode_array[array_key[0][0][0]] -= 2; // No mode for k=0
|
||||
nmode_array[array_key[0][N1 / 2][0]] -= 1;
|
||||
nmode_array[array_key[0][0][N2_HC - 1]] -= 1;
|
||||
nmode_array[array_key[0][N1 / 2][N2_HC - 1]] -= 1;
|
||||
}
|
||||
|
||||
if (startN0 <= N0 / 2 && localN0 + startN0 > N0 / 2) {
|
||||
adjust[N0 / 2][0][0] = 1;
|
||||
adjust[N0 / 2][N1 / 2][0] = 1;
|
||||
adjust[N0 / 2][0][N2_HC - 1] = 1;
|
||||
adjust[N0 / 2][N1 / 2][N2_HC - 1] = 1;
|
||||
|
||||
nmode_array[array_key[N0 / 2][0][0]] -=
|
||||
1; // Hermiticity removes one free mode
|
||||
nmode_array[array_key[N0 / 2][N1 / 2][0]] -= 1;
|
||||
nmode_array[array_key[N0 / 2][0][N2_HC - 1]] -= 1;
|
||||
nmode_array[array_key[N0 / 2][N1 / 2][N2_HC - 1]] -= 1;
|
||||
}
|
||||
|
||||
cons.template print<LOG_DEBUG>(
|
||||
format("Reducing mode counting: num_elements=%d") %
|
||||
nmode_array.num_elements());
|
||||
manager.getComm()->all_reduce_t(
|
||||
MPI_IN_PLACE, nmode_array.data(), nmode_array.num_elements(),
|
||||
MPI_SUM);
|
||||
cons.template print<LOG_DEBUG>(
|
||||
format("Reducing key counting: num_elements=%d") %
|
||||
array_key_counts.num_elements());
|
||||
manager.getComm()->all_reduce_t(
|
||||
MPI_IN_PLACE, array_key_counts.data(),
|
||||
array_key_counts.num_elements(), MPI_SUM);
|
||||
}
|
||||
|
||||
} // namespace init_helpers
|
||||
|
||||
class PowerSpectrumSampler_Base : public MarkovSampler {
|
||||
protected:
|
||||
typedef FFTW_Manager_3d<double> FFTMgr;
|
||||
|
||||
long N0, N1, N2, N2_HC;
|
||||
long fourierLocalSize;
|
||||
long startN0, localN0;
|
||||
long N_fourier_elements, local_fourier_elements;
|
||||
long Ntot;
|
||||
int N_k;
|
||||
double kmin, kmax;
|
||||
double volNorm, volume;
|
||||
double L0, L1, L2;
|
||||
|
||||
FFTMgr *mgr;
|
||||
|
||||
IArrayType *keys, *adjustMul;
|
||||
IArrayType1d *key_counts, *nmode;
|
||||
ArrayType1d *P, *k;
|
||||
RandomGen *rgen;
|
||||
MPI_SyncBundle P_sync;
|
||||
MPI_Communication *comm;
|
||||
|
||||
public:
|
||||
PowerSpectrumSampler_Base(MPI_Communication *lcomm)
|
||||
: mgr(0), keys(0), key_counts(0), nmode(0), P(0), k(0), rgen(0),
|
||||
comm(lcomm) {}
|
||||
virtual ~PowerSpectrumSampler_Base();
|
||||
|
||||
bool restore_base(MarkovState &state);
|
||||
void initialize_base(MarkovState &state);
|
||||
};
|
||||
|
||||
class PowerSpectrumSampler_Coloring : public PowerSpectrumSampler_Base {
|
||||
protected:
|
||||
MFCalls::plan_type analysis_plan, synthesis_plan;
|
||||
MFCalls::complex_type *tmp_fourier;
|
||||
MFCalls::real_type *tmp_real;
|
||||
ArrayType1d sqrt_P_info;
|
||||
|
||||
int Ncatalog;
|
||||
|
||||
public:
|
||||
PowerSpectrumSampler_Coloring(MPI_Communication *comm)
|
||||
: PowerSpectrumSampler_Base(comm), tmp_fourier(0), tmp_real(0),
|
||||
sqrt_P_info(boost::extents[0]) {}
|
||||
virtual ~PowerSpectrumSampler_Coloring();
|
||||
|
||||
bool initialize_coloring(MarkovState &state);
|
||||
bool restore_coloring(MarkovState &state);
|
||||
|
||||
void update_s_field_from_x(MarkovState &state);
|
||||
void
|
||||
update_s_field_from_x(MarkovState &state, const ArrayType1d &powerSpectrum);
|
||||
};
|
||||
|
||||
} // namespace LibLSS
|
||||
|
||||
#endif
|
214
libLSS/samplers/core/ran_gig.cc
Normal file
214
libLSS/samplers/core/ran_gig.cc
Normal file
|
@ -0,0 +1,214 @@
|
|||
#include <math.h>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
#include <cfloat>
|
||||
#include <float.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <gsl/gsl_rng.h>
|
||||
#include <gsl/gsl_randist.h>
|
||||
#include "libLSS/samplers/core/ran_gig.h"
|
||||
|
||||
#define EPSILON 1e-10
|
||||
|
||||
using namespace std;
|
||||
|
||||
/* R_zeroin2() is faster for "expensive" f(), in those typical cases where
|
||||
* f(ax) and f(bx) are available anyway : */
|
||||
|
||||
double R_zeroin2( /* An estimate of the root */
|
||||
double ax, /* Left border | of the range */
|
||||
double bx, /* Right border| the root is seeked*/
|
||||
double fa, double fb, /* f(a), f(b) */
|
||||
double (*f)(double x, void *info), /* Function under investigation */
|
||||
void *info, /* Add'l info passed on to f */
|
||||
double *Tol, /* Acceptable tolerance */
|
||||
int *Maxit) /* Max # of iterations */
|
||||
{
|
||||
double a,b,c, fc; /* Abscissae, descr. see above, f(c) */
|
||||
double tol;
|
||||
int maxit;
|
||||
|
||||
a = ax; b = bx;
|
||||
c = a; fc = fa;
|
||||
maxit = *Maxit + 1; tol = * Tol;
|
||||
|
||||
/* First test if we have found a root at an endpoint */
|
||||
if(fa == 0.0) {
|
||||
*Tol = 0.0;
|
||||
*Maxit = 0;
|
||||
return a;
|
||||
}
|
||||
if(fb == 0.0) {
|
||||
*Tol = 0.0;
|
||||
*Maxit = 0;
|
||||
return b;
|
||||
}
|
||||
|
||||
while(maxit--) /* Main iteration loop */
|
||||
{
|
||||
double prev_step = b-a; /* Distance from the last but one
|
||||
to the last approximation */
|
||||
double tol_act; /* Actual tolerance */
|
||||
double p; /* Interpolation step is calcu- */
|
||||
double q; /* lated in the form p/q; divi-
|
||||
* sion operations is delayed
|
||||
* until the last moment */
|
||||
double new_step; /* Step at this iteration */
|
||||
|
||||
if( fabs(fc) < fabs(fb) )
|
||||
{ /* Swap data for b to be the */
|
||||
a = b; b = c; c = a; /* best approximation */
|
||||
fa=fb; fb=fc; fc=fa;
|
||||
}
|
||||
tol_act = 2.*EPSILON*fabs(b) + tol/2.;
|
||||
new_step = (c-b)/2.;
|
||||
|
||||
if( fabs(new_step) <= tol_act || fb == (double)0 )
|
||||
{
|
||||
*Maxit -= maxit;
|
||||
*Tol = fabs(c-b);
|
||||
return b; /* Acceptable approx. is found */
|
||||
}
|
||||
|
||||
/* Decide if the interpolation can be tried */
|
||||
if( fabs(prev_step) >= tol_act /* If prev_step was large enough*/
|
||||
&& fabs(fa) > fabs(fb) ) { /* and was in true direction,
|
||||
* Interpolation may be tried */
|
||||
register double t1,cb,t2;
|
||||
cb = c-b;
|
||||
if( a==c ) { /* If we have only two distinct */
|
||||
/* points linear interpolation */
|
||||
t1 = fb/fa; /* can only be applied */
|
||||
p = cb*t1;
|
||||
q = 1.0 - t1;
|
||||
}
|
||||
else { /* Quadric inverse interpolation*/
|
||||
|
||||
q = fa/fc; t1 = fb/fc; t2 = fb/fa;
|
||||
p = t2 * ( cb*q*(q-t1) - (b-a)*(t1-1.0) );
|
||||
q = (q-1.0) * (t1-1.0) * (t2-1.0);
|
||||
}
|
||||
if( p>(double)0 ) /* p was calculated with the */
|
||||
q = -q; /* opposite sign; make p positive */
|
||||
else /* and assign possible minus to */
|
||||
p = -p; /* q */
|
||||
|
||||
if( p < (0.75*cb*q-fabs(tol_act*q)/2.) /* If b+p/q falls in [b,c]*/
|
||||
&& p < fabs(prev_step*q/2.) ) /* and isn't too large */
|
||||
new_step = p/q; /* it is accepted
|
||||
* If p/q is too large then the
|
||||
* bisection procedure can
|
||||
* reduce [b,c] range to more
|
||||
* extent */
|
||||
}
|
||||
|
||||
if( fabs(new_step) < tol_act) { /* Adjust the step to be not less*/
|
||||
if( new_step > (double)0 ) /* than tolerance */
|
||||
new_step = tol_act;
|
||||
else
|
||||
new_step = -tol_act;
|
||||
}
|
||||
a = b; fa = fb; /* Save the previous approx. */
|
||||
b += new_step; fb = (*f)(b, info); /* Do step to a new approxim. */
|
||||
if( (fb > 0. && fc > 0.) || (fb < 0. && fc < 0.) ) {
|
||||
/* Adjust c for it to have a sign opposite to that of b */
|
||||
c = a; fc = fa;
|
||||
}
|
||||
|
||||
}
|
||||
/* failed! */
|
||||
*Tol = fabs(c-b);
|
||||
*Maxit = -1;
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
double R_zeroin( /* An estimate of the root */
|
||||
double ax, /* Left border | of the range */
|
||||
double bx, /* Right border| the root is seeked*/
|
||||
double (*f)(double x, void *info), /* Function under investigation */
|
||||
void *info, /* Add'l info passed on to f */
|
||||
double *Tol, /* Acceptable tolerance */
|
||||
int *Maxit) /* Max # of iterations */
|
||||
{
|
||||
double fa = (*f)(ax, info);
|
||||
double fb = (*f)(bx, info);
|
||||
return R_zeroin2(ax, bx, fa, fb, f, info, Tol, Maxit);
|
||||
}
|
||||
|
||||
|
||||
|
||||
double g(double y, void *params)
|
||||
{
|
||||
double *aux = (double *)params;
|
||||
double beta=aux[0];
|
||||
double lambda=aux[1];
|
||||
double m=aux[2];
|
||||
|
||||
return(0.5*beta*y*y*y - y*y*(0.5*beta*m+lambda+1) + y*((lambda-1)*m-0.5*beta) + 0.5*beta*m);
|
||||
}
|
||||
|
||||
double LibLSS::ran_gig(double chi, double psi, double lambda,gsl_rng * SEED)
|
||||
{
|
||||
// Function to generate random observations from a
|
||||
// generalized inverse Gaussian distribution. The
|
||||
// algorithm is based on that given by Dagpunar (1989)
|
||||
|
||||
if(chi<0.) {cout << "chi can not be negative"<<endl; return 0.;}
|
||||
if(psi<0.) {cout << "psi can not be negative"<<endl; return 0.;}
|
||||
|
||||
if((lambda>=0.)&&(psi==0.))
|
||||
{
|
||||
cout << "When lambda >= 0, psi must be > 0"<<endl;
|
||||
return 0.;
|
||||
}
|
||||
|
||||
if((lambda<=0.)&(chi==0.))
|
||||
{
|
||||
cout <<"When lambda <= 0, chi must be > 0"<<endl;
|
||||
return 0.;
|
||||
}
|
||||
|
||||
if(chi==0.) {cout <<"chi = 0, use rgamma"<<endl; return 0.;}
|
||||
if(psi==0.) {cout <<"algorithm only valid for psi > 0"<<endl; return 0.;}
|
||||
|
||||
double alpha=sqrt(psi/chi);
|
||||
double beta=sqrt(psi*chi);
|
||||
|
||||
double m=(lambda-1.+sqrt((lambda-1.)*(lambda-1.)+beta*beta))/beta;
|
||||
|
||||
double upper = m;
|
||||
|
||||
double params[3];
|
||||
params[0]=beta;
|
||||
params[1]=lambda;
|
||||
params[2]=m;
|
||||
|
||||
while(g(upper,params)<=0.) upper = 2.*upper;
|
||||
|
||||
|
||||
double tol=1e-10;
|
||||
int maxit=10000;
|
||||
|
||||
double yM =R_zeroin(0.,m,&g, ¶ms,&tol,&maxit);// uniroot(g,interval=c(0,m))$root
|
||||
double yP =R_zeroin(m,upper,&g, ¶ms,&tol,&maxit);// uniroot(g,interval=c(m,upper))$root
|
||||
|
||||
double a = (yP-m)*exp(-0.25*beta*(yP+1./yP-m-1./m)+(log(yP) -log(m))*(0.5*(lambda-1.)) );
|
||||
double b = (yM-m)*exp(-0.25*beta*(yM+1./yM-m-1./m)+(log(yM) -log(m))*(0.5*(lambda-1.)) );
|
||||
double c = -0.25*beta*(m+1./m) + 0.5*(lambda-1.)*log(m);
|
||||
|
||||
double y=0;
|
||||
|
||||
while(true){
|
||||
double R1 = gsl_rng_uniform (SEED);
|
||||
double R2 = gsl_rng_uniform (SEED);
|
||||
y= m + a*R2/R1 + b*(1.-R2)/R1;
|
||||
if((y>0.) && (-log(R1)>=-0.5*(lambda-1.)*log(y)+0.25*beta*(y+1./y)+c)) break;
|
||||
}
|
||||
|
||||
return(y/alpha);
|
||||
}
|
19
libLSS/samplers/core/ran_gig.h
Normal file
19
libLSS/samplers/core/ran_gig.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/ran_gig.h
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_RANGIG_H
|
||||
#define __LIBLSS_RANGIG_H
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
double ran_gig(double chi, double psi, double lambda,gsl_rng * SEED);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
392
libLSS/samplers/core/random_number.hpp
Normal file
392
libLSS/samplers/core/random_number.hpp
Normal file
|
@ -0,0 +1,392 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/random_number.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __RANDOM_NUMBER_HPP
|
||||
#define __RANDOM_NUMBER_HPP
|
||||
|
||||
#include <cmath>
|
||||
#include <boost/format.hpp>
|
||||
#include <functional>
|
||||
#include "libLSS/tools/console.hpp"
|
||||
#include "libLSS/tools/errors.hpp"
|
||||
#include "libLSS/tools/openmp.hpp"
|
||||
#include <H5Cpp.h>
|
||||
#include <CosmoTool/hdf5_array.hpp>
|
||||
#include <iostream>
|
||||
#include "libLSS/tools/array_concepts.hpp"
|
||||
#include "libLSS/tools/fusewrapper.hpp"
|
||||
#include "libLSS/tools/fused_array.hpp"
|
||||
#include "libLSS/tools/hdf5_type.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class RandomNumber;
|
||||
namespace Random_details {
|
||||
// This is a workaround for a bug in GCC compiler which
|
||||
// has a problem using boost::bind on member function in declspec.
|
||||
inline unsigned int real_poisson(RandomNumber *rgen, double nmean);
|
||||
inline double real_gaussian(RandomNumber *rgen, double dev);
|
||||
inline unsigned int real_gamma(RandomNumber *rgen, double a, double b);
|
||||
inline unsigned int real_negative_binomial(RandomNumber *rgen, double p, double n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fundamental class to provide random number generation.
|
||||
*/
|
||||
class RandomNumber
|
||||
{
|
||||
public:
|
||||
virtual ~RandomNumber() {}
|
||||
/**
|
||||
* This returns a random 32-bit integer, uniformly distributed.
|
||||
* @return a random integer
|
||||
*/
|
||||
virtual unsigned long int get() = 0;
|
||||
/**
|
||||
* This returns a uniformly distributed double precision floating point.
|
||||
* @param a random floating point.
|
||||
*/
|
||||
virtual double uniform() = 0;
|
||||
|
||||
/**
|
||||
* Provide a seed to initialize the Pseudo Random Number Generator.
|
||||
* @param s a seed value
|
||||
*/
|
||||
virtual void seed(unsigned long int s) = 0;
|
||||
/**
|
||||
* Save the internal state of the PRNG into the provided HDF5 group.
|
||||
* @param s an HDF5 group.
|
||||
*/
|
||||
virtual void save(H5_CommonFileGroup& s) = 0;
|
||||
/**
|
||||
* Restore the internal state of the PRNG from the provided HDF5 group.
|
||||
* @param s an HDF5 group.
|
||||
* @param flexible specify if we accept some inconsistency in the input group (i.e. different thread count).
|
||||
*/
|
||||
virtual void restore(H5_CommonFileGroup& s, bool flexible = false) = 0;
|
||||
|
||||
double gaussian_ratio();
|
||||
|
||||
/**
|
||||
* Generate a Poisson distributed random integer with the specified intensity.
|
||||
* @param mean Poisson intensity
|
||||
*/
|
||||
virtual unsigned int poisson(double mean) = 0;
|
||||
virtual unsigned int negative_binomial(double p, double n) = 0;
|
||||
|
||||
/**
|
||||
* Generate numbers that are uniformly distributed. The actual value in wrap is ignored. It is only
|
||||
* used to determine the rank of the required array.
|
||||
* @param wrap a wrapped expression to provide the rank of the output array.
|
||||
*/
|
||||
template<typename Array, bool copy>
|
||||
void uniform(LibLSS::FuseWrapper_detail::Wrapper<Array,copy> wrap) {
|
||||
wrap = b_va_fused<double,Array::dimensionality>([this](int, ...)->double { return this->uniform(); });
|
||||
}
|
||||
|
||||
// Only activate this overload if the type looks like an array
|
||||
template<typename Array, bool copy, typename Array2, bool copy2>
|
||||
auto gamma(LibLSS::FuseWrapper_detail::Wrapper<Array,copy> wrap, LibLSS::FuseWrapper_detail::Wrapper<Array2,copy2> wrap2)
|
||||
{
|
||||
return LibLSS::fwrap(
|
||||
LibLSS::b_va_fused<unsigned int>(
|
||||
std::bind(&LibLSS::Random_details::real_gamma,
|
||||
this, std::placeholders::_1, std::placeholders::_2),
|
||||
wrap.forward_wrap(),
|
||||
wrap2.forward_wrap()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an expression that generate random number that are distributed as a Negative Binomial
|
||||
* with an intensity as provided by the wrap expression, and an additional miss term with the second
|
||||
* expression.
|
||||
* @param wrap the expression providing the Poisson intensity.
|
||||
* @param wrap2 the expression providing the missed intensity.
|
||||
*/
|
||||
template<typename Array, bool copy, typename Array2, bool copy2>
|
||||
auto negative_binomial(LibLSS::FuseWrapper_detail::Wrapper<Array,copy> wrap, LibLSS::FuseWrapper_detail::Wrapper<Array2,copy2> wrap2)
|
||||
{
|
||||
return LibLSS::fwrap(
|
||||
LibLSS::b_va_fused<unsigned int>(
|
||||
std::bind(&LibLSS::Random_details::real_negative_binomial,
|
||||
this, std::placeholders::_1, std::placeholders::_2),
|
||||
wrap.forward_wrap(),
|
||||
wrap2.forward_wrap()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Build an expression that generate random number that are Poisson distributed
|
||||
* with an intensity as provided by the wrap expression.
|
||||
* @param wrap the expression providing the Poisson intensity.
|
||||
*/
|
||||
template<typename Array, bool copy>
|
||||
auto poisson(LibLSS::FuseWrapper_detail::Wrapper<Array,copy> wrap)
|
||||
{
|
||||
return LibLSS::fwrap(
|
||||
LibLSS::b_va_fused<unsigned int>(
|
||||
std::bind(&LibLSS::Random_details::real_poisson,
|
||||
this, std::placeholders::_1),
|
||||
wrap.forward_wrap()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build an expression that generate gaussian random number whose standard deviation is determined
|
||||
* by the input wrapped expression. The mean is set to zero.
|
||||
* @param wrap the expression providing the standard deviation.
|
||||
*/
|
||||
template<typename Array, bool copy>
|
||||
auto gaussian(LibLSS::FuseWrapper_detail::Wrapper<Array,copy> wrap)
|
||||
{
|
||||
return LibLSS::fwrap(
|
||||
LibLSS::b_va_fused<typename Array::element>(
|
||||
std::bind(&LibLSS::Random_details::real_gaussian,
|
||||
this, std::placeholders::_1),
|
||||
wrap.forward_wrap()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a single random number gaussian distributed
|
||||
*/
|
||||
double gaussian() { return gaussian_ratio(); }
|
||||
virtual double gamma(double a, double b) = 0;
|
||||
};
|
||||
|
||||
namespace Random_details {
|
||||
inline unsigned int real_poisson(RandomNumber *rgen, double nmean) {
|
||||
return rgen->poisson(nmean);
|
||||
}
|
||||
|
||||
inline unsigned int real_gamma(RandomNumber *rgen, double a, double b) {
|
||||
return rgen->gamma(a, b);
|
||||
}
|
||||
|
||||
inline unsigned int real_negative_binomial(RandomNumber *rgen, double a, double b) {
|
||||
return rgen->negative_binomial(a, b);
|
||||
}
|
||||
|
||||
inline double real_gaussian(RandomNumber *rgen, double a) {
|
||||
return rgen->gaussian()*a;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Random number generator that works in multi-threaded environment.
|
||||
* The base class is provided through a template argument.
|
||||
*/
|
||||
template<typename BaseGenerator>
|
||||
class RandomNumberThreaded: public RandomNumber {
|
||||
protected:
|
||||
RandomNumberThreaded()
|
||||
: gens(0), numGenerators(0) {
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
typedef BaseGenerator base_type;
|
||||
|
||||
BaseGenerator *gens;
|
||||
int numGenerators;
|
||||
|
||||
void realInit(BaseGenerator& b, int force_max) {
|
||||
using boost::format;
|
||||
|
||||
numGenerators = (force_max < 0) ? smp_get_max_threads() : force_max;
|
||||
|
||||
Console::instance().format<LOG_INFO>(
|
||||
"Initializing %d threaded random number generators", numGenerators
|
||||
);
|
||||
|
||||
gens = new BaseGenerator[numGenerators];
|
||||
|
||||
// Not great entropy
|
||||
for (int i = 0; i < numGenerators; i++)
|
||||
gens[i].seed(b.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param force_max an argument to specific the maximum number of threads that will
|
||||
* be used. If equal to -1, it will get the current limit from OpenMP.
|
||||
*/
|
||||
RandomNumberThreaded(int force_max) {
|
||||
BaseGenerator b;
|
||||
|
||||
realInit(b, force_max);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return the base generator for the current thread
|
||||
* @return the fundamental generator for the current thread.
|
||||
*/
|
||||
BaseGenerator &base() {
|
||||
return gens[smp_get_thread_id()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~RandomNumberThreaded() {
|
||||
if (gens == 0)
|
||||
return;
|
||||
|
||||
Console::instance().print<LOG_INFO>(
|
||||
"Cleaning up parallel random number generators"
|
||||
);
|
||||
|
||||
delete[] gens;
|
||||
}
|
||||
|
||||
virtual void seed(unsigned long s) {
|
||||
BaseGenerator b;
|
||||
Console::instance().format<LOG_VERBOSE>("THREADED: Changing random number generation seed with %ld", s);
|
||||
|
||||
b.seed(s);
|
||||
for (int i = 0; i < numGenerators; i++)
|
||||
gens[i].seed(b.get());
|
||||
}
|
||||
|
||||
virtual unsigned long get() {
|
||||
return base().get();
|
||||
}
|
||||
|
||||
virtual double uniform() {
|
||||
return base().uniform();
|
||||
}
|
||||
|
||||
virtual unsigned int poisson(double mean) {
|
||||
return base().poisson(mean);
|
||||
}
|
||||
|
||||
virtual double gamma(double a, double b) {
|
||||
return base().gamma(a, b);
|
||||
}
|
||||
|
||||
virtual unsigned int negative_binomial(double p, double n) {
|
||||
return base().negative_binomial(p, n);
|
||||
}
|
||||
|
||||
using RandomNumber::poisson;
|
||||
using RandomNumber::gamma;
|
||||
using RandomNumber::negative_binomial;
|
||||
using RandomNumber::gaussian;
|
||||
using RandomNumber::uniform;
|
||||
|
||||
|
||||
virtual void save(H5_CommonFileGroup& g) {
|
||||
using boost::str;
|
||||
using boost::format;
|
||||
boost::multi_array<int, 1> gen_array(boost::extents[1]);
|
||||
|
||||
gen_array[0] = numGenerators;
|
||||
CosmoTool::hdf5_write_array(g, "num_generators", gen_array);
|
||||
for (int i = 0; i < numGenerators; i++) {
|
||||
H5::Group subg = g.createGroup(str(format("generator_%d") % i));
|
||||
gens[i].save(subg);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void restore(H5_CommonFileGroup& g, bool flexible = false) {
|
||||
using boost::str;
|
||||
using boost::format;
|
||||
boost::multi_array<int, 1> gen_array;
|
||||
|
||||
CosmoTool::hdf5_read_array(g, "num_generators", gen_array);
|
||||
if (gen_array[0] != numGenerators) {
|
||||
std::string s = str(boost::format(
|
||||
"The current number of threads (%d) is not compatible with file state (%d)")
|
||||
% numGenerators % gen_array[0]);
|
||||
|
||||
if (!flexible) {
|
||||
error_helper<ErrorBadState>(s);
|
||||
} else {
|
||||
Console::instance().print<LOG_WARNING>(s);
|
||||
}
|
||||
}
|
||||
|
||||
int num_to_read = std::min(numGenerators, gen_array[0]);
|
||||
for (int i = 0; i < num_to_read; i++) {
|
||||
H5::Group subg = g.openGroup(str(format("generator_%d") % i));
|
||||
gens[i].restore(subg, flexible);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A random number generator that works in MPI environment.
|
||||
*/
|
||||
template<typename BaseGenerator>
|
||||
class RandomNumberMPI: public RandomNumberThreaded<BaseGenerator> {
|
||||
public:
|
||||
typedef RandomNumberThreaded<BaseGenerator> BaseClass;
|
||||
MPI_Communication *comm;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param comm an MPI communicator over which the PRNG must work.
|
||||
* @param force_max sets the maximum number of threads per MPI task that will in parallel.
|
||||
*/
|
||||
RandomNumberMPI(MPI_Communication *_comm, int force_max)
|
||||
: BaseClass(), comm(_comm) {
|
||||
BaseGenerator b;
|
||||
unsigned long int seedVal = 0;
|
||||
|
||||
if (comm->rank() == 0) {
|
||||
for (int r = 1; r < comm->size(); r++) {
|
||||
seedVal = b.get();
|
||||
comm->send(&seedVal, 1, translateMPIType<unsigned long int>(), r, 0);
|
||||
}
|
||||
} else {
|
||||
comm->recv(&seedVal, 1, translateMPIType<unsigned long int>(), 0, 0);
|
||||
}
|
||||
|
||||
b.seed(seedVal);
|
||||
|
||||
this->realInit(b, force_max);
|
||||
}
|
||||
|
||||
virtual void seed(unsigned long s) {
|
||||
BaseGenerator b;
|
||||
unsigned long int seedVal;
|
||||
|
||||
Console::instance().format<LOG_VERBOSE>("MPI: Changing random number generation seed with %ld", s);
|
||||
b.seed(s);
|
||||
if (comm->rank() == 0) {
|
||||
for (int r = 1; r < comm->size(); r++) {
|
||||
seedVal = b.get();
|
||||
comm->send(&seedVal, 1, translateMPIType<unsigned long int>(), r, 0);
|
||||
}
|
||||
seedVal = b.get();
|
||||
} else {
|
||||
comm->recv(&seedVal, 1, translateMPIType<unsigned long int>(), 0, 0);
|
||||
}
|
||||
|
||||
BaseClass::seed(seedVal);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#include "gaussian_ratio.tcc"
|
||||
|
||||
};
|
||||
|
||||
#endif
|
94
libLSS/samplers/core/types_samplers.hpp
Normal file
94
libLSS/samplers/core/types_samplers.hpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/core/types_samplers.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __LIBLSS_TYPES_SAMPLERS_HPP
|
||||
#define __LIBLSS_TYPES_SAMPLERS_HPP
|
||||
|
||||
#include "libLSS/mpi/generic_mpi.hpp"
|
||||
#include <CosmoTool/fourier/fft/fftw_calls.hpp>
|
||||
#ifdef ARES_MPI_FFTW
|
||||
# include <CosmoTool/fourier/fft/fftw_calls_mpi.hpp>
|
||||
#endif
|
||||
#include "libLSS/tools/fftw_allocator.hpp"
|
||||
#include "libLSS/tools/uninitialized_type.hpp"
|
||||
#include "libLSS/mcmc/state_element.hpp"
|
||||
#include "libLSS/samplers/core/random_number.hpp"
|
||||
#include <boost/multi_array/storage_order.hpp>
|
||||
#include "libLSS/tools/memusage.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
template <typename T, size_t N>
|
||||
using multi_array = boost::multi_array<T, N, LibLSS::track_allocator<T>>;
|
||||
|
||||
template <typename T, size_t N>
|
||||
using const_multi_array_ref = boost::const_multi_array_ref<T, N>;
|
||||
|
||||
template <typename T, size_t N>
|
||||
using multi_array_ref = boost::multi_array_ref<T, N>;
|
||||
|
||||
typedef CosmoTool::FFTW_Calls<double> FCalls;
|
||||
#ifdef ARES_MPI_FFTW
|
||||
typedef CosmoTool::FFTW_MPI_Calls<double> MPI_FCalls;
|
||||
typedef MPI_FCalls MFCalls;
|
||||
#else
|
||||
typedef FCalls MFCalls;
|
||||
#endif
|
||||
typedef ScalarStateElement<long> SLong;
|
||||
typedef ScalarStateElement<double> SDouble;
|
||||
typedef ScalarStateElement<bool> SBool;
|
||||
typedef ArrayStateElement<double, 3, FFTW_Allocator<double>, true> ArrayType;
|
||||
typedef ArrayStateElement<
|
||||
std::complex<double>, 3, FFTW_Allocator<std::complex<double>>, true>
|
||||
CArrayType;
|
||||
typedef ArrayStateElement<int, 3, LibLSS::track_allocator<int>, true>
|
||||
IArrayType;
|
||||
typedef ArrayStateElement<double, 1, LibLSS::track_allocator<double>>
|
||||
ArrayType1d;
|
||||
typedef ArrayStateElement<int, 1, LibLSS::track_allocator<int>> IArrayType1d;
|
||||
typedef RandomStateElement<RandomNumber> RandomGen;
|
||||
typedef ArrayStateElement<double, 3, FFTW_Allocator<double>, true>
|
||||
SelArrayType;
|
||||
|
||||
typedef CArrayType::ArrayType FFTW_Complex_Array;
|
||||
typedef ArrayType::ArrayType FFTW_Real_Array;
|
||||
|
||||
typedef CArrayType::RefArrayType FFTW_Complex_Array_ref;
|
||||
typedef ArrayType::RefArrayType FFTW_Real_Array_ref;
|
||||
|
||||
typedef UninitializedArray<
|
||||
FFTW_Complex_Array, FFTW_Allocator<std::complex<double>>>
|
||||
Uninit_FFTW_Complex_Array;
|
||||
typedef UninitializedArray<FFTW_Real_Array, FFTW_Allocator<double>>
|
||||
Uninit_FFTW_Real_Array;
|
||||
|
||||
namespace init_helpers {
|
||||
// This is a noop when no argument is given
|
||||
template <size_t i, typename Array>
|
||||
void ArrayDimension_adder(Array &A) {}
|
||||
|
||||
// Fill the i-th value of the array recursively.
|
||||
template <size_t i, typename Array, typename... Ntype>
|
||||
void ArrayDimension_adder(Array &A, size_t iN, Ntype... Ns) {
|
||||
A[i] = iN;
|
||||
ArrayDimension_adder<i + 1>(A, Ns...);
|
||||
}
|
||||
|
||||
} // namespace init_helpers
|
||||
|
||||
template <typename... Ntype>
|
||||
inline boost::array<size_t, sizeof...(Ntype)> ArrayDimension(Ntype... Ns) {
|
||||
boost::array<size_t, sizeof...(Ntype)> A;
|
||||
init_helpers::ArrayDimension_adder<0>(A, Ns...);
|
||||
return A;
|
||||
}
|
||||
|
||||
} // namespace LibLSS
|
||||
|
||||
#endif
|
124
libLSS/samplers/rgen/gsl_miser.hpp
Normal file
124
libLSS/samplers/rgen/gsl_miser.hpp
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/rgen/gsl_miser.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __GSL_RANDOM_NUMBER_MISER_HPP
|
||||
#define __GSL_RANDOM_NUMBER_MISER_HPP
|
||||
|
||||
#include <gsl/gsl_rng.h>
|
||||
#include <gsl/gsl_randist.h>
|
||||
#include <gsl/gsl_monte.h>
|
||||
#include <gsl/gsl_monte_miser.h>
|
||||
#include <cstring>
|
||||
#include "libLSS/tools/errors.hpp"
|
||||
#include "libLSS/samplers/core/random_number.hpp"
|
||||
#include "libLSS/samplers/rgen/gsl_random_number.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
/**
|
||||
* This is an adaptor class for the MISER integrator in GSL.
|
||||
* It handles the life cycle of the MISER object, and support for a generic
|
||||
* functor for the integrand.
|
||||
*/
|
||||
class GSL_Miser {
|
||||
protected:
|
||||
gsl_monte_miser_state *state;
|
||||
size_t Nd;
|
||||
|
||||
template<typename Functor>
|
||||
struct MiserCall {
|
||||
Functor f;
|
||||
|
||||
MiserCall(Functor g) : f(g) {}
|
||||
};
|
||||
|
||||
template<typename Functor>
|
||||
static double adaptor_functor(double *x, size_t, void *params)
|
||||
{
|
||||
MiserCall<Functor> *c = (MiserCall<Functor> *) params;
|
||||
|
||||
return c->f(x);
|
||||
}
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param dim number of dimensions over which the integration will occur.
|
||||
*/
|
||||
GSL_Miser(size_t dim)
|
||||
: state(0), Nd(dim) {
|
||||
state = gsl_monte_miser_alloc(dim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~GSL_Miser() {
|
||||
gsl_monte_miser_free(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Integrate the provided integrand over some range, with a maximum number of calls. A bound
|
||||
* on the maximum error is returned.
|
||||
* Here is a use example:
|
||||
*
|
||||
* @code
|
||||
* // ...
|
||||
* size_t calls = 10;
|
||||
* double xl[2] = {0, 0};
|
||||
* double xu[2] = {1, 2};
|
||||
* double value;
|
||||
*
|
||||
* GSL_Miser miser(2); // 2-dimensions
|
||||
* value = miser.integrate(rng, [](double *x) {
|
||||
* // do something with x[0], x[1]
|
||||
* return x[0]*x[0] + x[1]*x[1]; // for example sum(x^2)
|
||||
* }, xl, xu, calls, abserr);
|
||||
* //...
|
||||
* @endcode
|
||||
*
|
||||
* @param rng Class adapting the GSL random number generator
|
||||
* @param f Functor representing the integrand. It must have one pointer to double and return a double.
|
||||
* @param xl lower bound for integration (N-dimension contiguous C-array)
|
||||
* @param xu upper bound for integration
|
||||
* @param calls maximum number of calls
|
||||
* @param abserr return medium for estimated maximum absolute error
|
||||
*
|
||||
*/
|
||||
// Only valid for GSL
|
||||
template<typename Functor,typename A>
|
||||
double integrate(GSL_RandomNumber& rng, Functor f, A& xl, A& xu, size_t calls, double &abserr) {
|
||||
gsl_monte_function mf;
|
||||
MiserCall<Functor> call(f);
|
||||
double result;
|
||||
int err;
|
||||
|
||||
mf.f = &adaptor_functor<Functor>;
|
||||
mf.dim = Nd;
|
||||
mf.params = &call;
|
||||
|
||||
if ((err = gsl_monte_miser_integrate(&mf, &xl[0], &xu[0], Nd, calls, rng.rng, state, &result, &abserr)) != GSL_SUCCESS)
|
||||
error_helper<ErrorGSL>(boost::format("Error while doing monte carlo integration: error code = %d ") % err);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use a multi-threaded random number generator deriving from a base "Rng".
|
||||
* This is a helper class to unwrap the GSL base class for the random number generation.
|
||||
* @see integrate(GSL_RandomNumber& rng, Functor f, A& xl, A& xu, size_t calls, double &abserr)
|
||||
*/
|
||||
template<typename Rng, typename Functor, typename A>
|
||||
double integrate(RandomNumberThreaded<Rng>& rng, Functor f, A& xl, A& xu, size_t calls, double &abserr) {
|
||||
return integrate(rng.base(), f, xl, xu, calls, abserr);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
91
libLSS/samplers/rgen/gsl_random_number.hpp
Normal file
91
libLSS/samplers/rgen/gsl_random_number.hpp
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/rgen/gsl_random_number.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef __GSL_RANDOM_NUMBER_HPP
|
||||
#define __GSL_RANDOM_NUMBER_HPP
|
||||
|
||||
#include <gsl/gsl_rng.h>
|
||||
#include <gsl/gsl_randist.h>
|
||||
#include <cstring>
|
||||
#include "libLSS/tools/errors.hpp"
|
||||
#include "libLSS/samplers/core/random_number.hpp"
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
class GSL_RandomNumber: public RandomNumber
|
||||
{
|
||||
public:
|
||||
gsl_rng *rng;
|
||||
|
||||
GSL_RandomNumber() :
|
||||
rng(gsl_rng_alloc(gsl_rng_mt19937)) {
|
||||
}
|
||||
|
||||
~GSL_RandomNumber() {
|
||||
gsl_rng_free(rng);
|
||||
}
|
||||
|
||||
virtual double uniform() {
|
||||
return gsl_rng_uniform(rng);
|
||||
}
|
||||
|
||||
virtual double unitexp() {
|
||||
return gsl_ran_exponential(rng, 1.);
|
||||
}
|
||||
|
||||
virtual void seed(unsigned long i) {
|
||||
Console::instance().print<LOG_DEBUG>(boost::format("GSL: Changing random number generation seed with %ld") % i);
|
||||
gsl_rng_set(rng, i);
|
||||
}
|
||||
|
||||
virtual unsigned long get() {
|
||||
return gsl_rng_get(rng);
|
||||
}
|
||||
|
||||
using RandomNumber::poisson;
|
||||
using RandomNumber::gaussian;
|
||||
using RandomNumber::gamma;
|
||||
using RandomNumber::negative_binomial;
|
||||
|
||||
virtual unsigned int poisson(double mean) {
|
||||
return gsl_ran_poisson(rng, mean);
|
||||
}
|
||||
|
||||
virtual unsigned int negative_binomial(double p, double n) {
|
||||
return gsl_ran_negative_binomial(rng, p, n);
|
||||
}
|
||||
|
||||
virtual double gamma(double a, double b) {
|
||||
return gsl_ran_gamma(rng, a, b);
|
||||
}
|
||||
|
||||
virtual void save(H5_CommonFileGroup& g) {
|
||||
boost::multi_array<char, 1> out(boost::extents[gsl_rng_size(rng)]);
|
||||
::memcpy(out.origin(), gsl_rng_state(rng), gsl_rng_size(rng));
|
||||
CosmoTool::hdf5_write_array(g, "state", out);
|
||||
}
|
||||
|
||||
virtual void restore(H5_CommonFileGroup& g, bool flexible) {
|
||||
size_t sz = gsl_rng_size(rng);
|
||||
boost::multi_array<char, 1> in;
|
||||
|
||||
CosmoTool::hdf5_read_array(g, "state", in);
|
||||
|
||||
|
||||
if (in.shape()[0] != sz) {
|
||||
error_helper<ErrorIO>("Could not read state in GSL_RandomNumber");
|
||||
}
|
||||
memcpy(gsl_rng_state(rng), in.origin(), sz);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
231
libLSS/samplers/rgen/slice_sweep.hpp
Normal file
231
libLSS/samplers/rgen/slice_sweep.hpp
Normal file
|
@ -0,0 +1,231 @@
|
|||
/*+
|
||||
ARES/HADES/BORG Package -- ./libLSS/samplers/rgen/slice_sweep.hpp
|
||||
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
|
||||
Copyright (C) 2009-2020 Jens Jasche <jens.jasche@fysik.su.se>
|
||||
|
||||
Additional contributions from:
|
||||
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
|
||||
|
||||
+*/
|
||||
#ifndef _LIBLSS_SLICE_SWEEP_HPP
|
||||
#define _LIBLSS_SLICE_SWEEP_HPP
|
||||
|
||||
#include "libLSS/mpi/generic_mpi.hpp"
|
||||
#include <cmath>
|
||||
|
||||
// These algorithms are described in https://www.aquila-consortium.org/wiki/index.php/File:Slice_sampling_Neal_97.pdf
|
||||
|
||||
|
||||
namespace LibLSS {
|
||||
|
||||
namespace slice_details {
|
||||
template<typename LogLikelihood>
|
||||
double request(MPI_Communication *comm, LogLikelihood lh, double a, int ROOT) {
|
||||
int job = 1;
|
||||
comm->broadcast_t(&job, 1, ROOT);
|
||||
comm->broadcast_t(&a, 1, ROOT);
|
||||
return lh(a);
|
||||
}
|
||||
|
||||
inline void shutdown(MPI_Communication *comm, double a, int ROOT) {
|
||||
int job = 0;
|
||||
comm->broadcast_t(&job, 1, ROOT);
|
||||
comm->broadcast_t(&a, 1, ROOT);
|
||||
}
|
||||
|
||||
inline int grab_job(MPI_Communication *comm, double& a, int ROOT) {
|
||||
int job;
|
||||
comm->broadcast_t(&job, 1, ROOT);
|
||||
comm->broadcast_t(&a, 1, ROOT);
|
||||
return job;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Random, typename LogLikelihood>
|
||||
double slice_sweep(MPI_Communication *comm, Random& rng, LogLikelihood lh, double a0, double step, int ROOT = 0)
|
||||
{
|
||||
Console::instance().print<LOG_DEBUG>("Doing slicesweep EARLY init");
|
||||
if (comm->rank() != ROOT) {
|
||||
double v;
|
||||
while (slice_details::grab_job(comm, v, ROOT)) {
|
||||
lh(v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
Console::instance().print<LOG_DEBUG>("Doing slicesweep init");
|
||||
double logp0 = slice_details::request(comm, lh, a0, ROOT);
|
||||
double logu = logp0 + std::log(1-rng.uniform());//draw from (0,1], to avoid log(0)
|
||||
Console::instance().c_assert(!std::isnan(logu), "logu must not be a NaN");
|
||||
double rr = rng.uniform();
|
||||
double al = a0 - rr*step;
|
||||
double ar = a0 + (1-rr)*step;
|
||||
|
||||
Console::instance().print<LOG_DEBUG>(boost::format("First loop (logu = %lg)") % logu);
|
||||
while (true) {
|
||||
double logpl = slice_details::request(comm, lh, al, ROOT);
|
||||
if (logpl < logu)
|
||||
break;
|
||||
al -= step;
|
||||
}
|
||||
|
||||
Console::instance().print<LOG_DEBUG>("Second loop");
|
||||
while (true) {
|
||||
double logpr = slice_details::request(comm, lh, ar, ROOT);
|
||||
if (logpr < logu)
|
||||
break;
|
||||
ar += step;
|
||||
}
|
||||
|
||||
Console::instance().print<LOG_DEBUG>("Last loop");
|
||||
while (true) {
|
||||
double a1 = rng.uniform() * (ar - al) + al;
|
||||
double logp1 = slice_details::request(comm, lh, a1, ROOT);
|
||||
|
||||
if (logp1 > logu) {
|
||||
slice_details::shutdown(comm, a1, ROOT);
|
||||
return a1;
|
||||
} else {
|
||||
// Shrink bracket
|
||||
if (a1 > a0)
|
||||
ar = a1;
|
||||
else
|
||||
al = a1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Random, typename LogLikelihood>
|
||||
double slice_sweep(Random& rng, LogLikelihood lh, double a0, double step)
|
||||
{
|
||||
double logp0 = lh(a0);
|
||||
double logu = logp0 + std::log(1-rng.uniform());//draw from (0,1], to avoid log(0)
|
||||
Console::instance().c_assert(!std::isnan(logu), "logu must not be a NaN");
|
||||
double rr = rng.uniform();
|
||||
double al = a0 - rr*step;
|
||||
double ar = a0 + (1-rr)*step;
|
||||
|
||||
while (true) {
|
||||
double logpl = lh(al);
|
||||
if (logpl < logu)
|
||||
break;
|
||||
al -= step;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
double logpr = lh(ar);
|
||||
if (logpr < logu)
|
||||
break;
|
||||
ar += step;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
double a1 = rng.uniform() * (ar - al) + al;
|
||||
double logp1 = lh(a1);
|
||||
|
||||
if (logp1 > logu) {
|
||||
return a1;
|
||||
} else {
|
||||
// Shrink bracket
|
||||
if (a1 > a0)
|
||||
ar = a1;
|
||||
else
|
||||
al = a1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Random, typename LogLikelihood>
|
||||
double slice_sweep_double(MPI_Communication *comm, Random& rng, LogLikelihood lh, double a0, double step, int ROOT = 0)
|
||||
{
|
||||
ConsoleContext<LOG_DEBUG> ctx("slicesweep_double");
|
||||
|
||||
if (comm->rank() != ROOT) {
|
||||
double v;
|
||||
while (slice_details::grab_job(comm, v, ROOT)) {
|
||||
lh(v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
ctx.print("INIT");
|
||||
// Find the initial likelihood and the slice level
|
||||
double logp0 = slice_details::request(comm, lh, a0, ROOT);
|
||||
double logu = logp0 + std::log(1-rng.uniform());//draw from (0,1], to avoid log(0)
|
||||
Console::instance().c_assert(!std::isnan(logu), "logu must not be a NaN");
|
||||
|
||||
double rr = rng.uniform();
|
||||
double al = a0 - rr*step;
|
||||
double ar = a0 + (1-rr)*step;
|
||||
|
||||
ctx.print(boost::format("Step defining loop (logu = %lg)") % logu);
|
||||
double logpl = slice_details::request(comm, lh, al, ROOT);
|
||||
double logpr = slice_details::request(comm, lh, ar, ROOT);
|
||||
while (logpl >= logu || logpr >= logu) {
|
||||
double v= rng.uniform();
|
||||
if (v < 0.5) {
|
||||
al -= (ar - al);
|
||||
logpl = slice_details::request(comm, lh, al, ROOT);
|
||||
ctx.print(boost::format("new al=%g, logpl = %g") % al % logpl);
|
||||
} else {
|
||||
ar += (ar - al);
|
||||
logpr = slice_details::request(comm, lh, ar, ROOT);
|
||||
ctx.print(boost::format("new ar=%g, logpr = %g") % ar % logpr);
|
||||
}
|
||||
}
|
||||
|
||||
ctx.print("Sampling loop");
|
||||
while (true) {
|
||||
double a1 = rng.uniform() * (ar - al) + al;
|
||||
double logp1 = slice_details::request(comm, lh, a1, ROOT);
|
||||
|
||||
if (logp1 > logu) {
|
||||
double ar_hat = ar;
|
||||
double al_hat = al;
|
||||
double logpl_hat = slice_details::request(comm, lh, al_hat, ROOT);
|
||||
double logpr_hat = slice_details::request(comm, lh, ar_hat, ROOT);
|
||||
bool not_accepted = false;
|
||||
|
||||
ctx.print(boost::format("Got a candidate at a1=%g") % a1);
|
||||
|
||||
while ((ar_hat - al_hat) > (1.1*step) && !not_accepted) {
|
||||
double am = 0.5 * (ar_hat+al_hat);
|
||||
|
||||
bool D = ((a0 < am && a1 >= am) || (a0 >= am && a1 < am));
|
||||
|
||||
if (a1 < am) {
|
||||
ar_hat = am;
|
||||
logpr_hat = slice_details::request(comm, lh, ar_hat, ROOT);
|
||||
} else {
|
||||
al_hat = am;
|
||||
logpl_hat = slice_details::request(comm, lh, al_hat, ROOT);
|
||||
}
|
||||
|
||||
ctx.print(boost::format("ar_hat=%lg, al_hat=%lg, logpl_hat=%lg, logpr_hat=%lg, D=%d") % ar_hat % al_hat % logpl_hat % logpr_hat % D);
|
||||
|
||||
if (D && logu >= logpl_hat && logu >= logpr_hat) {
|
||||
// Not acceptable. Try again.
|
||||
ctx.print("Not good");
|
||||
not_accepted = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Go back outside
|
||||
if (not_accepted)
|
||||
continue;
|
||||
|
||||
slice_details::shutdown(comm, a1, ROOT);
|
||||
return a1;
|
||||
} else {
|
||||
// Shrink bracket
|
||||
if (a1 > a0)
|
||||
ar = a1;
|
||||
else
|
||||
al = a1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue