Modular Megafauna Model 1.1.5
A physiological, dynamic herbivore simulator in C++.
Loading...
Searching...
No Matches
forage_values.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2020 W. Traylor <wolfgang.traylor@senckenberg.de>
2//
3// SPDX-License-Identifier: LGPL-3.0-or-later
4
11#ifndef FAUNA_FORAGE_VALUES_H
12#define FAUNA_FORAGE_VALUES_H
13
14#include <array>
15#include <cmath>
16#include <numeric>
17#include <stdexcept>
18#include "Fauna/average.h"
19#include "Fauna/forage_types.h"
20
21namespace Fauna {
22class HerbivoreInterface; // for ForageDistribution
23
25enum class ForageValueTag {
30};
31
34
56template <ForageValueTag tag>
58 public:
60
66 ForageValues(const double init_value = 0.0) { set(init_value); }
67
69
77 const double na_value) const {
78 ForageValues<tag> result(*this);
79 for (int ft = 0; ft < array.size(); ft++) {
80 const double d = divisor.array[ft];
81 if (d != 0.0)
82 result.set((ForageType)ft, array[ft] / d); // normal
83 else
84 result.set((ForageType)ft, na_value); // division by zero
85 }
86 return result;
87 }
88
90
93 double get(const ForageType ft) const {
94 if (ft == ForageType::Inedible)
95 throw std::invalid_argument(
96 "Fauna::ForageValues<>::get() "
97 "The forage type `ForageType::Inedible` is not allowed.");
98 assert((int)ft < array.size());
99 assert((int)ft >= 0);
100 return array[(int)ft];
101 }
102
104
113 const double this_weight = 1.0,
114 const double other_weight = 1.0) {
115 for (int ft = 0; ft < array.size(); ft++)
116 set((ForageType)ft,
117 average(array[ft], other.array[ft], this_weight, other_weight));
118 return *this;
119 }
120
122
125 if (&other == this) return *this;
126 for (int ft = 0; ft < array.size(); ft++)
127 set((ForageType)ft, std::max(array[ft], other.array[ft]));
128 return *this;
129 }
130
132
135 if (&other == this) return *this;
136 for (int ft = 0; ft < array.size(); ft++)
137 set((ForageType)ft, std::min(array[ft], other.array[ft]));
138 return *this;
139 }
140
142 double operator[](const ForageType ft) const { return get(ft); }
143
145 double& operator[](const ForageType ft) {
146 if (ft == ForageType::Inedible)
147 throw std::invalid_argument(
148 "Fauna::ForageValues<>::get() "
149 "The forage type `ForageType::Inedible` is not allowed.");
150 assert((int)ft < array.size());
151 assert((int)ft >= 0);
152 return array[(int)ft];
153 }
154
156
162 void set(const ForageType forage_type, double value) {
163 check_value(value);
164 if (forage_type == ForageType::Inedible)
165 throw std::invalid_argument((std::string)"ForageValues<> "
166 "Forage type `ForageType::Inedible` is not allowed."+
167 " ("+get_forage_type_name(forage_type)+")");
168
169 // Change the value.
170 assert((int)forage_type < array.size());
171 assert((int)forage_type >= 0);
172 array[(int)forage_type] = value;
173 }
174
176
182 void set(double value) {
183 check_value(value);
184 array.fill(value);
185 }
186
188 double sum() const {
189 return std::accumulate(array.begin(), array.end(), 0.0);
190 }
191
193 ForageValues<tag>& operator+=(const double rhs) {
194 for (int ft = 0; ft < array.size(); ft++)
195 set((ForageType)ft, array[ft] + rhs);
196 return *this;
197 }
198 ForageValues<tag>& operator-=(const double rhs) {
199 for (int ft = 0; ft < array.size(); ft++)
200 set((ForageType)ft, array[ft] - rhs);
201 return *this;
202 }
203 ForageValues<tag>& operator*=(const double rhs) {
204 for (int ft = 0; ft < array.size(); ft++)
205 set((ForageType)ft, array[ft] * rhs);
206 return *this;
207 }
209 ForageValues<tag>& operator/=(const double rhs) {
210 if (rhs == 0)
211 throw std::domain_error("Fauna::ForageValues<> Division by zero.");
212 for (int ft = 0; ft < array.size(); ft++)
213 set((ForageType)ft, array[ft] / rhs);
214 return *this;
215 }
216
217 ForageValues<tag> operator+(const double rhs) const {
218 ForageValues<tag> result(*this);
219 return result.operator+=(rhs);
220 }
221 ForageValues<tag> operator-(const double rhs) const {
222 ForageValues<tag> result(*this);
223 return result.operator-=(rhs);
224 }
225 ForageValues<tag> operator*(const double rhs) const {
226 ForageValues<tag> result(*this);
227 return result.operator*=(rhs);
228 }
230 ForageValues<tag> operator/(const double rhs) const {
231 ForageValues<tag> result(*this);
232 return result.operator/=(rhs);
233 }
234
236 ForageValues<tag> result(*this);
237 return result.operator+=(rhs);
238 }
240 ForageValues<tag> result(*this);
241 return result.operator-=(rhs);
242 }
244 ForageValues<tag> result(*this);
245 return result.operator*=(rhs);
246 }
249 ForageValues<tag> result(*this);
250 return result.operator/=(rhs);
251 }
252
254 for (int ft = 0; ft < array.size(); ft++)
255 set((ForageType)ft, array[ft] + rhs.array[ft]);
256 return *this;
257 }
259 for (int ft = 0; ft < array.size(); ft++)
260 set((ForageType)ft, array[ft] - rhs.array[ft]);
261 return *this;
262 }
264 for (int ft = 0; ft < array.size(); ft++)
265 set((ForageType)ft, array[ft] * rhs.array[ft]);
266 return *this;
267 }
270 for (int ft = 0; ft < array.size(); ft++) {
271 if (rhs.array[ft] == 0)
272 throw std::domain_error(
273 (std::string) "Fauna::ForageValues<> Division by zero." + " (" +
275 set((ForageType)ft, array[ft] / rhs.array[ft]);
276 }
277 return *this;
278 }
279
280 bool operator==(const ForageValues<tag>& rhs) const {
281 for (int ft = 0; ft < array.size(); ft++)
282 if (array[ft] != rhs.array[ft]) return false;
283 return true;
284 }
285
286 // TODO: Is this function necessary and logical?
287 bool operator!=(const ForageValues<tag>& rhs) const {
288 for (int ft = 0; ft < array.size(); ft++)
289 if (array[ft] == rhs.array[ft]) return false;
290 return true;
291 }
292
293 bool operator<(const ForageValues<tag>& rhs) const {
294 for (int ft = 0; ft < array.size(); ft++)
295 if (array[ft] >= rhs.array[ft]) return false;
296 return true;
297 }
298 bool operator<=(const ForageValues<tag>& rhs) const {
299 for (int ft = 0; ft < array.size(); ft++)
300 if (array[ft] > rhs.array[ft]) return false;
301 return true;
302 }
303 bool operator>(const ForageValues<tag>& rhs) const {
304 for (int ft = 0; ft < array.size(); ft++)
305 if (array[ft] <= rhs.array[ft]) return false;
306 return true;
307 }
308 bool operator>=(const ForageValues<tag>& rhs) const {
309 for (int ft = 0; ft < array.size(); ft++)
310 if (array[ft] < rhs.array[ft]) return false;
311 return true;
312 } // Operator overload
314
316
329 constexpr static const double IMPRECISION_TOLERANCE = 1e-3;
330
331 private:
333 std::array<double, 1> array;
334
336
340 void check_value(double& value) const {
341 switch (tag) {
343 if (value < 0.0) {
344 // Correct floating point rounding errors.
345 if (value >= -IMPRECISION_TOLERANCE)
346 value = 0.0;
347 else
348 throw std::invalid_argument(
349 "ForageValues<PositiveAndZero> Value < 0 not allowed. "
350 "(value == " +
351 std::to_string(value) + ")");
352 }
353 break;
355 if (value < 0.0 || value > 1.0) {
356 // Correct floating point rounding errors.
357 if (value < 0.0 && value >= 0.0 - IMPRECISION_TOLERANCE)
358 value = 0.0;
359 else if (value > 1.0 && value <= 1.0 + IMPRECISION_TOLERANCE)
360 value = 1.0;
361 else
362 throw std::invalid_argument(
363 "ForageValues<ZeroToOne> Value is not in interval [0,1]. "
364 "(value == " +
365 std::to_string(value) + ")");
366 }
367 break;
368 default:
369 throw std::logic_error(
370 "ForageValues<> "
371 "ForageValueTag not implemented.");
372 }
373 if (std::isnan(value))
374 throw std::invalid_argument(
375 "ForageValues<> NAN is not allowed as a value.");
376 if (std::isinf(value))
377 throw std::invalid_argument(
378 "ForageValues<> INFINITY is not allowed as a value.");
379 }
380};
381
384
387
390
393
396
398typedef std::vector<std::pair<HerbivoreInterface*, ForageMass>>
400
404
412 const double lhs, const ForageFraction& rhs) {
414 for (const auto ft : FORAGE_TYPES) result.set(ft, rhs[ft] * lhs);
415 return result;
416}
417
419 const ForageFraction& lhs,
422 for (const auto ft : FORAGE_TYPES) result.set(ft, rhs[ft] * lhs[ft]);
423 return result;
424}
425
428 const ForageFraction& rhs) {
429 return operator*(rhs, lhs);
430}
434
439// Note that we don’t use the typedef "ForageFraction" as the type of parameter
440// "fractions" here because Doxygen (1.8.16) does not recognize it and throws a
441// warning.
442ForageValues<ForageValueTag::PositiveAndZero> foragefractions_to_foragevalues(
443 const ForageValues<ForageValueTag::ZeroToOne>& fractions);
444
446
457 const ForageValues<ForageValueTag::PositiveAndZero> values,
458 const double tolerance);
459
461
469// Note that we don’t use the typedefs "ForageFraction" and "ForageEnergy" as
470// the parameter types here because Doxygen (1.8.16) does not recognize it and
471// throws a warning.
473 const ForageValues<ForageValueTag::PositiveAndZero>& mj_per_kg,
474 const ForageValues<ForageValueTag::ZeroToOne>& mj_proportions);
475
476} // namespace Fauna
477#endif // FAUNA_FORAGE_VALUES_H
Helper functions/classes to aggregate data.
Definition: forage_values.h:57
bool operator>=(const ForageValues< tag > &rhs) const
Definition: forage_values.h:308
static constexpr const double IMPRECISION_TOLERANCE
Tolerance range for imprecise floating point results.
Definition: forage_values.h:329
bool operator!=(const ForageValues< tag > &rhs) const
Definition: forage_values.h:287
ForageValues< tag > & operator*=(const ForageValues< tag > &rhs)
Definition: forage_values.h:263
ForageValues< tag > operator-(const ForageValues< tag > &rhs) const
Definition: forage_values.h:239
void set(const ForageType forage_type, double value)
Set a value, only finite values are allowed.
Definition: forage_values.h:162
double operator[](const ForageType ft) const
Read-only value access.
Definition: forage_values.h:142
ForageValues< tag > & operator-=(const ForageValues< tag > &rhs)
Definition: forage_values.h:258
ForageValues< tag > operator+(const double rhs) const
Definition: forage_values.h:217
void check_value(double &value) const
Helper function to throw exceptions in the set() functions.
Definition: forage_values.h:340
ForageValues< tag > operator*(const ForageValues< tag > &rhs) const
Definition: forage_values.h:243
ForageValues< tag > operator*(const double rhs) const
Definition: forage_values.h:225
ForageValues< tag > divide_safely(const ForageValues< tag > &divisor, const double na_value) const
Divide safely also by zero values.
Definition: forage_values.h:76
ForageValues< tag > & operator-=(const double rhs)
Definition: forage_values.h:198
bool operator<(const ForageValues< tag > &rhs) const
Definition: forage_values.h:293
bool operator==(const ForageValues< tag > &rhs) const
Definition: forage_values.h:280
double get(const ForageType ft) const
Get a value (read-only).
Definition: forage_values.h:93
ForageValues< tag > & operator/=(const ForageValues< tag > &rhs)
Definition: forage_values.h:269
bool operator>(const ForageValues< tag > &rhs) const
Definition: forage_values.h:303
double sum() const
Sum of all values.
Definition: forage_values.h:188
ForageValues< tag > & min(const ForageValues< tag > &other)
For each forage type, take the minimum value.
Definition: forage_values.h:134
ForageValues< tag > operator+(const ForageValues< tag > &rhs) const
Definition: forage_values.h:235
ForageValues< tag > & operator+=(const ForageValues< tag > &rhs)
Definition: forage_values.h:253
ForageValues< tag > & operator/=(const double rhs)
Definition: forage_values.h:209
ForageValues< tag > & operator*=(const double rhs)
Definition: forage_values.h:203
ForageValues< tag > & max(const ForageValues< tag > &other)
For each forage type, take the maximum value.
Definition: forage_values.h:124
ForageValues< tag > & operator+=(const double rhs)
Definition: forage_values.h:193
ForageValues< tag > operator/(const double rhs) const
Definition: forage_values.h:230
bool operator<=(const ForageValues< tag > &rhs) const
Definition: forage_values.h:298
double & operator[](const ForageType ft)
Write access to values.
Definition: forage_values.h:145
ForageValues< tag > operator-(const double rhs) const
Definition: forage_values.h:221
std::array< double, 1 > array
Forage values for all but ForageType::Inedible.
Definition: forage_values.h:333
ForageValues< tag > operator/(const ForageValues< tag > &rhs) const
Definition: forage_values.h:248
ForageValues< tag > & merge(const ForageValues< tag > &other, const double this_weight=1.0, const double other_weight=1.0)
Merge this object with another one by building (weighted) means.
Definition: forage_values.h:112
ForageValues(const double init_value=0.0)
Constructor with initializing value.
Definition: forage_values.h:66
void set(double value)
Set all forage types to one value.
Definition: forage_values.h:182
Definition of forage types (grass, browse, etc.)
Definition: average.h:16
const std::string & get_forage_type_name(const ForageType)
Get a short, lowercase string identifier for a forage type.
Definition: forage_types.cpp:30
std::vector< std::pair< HerbivoreInterface *, ForageMass > > ForageDistribution
Data structure defining which herbivore gets what to eat [kgDM/km²].
Definition: forage_values.h:399
ForageFraction foragevalues_to_foragefractions(const ForageValues< ForageValueTag::PositiveAndZero > values, const double tolerance)
Convert forage values to fractional values.
Definition: forage_values.cpp:22
ForageValues< ForageValueTag::PositiveAndZero > ForageEnergyContent
Net energy content [MJ/kgDM] for different forage types.
Definition: forage_values.h:389
ForageValues< ForageValueTag::PositiveAndZero > foragefractions_to_foragevalues(const ForageValues< ForageValueTag::ZeroToOne > &fractions)
Convert forage fractions (in [0,1]) into values in [0,∞].
Definition: forage_values.cpp:16
ForageValues< ForageValueTag::PositiveAndZero > ForageMass
Dry matter mass values [kgDM or kgDM/km²] for different forage types.
Definition: forage_values.h:395
double average(const double a, const double b, const double weight_a=1.0, const double weight_b=1.0)
Build weighted average of two numbers.
Definition: average.cpp:25
ForageValues< ForageValueTag::ZeroToOne > ForageFraction
A fraction for each forage type.
Definition: forage_values.h:392
ForageValues< ForageValueTag::PositiveAndZero > ForageEnergy
Energy values [MJ] for different forage types.
Definition: forage_values.h:386
ForageType
Different types of forage.
Definition: forage_types.h:21
@ Inedible
Plants that are not edible for herbivores.
ForageFraction convert_mj_to_kg_proportionally(const ForageValues< ForageValueTag::PositiveAndZero > &mj_per_kg, const ForageValues< ForageValueTag::ZeroToOne > &mj_proportions)
Convert forage energy to mass keeping the energy-wise proportions.
Definition: forage_values.cpp:51
ForageValueTag
Describes which values are allowed in Fauna::ForageValues.
Definition: forage_values.h:25
@ ZeroToOne
Only values in interval [0,1] are allowed.
@ PositiveAndZero
Only values in interval [0,∞) are allowed.
const std::set< ForageType > FORAGE_TYPES
Definition: forage_types.cpp:27
ForageValues< ForageValueTag::ZeroToOne > Digestibility
Digestibility [fraction] for different forage types.
Definition: forage_values.h:383
ForageValues< ForageValueTag::PositiveAndZero > operator*(const double lhs, const ForageFraction &rhs)
Multiply forage fractions with coefficient, allowing numbers >0.
Definition: forage_values.h:411