Utopia 2
Framework for studying models of complex & adaptive systems.
Loading...
Searching...
No Matches
model.hh
Go to the documentation of this file.
1#ifndef UTOPIA_CORE_MODEL_HH
2#define UTOPIA_CORE_MODEL_HH
3
4#include <algorithm>
5
6#include "exceptions.hh"
7#include "signal.hh"
8#include "ostream.hh"
9#include "logging.hh"
10#include "space.hh"
11#include "parallel.hh"
12
13#include "../data_io/hdffile.hh"
14#include "../data_io/hdfgroup.hh"
15#include "../data_io/cfg_utils.hh"
16#include "../data_io/monitor.hh"
17#include "../data_io/data_manager/data_manager.hh"
18#include "../data_io/data_manager/factory.hh"
19
20
21namespace Utopia {
22
30enum class WriteMode {
32
38 basic,
39
41
48 managed,
49
51
57 manual,
58
60 off
61};
62
65
66
68
81template<
82 typename RNGType=DefaultRNG,
84 typename SpaceType=DefaultSpace,
88 typename TimeType=std::size_t,
91 >
104
105
107
110template<class Derived, typename ModelTypes>
111class Model
112{
113public:
114 // -- Data types uses throughout the model class --------------------------
116 using Config = typename ModelTypes::Config;
117
120
123
125 using DataSet = typename ModelTypes::DataSet;
126
128 using RNG = typename ModelTypes::RNG;
129
131 using Space = typename ModelTypes::Space;
132
134 using Time = typename ModelTypes::Time;
135
137 using Monitor = typename ModelTypes::Monitor;
138
141
143 using Level = typename ModelTypes::Level;
144
145
146protected:
147 // -- Member declarations -------------------------------------------------
149 const std::string _name;
150
152 const std::string _full_name;
153
156
159
161 const std::shared_ptr<RNG> _rng;
162
164 const std::shared_ptr<spdlog::logger> _log;
165
167 std::shared_ptr<Space> _space;
168
171
174
176 const std::shared_ptr<DataGroup> _hdfgrp;
177
180
183
186
189
191
195
196private:
197 // .. Construction helpers ................................................
198
200
202 template<class Parent>
203 auto setup_logger(const Parent& parent_model) const {
204 auto log = spdlog::stdout_color_mt(
205 parent_model.get_logger()->name() + "." + _name
206 );
207
208 // Set this model instance's log level
209 if (_cfg["log_level"]) {
210 // Via value given in configuration
211 const auto lvl = get_as<std::string>("log_level", _cfg);
212 log->debug("Setting log level to '{}' ...", lvl);
213 log->set_level(spdlog::level::from_str(lvl));
214 }
215 else {
216 // No config value given; use the level of the parent's logger
217 log->set_level(parent_model.get_logger()->level());
218 }
219
220 log->info("Model logger initialized.");
221 return log;
222 }
223
225 auto setup_space() const {
226 if (_cfg["space"]) {
227 auto space = std::make_shared<Space>(_cfg["space"]);
228 _log->info(
229 "Using {}periodic space with extent {}.",
230 space->periodic ? "" : "non-", Utils::str(space->extent)
231 );
232 return space;
233 }
234 else {
235 _log->debug(
236 "No model-level space configured; using default space."
237 );
238 return std::make_shared<Space>();
239 }
240 }
241
242
243public:
244 // -- Constructor ---------------------------------------------------------
245
247
269 template < class ParentModel, class... WriterArgs >
271 const std::string& name,
273 const Config& custom_cfg = {},
274 std::tuple< WriterArgs... > w_args = {},
275 const DataIO::Default::DefaultDecidermap< Derived >&
276 w_deciders = DataIO::Default::default_deciders< Derived >,
277 const DataIO::Default::DefaultTriggermap< Derived >&
278 w_triggers = DataIO::Default::default_triggers< Derived >
279 )
280 :
281 // First thing: setup name and position within model hierarchy
282 _name(name),
283 _full_name(parent_model.get_full_name() + "." + name),
285
286 // Retrieve the appropriate configuration entry from the parent model
287 _cfg(custom_cfg.size() ? custom_cfg
288 : get_as<Config>(_name, parent_model.get_cfg())),
289
290 // Construct infrastructure objects using information from parent
293
294 // Determine space and time
296 _time(0),
298 : get_as<Time>("num_steps", _cfg,
299 std::numeric_limits<Time>::max())),
300
301 // Extract the other information from the parent model object
302 _hdfgrp(parent_model.get_hdfgrp()->open_group(_name)),
303 _write_start(get_as<Time>("write_start", _cfg,
305 _write_every(get_as<Time>("write_every", _cfg,
307
308 // Set up the monitor, using the parent model's monitor to place it in
309 // a hierarchy equivalent to the model hierarchy
311
312 // Default-construct the data maanger; only used if needed, see below.
314 {
315 // Provide some information, also depending on write mode
316 _log->info("Model base constructor for '{}' finished.", _name);
317 _log->info(" full_name: {}", _full_name);
318 _log->info(" level: {}", _level);
319 _log->info(" time_max: {:7d}", _time_max);
320
321 if constexpr (_write_mode == WriteMode::basic) {
322 _log->info(" write_mode: {:>7s}", "basic");
323 _log->info(" write_start: {:7d}", _write_start);
324 _log->info(" write_every: {:7d}", _write_every);
325 _log->info(" #writes: {:7d}", get_remaining_num_writes());
326
327 // Store relevant info in base group attributes
328 _hdfgrp->add_attribute("write_mode", "basic");
329 _hdfgrp->add_attribute("write_start", _write_start);
330 _hdfgrp->add_attribute("write_every", _write_every);
331 _hdfgrp->add_attribute("time_max", _time_max);
332 }
333 else if constexpr (_write_mode == WriteMode::manual) {
334 _log->info(" write_mode: {:>7s}", "manual");
335 _hdfgrp->add_attribute("write_mode", "manual");
336 }
337 else if constexpr (_write_mode == WriteMode::off) {
338 _log->info(" write_mode: {:>7s}", "off");
339 _hdfgrp->add_attribute("write_mode", "off");
340 }
341 else if constexpr (_write_mode == WriteMode::managed) {
342 static_assert(sizeof...(WriterArgs) > 0,
343 "No arguments to construct write_tasks given!");
344
345 _log->info(" write_mode: {:>7s}", "managed");
346
347 // Store relevant info in base group attributes
348 _hdfgrp->add_attribute("write_mode", "managed");
349
350 // Some convenience key checks for nicer error messages.
351 if (not _cfg["data_manager"]) {
352 throw KeyError("data_manager", _cfg,
353 "Cannot set up DataManager!");
354 }
355 const auto dm_cfg = _cfg["data_manager"];
356
357 if (not dm_cfg["tasks"]) {
358 throw KeyError("tasks", dm_cfg,
359 "Cannot set up DataManager tasks!");
360 }
361 if (not dm_cfg["deciders"]) {
362 throw KeyError("deciders", dm_cfg,
363 "Cannot set up DataManager deciders!");
364 }
365 if (not dm_cfg["triggers"]) {
366 throw KeyError("triggers", dm_cfg,
367 "Cannot set up DataManager triggers!");
368 }
369
370 _log->info("Invoking DataManager task factory ...");
371
372 _datamanager = DataIO::DataManagerFactory<Derived>()(
374 );
375
376 _log->info("DataManager set up with {} task(s), {} decider(s), "
377 "and {} trigger(s).", _datamanager.get_tasks().size(),
378 _datamanager.get_deciders().size(),
379 _datamanager.get_triggers().size());
380 }
381 }
382
383
384
385 // -- Getters -------------------------------------------------------------
386
388 const std::shared_ptr<Space>& get_space() const {
389 return _space;
390 }
391
393 Time get_time() const {
394 return _time;
395 }
396
398
404 if (_time_max == std::numeric_limits<Time>::max()) {
405 this->_log->warn("Accessing the `time_max` of (sub-)model {} with "
406 "unlimited value!", this->get_full_name());
407 }
408 return _time_max;
409 }
410
412 Config get_cfg() const {
413 return _cfg;
414 }
415
417 std::string get_name() const {
418 return _name;
419 }
420
422 std::string get_full_name() const {
423 return _full_name;
424 }
425
427 std::shared_ptr<DataGroup> get_hdfgrp() const {
428 return _hdfgrp;
429 }
430
433 return _write_start;
434 }
435
438 return _write_every;
439 }
440
443 return _datamanager;
444 }
445
447
453 static_assert(
458 );
459
460 if constexpr (_write_mode == WriteMode::basic) {
461 if (_time_max == std::numeric_limits<hsize_t>::max()) {
462 return std::numeric_limits<hsize_t>::max();
463 }
464 return ( (_time_max - std::max(_time, _write_start))
465 / _write_every) + 1;
466 }
467 else if constexpr (_write_mode == WriteMode::manual) {
468 if (_time_max - _time == std::numeric_limits<hsize_t>::max()) {
469 return std::numeric_limits<hsize_t>::max();
470 }
471 return _time_max - _time + 1;
472 }
473 else {
474 return 0;
475 }
476
477 }
478
480 std::shared_ptr<RNG> get_rng() const {
481 return _rng;
482 }
483
485 std::shared_ptr<spdlog::logger> get_logger() const {
486 return _log;
487 }
488
491 return _monitor;
492 }
493
495 std::shared_ptr<MonitorManager> get_monitor_manager() const {
496 return _monitor.get_monitor_manager();
497 }
498
500 Level get_level() const {
501 return _level;
502 }
503
504
505 // -- Simulation control --------------------------------------------------
507
509 virtual void prolog () {
510 __prolog();
511 }
512
514
516 virtual void epilog () {
517 __epilog();
518 }
519
521
527 void iterate () {
528 // -- Perform the simulation step
531
532 // -- Monitoring
533 /* If the model is at the first hierarchical level, check whether the
534 * monitor entries should be collected and emitted. This leads to a
535 * flag being set in the monitor manager, such that the submodels do
536 * not have to do the check against the timer as well and that all
537 * collected data stems from the same time step.
538 */
539 if (_level == 1) {
540 _monitor.get_monitor_manager()->check_timer();
541 __monitor();
542
543 // If enabled for this step, perform the emission of monitor data
544 // NOTE At this point, we can be sure that all submodels have
545 // already run, because their iterate functions were called
546 // in the perform_step of the level 1 model.
547 _monitor.get_monitor_manager()->emit_if_enabled();
548 }
549 else {
550 __monitor();
551 }
552
553 // -- Data output
554 if constexpr (_write_mode == WriteMode::basic) {
555 if ( (_time >= _write_start)
556 and (_time - _write_start) % _write_every == 0) {
557 __write_data();
558 }
559 }
560 else if constexpr (_write_mode == WriteMode::manual) {
561 __write_data();
562 }
563 else if constexpr (_write_mode == WriteMode::managed) {
564 _datamanager(static_cast<Derived&>(*this));
565 }
566
567 if (_level == 1) {
568 _log->debug("Finished iteration: {:7d} / {:d}", _time, _time_max);
569 }
570 else {
571 _log->debug("Finished iteration: {:7d}", _time);
572 }
573 }
574
576
581 void run () {
582 if (_level > 1 and get_time_max() == std::numeric_limits<Time>::max()) {
583 throw std::runtime_error(fmt::format("Cannot perform run on "
584 "(sub-)model {} with unlimited `time_max`. You need to provide "
585 "`num_steps` to the model's configuration in order to use the "
586 "`run` method. See the nested models guide for further "
587 "information!", get_full_name()));
588 }
589
590 // First, attach the signal handler, such that the while loop below can
591 // be left upon receiving of a signal.
593
594 // call the prolog of the model
595 prolog();
596
597 // Now, let's go repeatedly iterate the model ...
598 _log->info("Running from current time {} to {} ...",
600
601 while (_time < _time_max) {
602 iterate();
603
604 if (stop_now.load()) {
605 const auto signum = received_signum.load();
606
607 if (signum == SIGUSR1) {
608 _log->warn("The stop condition for this run is fulfilled. "
609 "Not iterating further ...");
610 }
611 else {
612 _log->warn("Was told to stop. Not iterating further ...");
613 }
614
615 _log->info("Invoking epilog ...");
616 epilog();
617
618 throw GotSignal(received_signum.load());
619 }
620 }
621
622 _log->info("Run finished. Current time: {}", _time);
623
624 // call the epilog of the model
625 epilog();
626 }
627
628
629protected:
630 // -- Functions requiring/allowing user-defined implementations -----------
631
634 impl().perform_step();
635 }
636
638 /* The child implementation of this function will only be called if the
639 * monitor manager has determined that an emission will occur, because it
640 * only makes sense to collect data if it will be emitted in this step.
641 */
642 void __monitor () {
643 if (_monitor.get_monitor_manager()->emit_enabled()) {
644 // Perform actions that should only happen once by the monitor at
645 // the highest level of the model hierarchy.
646 if (_level == 1){
647 // Supply the global time. When reaching this point, all sub-
648 // models will also have reached this time.
649 _monitor.get_monitor_manager()->set_time_entries(_time,
650 _time_max);
651 // This method also sets the other top level entries
652 }
653
654 // Call the child's implementation of the monitor functions.
655 impl().monitor();
656 }
657 }
658
660 void __write_data () {
661 _log->trace("Calling write_data ...");
662 impl().write_data();
663 }
664
667 // Select the required WriteMode
668 // Decide on whether the initial state needs to be written
669 if constexpr (_write_mode == WriteMode::basic) {
670 if (_write_start == _time) {
671 _log->info("Writing initial state ...");
672 __write_data();
673 }
674 }
675 else if constexpr (_write_mode == WriteMode::manual) {
676 __write_data();
677 }
678 else if constexpr (_write_mode == WriteMode::managed) {
679 _datamanager(static_cast<Derived&>(*this));
680 }
681
682 }
683
685
687 void increment_time (const Time dt=1) {
688 _time += dt;
689 }
690
692
695 void __prolog () {
697
698 this->_log->debug("Prolog finished.");
699 }
700
702
705 void __epilog () {
706 this->_log->debug("Epilog finished.");
707 }
708
709
710 // -- CRTP ----------------------------------------------------------------
713 return static_cast<Derived&>(*this);
714 }
715
717 const Derived& impl () const {
718 return static_cast<const Derived&>(*this);
719 }
720
721
722public:
723 // -- Convenience functions -----------------------------------------------
724
751 std::shared_ptr<DataSet>
752 create_dset(const std::string name,
753 const std::shared_ptr<DataGroup>& hdfgrp,
754 std::vector<hsize_t> add_write_shape,
755 const std::size_t compression_level=1,
756 const std::vector<hsize_t> chunksize={})
757 {
758 _log->debug("Creating dataset '{}' in group '{}' ...",
759 name, hdfgrp->get_path());
760
761 // Calculate the number of time steps to be written
763
764 // Calculate the shape of the dataset
766 auto capacity = add_write_shape;
767
768 // Create the dataset and return it.
769 const auto dset = hdfgrp->open_dataset(name, capacity,
771 _log->debug("Successfully created dataset '{}'.", name);
772
773 // Write further attributes, if not specifically suppressed
774 if (get_as<bool>("write_dim_labels_and_coords", _cfg, true)) {
775 // We know that dimension 0 is the time dimension. Add the
776 // attributes that specify dimension names and coordinates:
777 dset->add_attribute("dim_name__0", "time");
778 dset->add_attribute("coords_mode__time", "start_and_step");
779 dset->add_attribute("coords__time",
780 std::vector<std::size_t>{_write_start,
781 _write_every});
782 _log->debug("Added time dimension labels and coordinates to "
783 "dataset '{}'.", name);
784 }
785
786 return dset;
787 }
788
814 std::shared_ptr<DataSet>
815 create_dset(const std::string name,
816 const std::vector<hsize_t> add_write_shape,
817 const std::size_t compression_level=1,
818 const std::vector<hsize_t> chunksize={})
819 {
820 // Forward to the main create_dset function
821 return create_dset(name,
822 _hdfgrp, // The base group for this model
824 }
825
847 template<class CellManager>
848 std::shared_ptr<DataSet>
849 create_cm_dset(const std::string name,
850 const CellManager& cm,
851 const std::size_t compression_level=1,
852 const std::vector<hsize_t> chunksize={})
853 {
854 // Forward to the main create_dset function
855 const auto dset = create_dset(
856 name,
857 _hdfgrp,
858 {cm.cells().size()}, // -> 2D dataset
861 );
862
863 // Set attributes to mark this dataset as containing grid data
864 dset->add_attribute("content", "grid");
865
866 // Need further attributes to denote the grid structure, size, etc.
867 const auto grid_structure = cm.grid()->structure_name();
868 dset->add_attribute("grid_structure", grid_structure);
869 dset->add_attribute("grid_shape", cm.grid()->shape());
870 dset->add_attribute("space_extent", cm.grid()->space()->extent);
871 dset->add_attribute("periodic_space", cm.grid()->space()->periodic);
872
873 if (grid_structure == "hexagonal") {
874 // ... some additional info is needed, which is dependent on the
875 // way the HexagonalGrid maps cells
876 dset->add_attribute("coordinate_mode", "offset");
877 dset->add_attribute("offset_mode", "even");
878 dset->add_attribute("pointy_top", true);
879 }
880
881 // The CellManager uses "column-style" index ordering, also called
882 // "Fortran-style". This is relevant for assigning the correct IDs.
883 dset->add_attribute("index_order", "F");
884
885 _log->debug("Added attributes to dataset '{}' to mark it as storing "
886 "grid data.", name);
887
888 // Write additional attributes, if not specifically suppressed.
889 if (get_as<bool>("write_dim_labels_and_coords", _cfg, true)) {
890 // We know that the dimensions here refer to (time, cell ids).
891 // The time information is already added in create_dset; only need
892 // to add the ID information here
893 dset->add_attribute("dim_name__1", "ids");
894
895 // For ids, the dimensions are trivial
896 dset->add_attribute("coords_mode__ids", "range");
897 dset->add_attribute("coords__ids",
898 std::vector<std::size_t>{cm.cells().size()});
899
900 _log->debug("Added cell ID dimension labels and coordinates to "
901 "dataset '{}'.", name);
902 }
903
904 return dset;
905 }
906
907
937 template<class AgentManager>
938 std::shared_ptr<DataSet>
939 create_am_dset(const std::string name,
940 const AgentManager& am,
941 const std::size_t compression_level=1,
942 const std::vector<hsize_t> chunksize = {})
943 {
944 // Forward to the main create_dset function
945 const auto dset = create_dset(
946 name,
947 _hdfgrp,
948 {am.agents().size()}, // --> 2D: time, agents
951 );
952
953 // Set attribute to store the agent managers' extent of space
954 dset->add_attribute("space_extent", am.space()->extent);
955 _log->debug("Added attribute to dataset '{}' to store space extent",
956 name);
957
958 // Write additional attributes, if not specifically suppressed.
959 if (get_as<bool>("write_dim_labels_and_coords", _cfg, true)) {
960 // We know that the dimensions here refer to (time, agent ids). The
961 // time information is already added in create_dset; add only ID
962 // information here. Note that this assumes trivial and constant
963 // agent IDs!
964 dset->add_attribute("dim_name__1", "ids");
965
966 // For ids, the dimensions are trivial
967 dset->add_attribute("coords_mode__ids", "trivial");
968
969 _log->debug("Added agent index dimension labels and coordinates "
970 "to dataset '{}'.", name);
971 }
972
973 return dset;
974 }
975
976
977private:
978 // -- Private Helper Methods ----------------------------------------------
979
981
991 _log->debug("Attaching signal handlers for SIGINT and SIGTERM ...");
992
995
996 _log->debug("Attaching signal handler for stop conditions, triggered "
997 "by SIGUSR1 ({:d}) ...", SIGUSR1);
999
1000 _log->debug("Signal handlers attached.");
1001 }
1002};
1003
1004
1005
1007
1015template<typename RNG=DefaultRNG>
1017{
1018protected:
1020
1023
1026
1027 using Time = std::size_t;
1028 using Level = std::size_t;
1029
1032
1035
1037 const std::shared_ptr<HDFFile> _hdffile;
1038
1040 const std::shared_ptr<RNG> _rng;
1041
1043
1046 const std::shared_ptr<spdlog::logger> _log;
1047
1049 const std::shared_ptr<MonitorManager> _monitor_mgr;
1050
1053
1054public:
1056
1063 PseudoParent (const std::string cfg_path)
1064 :
1065 // The hierarchical level is 0
1066 _level(0),
1067 // Initialize the config node from the path to the config file
1069 // Create a file at the specified output path and store the shared pointer
1071 get_as<std::string>("output_path", _cfg),
1072 get_as<std::string>("output_file_mode", _cfg, "w")
1073 )),
1074 // Initialize the RNG from a seed
1075 _rng(std::make_shared<RNG>(get_as<int>("seed", _cfg))),
1076 // And initialize the root logger at warning level
1078 // Create a monitor manager and a root monitor
1080 get_as<double>("monitor_emit_interval", _cfg))
1081 ),
1083 {
1084 setup_loggers(); // global loggers
1085 set_log_level(); // this log level
1087
1088 _log->info("Initialized PseudoParent from config file");
1089 _log->debug("cfg_path: {}", cfg_path);
1090 _log->debug("output_path: {}", get_as<std::string>("output_path",
1091 _cfg));
1092 _log->debug("RNG seed: {}", get_as<int>("seed", _cfg));
1093 _log->debug("emit_interval: {}s",
1094 get_as<double>("monitor_emit_interval", _cfg));
1095 }
1096
1097
1099
1106 PseudoParent (const std::string cfg_path,
1107 const std::string output_path,
1108 const int seed=42,
1109 const std::string output_file_mode="w",
1110 const double emit_interval=5.)
1111 :
1112 // The hierarchical level is 0
1113 _level(0),
1114 // Initialize the config node from the path to the config file
1116 // Create a file at the specified output path
1118 // Initialize the RNG from a seed
1119 _rng(std::make_shared<RNG>(seed)),
1120 // And initialize the root logger at warning level
1122 // Create a monitor manager and a "root" monitor
1125 {
1126 setup_loggers(); // global loggers
1127 set_log_level(); // this log level
1129
1130 _log->info("Initialized PseudoParent from parameters");
1131 _log->debug("cfg_path: {}", cfg_path);
1132 _log->debug("output_path: {} (mode: {})",
1134 _log->debug("RNG seed: {}", seed);
1135 _log->debug("emit_interval: {}", emit_interval);
1136 }
1137
1138
1139
1140 // -- Getters -- //
1141
1144 return _level;
1145 }
1146
1148 std::string get_full_name() const {
1149 return "";
1150 }
1151
1153 Config get_cfg() const {
1154 return _cfg;
1155 }
1156
1158 std::shared_ptr<HDFFile> get_hdffile() const {
1159 return _hdffile;
1160 }
1161
1163 std::shared_ptr<HDFGroup> get_hdfgrp() const {
1164 return _hdffile->get_basegroup();
1165 }
1166
1169 return get_as<Time>("write_start", _cfg, 0);
1170 }
1171
1174 return get_as<Time>("write_every", _cfg, 1);
1175 }
1176
1178 std::shared_ptr<RNG> get_rng() const {
1179 return _rng;
1180 }
1181
1183 std::shared_ptr<spdlog::logger> get_logger() const {
1184 return _log;
1185 }
1186
1188
1192 return get_as<Time>("num_steps", _cfg);
1193 }
1194
1196 std::shared_ptr<MonitorManager> get_monitor_manager() const {
1197 return _monitor_mgr;
1198 }
1199
1201 const Monitor& get_monitor() const {
1202 return _monitor;
1203 }
1204
1205
1206private:
1207
1209
1217 void setup_loggers () const {
1219 spdlog::level::from_str(
1220 get_as<std::string>("core", _cfg["log_levels"])
1221 ),
1222 spdlog::level::from_str(
1223 get_as<std::string>("data_io", _cfg["log_levels"])
1224 ),
1225 spdlog::level::from_str(
1226 get_as<std::string>("data_mngr", _cfg["log_levels"], "warn")
1227 ),
1228 get_as<std::string>("log_pattern", _cfg, "")
1229 );
1230 }
1231
1233 void set_log_level () const {
1234 _log->set_level(
1235 spdlog::level::from_str(get_as<std::string>("model",
1236 _cfg["log_levels"]))
1237 );
1238 }
1239};
1240
1241
1242// end group Model
1247} // namespace Utopia
1248
1249#endif // UTOPIA_CORE_MODEL_HH
The agent manager manages the agents living in a model.
Definition agent_manager.hh:31
Manages a physical space, its grid discretization, and cells on that grid.
Definition cell_manager.hh:41
const std::shared_ptr< GridType > & grid() const
Return const reference to the grid.
Definition cell_manager.hh:214
const CellContainer< Cell > & cells() const
Return const reference to the managed CA cells.
Definition cell_manager.hh:219
Manage different tasks of writing out data from a source in a uniform yet flexible way....
Definition data_manager.hh:131
TriggerMap & get_triggers()
Get the container of trigger objects.
Definition data_manager.hh:493
DeciderMap & get_deciders()
Get the container of decider objects.
Definition data_manager.hh:471
TaskMap & get_tasks()
Get the container of task objects.
Definition data_manager.hh:482
Class representing a HDFDataset, wich reads and writes data and attributes.
Definition hdfdataset.hh:53
Class representing a HDF5 file.
Definition hdffile.hh:62
Class represting a HDFGroup, an object analogous to a folder for HDFFiles.
Definition hdfgroup.hh:41
The Monitor monitors entries that are emitted if a given time has passed.
Definition monitor.hh:323
The MonitorManager manages the monitor entries and MonitorTimer.
Definition monitor.hh:159
An exception for when the program should end due to handling of a signal.
Definition exceptions.hh:51
Base class interface for Models using the CRT Pattern.
Definition model.hh:112
void __prolog()
The default prolog of a model.
Definition model.hh:695
DataManager get_datamanager() const
return the datamanager
Definition model.hh:442
std::shared_ptr< DataSet > create_cm_dset(const std::string name, const CellManager &cm, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
Create a dataset storing data from a CellManager.
Definition model.hh:849
auto setup_logger(const Parent &parent_model) const
Constructs this models logger instance from the parent.
Definition model.hh:203
auto setup_space() const
Constructs the Space from configuration or uses the default Space.
Definition model.hh:225
typename ModelTypes::MonitorManager MonitorManager
Data type for the monitor manager.
Definition model.hh:140
typename ModelTypes::Level Level
Data type for the hierarchical level.
Definition model.hh:143
const std::shared_ptr< DataGroup > _hdfgrp
The HDF group this model instance should write its data to.
Definition model.hh:176
void __write_initial_state()
Write the initial state.
Definition model.hh:666
DataManager _datamanager
Manager object for handling data output; see DataManager.
Definition model.hh:194
std::shared_ptr< DataGroup > get_hdfgrp() const
Return a pointer to the HDF group this model stores data in.
Definition model.hh:427
std::shared_ptr< spdlog::logger > get_logger() const
Return a pointer to the logger of this model.
Definition model.hh:485
std::shared_ptr< MonitorManager > get_monitor_manager() const
Get the monitor manager of the root model.
Definition model.hh:495
Monitor _monitor
The monitor.
Definition model.hh:188
void run()
Run the model from the current time to the maximum time.
Definition model.hh:581
void iterate()
Iterate one (time) step of this model.
Definition model.hh:527
void __attach_sig_handlers() const
Attaches signal handlers: SIGINT, SIGTERM, SIGUSR1.
Definition model.hh:990
Monitor get_monitor() const
Return the monitor of this model.
Definition model.hh:490
const Time _write_start
First time at which write_data is called.
Definition model.hh:182
Time get_time_max() const
Return the maximum time possible for this model.
Definition model.hh:403
const Derived & impl() const
const cast to the derived interface
Definition model.hh:717
typename ModelTypes::DataSet DataSet
Data type that is used for storing data.
Definition model.hh:125
const Config _cfg
Config node belonging to this model instance.
Definition model.hh:158
const Time _write_every
How often to call write_data from iterate.
Definition model.hh:185
std::shared_ptr< DataSet > create_dset(const std::string name, const std::vector< hsize_t > add_write_shape, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
Create a new dataset within the model's base data group.
Definition model.hh:815
Time _time
Model-internal current time stamp.
Definition model.hh:170
typename ModelTypes::Space Space
Data type of the space this model resides in.
Definition model.hh:131
const std::string _name
Name of the model instance.
Definition model.hh:149
std::string get_full_name() const
Return the full name of this model within the model hierarchy.
Definition model.hh:422
std::string get_name() const
Return the name of this model instance.
Definition model.hh:417
Time get_time() const
Return the current time of this model.
Definition model.hh:393
Derived & impl()
cast to the derived class
Definition model.hh:712
void __monitor()
Monitor information in the terminal.
Definition model.hh:642
const Time _time_max
Model-internal maximum time stamp.
Definition model.hh:173
void __perform_step()
Perform the computation of a step.
Definition model.hh:633
Model(const std::string &name, const ParentModel &parent_model, const Config &custom_cfg={}, std::tuple< WriterArgs... > w_args={}, const DataIO::Default::DefaultDecidermap< Derived > &w_deciders=DataIO::Default::default_deciders< Derived >, const DataIO::Default::DefaultTriggermap< Derived > &w_triggers=DataIO::Default::default_triggers< Derived >)
Constructs a Model instance.
Definition model.hh:270
void __write_data()
Write data; calls the implementation's write_data method.
Definition model.hh:660
hsize_t get_remaining_num_writes() const
Return the number of remaining write_data calls this model will make.
Definition model.hh:452
virtual void epilog()
A function that is called after the last iteration of a model.
Definition model.hh:516
Config get_cfg() const
Return the config node of this model.
Definition model.hh:412
Time get_write_start() const
Return the parameter that controls when write_data is called first.
Definition model.hh:432
Level get_level() const
Return the hierarchical level within the model hierarchy.
Definition model.hh:500
const Level _level
The level within the model hierarchy.
Definition model.hh:155
typename ModelTypes::DataGroup DataGroup
Data type that is used for storing datasets.
Definition model.hh:122
virtual void prolog()
A function that is called before starting model iteration.
Definition model.hh:509
void __epilog()
The default epilog of a model.
Definition model.hh:705
typename ModelTypes::Time Time
Data type for the model time.
Definition model.hh:134
typename ModelTypes::Config Config
Data type that holds the configuration.
Definition model.hh:116
typename ModelTypes::Monitor Monitor
Data type for the monitor.
Definition model.hh:137
std::shared_ptr< DataSet > create_am_dset(const std::string name, const AgentManager &am, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
Create a dataset storing data from a AgentManager.
Definition model.hh:939
typename ModelTypes::RNG RNG
Data type of the shared RNG.
Definition model.hh:128
Time get_write_every() const
Return the parameter that controls how often write_data is called.
Definition model.hh:437
const std::string _full_name
The full name within the model hierarchy.
Definition model.hh:152
std::shared_ptr< RNG > get_rng() const
Return a pointer to the shared RNG.
Definition model.hh:480
const std::shared_ptr< spdlog::logger > _log
The (model) logger.
Definition model.hh:164
void increment_time(const Time dt=1)
Increment time.
Definition model.hh:687
static constexpr WriteMode _write_mode
Which data-writing mode the base model should use.
Definition model.hh:179
const std::shared_ptr< RNG > _rng
The RNG shared between models.
Definition model.hh:161
std::shared_ptr< DataSet > create_dset(const std::string name, const std::shared_ptr< DataGroup > &hdfgrp, std::vector< hsize_t > add_write_shape, const std::size_t compression_level=1, const std::vector< hsize_t > chunksize={})
Create a new dataset within the given group.
Definition model.hh:752
const std::shared_ptr< Space > & get_space() const
Return the space this model resides in.
Definition model.hh:388
std::shared_ptr< Space > _space
The space this model resides in.
Definition model.hh:167
static void init(const DataIO::Config &cfg)
Initialize parallel features based on configuration setting.
Definition parallel.hh:113
A class to use at the top level of the model hierarchy as a mock parent.
Definition model.hh:1017
std::shared_ptr< MonitorManager > get_monitor_manager() const
Return the monitor manager of this model.
Definition model.hh:1196
Utopia::DataIO::Config Config
Definition model.hh:1019
Monitor _monitor
The monitor instance of this root model.
Definition model.hh:1052
void set_log_level() const
Set the log level for the pseudo parent from the base_cfg.
Definition model.hh:1233
std::size_t Level
Definition model.hh:1028
std::shared_ptr< HDFFile > get_hdffile() const
Return a pointer to the HDF data file.
Definition model.hh:1158
const Config _cfg
The config node.
Definition model.hh:1034
Level get_level() const
Return the hierarchical level within the model hierarchy.
Definition model.hh:1143
const std::shared_ptr< RNG > _rng
Pointer to a RNG that can be shared between models.
Definition model.hh:1040
const Monitor & get_monitor() const
Return the monitor of this model.
Definition model.hh:1201
const std::shared_ptr< spdlog::logger > _log
Pointer to the logger of this (pseudo) model.
Definition model.hh:1046
std::shared_ptr< HDFGroup > get_hdfgrp() const
Return a pointer to the HDF group, which is the base group of the file.
Definition model.hh:1163
Time get_time_max() const
The maximum time value as it can be found in the config.
Definition model.hh:1191
const std::shared_ptr< MonitorManager > _monitor_mgr
The monitor manager.
Definition model.hh:1049
Time get_write_start() const
Return the parameter that controls when write_data is called first.
Definition model.hh:1168
PseudoParent(const std::string cfg_path, const std::string output_path, const int seed=42, const std::string output_file_mode="w", const double emit_interval=5.)
Constructor that allows granular control over config parameters.
Definition model.hh:1106
PseudoParent(const std::string cfg_path)
Constructor that only requires path to a config file.
Definition model.hh:1063
std::size_t Time
Definition model.hh:1027
Time get_write_every() const
Return the parameter that controls how often write_data is called.
Definition model.hh:1173
const Level _level
The hierarchical level.
Definition model.hh:1031
void setup_loggers() const
Set up the global loggers with levels specified in the config file.
Definition model.hh:1217
std::shared_ptr< RNG > get_rng() const
Return a pointer to the RNG.
Definition model.hh:1178
std::string get_full_name() const
Return the full name of the PseudoParent: an empty string.
Definition model.hh:1148
const std::shared_ptr< HDFFile > _hdffile
Pointer to the HDF5 file where data is written to.
Definition model.hh:1037
Config get_cfg() const
Return the config node of the Pseudo model, i.e. the root node.
Definition model.hh:1153
std::shared_ptr< spdlog::logger > get_logger() const
Return a pointer to the logger of this model.
Definition model.hh:1183
YAML::Node Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition types.hh:71
ReturnType get_as(const std::string &key, const DataIO::Config &node)
This function is a wrapper around the yaml-cpp YAML::Node::as function.
Definition cfg_utils.hh:158
Container select_entities(const Manager &mngr, const DataIO::Config &sel_cfg)
Select entities according to parameters specified in a configuration.
Definition select.hh:213
std::shared_ptr< spdlog::logger > init_logger(const std::string name, const spdlog::level::level_enum level, const bool throw_on_exist=true)
Initialize a logger with a certain name and log level.
Definition logging.hh:31
void setup_loggers(const spdlog::level::level_enum level_core=spdlog::level::warn, const spdlog::level::level_enum level_data_io=spdlog::level::warn, const spdlog::level::level_enum level_data_mngr=spdlog::level::warn, const std::string &log_pattern="")
Set up and register the global loggers and set the global log pattern.
Definition logging.hh:66
WriteMode
How to write data in the models.
Definition model.hh:30
constexpr WriteMode DefaultWriteMode
Alias for the default write mode.
Definition model.hh:64
Space< 2 > DefaultSpace
The default Space object to be used throughout Utopia.
Definition space.hh:220
@ off
The write_data method is never called.
@ manual
Fully manual: write_data method is always called.
@ managed
Use the DataManager to handle output.
@ basic
Basic writing features: write_start, write_every.
@ off
Immediately apply the rule sequentially.
std::string str(T &&t)
Turn any object for which operator<< exists into a string. Mostly useful for logging data via spdlog ...
Definition ostream.hh:164
Definition agent.hh:11
std::atomic< bool > stop_now
The flag indicating whether to stop whatever is being done right now.
Definition signal.hh:15
std::mt19937 DefaultRNG
Type of default random number generator.
Definition types.hh:17
std::atomic< int > received_signum
The received signal value.
Definition signal.hh:18
void attach_signal_handler(int signum, Handler &&handler)
Attaches a signal handler for the given signal via sigaction.
Definition signal.hh:35
Definition parallel.hh:235
Wrapper struct for defining model class data types.
Definition model.hh:92
ConfigType Config
Definition model.hh:96
TimeType Time
Definition model.hh:99
static constexpr WriteMode write_mode
Definition model.hh:94
std::size_t Level
Definition model.hh:102
RNGType RNG
Definition model.hh:93
MonitorManagerType MonitorManager
Definition model.hh:101
DataSetType DataSet
Definition model.hh:98
MonitorType Monitor
Definition model.hh:100
SpaceType Space
Definition model.hh:95
DataGroupType DataGroup
Definition model.hh:97