1 #ifndef UTOPIA_MODELS_ENVIRONMENT_HH
2 #define UTOPIA_MODELS_ENVIRONMENT_HH
6 #include <unordered_map>
26 namespace Environment {
36 using namespace ParameterFunctionCollection;
37 using namespace StateFunctionCollection;
49 virtual double get_env(
const std::string&)
const = 0;
52 virtual void set_env(
const std::string&,
const double&) = 0;
66 double get_env(
const std::string&)
const override {
67 throw std::invalid_argument(
"Accessing getter of the dummy type of "
72 void set_env(
const std::string&,
const double&)
override {
73 throw std::invalid_argument(
"Accessing setter of the dummy type of "
91 virtual double get_env(
const std::string&)
const = 0;
94 virtual void set_env(
const std::string&,
const double&) = 0;
108 double get_env(
const std::string&)
const override {
109 throw std::invalid_argument(
"Accessing getter of the dummy type of "
114 void set_env(
const std::string&,
const double&)
override {
115 throw std::invalid_argument(
"Accessing setter of the dummy type of "
137 bool standalone=
false>
139 public Model<Environment<EnvParam, EnvCellState, standalone>, ModelTypes>
214 std::unordered_map<std::string, std::shared_ptr<DataSet>>
_dsets_state;
217 std::unordered_map<std::string, std::shared_ptr<DataSet>>
_dsets_param;
232 template<
class ParentModel,
class CellManager>
234 const std::string& name,
235 ParentModel& parent_model,
241 Base(name, parent_model, custom_cfg),
244 _cm(*
this, associate_cm.cfg()),
254 _init_env_state_funcs{},
262 if constexpr (not std::is_same<CellManager, DummyCellManager>()) {
263 for (std::size_t i=0; i < _cm.
cells().size(); i++) {
264 associate_cm.cells()[i]->custom_links().env = _cm.
cells()[i];
268 "Associated '{}' cells with those of the parent model '{}'.",
269 this->_name, parent_model.get_name()
272 else if constexpr (not standalone) {
275 static_assert(std::is_same<EnvCellState, DummyEnvCellState>(),
276 "The cm for association of environment cells cannot "
277 "be the DummyCellManager! \n"
278 "Setup the model with type DummyEnvCellState for "
279 "standalone model or pass a cell manager for "
280 "associated model.");
282 this->_log->info(
"Setting up '{}' as coupled model without "
283 "associated cell manager.", this->_name);
286 this->_log->info(
"Setting up '{}' as standalone model ...",
291 static_assert(std::is_base_of<BaseEnvCellState, EnvCellState>::value,
292 "The model's EnvCellState must derive from "
293 "Utopia::Models::Environment::BaseEnvCellState!");
296 static_assert(std::is_base_of<BaseEnvParam, EnvParam>::value,
297 "The model's EnvParam must derive from "
298 "Utopia::Models::Environment::BaseEnvParam!");
301 apply_rule<Update::sync>(
302 [
this](
const auto& cell){
303 auto& state = cell->state;
309 this->_log->debug(
"Cell barycenters cached.");
313 if (this->_cfg[
"env_param_funcs"]) {
314 setup_env_param_funcs(this->_cfg[
"env_param_funcs"]);
318 this->_log->debug(
"Applying {} initial environment param function{} ...",
319 _env_param_funcs.size(),
320 _env_param_funcs.size() != 1 ?
"s" :
"");
321 for (
auto& epfb : _env_param_funcs) {
322 if (epfb.invoke_at_initialization) {
323 apply_env_param_func(epfb,
true);
328 if (this->_cfg[
"init_env_state_funcs"]) {
329 setup_env_state_funcs<true>(this->_cfg[
"init_env_state_funcs"]);
331 if (this->_cfg[
"env_state_funcs"]) {
332 setup_env_state_funcs<false>(this->_cfg[
"env_state_funcs"]);
336 this->_log->info(
"Applying {} initial environment state function{} ...",
337 _init_env_state_funcs.size(),
338 _init_env_state_funcs.size() != 1 ?
"s" :
"");
339 for (
auto& esfb : _init_env_state_funcs) {
340 apply_env_state_func(esfb);
343 this->_log->info(
"{} set up.", this->_name);
355 template <
typename ParentModel>
369 for (
auto& epfb : _env_param_funcs) {
370 apply_env_param_func(epfb);
372 for (
auto& esfb : _env_state_funcs) {
373 apply_env_state_func(esfb);
392 for (
auto& [key, dset] : _dsets_param) {
393 dset->write(_params.
get_env(key));
397 for (
auto& param_dset_pair : _dsets_state) {
398 const auto key = std::get<0>(param_dset_pair);
399 auto& dset = std::get<1>(param_dset_pair);
401 dset->write(_cm.
cells().begin(), _cm.
cells().end(),
402 [key](
const auto& cell) {
403 return cell->state.get_env(key);
413 return this->_params.
get_env(param_name);
418 this->_params.
set_env(param_name, value);
422 const auto&
cm()
const {
433 _env_param_funcs.push_back(epfb);
434 this->_log->debug(
"Added environment param function '{}'.", epfb.name);
443 const std::string& param_name,
444 std::tuple<
bool,
bool, std::set<Time>> times_tuple)
460 auto invoke_times_tuple = extract_times_and_initialization<Time>(cfg);
461 add_env_param_func(name, epf, param_name, invoke_times_tuple);
468 template<
bool add_to_initial=false,
class ESFB>
470 if constexpr (add_to_initial) {
471 _init_env_state_funcs.push_back(esfb);
474 _env_state_funcs.push_back(esfb);
476 this->_log->debug(
"Added {}environment function '{}'.",
477 add_to_initial ?
"initial " :
"", esfb.name);
487 template<
bool add_to_initial=false>
490 std::pair<
bool, std::set<Time>> times_pair = {
true, {}},
495 EnvCellContainer cell_selection = {};
496 if (not select_cfg.IsNull()) {
497 std::string generate = get_as<std::string>(
"generate", select_cfg);
498 if (generate ==
"once") {
499 fix_selection =
true;
501 else if (generate ==
"always") {
502 fix_selection =
false;
505 throw std::invalid_argument(
"Key 'generate' in 'select' "
506 "feature of environment state function '"
507 + name +
"' must be 'once' to fix selection or "
508 "'always' to generate it on the fly, but was '"
513 this->_log->debug(
"Generating a selection of cells and fixing "
514 "it for the rule '{}'.", name);
519 fix_selection =
false;
522 add_env_state_func<add_to_initial>(
523 EnvStateFuncBundle(name, esf, update, add_to_initial, times_pair,
524 {fix_selection, cell_selection, select_cfg})
535 template<
bool add_to_initial=false>
537 const std::string& name,
542 auto times_pair = extract_times<Time>(cfg);
545 select_cfg = get_as<Config>(
"select", cfg, {});
548 add_env_state_func<add_to_initial>(name, esf, update, times_pair,
554 if (_dsets_param.find(key) != _dsets_param.end()) {
555 throw std::invalid_argument(
"Parameter '" + key +
"' is already "
558 _dsets_param.insert({key, this->create_dset(key, {})});
565 for (
const auto& key : keys) {
566 track_parameter(key);
572 if (_dsets_state.find(key) != _dsets_state.end()) {
573 throw std::invalid_argument(
"State '" + key +
"' is already "
576 _dsets_state.insert({key, this->create_cm_dset(key, _cm)});
583 for (
const auto& key : keys) {
591 this->_log->info(
"Setting up environment param function sequence "
592 "from {} configuration entr{} ...",
593 cfg.size(), cfg.size() != 1 ?
"ies" :
"y");
596 if (not cfg or not cfg.size()) {
600 if (not cfg.IsSequence()) {
601 throw std::invalid_argument(
"The config for initializing the "
602 "environment functions must be a sequence!");
606 for (
const auto& epfs : cfg) {
610 for (
const auto& epf_pair : epfs) {
613 const auto epf_name = epf_pair.first.as<std::string>();
615 this->_log->trace(
" Function name: {}", epf_name);
618 for (
const auto& kv_pair : epf_pair.second) {
620 const auto param_name = kv_pair.first.as<std::string>();
621 const auto& epf_cfg = kv_pair.second;
624 if (epf_name ==
"increment") {
626 add_env_param_func_from_cfg(
627 epf_name+
"."+param_name, epf, param_name, epf_cfg
630 else if (epf_name ==
"random") {
631 auto epf =
epf_random(*
this, param_name, epf_cfg);
632 add_env_param_func_from_cfg(
633 epf_name+
"."+param_name, epf, param_name, epf_cfg
636 else if (epf_name ==
"rectangular") {
638 add_env_param_func_from_cfg(
639 epf_name+
"."+param_name, epf, param_name, epf_cfg
642 else if (epf_name ==
"set") {
643 auto epf =
epf_set(*
this, epf_cfg);
644 add_env_param_func_from_cfg(
645 epf_name+
"."+param_name, epf, param_name, epf_cfg
648 else if (epf_name ==
"sinusoidal") {
650 add_env_param_func_from_cfg(
651 epf_name+
"."+param_name, epf, param_name, epf_cfg
656 else if (epf_name !=
"void") {
657 throw std::invalid_argument(
"No environment parameter "
658 "function '" + epf_name +
"' available to "
659 "construct! Choose from: increment, random, "
660 "rectangular, set, sinusoidal.");
663 this->_log->debug(
"Added '{}' environment parameter "
664 "function for parameter '{}'.", epf_name, param_name);
671 template<
bool add_to_initial=false>
673 this->_log->info(
"Setting up {}environment state function sequence "
674 "from {} configuration entr{} ...",
675 add_to_initial ?
"initial " :
"",
676 cfg.size(), cfg.size() != 1 ?
"ies" :
"y");
679 if (not cfg or not cfg.size()) {
683 if (not cfg.IsSequence()) {
684 throw std::invalid_argument(
"The config for initializing the "
685 "environment state functions must be a sequence!");
689 for (
const auto& esfs : cfg) {
693 for (
const auto& esf_pair : esfs) {
696 const auto esf_name = esf_pair.first.as<std::string>();
698 this->_log->trace(
" Function name: {}", esf_name);
701 for (
const auto& kv_pair : esf_pair.second) {
703 const auto param_name = kv_pair.first.as<std::string>();
704 const auto& esf_cfg = kv_pair.second;
707 if (esf_name ==
"noise") {
708 auto esf_update_pair =
esf_noise(*
this, param_name,
710 add_env_state_func_from_cfg<add_to_initial>(
711 "noise."+param_name, esf_update_pair.first,
712 esf_update_pair.second, esf_cfg
715 else if (esf_name ==
"slope") {
716 auto esf_update_pair =
esf_slope(*
this, param_name,
718 _cm.
space()->extent);
719 add_env_state_func_from_cfg<add_to_initial>(
720 "slope."+param_name, esf_update_pair.first,
721 esf_update_pair.second, esf_cfg
724 else if (esf_name ==
"steps") {
725 auto esf_update_pair =
esf_steps(*
this, param_name,
727 add_env_state_func_from_cfg<add_to_initial>(
728 "steps."+param_name, esf_update_pair.first,
729 esf_update_pair.second, esf_cfg
732 else if (esf_name ==
"uniform") {
733 auto esf_update_pair =
esf_uniform(*
this, param_name,
735 add_env_state_func_from_cfg<add_to_initial>(
736 "uniform."+param_name, esf_update_pair.first,
737 esf_update_pair.second, esf_cfg
741 else if (esf_name !=
"void") {
742 throw std::invalid_argument(
"No environment state "
743 "function '" + esf_name +
"' available to "
744 "construct! Choose from: noise, slope, steps, "
748 this->_log->trace(
"Added '{}' environment state"
749 "function for parameter '{}'.", esf_name, param_name);
761 if (initialization) {
762 if (not epfb.invoke_at_initialization) {
763 this->_log->trace(
"Not invoking environment function '{}' at "
764 "initialization.", epfb.name);
768 else if (not epfb.invoke_always) {
775 if ( epfb.times.size()
776 and *epfb.times.begin() == (this->_time + 1))
779 epfb.times.erase(epfb.times.begin());
782 this->_log->trace(
"Not invoking environment function '{}' in "
783 "this iteration.", epfb.name);
788 this->_log->debug(
"Applying environment parameter function '{}' ...",
790 this->_params.
set_env(epfb.param_name, epfb.func());
798 if (not esfb.invoke_always) {
805 if ( esfb.times.size()
806 and *esfb.times.begin() == (this->_time + 1))
809 esfb.times.erase(esfb.times.begin());
812 this->_log->trace(
"Not invoking environment function '{}' in "
813 "this iteration.", esfb.name);
818 this->_log->debug(
"Applying environment state function '{}' ...",
823 if (esfb.fix_selection) {
824 cell_selection = esfb.cell_selection;
826 else if (not esfb.select_cfg.IsNull()) {
827 this->_log->debug(
"Generating a new selection of cells for "
828 "environment state function '{}' ...", esfb.name);
832 cell_selection = _cm.
cells();
835 this->_log->debug(
"Applying to {} cells ...",
836 (cell_selection.size() == _cm.
cells().size() ?
841 apply_rule<Update::sync>(esfb.func, cell_selection);
844 apply_rule<Update::async>(esfb.func, cell_selection, *this->_rng);
849 throw std::invalid_argument(
"Unsupported `update` argument!");
const CellContainer< Cell > & cells() const
Return const reference to the managed CA cells.
Definition: cell_manager.hh:219
typename std::function< CellState(const std::shared_ptr< Cell > &)> RuleFunc
The type of a rule function acting on cells of this cell manager.
Definition: cell_manager.hh:84
CellContainer< Cell > select_cells(Args &&... args) const
Select cells using the Utopia::select_entities interface.
Definition: cell_manager.hh:342
SpaceVec barycenter_of(const Cell &cell) const
Returns the barycenter of the given cell.
Definition: cell_manager.hh:249
const std::shared_ptr< Space > & space() const
Return pointer to the space, for convenience.
Definition: cell_manager.hh:209
Base class interface for Models using the CRT Pattern.
Definition: model.hh:112
typename ModelTypes::DataSet DataSet
Data type that is used for storing data.
Definition: model.hh:125
typename ModelTypes::DataGroup DataGroup
Data type that is used for storing datasets.
Definition: model.hh:122
typename ModelTypes::Time Time
Data type for the model time.
Definition: model.hh:134
The Environment model provides a non-uniform, dynamic parameter background.
Definition: Environment.hh:140
std::vector< EnvParamFuncBundle > _env_param_funcs
Container of functions that are invoked every time step.
Definition: Environment.hh:202
CellManager _cm
The cell manager.
Definition: Environment.hh:195
std::vector< EnvStateFuncBundle > _init_env_state_funcs
Container of rule functions that are invoked once at initialisation.
Definition: Environment.hh:206
void add_env_state_func(ESFB &&esfb)
Add a rule function at the end of the sequence of state functions.
Definition: Environment.hh:469
typename Base::Time Time
The type of the model time.
Definition: Environment.hh:164
std::unordered_map< std::string, std::shared_ptr< DataSet > > _dsets_state
Dynamically generated map of datasets of cell states.
Definition: Environment.hh:214
typename Base::DataSet DataSet
Data type for a dataset.
Definition: Environment.hh:152
void setup_env_state_funcs(const Config &cfg)
Construct the rule funcs sequence from cfg.
Definition: Environment.hh:672
void setup_env_param_funcs(const Config &cfg)
Construct the rule funcs sequencefor EnvParam from cfg.
Definition: Environment.hh:590
typename Base::DataGroup DataGroup
Data type of the group to write model data to, holding datasets.
Definition: Environment.hh:149
DataIO::Config Config
Configuration node type alias.
Definition: Environment.hh:180
void monitor()
Monitor model information.
Definition: Environment.hh:379
void set_parameter(const std::string ¶m_name, double value)
Change the current value of the parameter with param_name.
Definition: Environment.hh:417
CellContainer< typename CellManager::Cell > EnvCellContainer
The type of the EnvCellContainer.
Definition: Environment.hh:161
EnvParam _params
The environment parameters.
Definition: Environment.hh:198
void apply_env_state_func(ESFB &&esfb)
Apply a given environment state function.
Definition: Environment.hh:796
const auto & cm() const
Return a const reference to the cell manager.
Definition: Environment.hh:422
std::vector< EnvStateFuncBundle > _env_state_funcs
Container of rule functions that are invoked every time step.
Definition: Environment.hh:210
void add_env_state_func_from_cfg(const std::string &name, const EnvStateFunc &esf, const Update &update=Update::sync, const Config &cfg={})
Add a rule function at the end of the sequence of environment functions.
Definition: Environment.hh:536
void add_env_param_func(EPFB &&epfb)
Add a rule function at the end of the sequence of parameter functions.
Definition: Environment.hh:432
void add_env_state_func(const std::string &name, const EnvStateFunc &esf, const Update &update=Update::sync, std::pair< bool, std::set< Time >> times_pair={true, {}}, Config select_cfg={})
Add a rule function at the end of the sequence of environment functions.
Definition: Environment.hh:488
typename std::function< double()> EnvParamFunc
The type of the environment parameter functions.
Definition: Environment.hh:167
void perform_step()
Iterate a single step.
Definition: Environment.hh:368
void track_parameters(const std::vector< std::string > &keys)
Track multiple parameters.
Definition: Environment.hh:564
void add_env_param_func(const std::string &name, const EnvParamFunc &epf, const std::string ¶m_name, std::tuple< bool, bool, std::set< Time >> times_tuple)
Add a param function at the end of the sequence of env functions.
Definition: Environment.hh:442
typename CellManager::RuleFunc EnvStateFunc
The type of the environment state functions; basically a rule function.
Definition: Environment.hh:173
double get_parameter(const std::string ¶m_name) const
Return the current value of the parameter with param_name.
Definition: Environment.hh:412
Environment(const std::string &name, ParentModel &parent_model, CellManager &&associate_cm, const DataIO::Config &custom_cfg={})
Construct the Environment model associated to a CellManager.
Definition: Environment.hh:233
void apply_env_param_func(EPFB &&epfb, bool initialization=false)
Apply a given environment parameter function.
Definition: Environment.hh:759
Environment(const std::string name, ParentModel &parent)
Construct Environment without associated CellManager.
Definition: Environment.hh:356
void write_data()
Write data.
Definition: Environment.hh:390
void track_state(const std::string &key)
Mark a state as being tracked, i.e. store its data in write_data.
Definition: Environment.hh:571
std::unordered_map< std::string, std::shared_ptr< DataSet > > _dsets_param
Dynamically generated map of datasets of parameters.
Definition: Environment.hh:217
void track_states(const std::vector< std::string > &keys)
Track multiple states.
Definition: Environment.hh:582
void track_parameter(const std::string &key)
Mark a parameter as being tracked, i.e. store its data in write_data.
Definition: Environment.hh:553
void add_env_param_func_from_cfg(const std::string &name, const EnvParamFunc &epf, const std::string ¶m_name, const Config &cfg={})
Add a param function at the end of the sequence of env functions.
Definition: Environment.hh:456
YAML::Node Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition: types.hh:71
std::string to_string(const Config &node)
Given a config node, returns a string representation of it.
Definition: cfg_utils.hh:110
EnvParamFunc epf_sinusoidal(const EnvModel &model, const Config &cfg)
Creates a rule function for sinusoidal parameter values.
Definition: env_param_func_collection.hh:270
std::pair< EnvStateFunc, Update > esf_uniform(const EnvModel &, const std::string ¶m_name, const Config &cfg)
Creates a rule function for spatially uniform parameter values.
Definition: env_state_func_collection.hh:260
EnvParamFunc epf_random(const EnvModel &model, const std::string ¶m_name, const Config &cfg)
Creates a rule function for random parameter values.
Definition: env_param_func_collection.hh:106
EnvParamFunc epf_increment(const EnvModel &model, const std::string param_name, const Config &cfg)
Creates a rule function for incrementing parameter values.
Definition: env_param_func_collection.hh:73
std::pair< EnvStateFunc, Update > esf_steps(const EnvModel &, const std::string ¶m_name, const Config &cfg)
Creates a rule function for spatial steps in the parameter values.
Definition: env_state_func_collection.hh:201
EnvParamFunc epf_rectangular(const EnvModel &model, const Config &cfg)
Creates a rule function for rectangular function like parameter values.
Definition: env_param_func_collection.hh:181
std::pair< EnvStateFunc, Update > esf_slope(const EnvModel &, const std::string ¶m_name, const Config &cfg, const Extent &extent)
Creates a rule function for spatially linearly parameter values.
Definition: env_state_func_collection.hh:151
EnvParamFunc epf_set(const EnvModel &, const Config &cfg)
Creates a rule function for setting a parameter value.
Definition: env_param_func_collection.hh:236
std::pair< EnvStateFunc, Update > esf_noise(const EnvModel &model, const std::string ¶m_name, const Config &cfg)
Creates a rule function for noisy parameter values.
Definition: env_state_func_collection.hh:77
Update
Update modes when applying rules.
Definition: state.hh:20
@ async
Asynchronous update.
@ sync
Synchronous update.
DataIO::Config Config
Configuration node type alias.
Definition: env_param_func_collection.hh:13
arma::Col< double >::fixed< dim > SpaceVecType
Type for vector-like data that is associated with a physical space.
Definition: types.hh:61
EntityContainer< CellType > CellContainer
Type of the variably sized container for cells.
Definition: types.hh:26
A non-abstract EnvCellState, derived from the base class.
Definition: Environment.cc:50
A non-abstract EnvParam, derived from the base class.
Definition: Environment.cc:11
double get_env(const std::string &key) const override
Getter.
Definition: Environment.cc:23
void set_env(const std::string &key, const double &value) override
Setter.
Definition: Environment.cc:32
The entity traits struct gathers types to be used for specializing an entity.
Definition: entity.hh:49
Wrapper struct for defining model class data types.
Definition: model.hh:92
Base type for environment cell states.
Definition: Environment.hh:82
virtual void set_env(const std::string &, const double &)=0
Set an environment variable.
virtual double get_env(const std::string &) const =0
Get an environment variable.
SpaceVec position
Cached barycenter of the cell.
Definition: Environment.hh:86
SpaceVecType< 2 > SpaceVec
Definition: Environment.hh:83
virtual ~BaseEnvCellState()=default
Base type for environment parameter.
Definition: Environment.hh:45
virtual double get_env(const std::string &) const =0
Get an environment variable.
virtual ~BaseEnvParam()=default
virtual void set_env(const std::string &, const double &)=0
Set an environment variable.
Dummy type for environment cell states.
Definition: Environment.hh:102
double get_env(const std::string &) const override
Getter.
Definition: Environment.hh:108
~DummyEnvCellState()=default
void set_env(const std::string &, const double &) override
Setter.
Definition: Environment.hh:114
DummyEnvCellState(const DataIO::Config &)
Definition: Environment.hh:103
Dummy type for environment parameter.
Definition: Environment.hh:60
double get_env(const std::string &) const override
Getter.
Definition: Environment.hh:66
DummyEnvParam(const DataIO::Config &)
Definition: Environment.hh:61
void set_env(const std::string &, const double &) override
Setter.
Definition: Environment.hh:72
A dummy CellManager type that is used in standalone mode.
Definition: Environment.hh:184
DataIO::Config cfg() const
Always returns an empty node.
Definition: Environment.hh:186
A bundle wrapping a (iterative) function with metadata.
Definition: func_bundle.hh:42
A bundle wrapping a (rule-)function with metadata.
Definition: func_bundle.hh:71