Utopia  2
Framework for studying models of complex & adaptive systems.
defaults.hh
Go to the documentation of this file.
1 #ifndef UTOPIA_DATAIO_DATA_MANAGER_DEFAULTS_HH
2 #define UTOPIA_DATAIO_DATA_MANAGER_DEFAULTS_HH
3 
4 #include <boost/hana/ext/std/tuple.hpp>
5 #include <boost/hana/fold.hpp>
6 #include <boost/hana/zip.hpp>
7 #include <unordered_map>
8 
9 #include "../cfg_utils.hh"
10 #include "write_task.hh"
11 
12 namespace Utopia
13 {
14 namespace DataIO
15 {
16 namespace Default
17 {
18 
28 // =============================================================================
29 // ================================ Writer Tasks ===============================
30 // =============================================================================
31 
34  std::function< std::shared_ptr< HDFGroup >(std::shared_ptr< HDFGroup >&&) >;
35 
37 template < typename Model >
39  std::function< void(std::shared_ptr< HDFDataset >&, Model&) >;
40 
42 template < typename Model >
43 using DefaultBuilder = std::function< std::shared_ptr< HDFDataset >(
44  std::shared_ptr< HDFGroup >&, Model&) >;
45 
47 template < typename Model >
49  std::function< void(std::shared_ptr< HDFGroup >&, Model&) >;
50 
52 template < typename Model >
54  std::function< void(std::shared_ptr< HDFDataset >&, Model&) >;
55 
64 template < typename Model >
70 
71 // =============================================================================
72 // ================================ Execution Process ==========================
73 // =============================================================================
74 
84 {
94  template < class Datamanager, class Model >
95  void
96  operator()(Datamanager& dm, Model& m)
97  {
98  auto& tasks = dm.get_tasks();
99  for (auto& taskpair : tasks)
100  {
101  // TODO Instead of nullptr-check, check boolean?!
102  if (taskpair.second->base_group == nullptr)
103  {
104  taskpair.second->base_group =
105  taskpair.second->build_basegroup(m.get_hdfgrp());
106  }
107  }
108  for (auto& [name, trigger] : dm.get_triggers())
109  {
110  if ((*trigger)(m))
111  {
112  for (auto& taskname : dm.get_trigger_task_map()[name])
113  {
114  // using this ref variable avoids recomputing
115  // 'taskname''s hash all the time, should give minor
116  // performance improvement
117  auto& task = tasks[taskname];
118 
119  task->active_dataset =
120  task->build_dataset(
121  task->base_group, m);
122 
123  if (task->write_attribute_basegroup)
124  {
125  task->write_attribute_basegroup(
126  task->base_group, m);
127  }
128  }
129  }
130  }
131 
132  for (auto& [name, decider] : dm.get_deciders())
133  {
134  if ((*decider)(m))
135  {
136  for (auto& taskname : dm.get_decider_task_map()[name])
137  {
138  auto& task = tasks[taskname];
139 
140  task->write_data(task->active_dataset,
141  m);
142  if (task->write_attribute_active_dataset)
143  {
144  task->write_attribute_active_dataset(
145  task->active_dataset, m);
146  }
147  }
148  }
149  }
150  }
151 };
152 
153 
154 // =============================================================================
155 // ================================ Decider ====================================
156 // =============================================================================
157 
165 template<typename Model>
166 struct Decider {
167 
168  virtual bool operator()(Model&) = 0;
169  virtual void set_from_cfg(const Config&) = 0;
170 
171  Decider() = default;
172  Decider(const Decider&) = default;
173  Decider(Decider&&) = default;
174  Decider&
175  operator=(const Decider&) = default;
176  Decider&
177  operator=(Decider&&) = default;
178  virtual ~Decider() = default;
179 };
180 
181 
183 
186 template < typename Model >
187 struct IntervalDecider : Decider< Model >
188 {
189 
192 
194  std::list< std::array< std::size_t, 3 > > intervals;
195 
196  virtual bool
197  operator()(Model& m) override
198  {
199  // Are at the end of the current interval; pop it, such that
200  // at next invocation the front is the new interval
201  if (intervals.size() != 0 and m.get_time() == intervals.front()[1])
202  {
203  intervals.pop_front();
204  }
205 
206  if (intervals.size() != 0)
207  {
208  const auto [start, stop, step] = intervals.front();
209  // Check if within [start, end) interval
210  if ((m.get_time() >= start) and (m.get_time() < stop) and
211  ((m.get_time() - start) % step == 0))
212  {
213  return true;
214  }
215  }
216  return false;
217  }
223  virtual void
224  set_from_cfg(const Config& cfg) override
225  {
226  auto tmp = get_as< std::list< std::vector< std::size_t > > >(
227  "intervals", cfg);
228  for (std::vector< std::size_t > tmp_interval : tmp)
229  {
230  if (tmp_interval.size() == 2)
231  {
232  tmp_interval.push_back(1);
233  }
234  else if (tmp_interval.size() != 3)
235  {
236  throw Utopia::KeyError("intervals", cfg,
237  fmt::format("Array of unexpected length {}! "
238  "Expected array of length 2 or 3 [start, stop, step] "
239  "with step optional (default 1).",
240  tmp_interval.size())
241  );
242  }
243 
244  std::array< std::size_t, 3 > interval;
245  std::copy(tmp_interval.begin(), tmp_interval.end(),
246  interval.begin());
247  intervals.push_back(interval);
248  }
249  }
250 
251  IntervalDecider() = default;
252  IntervalDecider(const IntervalDecider&) = default;
255  operator=(const IntervalDecider&) = default;
258  virtual ~IntervalDecider() = default;
259 };
260 
264 template < typename Model >
265 struct OnceDecider : Decider< Model >
266 {
269  std::size_t time;
270 
271  virtual bool
272  operator()(Model& m) override
273  {
274  return (m.get_time() == time);
275  }
276 
282  virtual void
283  set_from_cfg(const Config& cfg) override
284  {
285  time = get_as< std::size_t >("time", cfg);
286  }
287 
289  OnceDecider() = default;
290 
291  OnceDecider(const OnceDecider&) = default;
292  OnceDecider(OnceDecider&&) = default;
293  OnceDecider&
294  operator=(const OnceDecider&) = default;
295  OnceDecider&
296  operator=(OnceDecider&&) = default;
297  virtual ~OnceDecider() = default;
298 };
299 
303 template < typename Model >
304 struct AlwaysDecider : Decider< Model >
305 {
308 
309  virtual bool
310  operator()(Model&) override
311  {
312  return true;
313  }
314 
315  // dummy implementation of
316  virtual void
317  set_from_cfg(const Config&) override {}
318 
319  AlwaysDecider() = default;
320 
321  AlwaysDecider(const AlwaysDecider&) = default;
324  operator=(const AlwaysDecider&) = default;
326  operator=(AlwaysDecider&&) = default;
327  virtual ~AlwaysDecider() = default;
328 };
329 
336 template < typename Model, typename... Deciders >
337 struct CompositeDecider : Decider< Model >
338 {
341 
343  std::tuple< Deciders... > held_deciders;
344 
350  virtual bool
351  operator()(Model& m) override
352  {
353  return boost::hana::fold(
354  held_deciders, false, [&m](bool res, auto&& decider) {
355  return (res or decider(m));
356  });
357  }
358 
366  virtual void
367  set_from_cfg(const Config& cfg) override
368  {
369  // BAD: User has to be smart about it, because it breaks
370  // if args are not the same order as Deciders...
371  std::array< const Config&, sizeof...(Deciders) > configs;
372 
373  // make the args node for each decider into an array
374  auto conf_it = configs.begin();
375 
376  for (auto it = cfg.begin(); it != cfg.end(); ++it, ++conf_it)
377  {
378  *conf_it = it->second["args"];
379  }
380 
381  // then iterate over the zipped confs and deciders and built the
382  // deciders with their respective config
383  boost::hana::for_each(boost::hana::zip(configs, held_deciders),
384  [](auto&& conf_dcd_pair) {
385  auto&& [c, d] = conf_dcd_pair;
386  d.set_from_cfg(c);
387  });
388  }
389 
390  CompositeDecider() = default;
393  operator=(const CompositeDecider&) = default;
396  virtual ~CompositeDecider() = default;
397 };
398 
399 // =============================================================================
400 // =========================== Default type maps ==============================
401 // =============================================================================
402 
403 template < typename Model >
404 using DefaultDecidermap = std::unordered_map<
405  std::string,
406  std::function< std::shared_ptr< Decider< Model > >() > >;
407 
419 template < typename Model >
421  { std::string("always"),
422  []() { return std::make_shared< AlwaysDecider< Model > >(); } },
423  { std::string("once"),
424  []() { return std::make_shared< OnceDecider< Model > >(); } },
425  { std::string("interval"),
426  []() { return std::make_shared< IntervalDecider< Model > >(); } }
427 };
428 
429 // =============================================================================
430 // ================================ Triggers
431 // ===================================
432 // =============================================================================
433 
438 template < typename Model >
440 
441 template < typename Model >
443 
444 template < typename Model >
446 
447 template < typename Model >
449 
450 template < typename Model, typename... Deciders >
451 using CompositeTrigger = CompositeDecider< Model, Deciders... >;
452 
453 template < typename Model >
460 template < typename Model >
461 static DefaultTriggermap<Model> default_triggers = default_deciders< Model >;
462 
467 } // namespace Default
468 } // namespace DataIO
469 } // namespace Utopia
470 
471 #endif
For access to a dict-like structure with a bad key.
Definition: exceptions.hh:67
Base class interface for Models using the CRT Pattern.
Definition: model.hh:112
std::shared_ptr< DataGroup > get_hdfgrp() const
Return a pointer to the HDF group this model stores data in.
Definition: model.hh:427
Time get_time() const
Return the current time of this model.
Definition: model.hh:393
OutputIt copy(const Utopia::ExecPolicy policy, InputIt first, InputIt last, OutputIt d_first)
Copy the input range to a new range.
Definition: parallel.hh:324
void for_each(const Utopia::ExecPolicy policy, InputIt first, InputIt last, UnaryFunction f)
Apply a function to a range.
Definition: parallel.hh:346
YAML::Node Config
Type of a variadic dictionary-like data structure used throughout Utopia.
Definition: types.hh:71
static DefaultDecidermap< Model > default_deciders
Map that names the deciders supplied by default such that they can be addressed in a config file.
Definition: defaults.hh:420
std::function< void(std::shared_ptr< HDFDataset > &, Model &) > DefaultAttributeWriterDataset
Type of the default attribute writer for datasets.
Definition: defaults.hh:54
std::function< std::shared_ptr< HDFGroup >(std::shared_ptr< HDFGroup > &&) > DefaultBaseGroupBuilder
Type of the default group builder.
Definition: defaults.hh:34
std::unordered_map< std::string, std::function< std::shared_ptr< Decider< Model > >() > > DefaultDecidermap
Definition: defaults.hh:406
std::function< std::shared_ptr< HDFDataset >(std::shared_ptr< HDFGroup > &, Model &) > DefaultBuilder
Type of the default dataset builder.
Definition: defaults.hh:44
std::function< void(std::shared_ptr< HDFGroup > &, Model &) > DefaultAttributeWriterGroup
Type of the default attribute writer for groups.
Definition: defaults.hh:49
DefaultDecidermap< Model > DefaultTriggermap
Definition: defaults.hh:454
std::function< void(std::shared_ptr< HDFDataset > &, Model &) > DefaultDataWriter
Type of the default data writer.
Definition: defaults.hh:39
static DefaultTriggermap< Model > default_triggers
Default trigger factories. Equal to deciders because while the task they fullfill is different,...
Definition: defaults.hh:461
Definition: agent.hh:11
Decider which always returns true.
Definition: defaults.hh:305
AlwaysDecider & operator=(const AlwaysDecider &)=default
virtual void set_from_cfg(const Config &) override
Definition: defaults.hh:317
virtual bool operator()(Model &) override
Definition: defaults.hh:310
AlwaysDecider & operator=(AlwaysDecider &&)=default
AlwaysDecider(AlwaysDecider &&)=default
AlwaysDecider(const AlwaysDecider &)=default
Combines a number of deciders; returns true if any of them is true.
Definition: defaults.hh:338
std::tuple< Deciders... > held_deciders
Tuple of associated decider objects.
Definition: defaults.hh:343
CompositeDecider & operator=(CompositeDecider &&)=default
virtual void set_from_cfg(const Config &cfg) override
Set the decider up from a given config node.
Definition: defaults.hh:367
virtual bool operator()(Model &m) override
Evaluates the composite deciders; returns true if any is true.
Definition: defaults.hh:351
CompositeDecider & operator=(const CompositeDecider &)=default
CompositeDecider(const CompositeDecider &)=default
Common interface for all deciders (and triggers, for that matter). Every decider/Trigger must inherit...
Definition: defaults.hh:166
virtual void set_from_cfg(const Config &)=0
virtual bool operator()(Model &)=0
Decider & operator=(const Decider &)=default
Decider(const Decider &)=default
Decider & operator=(Decider &&)=default
Functor representing what is considered the most widely used execution process for writing data.
Definition: defaults.hh:84
void operator()(Datamanager &dm, Model &m)
Call operator for executing the execution process.
Definition: defaults.hh:96
A decider that returns true when within certain time intervals.
Definition: defaults.hh:188
IntervalDecider(const IntervalDecider &)=default
IntervalDecider & operator=(IntervalDecider &&)=default
IntervalDecider & operator=(const IntervalDecider &)=default
virtual bool operator()(Model &m) override
Definition: defaults.hh:197
IntervalDecider(IntervalDecider &&)=default
virtual void set_from_cfg(const Config &cfg) override
Set the decider up from a given config node.
Definition: defaults.hh:224
std::list< std::array< std::size_t, 3 > > intervals
The sequence of intervals within to return true.
Definition: defaults.hh:194
Decider which only returns true at a certain time.
Definition: defaults.hh:266
OnceDecider & operator=(const OnceDecider &)=default
virtual void set_from_cfg(const Config &cfg) override
Set the decider up from a given config node.
Definition: defaults.hh:283
std::size_t time
Definition: defaults.hh:269
virtual bool operator()(Model &m) override
Definition: defaults.hh:272
OnceDecider(const OnceDecider &)=default
OnceDecider(OnceDecider &&)=default
OnceDecider & operator=(OnceDecider &&)=default
OnceDecider()=default
Construct a OnceDecider that evaluates to true at time zero.
Encapsulate a task for writing data to a destination. Containes a callable 'writer' responisible for ...
Definition: write_task.hh:50