Initial import

This commit is contained in:
Guilhem Lavaux 2023-05-29 10:41:03 +02:00
commit 56a50eead3
820 changed files with 192077 additions and 0 deletions

View 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

View 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 );
}

View 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

View 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));
}

View 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

View 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);
}

View 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

View 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));
}

View 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

View 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);
}

View 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

View 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
)
);
}
}
}
}

View 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