Utopia 2
Framework for studying models of complex & adaptive systems.
Loading...
Searching...
No Matches
Geomorphology.hh
Go to the documentation of this file.
1#ifndef GEOMORPHOLOGY_HH
2#define GEOMORPHOLOGY_HH
3
4#include <cmath>
5#include <functional>
6#include <random>
7
11
12namespace Utopia {
13namespace Models {
14namespace Geomorphology {
15
19 double rock;
20
23
25 double waterline() const { return rock + watercolumn; };
26
29
32
35
37
41 template<class RNG>
43 const std::shared_ptr<RNG>& rng)
44 :
47 {
48 std::normal_distribution<> init_height{
49 get_as<double>("initial_height_mean", cfg),
50 get_as<double>("initial_height_var", cfg)
51 };
52 rock = init_height(*rng);
53 }
54};
55
56
58
66
69
72 public Model<Geomorphology, GeomorphologyTypes>
73{
74public:
77
79 using DataSet = typename Base::DataSet;
80
83
86
89
92
95
96private:
97 // Base members: _time, _name, _cfg, _hdfgrp, _rng, _monitor
98
99 // -- Members -------------------------------------------------------------
100
103
104
105 // -- The boundary conditions (aka parameters) of the model
106
108 std::normal_distribution<> _uplift;
109
112
115
117
122
124
132
133 // A map of lowest neighbors
134 std::unordered_map<GeomorphologyCellIndexType,
135 std::shared_ptr<GeomorphologyCellType>> _lowest_neighbors;
136
137
138 const double _float_precision;
139
141 std::uniform_real_distribution<> _prob_dist;
142
143 // -- Datasets ------------------------------------------------------------
144 std::shared_ptr<DataSet> _dset_height;
145 std::shared_ptr<DataSet> _dset_drainage_area;
146 std::shared_ptr<DataSet> _dset_watercolumn;
147
148
149public:
150 // -- Model Setup ---------------------------------------------------------
152
160 template<class ParentModel>
162 const std::string& name,
164 const DataIO::Config& custom_cfg = {}
165 )
166 :
167 // Construct the base class
169
170 // Initialize the cell manager, binding it to this model
171 _cm(*this),
172
173 _uplift{get_as<double>("uplift_mean", this->_cfg),
174 get_as<double>("uplift_var", this->_cfg)},
175 _stream_power_coef(get_as<double>("stream_power_coef", this->_cfg)),
176 _toppling_frequency(get_as<double>("toppling_frequency", this->_cfg)),
177 _toppling_critical_height(get_as<double>("toppling_critical_height",
178 this->_cfg)),
180 get_as<double>("toppling_slope_reduction_factor", this->_cfg, 3.)),
181
182 _float_precision(1e-10),
183 _prob_dist(0., 1.),
184
185 // Create datasets using the helper functions for CellManager-data
186 _dset_height(this->create_cm_dset("height", _cm)),
187 _dset_drainage_area(this->create_cm_dset("drainage_area", _cm)),
188 _dset_watercolumn(this->create_cm_dset("watercolumn", _cm))
189 {
190 if (get_as<double>("uplift_var", this->_cfg) <= 1e-10) {
191 throw std::invalid_argument("Invalid argument: uplift_var must be "
192 "> _float_precision (1e-10)!");
193 }
194 // Update initial cell states
196
197
198 this->_log->debug("{} model fully set up.", this->_name);
199 }
200
202
208 // reset network
210
211 // connect cells to drainage network
213
214 // fill sinks with water
216
217 // get drainage area
219 _cm.cells());
220 }
221
223 void perform_step () {
224 // Erode
226
227 // Uplift
229
230 // Topple
232 *this->_rng);
233
234 // Build drainage network
236 }
237
239 void monitor () { return; }
240
242
246 void write_data () {
247 _dset_height->write(_cm.cells().begin(), _cm.cells().end(),
248 [](const auto& cell) { return cell->state.rock; }
249 );
250
251 _dset_drainage_area->write(_cm.cells().begin(), _cm.cells().end(),
252 [](const auto& cell) { return cell->state.drainage_area; }
253 );
254
255 _dset_watercolumn->write(_cm.cells().begin(), _cm.cells().end(),
256 [](const auto& cell) { return cell->state.watercolumn; }
257 );
258 }
259
260private:
261 // -- Helper functions ----------------------------------------------------
263 bool check_eq(const double& a, const double& b) {
264 return (a-b < _float_precision) && (b-a < _float_precision);
265 }
266
268 template <typename Cell>
269 bool check_eq_waterline(const Cell& a, const Cell& b) {
270 return check_eq(a->state.waterline(), b->state.waterline());
271 }
272
273 // -- Initialization function ---------------------------------------------
275
282 this->_log->debug("Initializing cells ..");
283
284 // Initialize altitude as an inclined plane
285 // (by making use of coordinates)
286 RuleFunc set_inclined_plane = [this](const auto& cell) {
287 auto state = cell->state;
288 auto pos = _cm.barycenter_of(cell);
289 double slope = get_as<double>("initial_slope",
290 this->_cfg["cell_manager"]["cell_params"]);
291 state.rock += slope*pos[1];
292 if (state.rock < _float_precision) {
293 std::uniform_real_distribution<> dist(0.,1e-5);
294 state.rock = dist(*this->_rng);
295 this->_log->warn("Received negative initial height. Was set "
296 "in [0.,1e-5]. Better chose the initial_height "
297 "distribution such that no negative values occur.");
298 }
299 return state;
300 };
302
303 // set bottom cells as outflow
305 // The rule to apply
306 [](const auto& cell){
307 auto state = cell->state;
308 state.is_outflow = true;
309 return state;
310 },
311 // The containers over which to iterate
312 _cm.boundary_cells("bottom")
313 );
314
315 // Build drainage network
316 this->_log->debug(" Initializing drainage network ...");
318
319 this->_log->debug("Cells fully set up.");
320 }
321
322
323 // -- Helper functions ----------------------------------------------------
324
326 template <typename Cell>
329 auto lowest_neighbor = cell;
330 for (const auto& n : this->_cm.neighbors_of(cell)) {
331 double height_diff = n->state.waterline() -
332 lowest_neighbor->state.waterline();
333
335 lowest_neighbors.push_back(n);
336 }
337
338 // If neighbor is lower, update lowest_neighbor and list
339 else if (height_diff < 0) {
341 lowest_neighbors.clear();
343 }
344 }
345
346 // If there is more than one lowest neighbor, select one randomly.
347 if (lowest_neighbors.size() > 1) {
348 std::uniform_int_distribution<> dist(0, lowest_neighbors.size() -1);
350 }
351 return lowest_neighbor;
352 }
353
355
366 {
367 auto it = std::begin(shore);
368 while(it != std::end(shore)) {
369 if (check_eq_waterline(*it, lake[0])) {
370 lake.push_back(*it);
371 auto nb = _cm.neighbors_of(*it);
372 for (auto it_lake : lake) {
373 nb.erase(std::remove(nb.begin(), nb.end(), it_lake),
374 nb.end());
375 }
376 for (auto it_shore : shore) {
377 nb.erase(std::remove(nb.begin(), nb.end(), it_shore),
378 nb.end());
379 }
380
381 auto next_it = it;
382 auto next = *next_it;
383 if (next_it != shore.end())
384 next_it++;
385 if (next_it != shore.end())
386 next = *next_it;
387 it = shore.erase(it);
388 if (!nb.empty()) {
389 if (it == shore.end())
390 next = nb[0];
391 shore.insert(shore.end(), nb.begin(), nb.end());
392 it = std::find(shore.begin(), shore.end(), next);
393 }
394 }
395 else
396 ++it;
397 }
398
399 return lake;
400 };
401
402
403 // -- Rule functions ------------------------------------------------------
405 RuleFunc uplift_rule = [this](const auto& cell) {
406 auto state = cell->state;
407 state.rock += this->_uplift(*(this->_rng));
408 return state;
409 };
410
412 RuleFunc erode = [this](const auto& cell) {
413 auto state = cell->state;
414
415 double slope = state.waterline();
416 if (not state.is_outflow) {
417 // slope = state->waterline - lowest_neighbor->waterline
418 slope -= _lowest_neighbors[cell->id()]->state.waterline();
419 }
420 // else: slope = state->waterline - 0.
421
422 double stream_power = ( _stream_power_coef * slope
423 * std::sqrt(state.drainage_area));
424 state.rock -= std::min(stream_power, state.rock);
425
426 return state;
427 };
428
430
436 RuleFunc toppling = [this](const auto& cell) {
437 auto state = cell->state;
438 if (_toppling_frequency == 0. or
440 ) {
441 // Done here.
442 return state;
443 }
444
445 auto nbrs = this->_cm.neighbors_of(cell);
446 auto heighest_neighbor = cell;
447 for (auto& nb : nbrs) {
448 if (nb->state.waterline() > heighest_neighbor->state.waterline())
449 {
451 }
452 }
453 double relief = ( heighest_neighbor->state.waterline()
454 - state.waterline());
456 if (this->_prob_dist(*(this->_rng)) < failure_prob) {
458 heighest_neighbor->state.rock -= relief / factor;
459 state.rock += relief / factor;
460 }
461
462 return state;
463 };
464
466 RuleFunc reset_network = [](const auto& cell) {
467 auto state = cell->state;
468 state.drainage_area = 1.;
469 state.was_drained = false;
470 state.watercolumn = 0.;
471 return state;
472 };
473
475
478 RuleFunc connect_cells = [this](const auto& cell) {
479 if (cell->state.is_outflow) {
480 _lowest_neighbors[cell->id()] = cell; // map to itself
481 return cell->state;
482 }
483
484 // Set lowest neighbor for cell, is itself is sink
486
487 return cell->state;
488 };
489
491
499 RuleFunc build_lake = [this](auto& cell) {
500 // return if cell has lower neighbor
501 if (cell->state.is_outflow or _lowest_neighbors[cell->id()] != cell) {
502 return cell->state;
503 }
504
508
509 double waterline = lake[0]->state.waterline();
510 bool no_sink = true;
511
512 // check for sink in new lake sites
513 for (const auto& lc : lake) {
514 if (lc->state.is_outflow) {
515 no_sink=false;
516 break;
517 }
518 }
519
520 // lowest shore cell is candidate for outflow
521 auto lowest_shore_cell = shore[0];
522 for (const auto& sc : shore) {
523 if (sc->state.waterline() < lowest_shore_cell->state.waterline())
524 {
526 }
527 }
528
529 // raise waterline while no outflow to lake
530 while (lowest_shore_cell->state.waterline() > waterline and no_sink)
531 {
532 // raise watercolumn to new waterline
533 waterline = lowest_shore_cell->state.waterline();
534 for (auto& lc : lake) {
535 lc->state.watercolumn = waterline - lc->state.rock;
536 }
537
538 // update lake and shore
540
541 for (const auto& lc : lake) {
542 if (lc->state.is_outflow) {
543 no_sink=false;
544 break;
545 }
546 }
547
548 // update lowest shore cell
550 for (const auto& sc : shore) {
551 if (sc->state.waterline() <
552 lowest_shore_cell->state.waterline())
553 {
555 }
556 }
557 }
558
560 if (not no_sink) {
561 for (const auto& lc : lake) {
562 if (lc->state.is_outflow) {
564 break;
565 }
566 }
567 }
568 else {
569 auto nbs = this->_cm.neighbors_of(lowest_shore_cell);
570 auto it_nb = nbs.begin();
571 while(it_nb != nbs.end()) {
572 if (not check_eq((*it_nb)->state.waterline(), waterline)) {
573 it_nb = nbs.erase(it_nb);
574 }
575 else if (lake.end() == std::find(lake.begin(), lake.end(),
576 *it_nb))
577 {
578 it_nb = nbs.erase(it_nb);
579 }
580 else { ++it_nb; }
581 }
582
583 if (nbs.size() > 1) {
584 std::uniform_int_distribution<> dist(0, nbs.size() - 1);
585 outflow_cell = nbs[dist(*(this->_rng))];
586 }
587 else { outflow_cell = nbs[0]; }
588 }
589
590 for (const auto& lc : lake) {
591 if (lc->state.is_outflow) {
592 _lowest_neighbors[lc->id()] = lc;
593 }
594 else {
596 }
597 }
598 if (not outflow_cell->state.is_outflow) {
600 }
601
602 return cell->state;
603 };
604
606
612 auto state = cell->state;
613 state.was_drained = true;
614
615 if (not state.is_outflow and _lowest_neighbors[cell->id()] == cell) {
616 throw std::runtime_error("No recipient assigned to a cell!");
617 }
618 // nothing to do here
619 if (state.is_outflow) {
620 return state;
621 }
622
623 // get downstream neighbor
625 downstream_cell->state.drainage_area += state.drainage_area;
626
627 // pass drainage to all already drained cells
628 while(not downstream_cell->state.is_outflow and
629 downstream_cell->state.was_drained)
630 {
632 downstream_cell->state.drainage_area += state.drainage_area;
633 if (downstream_cell->state.drainage_area > size(this->_cm.cells()))
634 {
635 throw std::runtime_error("Drainage network has loop!");
636 }
637 }
638
639 return state;
640 };
641};
642
643
644} // namespace Geomorphology
645} // namespace Models
646} // namespace Utopia
647
648#endif // GEOMORPHOLOGY_HH
A cell is a slightly specialized state container.
Definition cell.hh:40
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
SpaceVec barycenter_of(const Cell &cell) const
Returns the barycenter of the given cell.
Definition cell_manager.hh:249
CellContainer< Cell > boundary_cells(const std::string &select="all") const
Retrieve a container of cells that are at a specified boundary.
Definition cell_manager.hh:323
CellContainer< Cell > neighbors_of(const Cell &cell) const
Retrieve the given cell's neighbors.
Definition cell_manager.hh:458
const CellContainer< Cell > & cells() const
Return const reference to the managed CA cells.
Definition cell_manager.hh:219
Utopia::Cell< CellTraits > Cell
Type of the managed cells.
Definition cell_manager.hh:47
Base class interface for Models using the CRT Pattern.
Definition model.hh:112
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
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 std::string _name
Name of the model instance.
Definition model.hh:149
const std::shared_ptr< spdlog::logger > _log
The (model) logger.
Definition model.hh:164
const std::shared_ptr< RNG > _rng
The RNG shared between models.
Definition model.hh:161
A very simple geomorphology model.
Definition Geomorphology.hh:73
RuleFunc toppling
The rule how to topple / landslide.
Definition Geomorphology.hh:436
double _toppling_critical_height
The critical height difference to trigget a toppling event.
Definition Geomorphology.hh:121
bool check_eq_waterline(const Cell &a, const Cell &b)
Compare the waterline of two cells.
Definition Geomorphology.hh:269
double _stream_power_coef
The stream power coefficient.
Definition Geomorphology.hh:111
void monitor()
Provide monitoring data: tree density and number of clusters.
Definition Geomorphology.hh:239
RuleFunc uplift_rule
The rule how to uplift.
Definition Geomorphology.hh:405
void write_data()
Write the cell states (aka water content)
Definition Geomorphology.hh:246
typename GeomorphologyCellManager::RuleFunc RuleFunc
Rule function type, extracted from CellManager.
Definition Geomorphology.hh:94
GmorphCellContainer update_lakesites(GmorphCellContainer &lake, GmorphCellContainer &shore)
Update the CellContainer of lake and shore cells.
Definition Geomorphology.hh:364
void perform_step()
Perform step.
Definition Geomorphology.hh:223
RuleFunc erode
The rule how to erode with stream power.
Definition Geomorphology.hh:412
std::normal_distribution _uplift
The random uplift as normal distribution.
Definition Geomorphology.hh:108
RuleFunc build_lake
Fill a sink with water.
Definition Geomorphology.hh:499
std::shared_ptr< DataSet > _dset_watercolumn
Dataset of drainage area.
Definition Geomorphology.hh:146
typename Base::DataSet DataSet
Data type for a dataset.
Definition Geomorphology.hh:79
std::shared_ptr< DataSet > _dset_drainage_area
Dataset of rock height.
Definition Geomorphology.hh:145
GeomorphologyCellManager::Cell GeomorphologyCellType
A cell in the geomorphology model.
Definition Geomorphology.hh:85
RuleFunc reset_network
The rule to reset the drainage network.
Definition Geomorphology.hh:466
double _toppling_slope_reduction_factor
The factor by which to reduce the slope in a toppling event.
Definition Geomorphology.hh:131
Utopia::IndexType GeomorphologyCellIndexType
The index type of the Geomorphology cell manager.
Definition Geomorphology.hh:88
void build_network()
The set of seperately applied rules to build the drainage network.
Definition Geomorphology.hh:207
double _toppling_frequency
The frequency of possible toppling events per cell.
Definition Geomorphology.hh:114
std::uniform_real_distribution _prob_dist
precision when comparing floats
Definition Geomorphology.hh:141
Geomorphology(const std::string &name, ParentModel &parent_model, const DataIO::Config &custom_cfg={})
Dataset of watercolumn.
Definition Geomorphology.hh:161
void _initialize_cells()
The initialization of the cells.
Definition Geomorphology.hh:281
std::shared_ptr< DataSet > _dset_height
Definition Geomorphology.hh:144
RuleFunc pass_drainage_area
Make a drainage process from this cell.
Definition Geomorphology.hh:611
const double _float_precision
Definition Geomorphology.hh:138
Cell _lowest_grid_neighbor(const Cell &cell)
Return the lowest cell of the grid-Neighborhood, including cell itself.
Definition Geomorphology.hh:327
Utopia::CellContainer< GeomorphologyCellType > GmorphCellContainer
The type of a cell container in the Geomorphology model.
Definition Geomorphology.hh:91
GeomorphologyCellManager _cm
The cell manager for the forest fire model.
Definition Geomorphology.hh:102
RuleFunc connect_cells
Build a rudimentary network.
Definition Geomorphology.hh:478
bool check_eq(const double &a, const double &b)
Compare two floats for equality.
Definition Geomorphology.hh:263
std::unordered_map< GeomorphologyCellIndexType, std::shared_ptr< GeomorphologyCellType > > _lowest_neighbors
Definition Geomorphology.hh:135
Model< Geomorphology, GeomorphologyTypes > Base
The base model type.
Definition Geomorphology.hh:76
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
Definition agent.hh:11
EntityContainer< CellType > CellContainer
Type of the variably sized container for cells.
Definition types.hh:26
std::size_t IndexType
Type for indices, i.e. values used for container indexing, agent IDs, ...
Definition types.hh:40
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
The full cell struct for the Geomorphology model.
Definition Geomorphology.hh:17
bool was_drained
Was called for drainage area calculation.
Definition Geomorphology.hh:31
double rock
The cells topgraphic height.
Definition Geomorphology.hh:19
double watercolumn
The cells watercontent.
Definition Geomorphology.hh:22
bool is_outflow
Whether the cell is an outflow boundary cell.
Definition Geomorphology.hh:34
double drainage_area
The drainage area.
Definition Geomorphology.hh:28
GeomorphologyCell(const DataIO::Config &cfg, const std::shared_ptr< RNG > &rng)
Construct a cell from a configuration node and an RNG.
Definition Geomorphology.hh:42
double waterline() const
The height of the waterline.
Definition Geomorphology.hh:25