Initial import
This commit is contained in:
commit
56a50eead3
820 changed files with 192077 additions and 0 deletions
130
extra/hades/libLSS/physics/branch.cpp
Normal file
130
extra/hades/libLSS/physics/branch.cpp
Normal 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
|
76
extra/hades/libLSS/physics/branch.hpp
Normal file
76
extra/hades/libLSS/physics/branch.hpp
Normal 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
|
357
extra/hades/libLSS/physics/chain_forward_model.cpp
Normal file
357
extra/hades/libLSS/physics/chain_forward_model.cpp
Normal 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 ¶ms) {
|
||||
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 ¶meter) {
|
||||
// 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
|
99
extra/hades/libLSS/physics/chain_forward_model.hpp
Normal file
99
extra/hades/libLSS/physics/chain_forward_model.hpp
Normal 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 ¶ms) override;
|
||||
|
||||
boost::any getModelParam(
|
||||
std::string const &model_name, std::string const ¶meter) 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
|
114
extra/hades/libLSS/physics/forward_model.cpp
Normal file
114
extra/hades/libLSS/physics/forward_model.cpp
Normal 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 ¶ms) {
|
||||
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);
|
||||
}
|
399
extra/hades/libLSS/physics/forward_model.hpp
Normal file
399
extra/hades/libLSS/physics/forward_model.hpp
Normal 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 ¶ms);
|
||||
|
||||
|
||||
// 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 ¶meterName) {
|
||||
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
|
77
extra/hades/libLSS/physics/forwards/fnl.cpp
Normal file
77
extra/hades/libLSS/physics/forwards/fnl.cpp
Normal 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 ¶ms) {
|
||||
LIBLSS_AUTO_DEBUG_CONTEXT(ctx);
|
||||
return std::make_shared<ForwardFNL>(comm, box);
|
||||
}
|
||||
|
||||
LIBLSS_REGISTER_FORWARD_IMPL(PRIMORDIAL_FNL, build_primordial_FNL);
|
65
extra/hades/libLSS/physics/forwards/fnl.hpp
Normal file
65
extra/hades/libLSS/physics/forwards/fnl.hpp
Normal 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
|
205
extra/hades/libLSS/physics/forwards/primordial.cpp
Normal file
205
extra/hades/libLSS/physics/forwards/primordial.cpp
Normal 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 ¶ms) {
|
||||
// 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);
|
95
extra/hades/libLSS/physics/forwards/primordial.hpp
Normal file
95
extra/hades/libLSS/physics/forwards/primordial.hpp
Normal 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
|
35
extra/hades/libLSS/physics/forwards/registry.cpp
Normal file
35
extra/hades/libLSS/physics/forwards/registry.cpp
Normal 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);
|
||||
}
|
104
extra/hades/libLSS/physics/forwards/registry.hpp
Normal file
104
extra/hades/libLSS/physics/forwards/registry.hpp
Normal 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 ¶ms)>
|
||||
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
|
178
extra/hades/libLSS/physics/forwards/transfer_ehu.cpp
Normal file
178
extra/hades/libLSS/physics/forwards/transfer_ehu.cpp
Normal 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 ¶ms) {
|
||||
// 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);
|
97
extra/hades/libLSS/physics/forwards/transfer_ehu.hpp
Normal file
97
extra/hades/libLSS/physics/forwards/transfer_ehu.hpp
Normal 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
|
257
extra/hades/libLSS/physics/forwards/upgrade.cpp
Normal file
257
extra/hades/libLSS/physics/forwards/upgrade.cpp
Normal 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 ¶ms) {
|
||||
|
||||
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);
|
65
extra/hades/libLSS/physics/forwards/upgrade.hpp
Normal file
65
extra/hades/libLSS/physics/forwards/upgrade.hpp
Normal 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
|
191
extra/hades/libLSS/physics/haar.cpp
Normal file
191
extra/hades/libLSS/physics/haar.cpp
Normal 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 ¶ms) {
|
||||
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
|
65
extra/hades/libLSS/physics/haar.hpp
Normal file
65
extra/hades/libLSS/physics/haar.hpp
Normal 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
|
138
extra/hades/libLSS/physics/hades_log.cpp
Normal file
138
extra/hades/libLSS/physics/hades_log.cpp
Normal 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 ¶ms) {
|
||||
double ai = params.get<double>("a_initial");
|
||||
return std::make_shared<HadesLog>(comm, box, ai);
|
||||
}
|
||||
|
||||
LIBLSS_REGISTER_FORWARD_IMPL(HADES_LOG, build_hades_log);
|
56
extra/hades/libLSS/physics/hades_log.hpp
Normal file
56
extra/hades/libLSS/physics/hades_log.hpp
Normal 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
|
150
extra/hades/libLSS/physics/hades_pt.cpp
Normal file
150
extra/hades/libLSS/physics/hades_pt.cpp
Normal 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 ¶ms) {
|
||||
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);
|
68
extra/hades/libLSS/physics/hades_pt.hpp
Normal file
68
extra/hades/libLSS/physics/hades_pt.hpp
Normal 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
|
70
extra/hades/libLSS/physics/hermitic.hpp
Normal file
70
extra/hades/libLSS/physics/hermitic.hpp
Normal 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
|
21
extra/hades/libLSS/physics/likelihoods/base.cpp
Normal file
21
extra/hades/libLSS/physics/likelihoods/base.cpp
Normal 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
|
114
extra/hades/libLSS/physics/likelihoods/base.hpp
Normal file
114
extra/hades/libLSS/physics/likelihoods/base.hpp
Normal 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
|
371
extra/hades/libLSS/physics/model_io.cpp
Normal file
371
extra/hades/libLSS/physics/model_io.cpp
Normal 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
|
41
extra/hades/libLSS/physics/model_io.hpp
Normal file
41
extra/hades/libLSS/physics/model_io.hpp
Normal 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
|
173
extra/hades/libLSS/physics/model_io/base.hpp
Normal file
173
extra/hades/libLSS/physics/model_io/base.hpp
Normal 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
|
83
extra/hades/libLSS/physics/model_io/box.hpp
Normal file
83
extra/hades/libLSS/physics/model_io/box.hpp
Normal 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
|
233
extra/hades/libLSS/physics/model_io/input.hpp
Normal file
233
extra/hades/libLSS/physics/model_io/input.hpp
Normal 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
|
261
extra/hades/libLSS/physics/model_io/output.hpp
Normal file
261
extra/hades/libLSS/physics/model_io/output.hpp
Normal 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
|
190
extra/hades/libLSS/physics/sum.cpp
Normal file
190
extra/hades/libLSS/physics/sum.cpp
Normal 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 ¶ms) {
|
||||
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
|
68
extra/hades/libLSS/physics/sum.hpp
Normal file
68
extra/hades/libLSS/physics/sum.hpp
Normal 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
|
Loading…
Add table
Add a link
Reference in a new issue