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,130 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/branch.cpp
Copyright (C) 2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#include <boost/multi_array.hpp>
#include "libLSS/physics/cosmo.hpp"
#include "libLSS/mpi/generic_mpi.hpp"
#include "libLSS/physics/forward_model.hpp"
#include <list>
#include <boost/variant.hpp>
#include "libLSS/tools/errors.hpp"
#include "libLSS/physics/branch.hpp"
using namespace LibLSS;
BranchForwardModel::BranchForwardModel(
MPI_Communication *comm, const BoxModel &box)
: BORGForwardModel(comm, box) {}
BranchForwardModel::BranchForwardModel(
MPI_Communication *comm, const BoxModel &box, const BoxModel &outbox)
: BORGForwardModel(comm, box, outbox) {}
BranchForwardModel::~BranchForwardModel() {}
void BranchForwardModel::forwardModelSimple(CArrayRef &delta_init) {}
void BranchForwardModel::forwardModel_v2(ModelInput<3> delta_init) {
LIBLSS_AUTO_CONTEXT(LOG_VERBOSE, ctx);
for (auto &model : model_list) {
model->forwardModel_v2(delta_init.shallowClone());
}
}
void BranchForwardModel::getDensityFinal(ModelOutput<3> output) {
error_helper<ErrorNotImplemented>(
"getDensityFinal does not exist for BranchForwardModel.");
}
void BranchForwardModel::clear_chain() {
auto cleaner = [](auto &u) { u.reset(); };
boost::apply_visitor(cleaner, previous);
boost::apply_visitor(cleaner, next);
}
void BranchForwardModel::forwardModelRsdField(
ArrayRef &deltaf, double *vobs_ext) {}
// adjointModel auto release particles. Beware !
void BranchForwardModel::adjointModel_v2(ModelInputAdjoint<3> gradient_delta) {
LIBLSS_AUTO_CONTEXT(LOG_VERBOSE, ctx);
if (gradient_delta) {
error_helper<ErrorParams>(
"Input to adjointModel_v2 must be null for branch.");
}
}
void BranchForwardModel::getAdjointModelOutput(
ModelOutputAdjoint<3> ag_output) {
// FIXME: Very dumb choice at the moment, first one has the right of choice.
ag_output.setRequestedIO((*model_list.begin())->getPreferredInput());
ModelOutputAdjoint<3> common_output = ag_output.makeTempLike();
for (auto &model : model_list) {
ModelOutputAdjoint<3> tmp_output = common_output.shallowClone();
model->getAdjointModelOutput(std::move(tmp_output));
switch (ag_output.current) {
case PREFERRED_REAL:
fwrap(ag_output.getRealOutput()) =
fwrap(ag_output.getRealOutput()) + common_output.getRealOutput();
break;
case PREFERRED_FOURIER:
fwrap(ag_output.getFourierOutput()) =
fwrap(ag_output.getFourierOutput()) + common_output.getRealOutput();
break;
default:
error_helper<ErrorBadState>("Unknown ModelIO type");
break;
}
clearAdjointGradient();
}
}
void BranchForwardModel::releaseParticles() {
// Fill up with the chain
for (auto model : model_list) {
model->releaseParticles();
}
}
void BranchForwardModel::addModel(std::shared_ptr<BORGForwardModel> model) {
if (get_box_model() != model->get_box_model()) {
error_helper<ErrorParams>(
"Invalid model configuration with IO of the chain.");
}
model_list.push_back(model);
}
void BranchForwardModel::setAdjointRequired(bool required) {
for (auto model : model_list) {
model->setAdjointRequired(required);
}
}
void BranchForwardModel::updateCosmo() {
// Fill up with the chain
for (auto model : model_list) {
model->setCosmoParams(cosmo_params);
}
}
void BranchForwardModel::clearAdjointGradient() {
for (auto model : model_list) {
model->clearAdjointGradient();
}
}
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2020

View file

@ -0,0 +1,76 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/branch.hpp
Copyright (C) 2018-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2018-2019 Doogesh Kodi Ramanah <ramanah@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#pragma once
#ifndef __LIBLSS_BRANCH_FORWARD_MODEL_HPP
# define __LIBLSS_BRANCH_FORWARD_MODEL_HPP
# include <boost/multi_array.hpp>
# include "libLSS/physics/cosmo.hpp"
# include "libLSS/mpi/generic_mpi.hpp"
# include "libLSS/physics/forward_model.hpp"
# include <list>
# include <boost/variant.hpp>
namespace LibLSS {
class BranchForwardModel : public BORGForwardModel {
public:
ModelOutput<3> final_output;
ModelOutputAdjoint<3> ag_final_output;
typedef std::shared_ptr<DFT_Manager::U_ArrayReal> S_U_ArrayReal;
typedef std::shared_ptr<DFT_Manager::U_ArrayFourier> S_U_ArrayFourier;
S_U_ArrayReal final_real, ag_final_real;
S_U_ArrayFourier final_fourier, ag_final_fourier;
boost::variant<S_U_ArrayReal, S_U_ArrayFourier> previous, next;
BranchForwardModel(MPI_Communication *comm, const BoxModel &box);
BranchForwardModel(
MPI_Communication *comm, const BoxModel &box, const BoxModel &outbox);
~BranchForwardModel() override;
void forwardModelSimple(CArrayRef &delta_init) override;
void forwardModel_v2(ModelInput<3> delta_init) override;
void getDensityFinal(ModelOutput<3> output) override;
void clear_chain();
void forwardModelRsdField(ArrayRef &deltaf, double *vobs_ext) override;
// adjointModel auto release particles. Beware !
void adjointModel_v2(ModelInputAdjoint<3> gradient_delta) override;
void getAdjointModelOutput(ModelOutputAdjoint<3> ag_output) override;
void releaseParticles() override;
void addModel(std::shared_ptr<BORGForwardModel> model);
void setAdjointRequired(bool required) override;
void clearAdjointGradient() override;
protected:
std::list<std::shared_ptr<BORGForwardModel>> model_list;
void updateCosmo() override;
};
}; // namespace LibLSS
#endif
// ARES TAG: authors_num = 2
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2018-2020
// ARES TAG: name(1) = Doogesh Kodi Ramanah
// ARES TAG: email(1) = ramanah@iap.fr
// ARES TAG: year(1) = 2018-2019

View file

@ -0,0 +1,357 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/chain_forward_model.cpp
Copyright (C) 2018-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2018-2019 Doogesh Kodi Ramanah <ramanah@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#include <boost/multi_array.hpp>
#include "libLSS/physics/cosmo.hpp"
#include "libLSS/mpi/generic_mpi.hpp"
#include "libLSS/physics/forward_model.hpp"
#include <list>
#include <boost/variant.hpp>
#include "libLSS/tools/errors.hpp"
#include "libLSS/physics/chain_forward_model.hpp"
#include <boost/variant.hpp>
#include "libLSS/tools/overload.hpp"
using namespace LibLSS;
ChainForwardModel::ChainForwardModel(
MPI_Communication *comm, const BoxModel &box)
: BORGForwardModel(comm, box), accumulate(false) {}
ChainForwardModel::ChainForwardModel(
MPI_Communication *comm, const BoxModel &box, const BoxModel &outbox)
: BORGForwardModel(comm, box, outbox), accumulate(false) {}
ChainForwardModel::~ChainForwardModel() {}
void ChainForwardModel::accumulateAdjoint(bool do_accumulate) {
accumulate = do_accumulate;
}
bool ChainForwardModel::densityInvalidated() const {
bool r = false;
for (auto const &model : model_list) {
r = r || model->densityInvalidated();
}
return r;
}
void ChainForwardModel::forwardModelSimple(CArrayRef &delta_init) {}
void ChainForwardModel::forwardModel_v2(ModelInput<3> delta_init) {
LIBLSS_AUTO_CONTEXT(LOG_DEBUG, ctx);
ModelInput<3> input_array;
ModelInput<3> next_input(std::move(delta_init));
ModelOutput<3> next_output;
S_U_ArrayReal tmp_real;
S_U_ArrayFourier tmp_fourier;
BoxModel box_in, box_out;
// Fill up with the chain
auto iter = model_list.begin();
while (iter != model_list.end()) {
auto model = *iter;
++iter;
bool final_pass = (iter == model_list.end());
input_array = std::move(next_input);
PreferredIO nextIO =
final_pass ? model->getPreferredOutput() : (*iter)->getPreferredInput();
if (nextIO == PREFERRED_NONE) {
nextIO = model->getPreferredOutput();
if (nextIO == PREFERRED_NONE) {
nextIO = input_array.current;
}
}
box_in = model->get_box_model();
box_out = model->get_box_model_output();
// TODO: check box compatibilities
switch (nextIO) {
case PREFERRED_REAL:
tmp_real.reset();
tmp_real = std::move(model->out_mgr->allocate_ptr_array());
next_output = std::move(ModelOutput<3>(
model->out_mgr, box_out, tmp_real->get_array(), tmp_real));
next_input = std::move(ModelInput<3>(
model->out_mgr, box_out, tmp_real->get_array(), tmp_real));
if (final_pass) {
final_real = tmp_real;
final_output = std::move(ModelOutput<3>(
model->out_mgr, box_out, final_real->get_array(), final_real));
}
next = tmp_real;
break;
case PREFERRED_FOURIER:
tmp_fourier.reset();
tmp_fourier = std::move(model->out_mgr->allocate_ptr_complex_array());
next_output = std::move(ModelOutput<3>(
model->out_mgr, box_out, tmp_fourier->get_array(), tmp_fourier));
next_input = std::move(ModelInput<3>(
model->out_mgr, box_out, tmp_fourier->get_array(), tmp_fourier));
if (final_pass) {
final_fourier = tmp_fourier;
final_output = std::move(ModelOutput<3>(
model->out_mgr, box_out, final_fourier->get_array(),
final_fourier));
}
next = tmp_fourier;
break;
default:
error_helper<ErrorNotImplemented>("Invalid IO type.");
break;
}
model->forwardModel_v2(std::move(input_array));
model->getDensityFinal(std::move(next_output));
previous = next;
}
}
void ChainForwardModel::getDensityFinal(ModelOutput<3> output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
output.setRequestedIO(final_output.active);
output.copyFrom(final_output);
// Try to save some memory by releasing early the temporary allocation.
final_real.reset();
final_fourier.reset();
clear_chain();
}
void ChainForwardModel::clear_chain() {
auto cleaner = [](auto &u) { u.reset(); };
boost::apply_visitor(cleaner, previous);
boost::apply_visitor(cleaner, next);
}
void ChainForwardModel::forwardModelRsdField(
ArrayRef &deltaf, double *vobs_ext) {}
static void accumulator(ModelInputBase<3> &accum, ModelInputBase<3> &input) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
typedef ModelIO<3>::CArrayRef CArrayRef;
typedef ModelIO<3>::ArrayRef ArrayRef;
// This ensures that we capture incompatibilities.
accum.needDestroyInput();
boost::apply_visitor(
overload(
[&input](CArrayRef *v) {
// The preference is applied to the one being accumulated on the first ag.
input.setRequestedIO(PREFERRED_FOURIER);
fwrap(*v) = input.getFourierConst();
},
[&input](ArrayRef *v) {
// The preference is applied to the one being accumulated on the first ag.
input.setRequestedIO(PREFERRED_REAL);
fwrap(*v) = input.getRealConst();
},
[&](auto const *v) {
Console::instance().c_assert(false, "Impossible situation");
}),
accum.getHolder());
}
// adjointModel auto release particles. Beware !
void ChainForwardModel::adjointModel_v2(ModelInputAdjoint<3> gradient_delta) {
LIBLSS_AUTO_CONTEXT(LOG_DEBUG, ctx);
if (accumulate) {
if (!accumulateAg) {
accumulateAg = std::move(gradient_delta);
} else {
accumulator(accumulateAg, gradient_delta);
}
return;
} else {
accumulateAg = std::move(gradient_delta);
}
trigger_ag();
}
void ChainForwardModel::trigger_ag() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
ModelInputAdjoint<3> next_ag_input(std::move(accumulateAg)), ag_input;
ModelOutputAdjoint<3> ag_output;
std::shared_ptr<DFT_Manager::U_ArrayReal> tmp_real;
std::shared_ptr<DFT_Manager::U_ArrayFourier> tmp_fourier;
BoxModel box_in, box_out;
PreferredIO nextIO;
// Fill up with the chain
// Ordering here should be opposite to that in Forward model
auto iter = model_list_adjoint.begin();
while (iter != model_list_adjoint.end()) {
auto model = *iter;
++iter;
bool final_pass = (iter == model_list_adjoint.end());
box_in = model->get_box_model_output();
box_out = model->get_box_model();
nextIO =
final_pass ? model->getPreferredInput() : (*iter)->getPreferredOutput();
if (nextIO == PREFERRED_NONE) {
nextIO = model->getPreferredInput();
if (nextIO == PREFERRED_NONE) {
nextIO = next_ag_input.current;
}
}
ag_input = std::move(next_ag_input);
switch (nextIO) {
case PREFERRED_REAL:
ctx.print("Next wants real");
tmp_real.reset();
tmp_real = std::move(model->lo_mgr->allocate_ptr_array());
ag_output = std::move(ModelOutputAdjoint<3>(
model->lo_mgr, box_out, tmp_real->get_array(), tmp_real));
next_ag_input = std::move(ModelInputAdjoint<3>(
model->lo_mgr, box_out, tmp_real->get_array(), tmp_real));
if (final_pass) {
ag_final_real = tmp_real;
ag_final_output = std::move(ModelOutputAdjoint<3>(
model->lo_mgr, box_out, ag_final_real->get_array(), ag_final_real));
}
next = tmp_real;
break;
case PREFERRED_FOURIER:
ctx.print("Next wants Fourier");
tmp_fourier.reset();
tmp_fourier = std::move(model->lo_mgr->allocate_ptr_complex_array());
ag_output = std::move(ModelOutputAdjoint<3>(
model->lo_mgr, box_out, tmp_fourier->get_array(), tmp_fourier));
next_ag_input = std::move(ModelInputAdjoint<3>(
model->lo_mgr, box_out, tmp_fourier->get_array(), tmp_fourier));
if (final_pass) {
ag_final_fourier = tmp_fourier;
ag_final_output = std::move(ModelOutputAdjoint<3>(
model->lo_mgr, box_out, ag_final_fourier->get_array(),
ag_final_fourier));
}
next = tmp_fourier;
break;
default:
error_helper<ErrorNotImplemented>("Invalid IO type");
break;
}
model->adjointModel_v2(std::move(ag_input));
model->getAdjointModelOutput(std::move(ag_output));
previous = next;
}
}
void ChainForwardModel::getAdjointModelOutput(ModelOutputAdjoint<3> ag_output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
if (accumulate && accumulateAg) {
trigger_ag();
}
ag_output.setRequestedIO(ag_final_output.active);
ag_output.copyFrom(ag_final_output);
ag_final_fourier.reset();
ag_final_real.reset();
clear_chain();
}
void ChainForwardModel::releaseParticles() {
// Fill up with the chain
for (auto model : model_list) {
model->releaseParticles();
}
}
void ChainForwardModel::addModel(
std::shared_ptr<BORGForwardModel> model, std::string const &n) {
named_models[n] = model;
addModel(model);
}
std::shared_ptr<BORGForwardModel>
ChainForwardModel::queryModel(std::string const &n) {
return named_models[n];
}
void ChainForwardModel::addModel(std::shared_ptr<BORGForwardModel> model) {
if (model_list.size() == 0) {
if (box_input != model->get_box_model()) {
error_helper<ErrorParams>(
"Invalid model configuration with IO of the chain.");
}
} else {
if (box_output != model->get_box_model()) {
error_helper<ErrorParams>(
"Invalid model configuration with IO of the chain.");
}
}
model_list.push_back(model);
model_list_adjoint.insert(model_list_adjoint.begin(), model);
box_output = model->get_box_model_output();
out_mgr = model->out_mgr;
}
void ChainForwardModel::setAdjointRequired(bool required) {
for (auto &model : model_list) {
model->setAdjointRequired(required);
}
}
void ChainForwardModel::updateCosmo() {
// Fill up with the chain
for (auto &model : model_list) {
model->setCosmoParams(cosmo_params);
}
}
void ChainForwardModel::setModelParams(ModelDictionnary const &params) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
for (auto &model : model_list) {
model->setModelParams(params);
}
}
void ChainForwardModel::clearAdjointGradient() {
for (auto &model : model_list) {
model->clearAdjointGradient();
}
}
boost::any ChainForwardModel::getModelParam(
std::string const &name, std::string const &parameter) {
// Nothing to return here
if (name == modelName)
return boost::any();
for (auto &model : model_list) {
auto ret = model->getModelParam(name, parameter);
if (!ret.empty())
return ret;
}
return boost::any();
}
// ARES TAG: authors_num = 2
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2018-2020
// ARES TAG: name(1) = Doogesh Kodi Ramanah
// ARES TAG: email(1) = ramanah@iap.fr
// ARES TAG: year(1) = 2018-2019

View file

@ -0,0 +1,99 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/chain_forward_model.hpp
Copyright (C) 2018-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2018-2019 Doogesh Kodi Ramanah <ramanah@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#ifndef __LIBLSS_CHAIN_FORWARD_MODEL_HPP
# define __LIBLSS_CHAIN_FORWARD_MODEL_HPP
# include <boost/multi_array.hpp>
# include "libLSS/physics/cosmo.hpp"
# include "libLSS/mpi/generic_mpi.hpp"
# include "libLSS/physics/forward_model.hpp"
# include <list>
# include <map>
# include <boost/variant.hpp>
namespace LibLSS {
class ChainForwardModel : public BORGForwardModel {
public:
ModelOutput<3> final_output;
ModelOutputAdjoint<3> ag_final_output;
typedef std::shared_ptr<DFT_Manager::U_ArrayReal> S_U_ArrayReal;
typedef std::shared_ptr<DFT_Manager::U_ArrayFourier> S_U_ArrayFourier;
S_U_ArrayReal final_real, ag_final_real;
S_U_ArrayFourier final_fourier, ag_final_fourier;
boost::variant<S_U_ArrayReal, S_U_ArrayFourier> previous, next;
bool accumulate;
ModelInputAdjoint<3> accumulateAg;
ChainForwardModel(MPI_Communication *comm, const BoxModel &box);
ChainForwardModel(
MPI_Communication *comm, const BoxModel &box, const BoxModel &outbox);
virtual ~ChainForwardModel();
bool densityInvalidated() const override;
void forwardModelSimple(CArrayRef &delta_init) override;
void forwardModel_v2(ModelInput<3> delta_init) override;
void getDensityFinal(ModelOutput<3> output) override;
void clear_chain();
void forwardModelRsdField(ArrayRef &deltaf, double *vobs_ext) override;
// adjointModel auto release particles. Beware !
void adjointModel_v2(ModelInputAdjoint<3> gradient_delta) override;
void getAdjointModelOutput(ModelOutputAdjoint<3> ag_output) override;
void releaseParticles() override;
void addModel(std::shared_ptr<BORGForwardModel> model);
void
addModel(std::shared_ptr<BORGForwardModel> model, std::string const &name);
std::shared_ptr<BORGForwardModel> queryModel(std::string const &name);
void setAdjointRequired(bool required) override;
void clearAdjointGradient() override;
void setModelParams(ModelDictionnary const &params) override;
boost::any getModelParam(
std::string const &model_name, std::string const &parameter) override;
void accumulateAdjoint(bool do_accumulate) override;
protected:
std::list<std::shared_ptr<BORGForwardModel>> model_list;
std::list<std::shared_ptr<BORGForwardModel>> model_list_adjoint;
std::map<std::string, std::shared_ptr<BORGForwardModel>> named_models;
void updateCosmo() override;
void trigger_ag();
};
}; // namespace LibLSS
#endif
// ARES TAG: authors_num = 2
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2018-2020
// ARES TAG: name(1) = Doogesh Kodi Ramanah
// ARES TAG: email(1) = ramanah@iap.fr
// ARES TAG: year(1) = 2018-2019

View file

@ -0,0 +1,114 @@
/// Docs for forward_model
/*+
ARES/HADES/BORG Package -- -- ./libLSS/physics/forward_model.hpp
Copyright (C) 2014-2019 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2009-2019 Jens Jasche <jens.jasche@fysik.su.se>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2016-2019)
This program is free software; you can redistribute it and/or modify it
under the terms of either the CeCILL license or the GNU General Public
license, as included with the software package.
The text of the license is located in Licence_CeCILL_V2.1-en.txt
and GPL.txt in the root directory of the source package.
+*/
#include <boost/preprocessor/stringize.hpp>
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/multi_array.hpp>
#include "libLSS/physics/cosmo.hpp"
#include "libLSS/mpi/generic_mpi.hpp"
#include "libLSS/tools/mpi_fftw_helper.hpp"
#include "libLSS/tools/errors.hpp"
#include "libLSS/tools/hdf5_type.hpp"
#include "libLSS/physics/forward_model.hpp"
using namespace LibLSS;
void BORGForwardModel::setup(bool distinct_io) {
Console::instance().print<LOG_VERBOSE>("Setup FWD");
LibLSS::ConsoleContext<LOG_VERBOSE> ctx("BORGForwardModel::setup");
volume = L0 * L1 * L2;
volNorm = volume / (N0 * N1 * N2);
vobs.resize(boost::extents[3]);
lo_mgr = std::make_unique<DFT_Manager>(
box_input.N0, box_input.N1, box_input.N2, comm);
startN0 = lo_mgr->startN0;
localN0 = lo_mgr->localN0;
N2_HC = lo_mgr->N2_HC;
N2real = lo_mgr->N2real;
if (distinct_io) {
out_mgr = std::make_unique<DFT_Manager>(
box_output.N0, box_output.N1, box_output.N2, comm);
} else
out_mgr = lo_mgr;
analysis_plan = 0;
synthesis_plan = 0;
}
void BORGForwardModel::setupDefault() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
ctx.print("Allocate real");
tmp_real_field = lo_mgr->allocate_ptr_array();
ctx.print("Allocate complex");
tmp_complex_field = lo_mgr->allocate_ptr_complex_array();
ctx.print("Plan r2c");
analysis_plan = lo_mgr->create_r2c_plan(
tmp_real_field->get_array().data(),
tmp_complex_field->get_array().data());
ctx.print("Plan 2c2r");
synthesis_plan = lo_mgr->create_c2r_plan(
tmp_complex_field->get_array().data(),
tmp_real_field->get_array().data());
}
void BORGForwardModel::setCosmoParams(
const CosmologicalParameters &p_cosmo_params) {
this->cosmo_params = p_cosmo_params;
this->params["cosmology"] = p_cosmo_params;
updateCosmo();
}
#define COSMO_ATTRIBUTE(r, q, element) \
{ \
BOOST_PP_STRINGIZE(element), \
[](CosmologicalParameters &p, double v) { p.element = v; } \
},
// clang-format off
static std::map<
std::string, std::function<void(CosmologicalParameters &, double)>>
g_dispatcher{
BOOST_PP_SEQ_FOR_EACH(COSMO_ATTRIBUTE, _,
(sigma8)(omega_r)
(omega_m)(omega_k)(omega_b)(omega_q)(w)(n_s)(fnl)(wprime)(h)
)
};
// clang-format on
void BORGForwardModel::setModelParams(ModelDictionnary const &params) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
bool runUpdateCosmo = false;
for (auto &x : params) {
// Special cases, cosmology can also be updated that way.
if (x.first.rfind("cosmology.") == 0) {
ctx.format("Updating cosmo params %s", x.first.substr(10));
g_dispatcher[x.first.substr(10)](
this->cosmo_params, boost::any_cast<double>(x.second));
runUpdateCosmo = true;
} else
this->params[x.first] = x.second;
}
if (runUpdateCosmo)
setCosmoParams(this->cosmo_params);
}

View file

@ -0,0 +1,399 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forward_model.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_BORG_FORWARD_MODEL_HPP
#define __LIBLSS_BORG_FORWARD_MODEL_HPP
#include <map>
#include <boost/any.hpp>
#include <boost/multi_array.hpp>
#include "libLSS/physics/cosmo.hpp"
#include "libLSS/mpi/generic_mpi.hpp"
#include "libLSS/tools/mpi_fftw_helper.hpp"
#include "libLSS/tools/errors.hpp"
#include "libLSS/tools/memusage.hpp"
#include "libLSS/tools/hdf5_type.hpp"
#include "libLSS/physics/model_io.hpp"
namespace LibLSS {
typedef std::map<std::string, boost::any> ModelDictionnary;
struct BORGForwardModelTypes {
typedef FFTW_Manager_3d<double> DFT_Manager;
typedef boost::multi_array<double, 2> PhaseArray;
typedef boost::multi_array_ref<double, 2> PhaseArrayRef;
typedef ModelIO<3>::ArrayRef ArrayRef;
typedef ModelIO<3>::CArrayRef CArrayRef;
};
class outOfBoundParam : virtual public ErrorBase {
public:
explicit outOfBoundParam(std::string const &p) : ErrorBase(p) {}
};
/**
* This defines the interface for a forward physical model in BORG.
*/
class BORGForwardModel : public BORGForwardModelTypes {
public:
std::shared_ptr<DFT_Manager> lo_mgr;
std::shared_ptr<DFT_Manager> out_mgr;
MPI_Communication *communicator() { return comm; }
BORGForwardModel(BORGForwardModel &&other) = default;
explicit BORGForwardModel(MPI_Communication *comm, const BoxModel &box)
: comm(comm), L0(box.L0), L1(box.L1), L2(box.L2), N0(box.N0),
N1(box.N1), N2(box.N2), xmin0(box.xmin0), xmin1(box.xmin1),
xmin2(box.xmin2), forwardModelHold(false), box_input(box),
box_output(box) {
setup(false);
}
explicit BORGForwardModel(
MPI_Communication *comm, const BoxModel &box, const BoxModel &box_out)
: comm(comm), L0(box.L0), L1(box.L1), L2(box.L2), N0(box.N0),
N1(box.N1), N2(box.N2), xmin0(box.xmin0), xmin1(box.xmin1),
xmin2(box.xmin2), forwardModelHold(false), box_input(box),
box_output(box_out) {
setup(true);
}
virtual ~BORGForwardModel() {
if (analysis_plan) {
lo_mgr->destroy_plan(analysis_plan);
lo_mgr->destroy_plan(synthesis_plan);
}
}
void setName(std::string const &name_) { modelName = name_; }
void holdParticles() { forwardModelHold = true; }
// Default is the standard historical behaviour
virtual PreferredIO getPreferredInput() const { return PREFERRED_FOURIER; }
virtual PreferredIO getPreferredOutput() const { return PREFERRED_REAL; }
// This executes the forward model but rely on auxiliary functions to pass down the result. So it holds
// internal information and need a release call.
virtual void forwardModelSimple(CArrayRef &delta_init) {
forwardModel_v2(ModelInput<3>(lo_mgr, box_input, delta_init, true));
}
virtual void forwardModel(
CArrayRef &delta_init, ArrayRef &delta_output, bool adjointNext) {
// Default implementation uses the v2 interface
// Warning. adjointNext do not exist anymore in the v2, it is superseded by setAdjointRequired.
fwrap(delta_init) = fwrap(delta_init) * get_box_model().volume();
forwardModel_v2(ModelInput<3>(lo_mgr, box_input, delta_init));
getDensityFinal(ModelOutput<3>(lo_mgr, box_output, delta_output));
}
virtual void forwardModel(
CArrayRef &delta_init, ArrayRef &delta_output, ArrayRef &vx,
ArrayRef &vy, ArrayRef &vz, bool adjointNext) {
error_helper<ErrorNotImplemented>(
"forwardModel is not supported velocity output");
}
virtual void forwardModelRsdField(ArrayRef &deltaf, double *vobs_ext) {
error_helper<ErrorNotImplemented>(
"forwardModelRsdField not supported here.");
}
/**
* @brief Run a forwardModel with APIv2. Only the input must be provided.
*
* @param delta_init ModelInput object holding the input array.
*/
virtual void forwardModel_v2(ModelInput<3> delta_init) {
error_helper<ErrorNotImplemented>("forwardModel_v2 not supported here.");
}
/**
* @brief Get the output of the forward model.
*
* @param delta_output ModelOutput object holding the output array.
*/
virtual void getDensityFinal(ModelOutput<3> delta_output) {
error_helper<ErrorNotImplemented>(
"forwardModel_v2 (getDensityFinal) not supported here.");
}
/**
* @brief Runs the adjoint model on the provided input vector.
*
* @param ag_delta_input Input vector adjoint model.
*/
virtual void adjointModel_v2(ModelInputAdjoint<3> ag_delta_input) {
error_helper<ErrorNotImplemented>("adjointModel_v2 not supported here.");
}
/**
* @brief Changes the behavior of adjointModel_v2 to accumulate all the vectors prior to computing the result.
*
* This changes the behavior of the adjoint forward model to accept to
* accumulate new adjoint vectors before computing the final result through
* `getAdjointModelOutput`.
*
* @param do_accumulate switch on the accumulate behaviour
*/
virtual void accumulateAdjoint(bool do_accumulate) {
error_helper<ErrorNotImplemented>("accumulateAdjoint not supported here.");
}
/**
* @brief Retrieve the output vector after the adjoint model has been run.
*
* @param ag_delta_output
*/
virtual void getAdjointModelOutput(ModelOutputAdjoint<3> ag_delta_output) {
error_helper<ErrorNotImplemented>(
"adjointModel_v2 (getAdjointModelOutput) not supported here.");
}
/**
* @brief Apply the jacobian
*
* @param gradient_delta
*/
[[deprecated("Replaced by adjointModel_v2, with better API")]]
virtual void adjointModel(ArrayRef &gradient_delta) {
adjointModel_v2(ModelInputAdjoint<3>(lo_mgr, box_input, gradient_delta));
getAdjointModelOutput(
ModelOutputAdjoint<3>(lo_mgr, box_output, gradient_delta));
}
virtual void releaseParticles() {}
void setCosmoParams(const CosmologicalParameters &p_cosmo_params);
// FIXME: Add a setModelParams API point with model name
//
/**
* @brief set model parameters call for all models subtended by this one.
*
* @params params a dictionnary of parameters
*/
virtual void setModelParams(ModelDictionnary const &params);
// FIXME: Add a getModelParam without name.
/**
* @brief Query a single parameter from a specific sub-model.
*/
virtual boost::any
getModelParam(std::string const &name, std::string const &parameterName) {
return boost::any();
}
void setObserver(const ArrayType1d::ArrayType &v) { this->vobs = v; }
/**
* @brief Indicate whether an adjoint model is required.
* The caller indicates it wants to be able to run adjointGradient.
* This may involve allocating a lot more memory during forward
* evaluation.
*
* @param on
*/
virtual void setAdjointRequired(bool on) {}
/**
* @brief Clear the internal buffers for adjoint gradient.
*
*/
virtual void clearAdjointGradient() {}
void save(CosmoTool::H5_CommonFileGroup &fg) {}
void restore(CosmoTool::H5_CommonFileGroup &fg) {}
BoxModel get_box_model() const {
BoxModel box;
box.L0 = L0;
box.L1 = L1;
box.L2 = L2;
box.N0 = N0;
box.N1 = N1;
box.N2 = N2;
box.xmin0 = xmin0;
box.xmin1 = xmin1;
box.xmin2 = xmin2;
return box;
}
BoxModel get_box_model_output() const { return box_output; }
virtual bool densityInvalidated() const { return true; }
private:
BORGForwardModel(const BORGForwardModel &) {}
BORGForwardModel &operator=(const BORGForwardModel &) { return *this; }
void setup(bool distinct_io);
protected:
void setupDefault();
MPI_Communication *comm;
double L0, L1, L2;
double volume, volNorm;
long N0, N1, N2, startN0, localN0, N2_HC, N2real;
double xmin0, xmin1, xmin2;
DFT_Manager::plan_type synthesis_plan, analysis_plan;
bool forwardModelHold;
BoxModel box_input, box_output;
std::unique_ptr<DFT_Manager::U_ArrayFourier> tmp_complex_field;
std::unique_ptr<DFT_Manager::U_ArrayReal> tmp_real_field;
typedef DFT_Manager::U_ArrayReal U_Array;
typedef DFT_Manager::U_ArrayFourier U_CArray;
typedef std::unique_ptr<U_Array> U_Array_p;
typedef std::unique_ptr<U_CArray> U_CArray_p;
typedef U_Array::array_type Array;
typedef U_CArray::array_type CArray;
CosmologicalParameters cosmo_params;
ModelDictionnary params;
ArrayType1d::ArrayType vobs;
std::string modelName;
virtual void updateCosmo() {}
void ensureInputEqualOutput() {
if (box_input == box_output)
return;
error_helper<ErrorBadState>(
"Input box must be the same as the output box.");
}
};
/**
* This define a gravity model which uses particles to trace matter flows.
*/
class ParticleBasedForwardModel : public BORGForwardModel {
public:
using BORGForwardModel::BORGForwardModel;
typedef boost::multi_array<double, 2>::const_array_view<2>::type
PhaseSubArray;
typedef boost::multi_array<double, 2>::array_view<2>::type PhaseSubArrayRW;
typedef boost::multi_array<size_t, 1>::const_array_view<1>::type IdSubArray;
typedef std::function<void(
double, size_t, IdSubArray, PhaseSubArray, PhaseSubArray)>
StepNotifier;
StepNotifier currentNotifier;
virtual IdSubArray getLagrangianIdentifiers() const {
boost::multi_array_types::index_gen i_gen;
typedef boost::multi_array_types::index_range range;
error_helper<ErrorNotImplemented>(
"getLagrangianIdentifiers is not implemented for this model.");
return boost::multi_array_ref<size_t, 1>(
0, boost::extents[0])[i_gen[range()]];
}
virtual size_t getNumberOfParticles() const = 0;
/**
* @brief Get the Particle Positions object
*
* @return PhaseSubArray
*/
virtual PhaseSubArray getParticlePositions() = 0;
/**
* @brief Get the Particle Velocities object
*
* @return PhaseSubArray
*/
virtual PhaseSubArray getParticleVelocities() = 0;
/**
* @brief Get the Velocity Multiplier
*
* @return double
*/
virtual double getVelocityMultiplier() { return 1.0; }
/**
* @brief Get the Supersampling Rate
*
* @return unsigned int
*/
virtual unsigned int getSupersamplingRate() const = 0;
/**
* @brief
*
* This computes the adjoint gradient on the particle positions, velocities
* Not all models may support this. The default implementation triggers an error.
*
* @param grad_pos
* @param grad_vel
*/
virtual void
adjointModelParticles(PhaseArrayRef &grad_pos, PhaseArrayRef &grad_vel) {
error_helper<ErrorNotImplemented>(
"adjointModelParticles is not implemented in this model.");
}
virtual void setStepNotifier(StepNotifier notifier) {
currentNotifier = notifier;
}
};
/**
* This is a type alias to specify how to store the BORG gravity model
* in the MarkovState dictionnary.
*/
typedef SharedObjectStateElement<BORGForwardModel> BorgModelElement;
template <typename Model>
void borgSaveParticles(
CosmoTool::H5_CommonFileGroup &g, Model &m, bool savepos, bool savevel,
int step = -1) {
typedef boost::multi_array<double, 2> VectorArray;
typedef UninitializedArray<VectorArray> U_VectorArray;
using range = boost::multi_array_types::index_range;
size_t numPart = m.getNumberOfParticles();
U_VectorArray pos_vel(boost::extents[numPart][3]);
if (savepos) {
m.copyParticlePositions(pos_vel.get_array(), step);
CosmoTool::hdf5_write_array(g, "u_pos", pos_vel.get_array());
}
if (savevel) {
m.copyParticleVelocities(pos_vel.get_array(), step);
CosmoTool::hdf5_write_array(g, "u_vel", pos_vel.get_array());
}
auto ids = m.getLagrangianIdentifiers();
typename decltype(ids)::index_gen i_gen;
boost::multi_array<size_t, 1> final_ids(boost::extents[numPart]);
LibLSS::copy_array(final_ids, ids[i_gen[range(0, numPart)]]);
CosmoTool::hdf5_write_array(g, "u_lagrangian_id", final_ids);
}
}; // namespace LibLSS
#endif

View file

@ -0,0 +1,77 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/fnl.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 <set>
#include <map>
#include "libLSS/physics/forwards/fnl.hpp"
#include "libLSS/physics/forwards/registry.hpp"
#include "libLSS/physics/model_io.hpp"
#include "libLSS/samplers/core/powerspec_tools.hpp"
#include "libLSS/tools/itertools.hpp"
#include <CosmoTool/cosmopower.hpp>
using namespace LibLSS;
ForwardFNL::ForwardFNL(MPI_Communication *comm, const BoxModel &box)
: BORGForwardModel(comm, box) {
ensureInputEqualOutput();
}
void ForwardFNL::forwardModel_v2(ModelInput<3> delta_init) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
// Setup the IO basis that is required for this forward.
delta_init.setRequestedIO(PREFERRED_REAL);
hold_input = std::move(delta_init);
}
void ForwardFNL::getDensityFinal(ModelOutput<3> delta_output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
delta_output.setRequestedIO(PREFERRED_REAL);
auto w_delta_init = fwrap(hold_input.getReal());
auto w_delta_output = fwrap(delta_output.getRealOutput());
w_delta_output =
(w_delta_init * w_delta_init * cosmo_params.fnl + w_delta_init);
}
void ForwardFNL::adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
in_gradient_delta.setRequestedIO(PREFERRED_REAL);
hold_ag_input = std::move(in_gradient_delta);
}
void ForwardFNL::getAdjointModelOutput(
ModelOutputAdjoint<3> out_gradient_delta) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
out_gradient_delta.setRequestedIO(PREFERRED_REAL);
auto w_in_gradient = fwrap(hold_ag_input.getReal());
auto w_out_gradient = fwrap(out_gradient_delta.getRealOutput());
auto w_delta_init = fwrap(hold_input.getReal());
w_out_gradient =
2 * w_delta_init * cosmo_params.fnl * w_in_gradient + w_in_gradient;
}
void ForwardFNL::clearAdjointGradient() {
hold_ag_input.clear();
hold_input.clear();
}
void ForwardFNL::forwardModelRsdField(ArrayRef &, double *) {}
void ForwardFNL::releaseParticles() {}
static std::shared_ptr<BORGForwardModel> build_primordial_FNL(
MPI_Communication *comm, BoxModel const &box, PropertyProxy const &params) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
return std::make_shared<ForwardFNL>(comm, box);
}
LIBLSS_REGISTER_FORWARD_IMPL(PRIMORDIAL_FNL, build_primordial_FNL);

View file

@ -0,0 +1,65 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/fnl.hpp
Copyright (C) 2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2020 Jens Jasche <jens.jasche@fysik.su.se>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#ifndef __LIBLSS_HADES_FORWARD_FNL_HPP
# define __LIBLSS_HADES_FORWARD_FNL_HPP
# pragma once
# include "libLSS/physics/forward_model.hpp"
# include "libLSS/tools/fusewrapper.hpp"
# include "libLSS/tools/errors.hpp"
# include "libLSS/physics/forwards/registry.hpp"
namespace LibLSS {
/**
* This class handles the addition of an fNL into primordial potential.
*/
class ForwardFNL : public BORGForwardModel {
public:
typedef IArrayType::ArrayType IArrayRef;
typedef ArrayType1d::ArrayType Array1dRef;
using BORGForwardModel::ArrayRef;
protected:
ModelInput<3> hold_input;
ModelInputAdjoint<3> hold_ag_input;
bool lazyInit;
public:
/**
* Constructor.
*/
explicit ForwardFNL(MPI_Communication *comm, const BoxModel &box);
virtual PreferredIO getPreferredInput() const { return PREFERRED_REAL; }
virtual PreferredIO getPreferredOutput() const { return PREFERRED_REAL; }
virtual void forwardModel_v2(ModelInput<3> delta_init);
virtual void getDensityFinal(ModelOutput<3> delta_output);
virtual void adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta);
virtual void
getAdjointModelOutput(ModelOutputAdjoint<3> out_gradient_delta);
virtual void forwardModelRsdField(ArrayRef &, double *);
virtual void clearAdjointGradient();
virtual void releaseParticles();
}; // namespace LibLSS
} // namespace LibLSS
LIBLSS_REGISTER_FORWARD_DECL(PRIMORDIAL_FNL);
#endif
// ARES TAG: num_authors = 2
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: year(0) = 2020
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: name(1) = Jens Jasche
// ARES TAG: year(1) = 2020
// ARES TAG: email(1) = jens.jasche@fysik.su.se

View file

@ -0,0 +1,205 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/primordial.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 <set>
#include <map>
#include "libLSS/physics/forwards/primordial.hpp"
#include "libLSS/physics/forwards/registry.hpp"
#include "libLSS/physics/model_io.hpp"
#include "libLSS/samplers/core/powerspec_tools.hpp"
#include "libLSS/tools/itertools.hpp"
#include <CosmoTool/cosmopower.hpp>
using namespace LibLSS;
ForwardPrimordial::ForwardPrimordial(
MPI_Communication *comm, const BoxModel &box, double af_)
: BORGForwardModel(comm, box), af(af_), D_init(1.0),
powerSpectrumKeys(lo_mgr->extents_complex()),
powerSpectrum(boost::extents[1]), lazyInit(false), invalid(true), accumulateAg(false) {
ensureInputEqualOutput();
// First look at the number of different keys
size_t endN0 = startN0 + localN0;
std::set<double> keyset;
std::map<double, int> keymap;
for (size_t i = startN0; i < endN0; i++) {
for (size_t j = 0; j < N1; j++) {
for (size_t k = 0; k < N2_HC; k++) {
double kx = kmode(i, N0, L0);
double ky = kmode(j, N1, L1);
double kz = kmode(k, N2, L2);
double key2 = (kx * kx + ky * ky + kz * kz);
keyset.insert(key2);
}
}
}
// Build inverse map
for (auto iter : itertools::enumerate(keyset)) {
keymap[iter.get<1>()] = iter.get<0>();
}
keyTranslate.resize(boost::extents[keymap.size()]);
// Assign each k mode its unique identifier
for (size_t i = startN0; i < endN0; i++) {
for (size_t j = 0; j < N1; j++) {
for (size_t k = 0; k < N2_HC; k++) {
double kx = kmode(i, N0, L0);
double ky = kmode(j, N1, L1);
double kz = kmode(k, N2, L2);
double key2 = (kx * kx + ky * ky + kz * kz);
int key = keymap[key2];
powerSpectrumKeys[i][j][k] = key;
keyTranslate[key] = std::sqrt(key2);
}
}
}
powerSpectrum.resize(boost::extents[keymap.size()]);
}
auto ForwardPrimordial::getPowerSpectrumArray() {
auto &local_keys = powerSpectrumKeys;
return fwrap(
b_fused_idx<double, 3>([this, &local_keys](size_t i, size_t j, size_t k) {
return powerSpectrum[local_keys[i][j][k]];
}));
}
void ForwardPrimordial::forwardModel_v2(ModelInput<3> delta_init) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
// Setup the IO basis that is required for this forward.
delta_init.setRequestedIO(PREFERRED_FOURIER);
hold_input = std::move(delta_init);
}
void ForwardPrimordial::getDensityFinal(ModelOutput<3> delta_output) {
delta_output.setRequestedIO(PREFERRED_FOURIER);
auto w_delta_init = fwrap(hold_input.getFourierConst());
auto w_delta_output = fwrap(delta_output.getFourierOutput());
w_delta_output = (w_delta_init)*getPowerSpectrumArray();
invalid = false;
}
void ForwardPrimordial::updateCosmo() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
if (cosmo_params == old_cosmo_params)
return;
invalid = true;
old_cosmo_params = cosmo_params;
Cosmology cosmo(cosmo_params);
CosmoTool::CosmoPower cpower;
D_init = cosmo.d_plus(af) /
cosmo.d_plus(
1.0); // Scale factor for initial conditions, sigma8 is at z=0
double h = cpower.h = cosmo_params.h;
cpower.OMEGA_B = cosmo_params.omega_b;
cpower.OMEGA_C = cosmo_params.omega_m - cosmo_params.omega_b;
cpower.SIGMA8 = cosmo_params.sigma8;
cpower.n = cosmo_params.n_s;
cpower.updateCosmology();
cpower.setFunction(CosmoTool::CosmoPower::HU_WIGGLES);
cpower.normalize();
cpower.setFunction(CosmoTool::CosmoPower::PRIMORDIAL_PS);
// TODO: For future we will generate the power spectrum here, inline
size_t endN0 = startN0 + localN0;
#pragma omp parallel for collapse(3)
for (size_t i = startN0; i < endN0; i++) {
for (size_t j = 0; j < N1; j++) {
for (size_t k = 0; k < N2_HC; k++) {
int key = powerSpectrumKeys[i][j][k];
double k_mode = keyTranslate[key];
double Qk_delta =
std::sqrt(cpower.power(k_mode * h) * h * h * h * volume);
if (k_mode > 0) {
double Qk_phi = -Qk_delta / (k_mode * k_mode);
powerSpectrum[key] = Qk_phi * D_init;
} else {
powerSpectrum[key] = 0;
}
}
}
}
}
/*
void ForwardPrimordial::setPowerSpectrum(
IArrayRef const &keys, Array1dRef const &P) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
powerSpectrum.resize(array::make_extent_from(P));
powerSpectrumKeys.resize(array::make_extent_from(keys));
fwrap(powerSpectrum) = std::sqrt(fwrap(P) * volume);
fwrap(powerSpectrumKeys) = keys;
}*/
void ForwardPrimordial::adjointModel_v2(
ModelInputAdjoint<3> in_gradient_delta) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
// Build strict range views (we do not want to see the
// the FFTW padding, ensure that the view object lives till the end of this function.
in_gradient_delta.setRequestedIO(PREFERRED_FOURIER);
if (accumulateAg) {
if (!hold_ag_input) {
hold_ag_input = std::move(in_gradient_delta);
// Mark that we will modify it so we need a local copy.
hold_ag_input.needDestroyInput();
} else {
auto w = fwrap(hold_ag_input.getFourier());
w = w + fwrap(in_gradient_delta.getFourierConst());
}
} else {
hold_ag_input = std::move(in_gradient_delta);
}
}
void ForwardPrimordial::getAdjointModelOutput(
ModelOutputAdjoint<3> out_gradient_delta) {
out_gradient_delta.setRequestedIO(PREFERRED_FOURIER);
auto w_in_gradient = fwrap(hold_ag_input.getFourierConst());
auto w_out_gradient = fwrap(out_gradient_delta.getFourierOutput());
w_out_gradient = w_in_gradient * getPowerSpectrumArray();
}
void ForwardPrimordial::clearAdjointGradient() {
hold_ag_input.clear();
hold_input.clear();
}
bool ForwardPrimordial::densityInvalidated() const { return invalid; }
void ForwardPrimordial::forwardModelRsdField(ArrayRef &, double *) {}
void ForwardPrimordial::releaseParticles() {}
static std::shared_ptr<BORGForwardModel> build_primordial(
MPI_Communication *comm, BoxModel const &box, PropertyProxy const &params) {
// double ai = params.get<double>("a_initial");
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
double af = params.get<double>("a_final"); // A_initial has no point
return std::make_shared<ForwardPrimordial>(comm, box, af);
}
LIBLSS_REGISTER_FORWARD_IMPL(PRIMORDIAL, build_primordial);

View file

@ -0,0 +1,95 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/primordial.hpp
Copyright (C) 2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2020 Jens Jasche <jens.jasche@fysik.su.se>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#ifndef __LIBLSS_HADES_FORWARD_PRIMORDIAL_HPP
# define __LIBLSS_HADES_FORWARD_PRIMORDIAL_HPP
# pragma once
# include "libLSS/physics/forward_model.hpp"
# include "libLSS/tools/fusewrapper.hpp"
# include "libLSS/tools/errors.hpp"
# include "libLSS/physics/forwards/registry.hpp"
namespace LibLSS {
/**
* This class handles the colouring of a white noise field with a cosmological
* power spectrum. It is best to provide a fourier and use the returned fourier
* field with the v2 interface. Otherwise extra FFT will be called to
* to match to v1 interface.
*/
class ForwardPrimordial : public BORGForwardModel {
public:
typedef IArrayType::ArrayType IArrayRef;
typedef ArrayType1d::ArrayType Array1dRef;
using BORGForwardModel::ArrayRef;
protected:
CosmologicalParameters old_cosmo_params;
double af, D_init;
LibLSS::multi_array<int, 3> powerSpectrumKeys;
LibLSS::multi_array<double, 1> powerSpectrum;
LibLSS::multi_array<double, 1> keyTranslate;
ModelInput<3> hold_input;
ModelInputAdjoint<3> hold_ag_input;
bool lazyInit;
bool invalid;
bool accumulateAg;
public:
/**
* Constructor.
*/
explicit ForwardPrimordial(
MPI_Communication *comm, const BoxModel &box, double af_);
PreferredIO getPreferredInput() const override { return PREFERRED_FOURIER; }
PreferredIO getPreferredOutput() const override {
return PREFERRED_FOURIER;
}
auto getPowerSpectrumArray();
void accumulateAdjoint(bool accumulate) override {
accumulateAg = accumulate;
}
void forwardModel_v2(ModelInput<3> delta_init) override;
void getDensityFinal(ModelOutput<3> delta_output) override;
void updateCosmo() override;
void adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta) override;
void clearAdjointGradient() override;
void
getAdjointModelOutput(ModelOutputAdjoint<3> out_gradient_delta) override;
void forwardModelRsdField(ArrayRef &, double *) override;
void releaseParticles() override;
bool densityInvalidated() const override;
}; // namespace LibLSS
} // namespace LibLSS
LIBLSS_REGISTER_FORWARD_DECL(PRIMORDIAL);
#endif
// ARES TAG: num_authors = 2
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: year(0) = 2020
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: name(1) = Jens Jasche
// ARES TAG: year(1) = 2020
// ARES TAG: email(1) = jens.jasche@fysik.su.se

View file

@ -0,0 +1,35 @@
#include "libLSS/tools/console.hpp"
#include "libLSS/physics/forwards/registry.hpp"
#include "libLSS/tools/static_init.hpp"
using namespace LibLSS;
namespace {
RegisterStaticInit init_registry([]() {
auto &cons = Console::instance();
cons.print<LOG_INFO_SINGLE>("Registered forward models:");
for (auto k : ForwardRegistry::instance().list()) {
cons.print<LOG_INFO_SINGLE>(" - " + k.first);
}
});
}
ForwardRegistry::ForwardRegistry() {}
ForwardRegistry &ForwardRegistry::instance() {
static ForwardRegistry this_instance;
return this_instance;
}
ForwardModelFactory ForwardRegistry::get(std::string const &n) {
auto iter = forwardRegistry.find(n);
if (iter == forwardRegistry.end())
error_helper<ErrorParams>("Invalid model name");
return iter->second;
}
ForwardModelFactory LibLSS::setup_forward_model(std::string const &n) {
return ForwardRegistry::instance().get(n);
}

View file

@ -0,0 +1,104 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/registry.hpp
Copyright (C) 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)
+*/
#pragma once
#ifndef __LIBLSS_PHYSICS_FORWARDS_REGISTRY_HPP
# define __LIBLSS_PHYSICS_FORWARDS_REGISTRY_HPP
# include <map>
# include <string>
# include <memory>
# include "libLSS/mpi/generic_mpi.hpp"
# include "libLSS/physics/forward_model.hpp"
# include "libLSS/tools/ptree_proxy.hpp"
# include "libLSS/tools/errors.hpp"
namespace LibLSS {
typedef std::function<std::shared_ptr<BORGForwardModel>(
MPI_Communication *comm, BoxModel const &box,
PropertyProxy const &params)>
ForwardModelFactory;
/**
* @brief Class that handles the automatic registration of forward model element.
*
* The models can be later automatically constructed provided a name, a box and a dictionary.
*/
class ForwardRegistry {
private:
std::map<std::string, ForwardModelFactory> forwardRegistry;
ForwardRegistry();
public:
static ForwardRegistry &instance();
/**
* @brief Register a new element factory. This is internal, do not call it directly.
*
* @param n
* @param factory
*/
void registerFactory(std::string const &n, ForwardModelFactory factory) {
forwardRegistry[n] = factory;
}
/**
* @brief List all registered models.
*
* @return std::map<std::string, ForwardModelFactory> const
*/
auto const list() { return forwardRegistry; }
/**
* @brief Lookup a factory
*
* @param n name
* @return ForwardModelFactory a factory
*/
ForwardModelFactory get(std::string const &n);
};
struct _RegisterForwardModel {
_RegisterForwardModel(std::string n, ForwardModelFactory factory) {
ForwardRegistry::instance().registerFactory(n, factory);
}
};
ForwardModelFactory setup_forward_model(std::string const &n);
/**
* @brief Declare an automatic registrator. This is required to get the dynamic linker includes the symbols.
*
*/
# define LIBLSS_REGISTER_FORWARD_DECL(NAME) \
AUTO_REGISTRATOR_DECL(Forward_##NAME)
# define LIBLSS_REGISTER_NAME(NAME) Forward_##NAME
# define MANGLED_LIBLSS_REGISTER_NAME(NAME) _register_##NAME
# define LIBLSS_REGISTER_NAMESTR(NAME) # NAME
/**
* @brief Implements an automatic registrator. A builder function must be provided as an argument.
*
*/
# define LIBLSS_REGISTER_FORWARD_IMPL(NAME, BUILDER) \
AUTO_REGISTRATOR_IMPL(LIBLSS_REGISTER_NAME(NAME)) \
namespace { \
_RegisterForwardModel MANGLED_LIBLSS_REGISTER_NAME(NAME)( \
LIBLSS_REGISTER_NAMESTR(NAME), BUILDER); \
}
} // namespace LibLSS
#endif
// ARES TAG: num_authors = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: year(0) = 2020
// ARES TAG: email(0) = guilhem.lavaux@iap.fr

View file

@ -0,0 +1,178 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/transfer_ehu.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 <set>
#include <map>
#include "libLSS/physics/forwards/transfer_ehu.hpp"
#include "libLSS/physics/forwards/registry.hpp"
#include "libLSS/physics/model_io.hpp"
#include "libLSS/samplers/core/powerspec_tools.hpp"
#include "libLSS/tools/itertools.hpp"
#include <CosmoTool/cosmopower.hpp>
using namespace LibLSS;
ForwardEisensteinHu::ForwardEisensteinHu(
MPI_Communication *comm, const BoxModel &box)
: BORGForwardModel(comm, box), powerSpectrumKeys(lo_mgr->extents_complex()),
powerSpectrum(boost::extents[1]), lazyInit(false), sign_k2(1),
invalid(true) {
ensureInputEqualOutput();
// First look at the number of different keys
size_t endN0 = startN0 + localN0;
std::set<double> keyset;
std::map<double, int> keymap;
for (size_t i = startN0; i < endN0; i++) {
for (size_t j = 0; j < N1; j++) {
for (size_t k = 0; k < N2_HC; k++) {
double kx = kmode(i, N0, L0);
double ky = kmode(j, N1, L1);
double kz = kmode(k, N2, L2);
double key2 = (kx * kx + ky * ky + kz * kz);
keyset.insert(key2);
}
}
}
// Build inverse map
for (auto iter : itertools::enumerate(keyset)) {
keymap[iter.get<1>()] = iter.get<0>();
}
keyTranslate.resize(boost::extents[keymap.size()]);
// Assign each k mode its unique identifier
for (size_t i = startN0; i < endN0; i++) {
for (size_t j = 0; j < N1; j++) {
for (size_t k = 0; k < N2_HC; k++) {
double kx = kmode(i, N0, L0);
double ky = kmode(j, N1, L1);
double kz = kmode(k, N2, L2);
double key2 = (kx * kx + ky * ky + kz * kz);
int key = keymap[key2];
powerSpectrumKeys[i][j][k] = key;
keyTranslate[key] = std::sqrt(key2);
}
}
}
powerSpectrum.resize(boost::extents[keymap.size()]);
}
auto ForwardEisensteinHu::getPowerSpectrumArray() {
auto &local_keys = powerSpectrumKeys;
return fwrap(
b_fused_idx<double, 3>([this, &local_keys](size_t i, size_t j, size_t k) {
return powerSpectrum[local_keys[i][j][k]];
}));
}
void ForwardEisensteinHu::forwardModel_v2(ModelInput<3> delta_init) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
// Setup the IO basis that is required for this forward.
delta_init.setRequestedIO(PREFERRED_FOURIER);
hold_input = std::move(delta_init);
}
void ForwardEisensteinHu::getDensityFinal(ModelOutput<3> delta_output) {
delta_output.setRequestedIO(PREFERRED_FOURIER);
auto w_delta_init = fwrap(hold_input.getFourierConst());
auto w_delta_output = fwrap(delta_output.getFourierOutput());
w_delta_output = (w_delta_init)*getPowerSpectrumArray();
invalid = false;
}
void ForwardEisensteinHu::updateCosmo() {
LIBLSS_AUTO_CONTEXT(LOG_VERBOSE, ctx);
if (cosmo_params == old_cosmo_params)
return;
invalid = true;
old_cosmo_params = cosmo_params;
Cosmology cosmo(cosmo_params);
CosmoTool::CosmoPower cpower;
double h = cpower.h = cosmo_params.h;
cpower.OMEGA_B = cosmo_params.omega_b;
cpower.OMEGA_C = cosmo_params.omega_m - cosmo_params.omega_b;
cpower.SIGMA8 = cosmo_params.sigma8;
cpower.n = cosmo_params.n_s;
cpower.updateCosmology();
cpower.setFunction(CosmoTool::CosmoPower::HU_WIGGLES);
cpower.normalize();
cpower.setFunction(CosmoTool::CosmoPower::MATTER_TK);
// TODO: For future we will generate the power spectrum here, inline
size_t endN0 = startN0 + localN0;
#pragma omp parallel for collapse(3)
for (size_t i = startN0; i < endN0; i++) {
for (size_t j = 0; j < N1; j++) {
for (size_t k = 0; k < N2_HC; k++) {
int key = powerSpectrumKeys[i][j][k];
double k_mode = keyTranslate[key];
double Qk_delta =
-sign_k2 * cpower.power(k_mode * h) * (k_mode * k_mode);
powerSpectrum[key] = Qk_delta;
}
}
}
}
void ForwardEisensteinHu::adjointModel_v2(
ModelInputAdjoint<3> in_gradient_delta) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
// Build strict range views (we do not want to see the
// the FFTW padding, ensure that the view object lives till the end of this function.
in_gradient_delta.setRequestedIO(PREFERRED_FOURIER);
hold_ag_input = std::move(in_gradient_delta);
}
void ForwardEisensteinHu::getAdjointModelOutput(
ModelOutputAdjoint<3> out_gradient_delta) {
out_gradient_delta.setRequestedIO(PREFERRED_FOURIER);
auto w_in_gradient = fwrap(hold_ag_input.getFourierConst());
auto w_out_gradient = fwrap(out_gradient_delta.getFourierOutput());
w_out_gradient = w_in_gradient * getPowerSpectrumArray();
}
void ForwardEisensteinHu::clearAdjointGradient() {
hold_ag_input.clear();
hold_input.clear();
}
void ForwardEisensteinHu::forwardModelRsdField(ArrayRef &, double *) {}
void ForwardEisensteinHu::releaseParticles() {}
bool ForwardEisensteinHu::densityInvalidated() const { return invalid; }
static std::shared_ptr<BORGForwardModel> build_eisenstein_hu(
MPI_Communication *comm, BoxModel const &box, PropertyProxy const &params) {
// double ai = params.get<double>("a_initial");
auto reverse_sign = params.get_optional<bool>("reverse_sign");
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
auto v = std::make_shared<ForwardEisensteinHu>(comm, box);
if (reverse_sign)
v->setReverseSign(*reverse_sign);
return v;
}
LIBLSS_REGISTER_FORWARD_IMPL(TRANSFER_EHU, build_eisenstein_hu);

View file

@ -0,0 +1,97 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/transfer_ehu.hpp
Copyright (C) 2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2020 Jens Jasche <jens.jasche@fysik.su.se>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#ifndef __LIBLSS_HADES_FORWARD_TRANSFER_EHU_HPP
# define __LIBLSS_HADES_FORWARD_TRANSFER_EHU_HPP
# pragma once
# include "libLSS/physics/forward_model.hpp"
# include "libLSS/tools/fusewrapper.hpp"
# include "libLSS/tools/errors.hpp"
# include "libLSS/physics/forwards/registry.hpp"
namespace LibLSS {
/**
* @brief Forward model element that applies a Eisensten&Hu transfer function
*
* It assumes that the input is a properly linearly-scaled gravitational potential.
*/
class ForwardEisensteinHu : public BORGForwardModel {
public:
typedef IArrayType::ArrayType IArrayRef;
typedef ArrayType1d::ArrayType Array1dRef;
using BORGForwardModel::ArrayRef;
protected:
CosmologicalParameters old_cosmo_params;
LibLSS::multi_array<int, 3> powerSpectrumKeys;
LibLSS::multi_array<double, 1> powerSpectrum;
LibLSS::multi_array<double, 1> keyTranslate;
ModelInput<3> hold_input;
ModelInputAdjoint<3> hold_ag_input;
bool lazyInit;
double sign_k2;
bool invalid;
bool accum;
public:
/**
* Constructor.
*/
explicit ForwardEisensteinHu(MPI_Communication *comm, const BoxModel &box);
PreferredIO getPreferredInput() const override { return PREFERRED_FOURIER; }
PreferredIO getPreferredOutput() const override {
return PREFERRED_FOURIER;
}
auto getPowerSpectrumArray();
void setReverseSign(bool reverse) { sign_k2 = reverse ? -1 : 1; }
void forwardModel_v2(ModelInput<3> delta_init) override;
void getDensityFinal(ModelOutput<3> delta_output) override;
void updateCosmo() override;
void adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta) override;
void accumulateAdjoint(bool do_accumulate) override {
accum = do_accumulate;
}
void clearAdjointGradient() override;
void
getAdjointModelOutput(ModelOutputAdjoint<3> out_gradient_delta) override;
void forwardModelRsdField(ArrayRef &, double *) override;
void releaseParticles() override;
bool densityInvalidated() const override;
}; // namespace LibLSS
} // namespace LibLSS
LIBLSS_REGISTER_FORWARD_DECL(TRANSFER_EHU);
#endif
// ARES TAG: num_authors = 2
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: year(0) = 2020
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: name(1) = Jens Jasche
// ARES TAG: year(1) = 2020
// ARES TAG: email(1) = jens.jasche@fysik.su.se

View file

@ -0,0 +1,257 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/upgrade.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/tools/fusewrapper.hpp"
#include "libLSS/tools/static_init.hpp"
#include "libLSS/physics/forwards/upgrade.hpp"
using namespace LibLSS;
static BoxModel mul_box(BoxModel inbox, unsigned int m) {
inbox.N0 *= m;
inbox.N1 *= m;
inbox.N2 *= m;
return inbox;
}
ForwardUpgrade::ForwardUpgrade(
MPI_Communication *comm, BoxModel const &box, unsigned int multiply)
: BORGForwardModel(comm, box, mul_box(box, multiply)) {
//ghosts.setup();
}
void ForwardUpgrade::forwardModel_v2(ModelInput<3> delta_init) {
delta_init.setRequestedIO(PREFERRED_FOURIER);
hold_input = std::move(delta_init);
}
namespace {
namespace details {
template <size_t Dim, size_t r, typename A>
auto _basic_range(
size_t id, std::array<ssize_t, Dim> const &source_N,
std::array<ssize_t, Dim> const &target_N, A a) {
typedef boost::multi_array_types::index_range range;
if (r == 0) {
if ((id & 1) != 0) {
return a[range(target_N[0] - source_N[0] / 2 + 1, target_N[0])];
} else {
return a[range(0, source_N[0] / 2)];
}
} else {
if ((id & (1UL << r)) != 0) {
return a[range(target_N[r] - source_N[r] / 2 + 1, target_N[r])];
} else {
return a[range(0, source_N[r] / 2)];
}
}
}
template <size_t Dim, size_t r, typename A>
auto _basic_slice(
size_t id, size_t nyquist_dir, std::array<ssize_t, Dim> const &source_N,
std::array<ssize_t, Dim> const &target_N, A a) {
typedef boost::multi_array_types::index_range range;
if (nyquist_dir == r) {
if ((id & (1UL << r)) == 0) {
return a[range(source_N[r] / 2, source_N[r] / 2 + 1)];
} else {
return a[range(
target_N[r] - source_N[r] / 2,
target_N[r] - source_N[r] / 2 + 1)];
}
} else {
if ((id & (1UL << r)) == 0) {
return a[range(0, source_N[r] / 2 + 1)];
} else {
return a[range(target_N[r] - source_N[r] / 2, target_N[r])];
}
}
}
template <size_t Dim, size_t r>
struct _gen_range {
static auto
gen(size_t id, std::array<ssize_t, Dim> const &source_N,
std::array<ssize_t, Dim> const &target_N) {
return _basic_range<Dim, r>(
id, source_N, target_N,
_gen_range<Dim, r - 1>::gen(id, source_N, target_N));
}
static auto slice(
size_t id, size_t nyquist_dir,
std::array<ssize_t, Dim> const &source_N,
std::array<ssize_t, Dim> const &target_N) {
return _basic_slice<Dim, r>(
id, nyquist_dir, source_N, target_N,
_gen_range<Dim, r - 1>::slice(id, nyquist_dir, source_N, target_N));
}
};
template <size_t Dim>
struct _gen_range<Dim, 0UL> {
static auto
gen(size_t id, std::array<ssize_t, Dim> const &source_N,
std::array<ssize_t, Dim> const &target_N) {
return _basic_range<Dim, 0>(id, source_N, target_N, boost::indices);
}
static auto slice(
size_t id, size_t nyquist_dir,
std::array<ssize_t, Dim> const &source_N,
std::array<ssize_t, Dim> const &target_N) {
return _basic_slice<Dim, 0>(
id, nyquist_dir, source_N, target_N, boost::indices);
}
};
template <size_t Dim>
auto gen_range(
size_t id, std::array<ssize_t, Dim> const &source_N,
std::array<ssize_t, Dim> const &target_N) {
return _gen_range<Dim, Dim - 1>::gen(id, source_N, target_N);
}
template <size_t Dim>
auto gen_slice(
size_t id, size_t nyquist_dir, std::array<ssize_t, Dim> const &source_N,
std::array<ssize_t, Dim> const &target_N) {
return _gen_range<Dim, Dim - 1>::slice(
id, nyquist_dir, source_N, target_N);
}
} // namespace details
using details::gen_range;
using details::gen_slice;
} // namespace
template <size_t Dim, typename OutArray, typename InputArray>
static void upgrade(
NBoxModel<Dim> const &in_box, NBoxModel<Dim> const &out_box,
OutArray &output, InputArray const &input) {
constexpr size_t Pairs = 1UL << (Dim - 1);
std::array<ssize_t, Dim> in_Ns, out_Ns;
in_box.fill(in_Ns);
out_box.fill(out_Ns);
fwrap(output) = 0;
for (size_t i = 0; i < Pairs; i++) {
auto r0 = gen_range(i, in_Ns, in_Ns);
auto r1 = gen_range(i, in_Ns, out_Ns);
fwrap(output[r1]) = fwrap(input[r0]);
for (unsigned nyquist = 0; nyquist < Dim; nyquist++) {
auto s0 = gen_slice(i, nyquist, in_Ns, out_Ns);
auto s1 = gen_slice(i, nyquist, in_Ns, in_Ns);
fwrap(output[s0]) = fwrap(input[s1]);
}
}
for (size_t i = 0; i < Pairs; i++) {
for (unsigned nyquist = 0; nyquist < Dim; nyquist++) {
{
auto s0 = gen_slice(i, nyquist, in_Ns, out_Ns);
fwrap(output[s0]) = 0.5 * fwrap(output[s0]);
}
}
}
}
template <size_t Dim, typename OutArray, typename InputArray>
static void adjoint_upgrade(
NBoxModel<Dim> const &in_box, NBoxModel<Dim> const &out_box,
OutArray &output, InputArray const &input) {
constexpr size_t Pairs = 1UL << (Dim - 1);
std::array<ssize_t, Dim> in_Ns, out_Ns;
in_box.fill(in_Ns);
out_box.fill(out_Ns);
fwrap(output) = 0;
for (size_t i = 0; i < Pairs; i++) {
for (unsigned nyquist = 0; nyquist < Dim; nyquist++) {
{
auto s0 = gen_slice(i, nyquist, in_Ns, in_Ns);
auto s1 = gen_slice(i, nyquist, in_Ns, out_Ns);
// double const fac = (nyquist==(Dim-1) ? 2 : 1);
fwrap(output[s0]) = fwrap(output[s0]) + fwrap(input[s1]);
}
}
}
for (unsigned nyquist = 0; nyquist < Dim; nyquist++)
{
auto s0 = gen_slice(1UL << nyquist, nyquist, in_Ns, in_Ns);
fwrap(output[s0]) = 0.5 * fwrap(output[s0]);
}
for (size_t i = 0; i < Pairs; i++) {
auto r0 = gen_range(i, in_Ns, in_Ns);
auto r1 = gen_range(i, in_Ns, out_Ns);
fwrap(output[r0]) = fwrap(input[r1]);
}
}
void ForwardUpgrade::getDensityFinal(ModelOutput<3> delta_output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
delta_output.setRequestedIO(PREFERRED_FOURIER);
auto &in_delta = hold_input.getFourierConst();
// ghosts.synchronize(in_delta);
upgrade(
get_box_model(), get_box_model_output(), delta_output.getFourierOutput(),
in_delta);
}
void ForwardUpgrade::adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta) {
in_gradient_delta.setRequestedIO(PREFERRED_FOURIER);
hold_adjoint = std::move(in_gradient_delta);
}
void ForwardUpgrade::getAdjointModelOutput(
ModelOutputAdjoint<3> out_gradient_delta) {
out_gradient_delta.setRequestedIO(PREFERRED_FOURIER);
adjoint_upgrade(
get_box_model(), get_box_model_output(),
out_gradient_delta.getFourierOutput(), hold_adjoint.getFourierConst());
}
static std::shared_ptr<BORGForwardModel> build_upgrade(
MPI_Communication *comm, BoxModel const &box, PropertyProxy const &params) {
int multiplier = params.get<int>("multiplier");
if (multiplier <= 1) {
error_helper<ErrorParams>("Invalid multiplier, it is required to be > 1");
}
// TODO: Setup transfer function
auto model = std::make_shared<ForwardUpgrade>(comm, box, multiplier);
return model;
}
LIBLSS_REGISTER_FORWARD_IMPL(Upgrade, build_upgrade);

View file

@ -0,0 +1,65 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/forwards/upgrade.hpp
Copyright (C) 2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2020 Jens Jasche <jens.jasche@fysik.su.se>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#pragma once
#ifndef __LIBLSS_HADES_FORWARD_UPGRAADE_HPP
# define __LIBLSS_HADES_FORWARD_UPGRADE_HPP
# include "libLSS/physics/forward_model.hpp"
# include "libLSS/tools/fusewrapper.hpp"
# include "libLSS/tools/errors.hpp"
# include "libLSS/physics/forwards/registry.hpp"
# include "libLSS/tools/mpi/ghost_planes.hpp"
namespace LibLSS {
/**
* @brief Upgrade forward model element
*
* It pads the fourier representation of the input field with zeros, treating Nyquist plane correctly.
*/
class ForwardUpgrade : public BORGForwardModel {
protected:
ModelInput<3> hold_input;
ModelInputAdjoint<3> hold_adjoint;
GhostPlanes<std::complex<double>, 2> ghosts;
public:
ForwardUpgrade(
MPI_Communication *comm, BoxModel const &box, unsigned int multiply);
PreferredIO getPreferredInput() const override { return PREFERRED_FOURIER; }
PreferredIO getPreferredOutput() const override {
return PREFERRED_FOURIER;
}
bool densityInvalidated() const override { return false; }
void forwardModel_v2(ModelInput<3> delta_init) override;
void getDensityFinal(ModelOutput<3> delta_output) override;
void adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta) override;
void
getAdjointModelOutput(ModelOutputAdjoint<3> out_gradient_delta) override;
};
} // namespace LibLSS
LIBLSS_REGISTER_FORWARD_DECL(Upgrade);
// ARES TAG: num_authors = 2
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: year(0) = 2020
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: name(1) = Jens Jasche
// ARES TAG: year(1) = 2020
// ARES TAG: email(1) = jens.jasche@fysik.su.se
#endif

View file

@ -0,0 +1,191 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/haar.cpp
Copyright (C) 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 <string>
#include "libLSS/tools/console.hpp"
#include "libLSS/physics/model_io.hpp"
#include "libLSS/physics/haar.hpp"
#include "libLSS/tools/fusewrapper.hpp"
#include "libLSS/physics/forwards/registry.hpp"
#include "libLSS/tools/ptree_proxy.hpp"
using namespace LibLSS;
void ForwardHaar::forwardModel_v2(ModelInput<3> delta_init) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
// Setup the IO basis that is required for this forward.
delta_init.setRequestedIO(PREFERRED_REAL);
delta_init.needDestroyInput();
hold_input = std::move(delta_init);
}
template <typename ArrayIn, typename ArrayOut>
void ihaar_1d(ArrayIn &&in, ArrayOut &&out) {
int N = in.shape()[0];
int k = 1;
while (2 * k <= N) {
for (int i = 0; i < k; i++) {
double a = in[i], b = in[i + k];
out[2 * i] = (a + b) * M_SQRT1_2;
out[2 * i + 1] = (a - b) * M_SQRT1_2;
}
// The last one does not need anything
k = k * 2;
if (k < N)
for (int i = 0; i < (2 * k); i++)
in[i] = out[i];
}
}
template <typename ArrayIn, typename ArrayOut>
void haar_1d(ArrayIn &&in, ArrayOut &&out) {
int N = in.shape()[0];
int k = N;
while (k > 1) {
k = k / 2;
for (int i = 0; i < k; i++) {
double a = in[2 * i], b = in[2 * i + 1];
out[i] = (a + b) * M_SQRT1_2;
out[i + k] = (a - b) * M_SQRT1_2;
}
// The last one does not need anything
if (k > 1)
for (int i = 0; i < (2 * k); i++)
in[i] = out[i];
}
}
template <typename ArrayIn, typename ArrayOut>
void haar_3d(ArrayIn &&in, ArrayOut &&out) {
typedef decltype(out) Array;
typedef boost::multi_array_types::index_range range;
using boost::indices;
size_t N0 = in.shape()[0], N1 = in.shape()[1], N2 = in.shape()[2];
#pragma omp parallel for schedule(static) collapse(2)
for (int j = 0; j < N1; j++) {
for (int k = 0; k < N2; k++) {
auto sub_idx = indices[range()][j][k];
haar_1d(in[sub_idx], out[sub_idx]);
}
}
#pragma omp parallel for schedule(static) collapse(2)
for (int j = 0; j < N0; j++) {
for (int k = 0; k < N2; k++) {
auto sub_idx = indices[j][range()][k];
// THIS IS NOT A TYPO! out and in are reversed here.
haar_1d(out[sub_idx], in[sub_idx]);
}
}
#pragma omp parallel for schedule(static) collapse(2)
for (int j = 0; j < N0; j++) {
for (int k = 0; k < N1; k++) {
auto sub_idx = indices[j][k][range()];
haar_1d(in[sub_idx], out[sub_idx]);
}
}
}
template <typename ArrayIn, typename ArrayOut>
void ihaar_3d(ArrayIn &&in, ArrayOut &&out) {
typedef decltype(out) Array;
typedef boost::multi_array_types::index_range range;
using boost::indices;
size_t N0 = in.shape()[0], N1 = in.shape()[1], N2 = in.shape()[2];
#pragma omp parallel for schedule(static) collapse(2)
for (int j = 0; j < N0; j++) {
for (int k = 0; k < N1; k++) {
auto sub_idx = indices[j][k][range()];
ihaar_1d(in[sub_idx], out[sub_idx]);
}
}
#pragma omp parallel for schedule(static) collapse(2)
for (int j = 0; j < N0; j++) {
for (int k = 0; k < N2; k++) {
auto sub_idx = indices[j][range()][k];
// THIS IS NOT A TYPO! out and in are reversed here.
ihaar_1d(out[sub_idx], in[sub_idx]);
}
}
#pragma omp parallel for schedule(static) collapse(2)
for (int j = 0; j < N1; j++) {
for (int k = 0; k < N2; k++) {
auto sub_idx = indices[range()][j][k];
ihaar_1d(in[sub_idx], out[sub_idx]);
}
}
}
void ForwardHaar::getDensityFinal(ModelOutput<3> delta_output) {
delta_output.setRequestedIO(PREFERRED_REAL);
size_t N2 = lo_mgr->N2;
typedef boost::multi_array_types::index_range range;
auto sub_array = boost::indices[range()][range()][range(0, N2)];
auto &out = delta_output.getRealOutput();
auto &in = hold_input.getReal();
if (do_inverse)
ihaar_3d(in[sub_array], out[sub_array]);
else
haar_3d(in[sub_array], out[sub_array]);
}
void ForwardHaar::adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
in_gradient_delta.setRequestedIO(PREFERRED_REAL);
in_gradient_delta.needDestroyInput();
hold_ag_input = std::move(in_gradient_delta);
}
void ForwardHaar::getAdjointModelOutput(
ModelOutputAdjoint<3> out_gradient_delta) {
out_gradient_delta.setRequestedIO(PREFERRED_REAL);
size_t N2 = lo_mgr->N2;
typedef boost::multi_array_types::index_range range;
auto sub_array = boost::indices[range()][range()][range(0, N2)];
auto &in = hold_ag_input.getReal();
auto &out = out_gradient_delta.getRealOutput();
// Haar transpose is its inverse.
if (do_inverse)
haar_3d(in[sub_array], out[sub_array]);
else
ihaar_3d(in[sub_array], out[sub_array]);
}
static std::shared_ptr<BORGForwardModel> build_haar(
MPI_Communication *comm, BoxModel const &box, PropertyProxy const &params) {
bool use_inverse = params.get("inverse", false);
return std::make_shared<ForwardHaar>(comm, box, use_inverse);
}
LIBLSS_REGISTER_FORWARD_IMPL(Haar, build_haar);
// ARES TAG: num_authors = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: year(0) = 2020
// ARES TAG: email(0) = guilhem.lavaux@iap.fr

View file

@ -0,0 +1,65 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/haar.hpp
Copyright (C) 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)
+*/
#pragma once
#ifndef __LIBLSS_HADES_FORWARD_HAAR_HPP
# define __LIBLSS_HADES_FORWARD_HAAR_HPP
# pragma once
# include "libLSS/physics/forward_model.hpp"
# include "libLSS/tools/fusewrapper.hpp"
# include "libLSS/tools/errors.hpp"
# include "libLSS/physics/forwards/registry.hpp"
namespace LibLSS {
/**
* This class handles the convolution of a real field by some Fourier kernel.
*/
class ForwardHaar : public BORGForwardModel {
protected:
bool do_inverse;
ModelInput<3> hold_input;
ModelInputAdjoint<3> hold_ag_input;
public:
/**
* Constructor.
*/
explicit ForwardHaar(
MPI_Communication *comm, const BoxModel &box, bool inverse = false)
: BORGForwardModel(comm, box), do_inverse(inverse) {
if (comm->size() > 1) {
error_helper<ErrorParams>(
"MPI is not supported. Comm size must be equal to one.");
}
ensureInputEqualOutput();
}
virtual PreferredIO getPreferredInput() const { return PREFERRED_REAL; }
virtual PreferredIO getPreferredOutput() const { return PREFERRED_REAL; }
virtual void forwardModel_v2(ModelInput<3> delta_init);
virtual void getDensityFinal(ModelOutput<3> delta_output);
virtual void adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta);
virtual void
getAdjointModelOutput(ModelOutputAdjoint<3> out_gradient_delta);
}; // namespace LibLSS
} // namespace LibLSS
LIBLSS_REGISTER_FORWARD_DECL(Haar);
#endif
// ARES TAG: num_authors = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: year(0) = 2020
// ARES TAG: email(0) = guilhem.lavaux@iap.fr

View file

@ -0,0 +1,138 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/hades_log.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/physics/forward_model.hpp"
#include "libLSS/tools/fusewrapper.hpp"
#include "libLSS/tools/errors.hpp"
#include "libLSS/physics/hades_log.hpp"
using namespace LibLSS;
HadesLog::HadesLog(
MPI_Communication *comm, const BoxModel &box, double ai_,
bool shifted_mean_)
: BORGForwardModel(comm, box), ai(ai_), D_init(1.0),
shifted_mean(shifted_mean_) {
setupDefault();
}
void HadesLog::forwardModelSimple(CArrayRef &delta_init) {
error_helper<ErrorNotImplemented>(
"No forwardModelSimple in Log forward model");
}
void HadesLog::clearAdjointGradient() { hold_in_gradient.clear(); }
void HadesLog::forwardModel_v2(ModelInput<3> delta_init) {
ConsoleContext<LOG_DEBUG> ctx("forward Hades Log");
delta_init.setRequestedIO(PREFERRED_REAL);
double G = 1; // Growth TBI
// Only bother of real values (no padding)
auto strict_field = delta_init.getRealConst()[lo_mgr->strict_range()];
// First part of the forward model, exponentiation and rescaling
auto fdelta = std::exp((G / D_init) * fwrap(strict_field));
// Compute mean and save it for later
if (shifted_mean) {
rho_mean = fdelta.sum() / (N0 * N1 * N2);
comm->all_reduce_t(MPI_IN_PLACE, &rho_mean, 1, MPI_SUM);
fwrap(tmp_real_field->get_array()[lo_mgr->strict_range()]) =
fdelta / rho_mean - 1;
} else
fwrap(tmp_real_field->get_array()[lo_mgr->strict_range()]) = fdelta;
}
void HadesLog::getDensityFinal(ModelOutput<3> delta_output) {
delta_output.setRequestedIO(PREFERRED_REAL);
// Compute zero mean density.
fwrap(delta_output.getRealOutput()[lo_mgr->strict_range()]) =
fwrap(tmp_real_field->get_array()[lo_mgr->strict_range()]);
}
void HadesLog::updateCosmo() {
ConsoleContext<LOG_DEBUG> ctx("Hades Log cosmo update");
if (old_params != cosmo_params) {
Cosmology cosmo(cosmo_params);
D_init = cosmo.d_plus(ai) /
cosmo.d_plus(1.0); // Scale factor for initial conditions
old_params = cosmo_params;
}
}
void HadesLog::forwardModelRsdField(ArrayRef &deltaf, double *vobs_ext) {
error_helper<ErrorNotImplemented>("No RSD support in Log forward model");
}
void HadesLog::adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta) {
ConsoleContext<LOG_DEBUG> ctx("adjoint Hades Log");
// Build strict range views (we do not want to see the
// the FFTW padding, ensure that the view object lives till the end of this function.
in_gradient_delta.setRequestedIO(PREFERRED_REAL);
auto in_gradient_view =
in_gradient_delta.getRealConst()[lo_mgr->strict_range()];
auto input_view = tmp_real_field->get_array()[lo_mgr->strict_range()];
// Wrap for automated vectorization.
auto w_gradient = fwrap(in_gradient_view);
double G = 1.0;
// Recompute forward transforms
if (shifted_mean) {
auto fdelta = (fwrap(input_view) + 1) * rho_mean;
// Gradient of the denominator
A_mean = (w_gradient * fdelta).sum() / rho_mean / (N0 * N1 * N2);
comm->all_reduce_t(MPI_IN_PLACE, &A_mean, 1, MPI_SUM);
ctx.format(
"D_init = %g, A_mean = %g, rho_mean = %g", D_init, A_mean, rho_mean);
}
hold_in_gradient = std::move(in_gradient_delta);
}
void HadesLog::getAdjointModelOutput(ModelOutputAdjoint<3> ag_delta_output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
ag_delta_output.setRequestedIO(PREFERRED_REAL);
auto in_gradient_view =
hold_in_gradient.getRealConst()[lo_mgr->strict_range()];
auto out_gradient_view =
ag_delta_output.getRealOutput()[lo_mgr->strict_range()];
auto input_view = tmp_real_field->get_array()[lo_mgr->strict_range()];
// Wrap for automated vectorization.
double G = 1.0;
auto w_gradient = fwrap(in_gradient_view);
if (shifted_mean) {
auto fdelta = (fwrap(input_view) + 1) * rho_mean;
// Complete gradient of numerator and denominator
fwrap(out_gradient_view) =
(w_gradient - A_mean) * fdelta * (G / (D_init * rho_mean));
} else {
auto fdelta = (fwrap(input_view));
// Complete gradient of numerator and denominator
fwrap(out_gradient_view) = (w_gradient)*fdelta * (G / D_init);
}
}
void HadesLog::releaseParticles() {}
static std::shared_ptr<BORGForwardModel> build_hades_log(
MPI_Communication *comm, BoxModel const &box, PropertyProxy const &params) {
double ai = params.get<double>("a_initial");
return std::make_shared<HadesLog>(comm, box, ai);
}
LIBLSS_REGISTER_FORWARD_IMPL(HADES_LOG, build_hades_log);

View file

@ -0,0 +1,56 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/hades_log.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_HADES_LOG_FORWARD_MODEL_HPP
#define __LIBLSS_HADES_LOG_FORWARD_MODEL_HPP
#pragma once
#include "libLSS/physics/forward_model.hpp"
#include "libLSS/tools/fusewrapper.hpp"
#include "libLSS/tools/errors.hpp"
#include "libLSS/physics/forwards/registry.hpp"
namespace LibLSS {
class HadesLog : public BORGForwardModel {
protected:
double ai, D_init;
double rho_mean, A_mean;
ModelInputAdjoint<3> hold_in_gradient;
CosmologicalParameters old_params;
bool shifted_mean;
public:
explicit HadesLog(
MPI_Communication *comm, const BoxModel &box,
double ai_, bool shifted_mean_ = true);
virtual void forwardModelSimple(CArrayRef &delta_init);
virtual void forwardModel_v2(ModelInput<3> delta_init);
virtual void getDensityFinal(ModelOutput<3> delta_output);
virtual void updateCosmo();
virtual void forwardModelRsdField(ArrayRef &deltaf, double *vobs_ext);
virtual void adjointModel_v2(ModelInputAdjoint<3> in_gradient_delta);
virtual void getAdjointModelOutput(ModelOutputAdjoint<3> ag_delta_output);
virtual void clearAdjointGradient();
virtual void releaseParticles();
};
} // namespace LibLSS
LIBLSS_REGISTER_FORWARD_DECL(HADES_LOG);
#endif

View file

@ -0,0 +1,150 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/hades_pt.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/physics/forward_model.hpp"
#include "libLSS/tools/fusewrapper.hpp"
#include "libLSS/tools/errors.hpp"
#include "libLSS/physics/hades_pt.hpp"
#include "libLSS/physics/forwards/registry.hpp"
using namespace LibLSS;
HadesLinear::HadesLinear(
MPI_Communication *comm, const BoxModel &box, const BoxModel &box_out,
double ai_, double af_)
: BORGForwardModel(comm, box, box_out), ai(ai_), af(af_), D_init(0) {
ensureInputEqualOutput();
setupDefault();
}
void HadesLinear::forwardModelSimple(CArrayRef &delta_init) {
error_helper<ErrorNotImplemented>(
"No forwardModelSimple in Linear forward model");
}
PreferredIO HadesLinear::getPreferredInput() const { return PREFERRED_NONE; }
PreferredIO HadesLinear::getPreferredOutput() const { return PREFERRED_NONE; }
void HadesLinear::forwardModel_v2(ModelInput<3> delta_init) {
LIBLSS_AUTO_DEBUG_CONTEXT2(ctx, "HadesLinear::forwardModel_v2");
double G = 1; // Growth TBI
// Only bother of real values (no padding)
ctx.print(boost::format("D_init=%g") % D_init);
// Compute zero mean density.
PreferredIO choice = delta_init.current;
delta_init.setRequestedIO(choice);
switch (choice) {
case PREFERRED_REAL: {
auto strict_field = tmp_real_field->get_array()[lo_mgr->strict_range()];
fwrap(strict_field) = fwrap(delta_init.getRealConst()[lo_mgr->strict_range()]) / D_init;
break;
}
case PREFERRED_FOURIER: {
auto &strict_field = tmp_complex_field->get_array();
fwrap(strict_field) = fwrap(delta_init.getFourierConst()) / D_init;
break;
}
default:
error_helper<ErrorNotImplemented>("Invalid IO");
}
lastInput = currentOutput = choice;
}
void HadesLinear::getDensityFinal(ModelOutput<3> delta_output) {
delta_output.setRequestedIO(currentOutput);
switch (currentOutput) {
case PREFERRED_REAL:
fwrap(delta_output.getRealOutput()) = tmp_real_field->get_array();
break;
case PREFERRED_FOURIER:
fwrap(delta_output.getFourierOutput()) = tmp_complex_field->get_array();
break;
default:
error_helper<ErrorNotImplemented>("Invalid IO");
break;
}
}
void HadesLinear::updateCosmo() {
ConsoleContext<LOG_DEBUG> ctx("HadesLinear::updateCosmo");
Cosmology cosmo(cosmo_params);
D_init = cosmo.d_plus(ai) /
cosmo.d_plus(af); // Scale factor for initial conditions
}
void HadesLinear::forwardModelRsdField(ArrayRef &deltaf, double *vobs_ext) {
error_helper<ErrorNotImplemented>("No RSD support in Linear forward model");
}
void HadesLinear::adjointModel_v2(ModelInputAdjoint<3> ag_delta_input) {
ConsoleContext<LOG_DEBUG> ctx("HadesLinear::adjointModel_v2");
ag_delta_input.setRequestedIO(currentOutput);
// Compute zero mean density.
switch (currentOutput) {
case PREFERRED_REAL: {
auto strict_field = tmp_real_field->get_array()[lo_mgr->strict_range()];
fwrap(strict_field) =
fwrap(ag_delta_input.getRealConst()[lo_mgr->strict_range()]) / D_init;
break;
}
case PREFERRED_FOURIER: {
auto &strict_field = tmp_complex_field->get_array();
fwrap(strict_field) = fwrap(ag_delta_input.getFourierConst()) / D_init;
break;
}
default:
error_helper<ErrorNotImplemented>("Invalid IO");
}
}
void HadesLinear::getAdjointModelOutput(ModelOutputAdjoint<3> ag_delta_output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
//if (lastInput != ag_delta_output.current) {
// error_helper<ErrorBadState>(
// "The forward and adjoint gradient pipeline is inconsistent.");
//}
ag_delta_output.setRequestedIO(currentOutput);
switch (currentOutput) {
case PREFERRED_REAL: {
auto strict_field = tmp_real_field->get_array()[lo_mgr->strict_range()];
auto w_gradient2 =
fwrap(ag_delta_output.getRealOutput()[lo_mgr->strict_range()]);
w_gradient2 = strict_field;
break;
}
case PREFERRED_FOURIER: {
auto strict_field = tmp_complex_field->get_array();
auto w_gradient2 = fwrap(ag_delta_output.getFourierOutput());
w_gradient2 = strict_field;
break;
}
default:
error_helper<ErrorNotImplemented>("Invalid IO");
}
}
void HadesLinear::releaseParticles() {}
static std::shared_ptr<BORGForwardModel> build_hades_linear(
MPI_Communication *comm, BoxModel const &box, PropertyProxy const &params) {
double ai = params.get<double>("a_initial");
double af = params.get<double>("a_final");
return std::make_shared<HadesLinear>(comm, box, box, ai, af);
}
LIBLSS_REGISTER_FORWARD_IMPL(HADES_PT, build_hades_linear);

View file

@ -0,0 +1,68 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/hades_pt.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_HADES_LINEAR_FORWARD_MODEL_HPP
#define __LIBLSS_HADES_LINEAR_FORWARD_MODEL_HPP
#include "libLSS/physics/forward_model.hpp"
#include "libLSS/tools/fusewrapper.hpp"
#include "libLSS/tools/errors.hpp"
#include "libLSS/physics/forwards/registry.hpp"
namespace LibLSS {
/**
* This is the example class to implement the linear gravity model (also
* known as PT model). It only really do two things: a fast fourier transform
* and a scaling by the linear growth function.
*/
class HadesLinear : public BORGForwardModel {
protected:
double ai, af, D_init;
PreferredIO currentOutput, lastInput;
public:
/**
* Consruct a new object.
* @param comm an MPI communicator
* @param box the box describing the input physical grid
* @param box_out the box describing the output physical grid (at the moment
* box == box_out is required)
* @param ai the universe scale factor at which the initial conditions
* are provided.
*/
explicit HadesLinear(
MPI_Communication *comm, const BoxModel &box, const BoxModel &box_out,
double ai_, double af_);
virtual void forwardModelSimple(CArrayRef &delta_init);
virtual PreferredIO getPreferredInput() const;
virtual PreferredIO getPreferredOutput() const;
virtual void forwardModel_v2(ModelInput<3> delta_init);
virtual void getDensityFinal(ModelOutput<3> delta_output);
virtual void updateCosmo();
virtual void forwardModelRsdField(ArrayRef &deltaf, double *vobs_ext);
virtual void adjointModel_v2(ModelInputAdjoint<3> ag_delta_input);
virtual void getAdjointModelOutput(ModelOutputAdjoint<3> ag_delta_output);
virtual void releaseParticles();
};
} // namespace LibLSS
LIBLSS_REGISTER_FORWARD_DECL(HADES_PT);
#endif

View file

@ -0,0 +1,70 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/hermitic.hpp
Copyright (C) 2014-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#ifndef __LIBLSS_PHYSICS_HERMITIC_HPP
# define __LIBLSS_PHYSICS_HERMITIC_HPP
# include "libLSS/tools/errors.hpp"
# include "libLSS/physics/forward_model.hpp"
# include "libLSS/physics/forwards/registry.hpp"
# include "libLSS/tools/fusewrapper.hpp"
# include "libLSS/tools/hermiticity_fixup.hpp"
namespace LibLSS {
class ForwardHermiticOperation : public BORGForwardModel {
protected:
Hermiticity_fixer<double, 3> fixer;
ModelInput<3> hold_input;
ModelInputAdjoint<3> hold_ag_input;
public:
explicit ForwardHermiticOperation(
MPI_Communication *comm, const BoxModel &box)
: BORGForwardModel(comm, box), fixer(lo_mgr) {}
virtual PreferredIO getPreferredInput() const { return PREFERRED_FOURIER; }
virtual PreferredIO getPreferredOutput() const { return PREFERRED_FOURIER; }
virtual void forwardModel_v2(ModelInput<3> input) {
input.setRequestedIO(PREFERRED_FOURIER);
hold_input = std::move(input);
}
virtual void getDensityFinal(ModelOutput<3> output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
output.setRequestedIO(PREFERRED_FOURIER);
fwrap(output.getFourierOutput()) = fwrap(hold_input.getFourierConst());
fixer.forward(output.getFourierOutput());
}
virtual void clearAdjointGradient() {
hold_input.clear();
hold_ag_input.clear();
}
virtual void adjointModel_v2(ModelInputAdjoint<3> ag_input) {
ag_input.setRequestedIO(PREFERRED_FOURIER);
hold_ag_input = std::move(ag_input);
}
virtual void getAdjointModelOutput(ModelOutputAdjoint<3> ag_output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
ag_output.setRequestedIO(PREFERRED_FOURIER);
fwrap(ag_output.getFourierOutput()) = hold_ag_input.getFourierConst();
fixer.adjoint(ag_output.getFourierOutput());
}
};
} // namespace LibLSS
#endif
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2014-2020

View file

@ -0,0 +1,21 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/likelihoods/base.cpp
Copyright (C) 2018 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#include "libLSS/physics/likelihoods/base.hpp"
namespace LibLSS {
namespace Likelihood {
const std::string MPI = "MPI", COLOR_MAP = "COLOR_MAP", GRID = "GRID",
MPI_GRID = "MPI_GRID", GRID_LENGTH = "GRID_LENGTH", DATA_GRID = "DATA_GRID";
}
} // namespace LibLSS
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2018

View file

@ -0,0 +1,114 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/likelihoods/base.hpp
Copyright (C) 2018 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#ifndef __LIBLSS_BORG_LIKELIHOODS_BASE_HPP
# define __LIBLSS_BORG_LIKELIHOODS_BASE_HPP
# include <string>
# include <boost/any.hpp>
# include <map>
# include <memory>
# include <array>
# include "libLSS/mpi/generic_mpi.hpp"
# include "libLSS/tools/defer.hpp"
# include "libLSS/tools/errors.hpp"
namespace LibLSS {
typedef std::map<std::string, boost::any> LikelihoodInfo;
namespace Likelihood {
typedef boost::multi_array<size_t, 1> GridSize;
typedef boost::multi_array<double, 1> GridLengths;
extern std::string const MPI, COLOR_MAP, DATA_GRID, GRID, MPI_GRID,
GRID_LENGTH;
template <typename T>
T query(LikelihoodInfo const &info, std::string const &key) {
auto i = info.find(key);
if (i == info.end()) {
error_helper<ErrorBadState>("No key " + key + " in info dictionnary");
}
try {
return boost::any_cast<T>(i->second);
} catch (boost::bad_any_cast& e) {
error_helper<ErrorBadState>("Type incompatible in any_cast (stored=" + std::string(i->second.type().name()) + "), requested=" + std::string(typeid(T).name()));
}
}
template <typename T>
T query_default(LikelihoodInfo const &info, std::string const &key, T const& default_value) {
auto i = info.find(key);
if (i == info.end()) {
return default_value;
}
try {
return boost::any_cast<T>(i->second);
} catch (boost::bad_any_cast& e) {
error_helper<ErrorBadState>("Type incompatible in any_cast (stored=" + std::string(i->second.type().name()) + "), requested=" + std::string(typeid(T).name()));
}
}
inline MPI_Communication *getMPI(LikelihoodInfo const &info) {
return query<MPI_Communication *>(info, MPI);
}
template <typename T, int N>
auto getArray(LikelihoodInfo const &info, std::string const &key) {
return query<std::shared_ptr<boost::multi_array_ref<T, N>>>(info, key);
}
template <typename T, int N>
auto getPromisedArray(LikelihoodInfo const &info, std::string const &key) {
return query<PromisePointer<boost::multi_array_ref<T, N>>>(info, key);
}
template <size_t N, size_t start, size_t skip, typename T>
auto multi_array_to_std(boost::multi_array_ref<T, 1> const &a) {
std::array<T, N> b;
for (size_t i = 0, j = start; i < N; i++, j += skip)
b[i] = a[j];
return b;
}
template <typename T, size_t N>
auto diff_array(std::array<T, N> const &a, std::array<T, N> const &b) {
std::array<T, N> c;
for (size_t i = 0; i < N; i++)
c[i] = a[i] - b[i];
return c;
}
inline auto gridResolution(LikelihoodInfo const &info) {
return multi_array_to_std<3, 0, 1>(query<GridSize>(info, GRID));
}
inline auto gridSide(LikelihoodInfo const &info) {
auto sides = query<GridLengths>(info, GRID_LENGTH);
auto a0 = multi_array_to_std<3, 0, 2>(sides);
auto a1 = multi_array_to_std<3, 1, 2>(sides);
return diff_array(a1, a0);
}
inline auto gridCorners(LikelihoodInfo const &info) {
return multi_array_to_std<3, 0, 2>(query<GridLengths>(info, GRID_LENGTH));
}
} // namespace Likelihood
} // namespace LibLSS
#endif
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2018

View file

@ -0,0 +1,371 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/model_io.cpp
Copyright (C) 2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#include <boost/variant.hpp>
#include <memory>
#include "libLSS/tools/fusewrapper.hpp"
#include "libLSS/physics/model_io.hpp"
#include "libLSS/tools/overload.hpp"
using namespace LibLSS;
using boost::multi_array_types::index_range;
template <size_t Nd, typename Super>
void LibLSS::ModelInputBase<Nd, Super>::setRequestedIO(PreferredIO opt) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
Console::instance().c_assert(
!this->uninitialized, "Model must be initialized");
this->active = opt;
if (opt == this->current)
return;
switch (opt) {
case PREFERRED_FOURIER:
transformInputRealToFourier();
break;
case PREFERRED_REAL:
transformInputFourierToReal();
break;
default:
Console::instance().c_assert(false, "Invalid IO");
break;
}
this->ioIsTransformed = true;
}
template <size_t Nd, typename Super>
void ModelInputBase<Nd, Super>::needDestroyInput() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
typedef typename ModelIO<Nd>::HolderType HolderType;
this->holder = boost::apply_visitor(
overload(
[&ctx](auto *v) {
ctx.print("Pass through");
return HolderType(v);
},
[&](CArrayRef const *v) {
ctx.print("Protect complex");
auto p = this->mgr->allocate_ptr_complex_array();
fwrap(*p) = fwrap(*v);
auto h = HolderType(&p->get_array());
this->hold_original = std::move(p);
return h;
},
[&](ArrayRef const *v) {
ctx.print("Protect real");
auto p = this->mgr->allocate_ptr_array();
fwrap(*p) = fwrap(*v);
auto h = HolderType(&p->get_array());
this->hold_original = std::move(p);
return h;
}),
this->holder);
}
template <size_t Nd, typename Super>
void ModelInputBase<Nd, Super>::transformInputRealToFourier() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
Console::instance().c_assert(
!this->uninitialized, "Model must be initialized");
if (!this->tmp_fourier) {
this->tmp_fourier = this->mgr->allocate_ptr_complex_array();
}
auto volatile_real = this->mgr->allocate_array();
auto plan = this->mgr->create_r2c_plan(
volatile_real.get_array().data(), this->tmp_fourier->get_array().data());
needDestroyInput();
try {
this->mgr->execute_r2c(
plan, boost::get<ArrayRef *>(this->holder)->data(),
this->tmp_fourier->get_array().data());
} catch (boost::bad_get const &e) {
error_helper<ErrorBadState>(
"Runtime error thrown: " + std::string(e.what()));
}
this->mgr->destroy_plan(plan);
if (scaler != 1) {
ctx.format(" -> Scaler %g", scaler);
auto w_c = fwrap(this->tmp_fourier->get_array());
w_c = w_c * scaler;
}
//this->hermitic_fixer(this->tmp_fourier->get_array());
}
template <size_t Nd, typename Super>
void ModelInputBase<Nd, Super>::transformInputFourierToReal() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
Console::instance().c_assert(
!this->uninitialized, "Model must be initialized");
if (!this->tmp_real) {
this->tmp_real = this->mgr->allocate_ptr_array();
}
auto volatile_fourier = this->mgr->allocate_complex_array();
auto plan = this->mgr->create_c2r_plan(
volatile_fourier.get_array().data(), this->tmp_real->get_array().data());
needDestroyInput();
try {
this->mgr->execute_c2r(
plan, boost::get<CArrayRef *>(this->holder)->data(),
this->tmp_real->get_array().data());
} catch (boost::bad_get const &e) {
error_helper<ErrorBadState>(
"Runtime error thrown: " + std::string(e.what()));
}
this->mgr->destroy_plan(plan);
if (scaler != 1) {
ctx.format(" -> Scaler %g", scaler);
auto w_r = fwrap(this->tmp_real->get_array());
w_r = w_r * scaler;
}
}
template <size_t Nd, typename Super>
void ModelOutputBase<Nd, Super>::transformOutputFourierToReal() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
Console::instance().c_assert(
!this->uninitialized, "Model must be initialized");
auto volatile_fourier = this->mgr->allocate_ptr_complex_array();
try {
auto &array = *boost::get<ArrayRef *>(this->holder);
auto plan = this->mgr->create_c2r_plan(
volatile_fourier->get_array().data(), array.data());
this->mgr->execute_c2r(
plan, this->tmp_fourier->get_array().data(), array.data());
this->mgr->destroy_plan(plan);
if (scaler != 1) {
ctx.format(" -> Scaler %g", scaler);
auto w_h = fwrap(array);
w_h = w_h * scaler;
}
} catch (boost::bad_get const &e) {
error_helper<ErrorBadState>(
"Runtime error thrown: " + std::string(e.what()));
}
}
template <size_t Nd, typename Super>
void ModelOutputBase<Nd, Super>::transformOutputRealToFourier() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
Console::instance().c_assert(
!this->uninitialized, "Model must be initialized");
auto volatile_real = this->mgr->allocate_ptr_array();
try {
auto &c_array = *boost::get<CArrayRef *>(this->holder);
auto plan = this->mgr->create_r2c_plan(
volatile_real->get_array().data(), c_array.data());
this->mgr->execute_r2c(
plan, this->tmp_real->get_array().data(), c_array.data());
this->mgr->destroy_plan(plan);
if (scaler != 1) {
ctx.format(" -> Scaler %g", scaler);
auto w_ch = fwrap(c_array);
w_ch = w_ch * scaler;
}
} catch (boost::bad_get const &e) {
error_helper<ErrorBadState>(
"Runtime error thrown: " + std::string(e.what()));
}
}
template <size_t Nd, typename Super>
void ModelOutputBase<Nd, Super>::triggerTransform() {
if (this->alreadyTransformed || this->uninitialized)
return;
if (this->ioIsTransformed) {
switch (this->current) {
case PREFERRED_FOURIER:
transformOutputRealToFourier();
break;
case PREFERRED_REAL:
transformOutputFourierToReal();
break;
default:
Console::instance().c_assert(false, "Invalid IO");
break;
}
}
alreadyTransformed = true;
}
template <size_t Nd, typename Super>
ModelOutputBase<Nd, Super>::~ModelOutputBase() {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
triggerTransform();
}
template <size_t Nd, typename Super>
void ModelOutputBase<Nd, Super>::setRequestedIO(PreferredIO opt) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
Console::instance().c_assert(
!this->uninitialized, "Model must be initialized");
this->active = opt;
if (opt == this->current)
return;
Console::instance().c_assert(
!this->ioIsTransformed, "Transformation already requested.");
switch (this->current) {
case PREFERRED_FOURIER:
// then opt is REAL
ctx.print("Want real ");
this->tmp_real = this->mgr->allocate_ptr_array();
break;
case PREFERRED_REAL:
ctx.print("Want fourier");
this->tmp_fourier = this->mgr->allocate_ptr_complex_array();
break;
default:
Console::instance().c_assert(false, "Invalid IO");
break;
}
this->ioIsTransformed = true;
}
template <size_t Nd, typename Super>
void ModelOutputBase<Nd, Super>::copyFrom(ModelOutputBase<Nd, Super> &other) {
Console::instance().c_assert(
!this->uninitialized, "Model must be initialized");
//other.triggerTransform();
Console::instance().c_assert(
this->active == other.active,
"this->active and other.active are different");
switch (other.active) {
case PREFERRED_FOURIER:
fwrap(this->getFourierOutput()) = other.getFourierOutput();
break;
case PREFERRED_REAL:
fwrap(this->getRealOutput()) = other.getRealOutput();
break;
default:
Console::instance().c_assert(false, "Invalid IO");
break;
}
}
template <size_t Nd, typename Super>
ModelInput<Nd> ModelInput<Nd, Super>::shallowClone() {
return boost::apply_visitor(
[this](auto const *v) {
return ModelInput<Nd>(
this->mgr, this->box, *v, this->hold_original, true, this->scaler);
},
this->holder);
}
template <size_t Nd, typename Super>
ModelInputAdjoint<Nd> ModelInputAdjoint<Nd, Super>::shallowClone() {
return boost::apply_visitor(
[this](auto const *v) {
return ModelInputAdjoint<Nd>(
this->mgr, this->box, *v, this->hold_original, true, this->scaler);
},
this->holder);
}
template <size_t Nd, typename Super>
ModelOutput<Nd> ModelOutput<Nd, Super>::shallowClone() {
return boost::apply_visitor(
overload(
[this](auto const *v) {
error_helper<ErrorBadState>("Output cannot be const");
return ModelOutput<Nd>();
},
[this](auto *v) {
return ModelOutput<Nd>(
this->mgr, this->box, *v, this->hold_original);
}),
this->holder);
}
template <size_t Nd, typename Super>
ModelOutputAdjoint<Nd> ModelOutputAdjoint<Nd, Super>::shallowClone() {
return boost::apply_visitor(
overload(
[this](auto const *v) {
error_helper<ErrorBadState>("Output cannot be const");
return ModelOutputAdjoint<Nd>();
},
[this](auto *v) {
return ModelOutputAdjoint<Nd>(
this->mgr, this->box, *v, this->hold_original);
}),
this->holder);
}
template <size_t Nd, typename Super>
ModelOutput<Nd> ModelOutput<Nd, Super>::makeTempLike() {
return boost::apply_visitor(
overload(
[this](CArrayRef const *v) {
auto tmp_p = this->mgr->allocate_ptr_complex_array();
auto &tmp = tmp_p->get_array();
return ModelOutput<Nd>(this->mgr, this->box, tmp, std::move(tmp_p));
},
[this](ArrayRef const *v) {
auto tmp_p = this->mgr->allocate_ptr_array();
auto &tmp = tmp_p->get_array();
return ModelOutput<Nd>(this->mgr, this->box, tmp, std::move(tmp_p));
}),
this->holder);
}
template <size_t Nd, typename Super>
ModelOutputAdjoint<Nd> ModelOutputAdjoint<Nd, Super>::makeTempLike() {
return boost::apply_visitor(
overload(
[this](CArrayRef const *v) {
auto tmp_p = this->mgr->allocate_ptr_complex_array();
auto &tmp = tmp_p->get_array();
return ModelOutputAdjoint<Nd>(
this->mgr, this->box, tmp, std::move(tmp_p));
},
[this](ArrayRef const *v) {
auto tmp_p = this->mgr->allocate_ptr_array();
auto &tmp = tmp_p->get_array();
return ModelOutputAdjoint<Nd>(
this->mgr, this->box, tmp, std::move(tmp_p));
}),
this->holder);
}
#define FORCE_IO_SET(q) \
template class LibLSS::detail_input::ModelInputBase<q>; \
template class LibLSS::detail_output::ModelOutputBase<q>; \
template class LibLSS::detail_input::ModelInput<q>; \
template class LibLSS::detail_input::ModelInputAdjoint<q>; \
template class LibLSS::detail_output::ModelOutput<q>; \
template class LibLSS::detail_output::ModelOutputAdjoint<q>;
// 2d does not work yet because of FFTW_Manager
//FORCE_IO_SET(2);
FORCE_IO_SET(3);
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2020

View file

@ -0,0 +1,41 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/model_io.hpp
Copyright (C) 2019-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#pragma once
#ifndef __LIBLSS_PHYSICS_MODELIO_HPP
# define __LIBLSS_PHYSICS_MODELIO_HPP
# include <memory>
# include "libLSS/physics/cosmo.hpp"
# include "libLSS/mpi/generic_mpi.hpp"
# include "libLSS/tools/mpi_fftw_helper.hpp"
# include "libLSS/tools/errors.hpp"
# include "libLSS/samplers/core/types_samplers.hpp"
# include <boost/variant.hpp>
# include "libLSS/physics/model_io/box.hpp"
# include "libLSS/physics/model_io/base.hpp"
# include "libLSS/physics/model_io/input.hpp"
# include "libLSS/physics/model_io/output.hpp"
namespace LibLSS {
using detail_input::ModelInput;
using detail_input::ModelInputAdjoint;
using detail_input::ModelInputBase;
using detail_output::ModelOutput;
using detail_output::ModelOutputAdjoint;
using detail_output::ModelOutputBase;
} // namespace LibLSS
#endif
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2019-2020

View file

@ -0,0 +1,173 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/model_io/base.hpp
Copyright (C) 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)
+*/
#pragma once
#ifndef __LIBLSS_PHYSICS_MODELIO_BASE_HPP
# define __LIBLSS_PHYSICS_MODELIO_BASE_HPP
# include "libLSS/samplers/core/types_samplers.hpp"
namespace LibLSS {
enum PreferredIO { PREFERRED_NONE, PREFERRED_FOURIER, PREFERRED_REAL };
namespace detail_model {
template <typename T>
struct _getPreferredType {};
template <>
struct _getPreferredType<CArrayType::RefArrayType> {
constexpr static const auto value = PREFERRED_FOURIER;
};
template <>
struct _getPreferredType<CArrayType::ArrayType> {
constexpr static const auto value = PREFERRED_FOURIER;
};
template <>
struct _getPreferredType<ArrayType::RefArrayType> {
constexpr static const auto value = PREFERRED_REAL;
};
template <>
struct _getPreferredType<ArrayType::ArrayType> {
constexpr static const auto value = PREFERRED_REAL;
};
template <typename T>
using getPreferredType = _getPreferredType<std::remove_cv_t<T>>;
/**
* @brief Holder to capture different basis of representation of BORG vectors
*/
template <size_t Nd>
struct ModelIO {
protected:
public:
enum { Ndims = Nd };
typedef ArrayType::ArrayType Array;
typedef ArrayType::RefArrayType ArrayRef;
typedef CArrayType::ArrayType CArray;
typedef CArrayType::RefArrayType CArrayRef;
typedef NBoxModel<Nd> BoxModelIO;
typedef std::shared_ptr<void> Holder;
typedef FFTW_Manager<double, Nd> Mgr;
typedef std::shared_ptr<Mgr> Mgr_p;
typedef boost::variant<
CArrayRef *, CArrayRef const *, ArrayRef *, ArrayRef const *>
HolderType;
Mgr_p mgr;
BoxModelIO box;
PreferredIO current, active;
HolderType holder;
enum Direction { INPUT, OUTPUT };
typedef typename Mgr::U_ArrayReal U_ArrayReal;
typedef typename Mgr::U_ArrayFourier U_ArrayFourier;
std::unique_ptr<U_ArrayReal> tmp_real;
std::unique_ptr<U_ArrayFourier> tmp_fourier;
Direction direction;
bool ioIsTransformed;
bool uninitialized;
Holder hold_original;
/**
* @brief Construct a new uninitialized Model IO object
*
*/
ModelIO() : uninitialized(true), current(PREFERRED_NONE), active(PREFERRED_NONE) {}
/**
* @brief Construct a new Model IO object, with Fourier default representation
*
* @param t
*/
template <typename T>
ModelIO(Mgr_p mgr_, BoxModelIO const &box_, T &t, Holder original)
: mgr(mgr_), box(box_), holder(&t),
current(getPreferredType<T>::value), ioIsTransformed(false),
uninitialized(false), hold_original(original) {
active = current;
}
/**
* @brief Construct a new Model IO object, with Fourier default representation
*
* @param t
*/
template <typename T>
ModelIO(Mgr_p mgr_, BoxModelIO const &box_, T &t)
: mgr(mgr_), box(box_), holder(&t),
current(getPreferredType<T>::value), ioIsTransformed(false),
uninitialized(false) {
active = current;
}
/**
* @brief Obtain the primary IO buffer from the callee.
* It is a variant type.
*/
HolderType getHolder() { return holder; }
/**
* @brief Clear the associated memory.
*
* WARNING: use of the object beyond this point is not advised.
*/
void clear() { hold_original.reset(); }
/**
* @brief bool operator to check whether the IO object is empty/uninitialized.
*
* @return bool true if initialized, false otherwise.
*/
operator bool() const { return !uninitialized; }
protected:
/**
* @brief Transfer ownership of the IO
*
* @param other
* @return ModelIO&& Return *this
*/
void transfer(ModelIO &&other) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
mgr = std::move(other.mgr);
box = other.box;
current = other.current;
holder = std::move(other.holder);
tmp_real = std::move(other.tmp_real);
tmp_fourier = std::move(other.tmp_fourier);
direction = other.direction;
ioIsTransformed = other.ioIsTransformed;
uninitialized = other.uninitialized;
other.uninitialized = true;
hold_original = std::move(other.hold_original);
active = other.active;
}
void hermitic_fixer(CArrayRef &data);
};
} // namespace detail_model
using detail_model::ModelIO;
} // namespace LibLSS
#endif
// ARES TAG: num_authors = 1
// ARES TAG: author(0) = Guilhem Lavaux
// ARES TAG: year(0) = 2020
// ARES TAG: email(0) = guilhem.lavaux@iap.fr

View file

@ -0,0 +1,83 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/model_io/box.hpp
Copyright (C) 2019-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#pragma once
#ifndef __LIBLSS_PHYSICS_MODELIO_BOX_HPP
# define __LIBLSS_PHYSICS_MODELIO_BOX_HPP
# include <memory>
# include "libLSS/physics/cosmo.hpp"
# include "libLSS/mpi/generic_mpi.hpp"
# include "libLSS/tools/mpi_fftw_helper.hpp"
# include "libLSS/tools/errors.hpp"
# include "libLSS/samplers/core/types_samplers.hpp"
# include <boost/variant.hpp>
namespace LibLSS {
template <size_t Nd>
struct NBoxModel {};
template <>
struct NBoxModel<2> {
double xmin0, xmin1;
double L0, L1;
long N0, N1;
void fill(std::array<ssize_t, 2> &N) const {
N[0] = N0;
N[1] = N1;
}
double volume() const { return L0 * L1; }
long numElements() const { return N0 * N1; }
bool operator==(NBoxModel<2> const &other) const {
return xmin0 == other.xmin0 && xmin1 == other.xmin1 && L0 == other.L0 &&
L1 == other.L1 && N0 == other.N0 && N1 == other.N1;
}
bool operator!=(NBoxModel<2> const &other) const {
return !operator==(other);
}
};
template <>
struct NBoxModel<3> {
double xmin0, xmin1, xmin2;
double L0, L1, L2;
long N0, N1, N2;
void fill(std::array<ssize_t, 3> &N) const {
N[0] = N0;
N[1] = N1;
N[2] = N2;
}
double volume() const { return L0 * L1 * L2; }
long numElements() const { return N0 * N1 * N2; }
bool operator==(NBoxModel<3> const &other) const {
return xmin0 == other.xmin0 && xmin1 == other.xmin1 &&
xmin2 == other.xmin2 && L0 == other.L0 && L1 == other.L1 &&
L2 == other.L2 && N0 == other.N0 && N1 == other.N1 &&
N2 == other.N2;
}
bool operator!=(NBoxModel<3> const &other) const {
return !operator==(other);
}
};
typedef NBoxModel<3> BoxModel;
} // namespace LibLSS
#endif
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2019-2020

View file

@ -0,0 +1,233 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/model_io/input.hpp
Copyright (C) 2019-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
namespace LibLSS {
namespace detail_input {
template <typename Ref>
struct ref_retriever {
template <typename U>
using detect = typename std::enable_if<
std::is_same<U *, Ref *>::value ||
std::is_same<U *, Ref const *>::value,
Ref const *>::type;
template <typename U>
using not_detect = typename std::enable_if<
!(std::is_same<U *, Ref *>::value ||
std::is_same<U *, Ref const *>::value),
Ref const *>::type;
template <typename U>
detect<U> operator()(U *u) {
return u;
}
template <typename U>
not_detect<U> operator()(U *u) {
throw boost::bad_get();
}
};
template <size_t Nd>
using BoxModelIO = NBoxModel<Nd>;
template <typename T, size_t Nd>
struct _normalization {};
template <size_t Nd>
struct _normalization<typename ModelIO<Nd>::CArrayRef, Nd> {
static double fwd(BoxModelIO<Nd> const &b) { return 1.0 / b.volume(); }
static double adj(BoxModelIO<Nd> const &b) {
return b.volume() / b.numElements();
}
};
template <size_t Nd>
struct _normalization<typename ModelIO<Nd>::CArray, Nd>
: _normalization<typename ModelIO<Nd>::CArrayRef, Nd> {};
template <size_t Nd>
struct _normalization<typename ModelIO<Nd>::ArrayRef, Nd> {
static double fwd(BoxModelIO<Nd> const &b) {
return b.volume() / b.numElements();
}
static double adj(BoxModelIO<Nd> const &b) { return 1.0 / b.volume(); }
};
template <size_t Nd>
struct _normalization<typename ModelIO<Nd>::Array, Nd>
: _normalization<typename ModelIO<Nd>::ArrayRef, Nd> {};
template <typename T, size_t Nd>
using normalization = _normalization<std::remove_cv_t<T>, Nd>;
template <size_t Nd, typename Super = ModelIO<Nd>>
class ModelInputBase : public Super {
protected:
typedef Super super_t;
typedef typename super_t::Mgr_p Mgr_p;
typedef typename super_t::CArrayRef CArrayRef;
typedef typename super_t::ArrayRef ArrayRef;
typedef typename super_t::BoxModelIO BoxModelIO;
typedef typename super_t::Holder Holder;
double scaler;
bool protect;
public:
template <typename T>
static inline typename std::add_const<T>::type &rdonly(T &t) {
return t;
}
ModelInputBase() : super_t() {}
template <typename T>
ModelInputBase(
Mgr_p mgr_, BoxModelIO const &box_, T &t, Holder original_,
double scaler_)
: super_t(mgr_, box_, t, original_), scaler(scaler_) {}
template <typename T>
ModelInputBase(Mgr_p mgr_, BoxModelIO const &box_, T &t, double scaler_)
: super_t(mgr_, box_, t), scaler(scaler_) {}
void needDestroyInput();
void setRequestedIO(PreferredIO opt);
ArrayRef const &getRealConst() const {
if (this->ioIsTransformed)
return this->tmp_real->get_array();
return *boost::apply_visitor(ref_retriever<ArrayRef>(), this->holder);
}
CArrayRef const &getFourierConst() const {
if (this->ioIsTransformed)
return this->tmp_fourier->get_array();
return *boost::apply_visitor(ref_retriever<CArrayRef>(), this->holder);
}
ArrayRef &getReal() {
if (this->ioIsTransformed)
return this->tmp_real->get_array();
try {
return *boost::get<ArrayRef *>(this->holder);
} catch (boost::bad_get const &e) {
error_helper<ErrorBadState>(
"Invalid RW access to input: " + std::string(e.what()));
}
}
CArrayRef &getFourier() {
if (this->ioIsTransformed)
return this->tmp_fourier->get_array();
try {
return *boost::get<CArrayRef *>(this->holder);
} catch (boost::bad_get const &e) {
error_helper<ErrorBadState>(
"Invalid RW access to input: " + std::string(e.what()));
}
}
void transformInputRealToFourier();
void transformInputFourierToReal();
double scaleFactor() const { return scaler; }
super_t &operator=(super_t const &) = delete;
protected:
void transfer(ModelInputBase<Nd> &&other) {
super_t::transfer(std::move(other));
scaler = other.scaler;
}
};
template <size_t Nd, typename Super = ModelInputBase<Nd>>
class ModelInput : public Super {
protected:
typedef Super super_t;
typedef typename super_t::Mgr_p Mgr_p;
typedef typename super_t::CArrayRef CArrayRef;
typedef typename super_t::ArrayRef ArrayRef;
typedef typename super_t::BoxModelIO BoxModelIO;
typedef typename super_t::Holder Holder;
public:
ModelInput() : super_t() {}
ModelInput(ModelInput<Nd> &&other) { this->operator=(std::move(other)); }
template <typename T>
ModelInput(
Mgr_p mgr_, BoxModelIO const &box_, T &t, Holder original_,
bool prenormed = false, double scale = 1.0)
: super_t(
mgr_, box_, t, original_,
scale * (prenormed ? 1 : normalization<T, Nd>::fwd(box_))) {}
template <typename T>
ModelInput(
Mgr_p mgr_, BoxModelIO const &box_, T &t, bool prenormed = false,
double scale = 1.0)
: super_t(
mgr_, box_, t,
scale * (prenormed ? 1 : normalization<T, Nd>::fwd(box_))) {}
ModelInput &&operator=(ModelInput &&other) {
super_t::transfer(std::move(other));
return std::move(*this);
}
ModelInput<Nd> shallowClone();
};
template <size_t Nd, typename Super = ModelInputBase<Nd>>
class ModelInputAdjoint : public Super {
protected:
typedef Super super_t;
typedef typename super_t::Mgr_p Mgr_p;
typedef typename super_t::CArrayRef CArrayRef;
typedef typename super_t::ArrayRef ArrayRef;
typedef typename super_t::BoxModelIO BoxModelIO;
typedef typename super_t::Holder Holder;
public:
ModelInputAdjoint() : super_t() {}
ModelInputAdjoint(ModelInputAdjoint<Nd> &&other) {
this->operator=(std::move(other));
}
template <typename T>
ModelInputAdjoint(
Mgr_p mgr_, BoxModelIO const &box_, T &t, bool prenormed = false,
double scale = 1.0)
: super_t(
mgr_, box_, t,
scale * (prenormed ? 1 : normalization<T, Nd>::adj(box_))) {}
template <typename T>
ModelInputAdjoint(
Mgr_p mgr_, BoxModelIO const &box_, T &t, Holder original_,
bool prenormed = false, double scale = 1.0)
: super_t(
mgr_, box_, t, original_,
scale * (prenormed ? 1 : normalization<T, Nd>::adj(box_))) {}
ModelInputAdjoint<Nd> &&operator=(ModelInputAdjoint<Nd> &&other) {
super_t::transfer(std::move(other));
return std::move(*this);
}
ModelInputAdjoint<Nd> shallowClone();
};
} // namespace detail_input
} // namespace LibLSS
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2019-2020

View file

@ -0,0 +1,261 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/model_io/output.hpp
Copyright (C) 2019-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
namespace LibLSS {
namespace detail_output {
template <size_t Nd>
using BoxModelIO = NBoxModel<Nd>;
template <typename T, size_t Nd>
struct _normalization;
template <size_t Nd>
struct _normalization<typename ModelIO<Nd>::CArrayRef, Nd> {
static double fwd(BoxModelIO<Nd> const &b) {
return b.volume() / b.numElements();
}
static double adj(BoxModelIO<Nd> const &b) { return 1 / b.volume(); }
};
template <size_t Nd>
struct _normalization<typename ModelIO<Nd>::CArray, Nd>
: _normalization<typename ModelIO<Nd>::CArrayRef, Nd> {};
template <size_t Nd>
struct _normalization<typename ModelIO<Nd>::ArrayRef, Nd> {
static double fwd(BoxModelIO<Nd> const &b) { return 1 / b.volume(); }
static double adj(BoxModelIO<Nd> const &b) {
return b.volume() / b.numElements();
}
};
template <size_t Nd>
struct _normalization<typename ModelIO<Nd>::Array, Nd>
: _normalization<typename ModelIO<Nd>::ArrayRef, Nd> {};
template <typename T, size_t Nd>
using normalization = _normalization<
typename std::remove_const<
typename std::remove_reference<T>::type>::type,
Nd>;
template <size_t Nd, typename Super = ModelIO<Nd>>
class ModelOutputBase : public Super {
protected:
typedef Super super_t;
typedef typename super_t::Mgr_p Mgr_p;
typedef typename super_t::CArrayRef CArrayRef;
typedef typename super_t::ArrayRef ArrayRef;
typedef typename super_t::BoxModelIO BoxModelIO;
typedef typename super_t::Holder Holder;
double scaler;
bool alreadyTransformed;
template <typename T>
using is_not_a_const =
typename std::enable_if<!std::is_const<T>::value, void>::type;
template <typename T>
using is_a_const =
typename std::enable_if<!std::is_const<T>::value, void>::type;
public:
ModelOutputBase() : super_t(), alreadyTransformed(false) {}
template <typename T, typename = is_not_a_const<T>>
ModelOutputBase(Mgr_p mgr_, BoxModel const &box_, T &t, double scaler_)
: super_t(mgr_, box_, t), scaler(scaler_), alreadyTransformed(false) {
}
template <typename T, typename = is_not_a_const<T>>
ModelOutputBase(
Mgr_p mgr_, BoxModel const &box_, T &t, Holder original_,
double scaler_)
: super_t(mgr_, box_, t, original_), scaler(scaler_),
alreadyTransformed(false) {}
~ModelOutputBase();
void setRequestedIO(PreferredIO opt);
inline ArrayRef &getRealOutput() {
if (this->active != PREFERRED_REAL)
error_helper<ErrorBadState>("Requesting (REAL) wrong output");
try {
return this->ioIsTransformed ? this->tmp_real->get_array()
: *boost::get<ArrayRef *>(this->holder);
} catch (boost::bad_get const &e) {
error_helper<ErrorBadState>(
"Bad access to output: " + std::string(e.what()));
}
}
inline CArrayRef &getFourierOutput() {
if (this->active != PREFERRED_FOURIER)
error_helper<ErrorBadState>("Requesting (FOURIER) wrong output");
try {
return this->ioIsTransformed ? this->tmp_fourier->get_array()
: *boost::get<CArrayRef *>(this->holder);
} catch (boost::bad_get const &e) {
error_helper<ErrorBadState>(
"Bad access to output: " + std::string(e.what()));
}
}
void copyFrom(ModelOutputBase<Nd, Super> &other);
void transformOutputRealToFourier();
void transformOutputFourierToReal();
protected:
void triggerTransform();
void transfer(ModelOutputBase &&other) {
scaler = other.scaler;
super_t::transfer(std::move(other));
}
};
/**
* @brief Class to handle output arrays from forward models.
*/
template <size_t Nd, typename Super = ModelOutputBase<Nd>>
class ModelOutput : public Super {
protected:
typedef Super super_t;
typedef typename super_t::Mgr_p Mgr_p;
typedef typename super_t::CArrayRef CArrayRef;
typedef typename super_t::ArrayRef ArrayRef;
typedef typename super_t::BoxModelIO BoxModelIO;
typedef typename super_t::Holder Holder;
public:
/**
* @brief Construct an empty output.
*
* The object is marked as uninitialized.
*/
ModelOutput() : super_t() {}
/**
* @brief Construct an output
*
* @param Mgr_p FFT manager associated
* @param BoxModelIO Object describing the physical size of the output.
* @param T an array that must come from a boost::multi_array/boost::multi_array_ref
*/
template <typename T>
ModelOutput(Mgr_p mgr_, BoxModelIO const &box_, T &t)
: super_t(mgr_, box_, t, normalization<T, Nd>::fwd(box_)) {}
/**
* @brief Construct an output
*
* @param Mgr_p FFT manager associated
* @param BoxModelIO Object describing the physical size of the output.
* @param T an array that must come from a boost::multi_array/boost::multi_array_ref
* @param Holder a shared_ptr object that can be used to prevent the memory from being deallocated.
*/
template <typename T>
ModelOutput(Mgr_p mgr_, BoxModelIO const &box_, T &t, Holder original_)
: super_t(mgr_, box_, t, original_, normalization<T, Nd>::fwd(box_)) {
}
/**
* @brief Move constructor
*/
ModelOutput(ModelOutput<Nd> &&other) {
this->operator=(std::move(other));
}
/**
* @brief Move assignment
*/
ModelOutput &&operator=(ModelOutput &&other) {
super_t::transfer(std::move(other));
return std::move(*this);
}
/**
* @brief Construct a model output with a memory backing that has the same property as the original
*
* The memory is allocated but *not* initialized.
*/
ModelOutput<Nd> makeTempLike();
ModelOutput<Nd> shallowClone();
};
template <size_t Nd, typename Super = ModelOutputBase<Nd>>
class ModelOutputAdjoint : public Super {
protected:
typedef Super super_t;
typedef typename super_t::Mgr_p Mgr_p;
typedef typename super_t::CArrayRef CArrayRef;
typedef typename super_t::ArrayRef ArrayRef;
typedef typename super_t::BoxModelIO BoxModelIO;
typedef typename super_t::Holder Holder;
public:
/**
* @brief Construct an empty adjoint gradient output.
*
* The object is marked as uninitialized.
*/
ModelOutputAdjoint() : super_t() {}
/**
* @brief Construct an adjoint gradient output
*
* @param Mgr_p FFT manager associated
* @param BoxModelIO Object describing the physical size of the output.
* @param T an array that must come from a boost::multi_array/boost::multi_array_ref
*/
template <typename T>
ModelOutputAdjoint(Mgr_p mgr_, BoxModelIO const &box_, T &t)
: super_t(mgr_, box_, t, normalization<T, Nd>::adj(box_)) {}
/**
* @brief Construct an adjoint gradient output
*
* @param Mgr_p FFT manager associated
* @param BoxModelIO Object describing the physical size of the output.
* @param T an array that must come from a boost::multi_array/boost::multi_array_ref
* @param Holder a shared_ptr object that can be used to prevent the memory from being deallocated.
*/
template <typename T>
ModelOutputAdjoint(
Mgr_p mgr_, BoxModelIO const &box_, T &t, Holder original_)
: super_t(mgr_, box_, t, original_, normalization<T, Nd>::adj(box_)) {
}
ModelOutputAdjoint(ModelOutputAdjoint &&other) {
this->operator=(std::move(other));
}
ModelOutputAdjoint &&operator=(ModelOutputAdjoint &&other) {
super_t::transfer(std::move(other));
return std::move(*this);
}
/**
* @brief Construct a model output with a memory backing that has the same property as the original
*
* The memory is allocated but *not* initialized.
*/
ModelOutputAdjoint<Nd> makeTempLike();
ModelOutputAdjoint<Nd> shallowClone();
};
} // namespace detail_output
} // namespace LibLSS
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2019-2020

View file

@ -0,0 +1,190 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/sum.cpp
Copyright (C) 2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#include <boost/multi_array.hpp>
#include "libLSS/physics/cosmo.hpp"
#include "libLSS/mpi/generic_mpi.hpp"
#include "libLSS/physics/forward_model.hpp"
#include <list>
#include <boost/variant.hpp>
#include "libLSS/tools/errors.hpp"
#include "libLSS/physics/sum.hpp"
using namespace LibLSS;
SumForwardModel::SumForwardModel(MPI_Communication *comm, const BoxModel &box)
: BORGForwardModel(comm, box) {}
SumForwardModel::SumForwardModel(
MPI_Communication *comm, const BoxModel &box, const BoxModel &outbox)
: BORGForwardModel(comm, box, outbox) {}
SumForwardModel::~SumForwardModel() {}
void SumForwardModel::forwardModel_v2(ModelInput<3> delta_init) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
for (auto &model : model_list) {
model->forwardModel_v2(delta_init.shallowClone());
}
}
void SumForwardModel::getDensityFinal(ModelOutput<3> output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
{
auto out_io = (*model_list.begin())->getPreferredOutput();
if (out_io != PREFERRED_NONE)
output.setRequestedIO(out_io);
}
ModelOutput<3> tmp;
double num = 1.0; //model_list.size();
auto accum = [num](auto &a, auto &b) {
fwrap(a) = fwrap(a) + (1.0 / num) * fwrap(b);
};
if (output.active == PREFERRED_REAL) {
auto tmp_p = out_mgr->allocate_ptr_array();
auto& tmp_a = tmp_p->get_array();
tmp = std::move(ModelOutput<3>(out_mgr, get_box_model_output(), tmp_a, std::move(tmp_p)));
fwrap(output.getRealOutput()) = 0.0;
} else {
auto tmp_p = out_mgr->allocate_ptr_complex_array();
auto& tmp_a = tmp_p->get_array();
tmp = std::move(ModelOutput<3>(out_mgr, get_box_model_output(), tmp_a, std::move(tmp_p)));
fwrap(output.getFourierOutput()) = 0.0;
}
for (auto &model : model_list) {
model->getDensityFinal(tmp.shallowClone());
switch (tmp.active) {
case PREFERRED_REAL:
accum(output.getRealOutput(), tmp.getRealOutput());
break;
case PREFERRED_FOURIER:
accum(output.getFourierOutput(), tmp.getFourierOutput());
break;
default:
error_helper<ErrorBadState>("Unknown IO type.");
break;
}
}
}
void SumForwardModel::adjointModel_v2(ModelInputAdjoint<3> gradient_delta) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
for (auto &model : model_list) {
model->adjointModel_v2(gradient_delta.shallowClone());
}
}
void SumForwardModel::getAdjointModelOutput(ModelOutputAdjoint<3> ag_output) {
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
{
auto in_io = (*model_list.begin())->getPreferredInput();
if (in_io != PREFERRED_NONE)
ag_output.setRequestedIO(in_io);
}
ModelOutputAdjoint<3> tmp;
double num = 1.0; //model_list.size();
auto accum = [num](auto &a, auto &b) {
fwrap(a) = fwrap(a) + (1.0 / num) * fwrap(b);
};
if (ag_output.active == PREFERRED_REAL) {
auto tmp_p = out_mgr->allocate_ptr_array();
auto& tmp_a = tmp_p->get_array();
tmp = std::move(ModelOutputAdjoint<3>(out_mgr, get_box_model_output(), tmp_a, std::move(tmp_p)));
fwrap(ag_output.getRealOutput()) = 0.0;
} else {
auto tmp_p = out_mgr->allocate_ptr_complex_array();
auto& tmp_a = tmp_p->get_array();
tmp = std::move(ModelOutputAdjoint<3>(out_mgr, get_box_model_output(), tmp_a, std::move(tmp_p)));
fwrap(ag_output.getFourierOutput()) = 0.0;
}
for (auto &model : model_list) {
model->getAdjointModelOutput(tmp.shallowClone());
switch (tmp.active) {
case PREFERRED_REAL:
accum(ag_output.getRealOutput(), tmp.getRealOutput());
break;
case PREFERRED_FOURIER:
accum(ag_output.getFourierOutput(), tmp.getFourierOutput());
break;
default:
error_helper<ErrorBadState>("Unknown IO type.");
break;
}
}
}
void SumForwardModel::releaseParticles() {
// Fill up with the chain
for (auto model : model_list) {
model->releaseParticles();
}
}
void SumForwardModel::addModel(std::shared_ptr<BORGForwardModel> model) {
if (get_box_model() != model->get_box_model()) {
error_helper<ErrorParams>(
"Invalid model configuration with IO of the chain.");
}
model_list.push_back(model);
}
void SumForwardModel::setAdjointRequired(bool required) {
for (auto& model : model_list) {
model->setAdjointRequired(required);
}
}
void SumForwardModel::updateCosmo() {
// Fill up with the chain
for (auto& model : model_list) {
model->setCosmoParams(cosmo_params);
}
}
void SumForwardModel::setModelParams(ModelDictionnary const &params) {
for (auto& model : model_list) {
model->setModelParams(params);
}
}
boost::any SumForwardModel::getModelParam(std::string const& name, std::string const& param) {
if (name == modelName) {
return boost::any();
}
for (auto& model : model_list) {
auto ret = model->getModelParam(name, param);
if (!ret.empty())
return ret;
}
return boost::any();
}
void SumForwardModel::clearAdjointGradient() {
for (auto model : model_list) {
model->clearAdjointGradient();
}
}
// ARES TAG: authors_num = 1
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2020

View file

@ -0,0 +1,68 @@
/*+
ARES/HADES/BORG Package -- ./extra/hades/libLSS/physics/sum.hpp
Copyright (C) 2018-2020 Guilhem Lavaux <guilhem.lavaux@iap.fr>
Copyright (C) 2018-2019 Doogesh Kodi Ramanah <ramanah@iap.fr>
Additional contributions from:
Guilhem Lavaux <guilhem.lavaux@iap.fr> (2023)
+*/
#pragma once
#ifndef __LIBLSS_SUM_FORWARD_MODEL_HPP
# define __LIBLSS_SUM_FORWARD_MODEL_HPP
# include <boost/multi_array.hpp>
# include "libLSS/physics/cosmo.hpp"
# include "libLSS/mpi/generic_mpi.hpp"
# include "libLSS/physics/forward_model.hpp"
# include <list>
# include <boost/variant.hpp>
namespace LibLSS {
class SumForwardModel : public BORGForwardModel {
public:
SumForwardModel(MPI_Communication *comm, const BoxModel &box);
SumForwardModel(
MPI_Communication *comm, const BoxModel &box, const BoxModel &outbox);
~SumForwardModel() override;
void forwardModel_v2(ModelInput<3> delta_init) override;
void getDensityFinal(ModelOutput<3> output) override;
void clear_chain();
// adjointModel auto release particles. Beware !
void adjointModel_v2(ModelInputAdjoint<3> gradient_delta) override;
void getAdjointModelOutput(ModelOutputAdjoint<3> ag_output) override;
void releaseParticles() override;
void addModel(std::shared_ptr<BORGForwardModel> model);
void setAdjointRequired(bool required) override;
void clearAdjointGradient() override;
void setModelParams(ModelDictionnary const& params) override;
boost::any getModelParam(std::string const& name, std::string const& param) override;
protected:
std::list<std::shared_ptr<BORGForwardModel>> model_list;
void updateCosmo() override;
};
}; // namespace LibLSS
#endif
// ARES TAG: authors_num = 2
// ARES TAG: name(0) = Guilhem Lavaux
// ARES TAG: email(0) = guilhem.lavaux@iap.fr
// ARES TAG: year(0) = 2018-2020
// ARES TAG: name(1) = Doogesh Kodi Ramanah
// ARES TAG: email(1) = ramanah@iap.fr
// ARES TAG: year(1) = 2018-2019