Line data Source code
1 : /*
2 : * Copyright (C) 2020-2025 MEmilio
3 : *
4 : * Authors: Daniel Abele, Elisabeth Kluth, Khoa Nguyen
5 : *
6 : * Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
7 : *
8 : * Licensed under the Apache License, Version 2.0 (the "License");
9 : * you may not use this file except in compliance with the License.
10 : * You may obtain a copy of the License at
11 : *
12 : * http://www.apache.org/licenses/LICENSE-2.0
13 : *
14 : * Unless required by applicable law or agreed to in writing, software
15 : * distributed under the License is distributed on an "AS IS" BASIS,
16 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 : * See the License for the specific language governing permissions and
18 : * limitations under the License.
19 : */
20 : #ifndef MIO_ABM_PARAMETERS_H
21 : #define MIO_ABM_PARAMETERS_H
22 :
23 : #include "abm/mask_type.h"
24 : #include "abm/time.h"
25 : #include "abm/virus_variant.h"
26 : #include "abm/protection_event.h"
27 : #include "abm/test_type.h"
28 : #include "memilio/config.h"
29 : #include "memilio/io/default_serialize.h"
30 : #include "memilio/io/io.h"
31 : #include "memilio/math/time_series_functor.h"
32 : #include "memilio/utils/custom_index_array.h"
33 : #include "memilio/utils/uncertain_value.h"
34 : #include "memilio/utils/parameter_set.h"
35 : #include "memilio/utils/index_range.h"
36 : #include "memilio/epidemiology/age_group.h"
37 : #include "memilio/epidemiology/damping.h"
38 : #include "memilio/epidemiology/contact_matrix.h"
39 :
40 : #include <algorithm>
41 : #include <limits>
42 : #include <string>
43 :
44 : namespace mio
45 : {
46 : namespace abm
47 : {
48 :
49 : /**
50 : * @brief Time that a Person is infected but not yet infectious.
51 : */
52 : struct IncubationPeriod {
53 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
54 909 : static Type get_default(AgeGroup size)
55 : {
56 909 : return Type({VirusVariant::Count, size}, 1.);
57 : }
58 27 : static std::string name()
59 : {
60 27 : return "IncubationPeriod";
61 : }
62 : };
63 :
64 : struct InfectedNoSymptomsToSymptoms {
65 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
66 909 : static Type get_default(AgeGroup size)
67 : {
68 909 : return Type({VirusVariant::Count, size}, 1.);
69 : }
70 27 : static std::string name()
71 : {
72 27 : return "InfectedNoSymptomsToSymptoms";
73 : }
74 : };
75 :
76 : struct InfectedNoSymptomsToRecovered {
77 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
78 909 : static Type get_default(AgeGroup size)
79 : {
80 909 : return Type({VirusVariant::Count, size}, 1.);
81 : }
82 27 : static std::string name()
83 : {
84 27 : return "InfectedNoSymptomsToRecovered";
85 : }
86 : };
87 :
88 : struct InfectedSymptomsToRecovered {
89 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
90 909 : static Type get_default(AgeGroup size)
91 : {
92 909 : return Type({VirusVariant::Count, size}, 1.);
93 : }
94 27 : static std::string name()
95 : {
96 27 : return "InfectedSymptomsToRecovered";
97 : }
98 : };
99 :
100 : struct InfectedSymptomsToSevere {
101 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
102 909 : static Type get_default(AgeGroup size)
103 : {
104 909 : return Type({VirusVariant::Count, size}, 1.);
105 : }
106 27 : static std::string name()
107 : {
108 27 : return "InfectedSymptomsToSevere";
109 : }
110 : };
111 :
112 : struct SevereToCritical {
113 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
114 909 : static Type get_default(AgeGroup size)
115 : {
116 909 : return Type({VirusVariant::Count, size}, 1.);
117 : }
118 27 : static std::string name()
119 : {
120 27 : return "SevereToCritical";
121 : }
122 : };
123 :
124 : struct SevereToRecovered {
125 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
126 909 : static Type get_default(AgeGroup size)
127 : {
128 909 : return Type({VirusVariant::Count, size}, 1.);
129 : }
130 27 : static std::string name()
131 : {
132 27 : return "SevereToRecovered";
133 : }
134 : };
135 :
136 : struct SevereToDead {
137 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
138 909 : static Type get_default(AgeGroup size)
139 : {
140 909 : return Type({VirusVariant::Count, size}, 1.);
141 : }
142 27 : static std::string name()
143 : {
144 27 : return "SevereToDead";
145 : }
146 : };
147 :
148 : struct CriticalToRecovered {
149 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
150 909 : static Type get_default(AgeGroup size)
151 : {
152 909 : return Type({VirusVariant::Count, size}, 1.);
153 : }
154 27 : static std::string name()
155 : {
156 27 : return "CriticalToRecovered";
157 : }
158 : };
159 :
160 : struct CriticalToDead {
161 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
162 909 : static Type get_default(AgeGroup size)
163 : {
164 909 : return Type({VirusVariant::Count, size}, 1.);
165 : }
166 27 : static std::string name()
167 : {
168 27 : return "CriticalToDead";
169 : }
170 : };
171 :
172 : struct RecoveredToSusceptible {
173 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
174 909 : static Type get_default(AgeGroup size)
175 : {
176 909 : return Type({VirusVariant::Count, size}, 1.);
177 : }
178 27 : static std::string name()
179 : {
180 27 : return "RecoveredToSusceptible";
181 : }
182 : };
183 : /**
184 : * @brief Parameters for the ViralLoad course. Default values taken as constant values from the average from
185 : * https://github.com/VirologyCharite/SARS-CoV-2-VL-paper/tree/main
186 : * Section 3.3.1 or see also supplementary materials Fig. S5.
187 : */
188 : struct ViralLoadDistributionsParameters {
189 : UniformDistribution<double>::ParamType viral_load_peak;
190 : UniformDistribution<double>::ParamType viral_load_incline;
191 : UniformDistribution<double>::ParamType viral_load_decline;
192 :
193 : /// This method is used by the default serialization feature.
194 27 : auto default_serialize()
195 : {
196 54 : return Members("ViralLoadDistributionsParameters")
197 81 : .add("viral_load_peak", viral_load_peak)
198 81 : .add("viral_load_incline", viral_load_incline)
199 81 : .add("viral_load_decline", viral_load_decline);
200 : }
201 : };
202 :
203 : struct ViralLoadDistributions {
204 : using Type = CustomIndexArray<ViralLoadDistributionsParameters, VirusVariant, AgeGroup>;
205 918 : static Type get_default(AgeGroup size)
206 : {
207 918 : Type default_val({VirusVariant::Count, size},
208 918 : ViralLoadDistributionsParameters{{8.1, 8.1}, {2., 2.}, {-0.17, -0.17}});
209 1836 : return default_val;
210 918 : }
211 27 : static std::string name()
212 : {
213 27 : return "ViralLoadDistributions";
214 : }
215 : };
216 :
217 : /**
218 : * @brief Parameters for the Infectivity. Default values taken as constant values that match the graph 2C from
219 : * https://github.com/VirologyCharite/SARS-CoV-2-VL-paper/tree/main
220 : */
221 : struct InfectivityDistributionsParameters {
222 : UniformDistribution<double>::ParamType infectivity_alpha;
223 : UniformDistribution<double>::ParamType infectivity_beta;
224 :
225 : /// This method is used by the default serialization feature.
226 27 : auto default_serialize()
227 : {
228 54 : return Members("InfectivityDistributionsParameters")
229 81 : .add("infectivity_alpha", infectivity_alpha)
230 81 : .add("infectivity_beta", infectivity_beta);
231 : }
232 : };
233 :
234 : struct InfectivityDistributions {
235 : using Type = CustomIndexArray<InfectivityDistributionsParameters, VirusVariant, AgeGroup>;
236 918 : static Type get_default(AgeGroup size)
237 : {
238 918 : Type default_val({VirusVariant::Count, size}, InfectivityDistributionsParameters{{-7., -7.}, {1., 1.}});
239 1836 : return default_val;
240 918 : }
241 27 : static std::string name()
242 : {
243 27 : return "InfectivityDistributions";
244 : }
245 : };
246 :
247 : /**
248 : * @brief Probability that an Infection is detected.
249 : */
250 : struct DetectInfection {
251 : using Type = CustomIndexArray<UncertainValue<>, VirusVariant, AgeGroup>;
252 909 : static Type get_default(AgeGroup size)
253 : {
254 909 : return Type({VirusVariant::Count, size}, 1.);
255 : }
256 27 : static std::string name()
257 : {
258 27 : return "DetectInfection";
259 : }
260 : };
261 :
262 : /**
263 : * @brief Effectiveness of a Mask of a certain MaskType% against an Infection%.
264 : */
265 : struct MaskProtection {
266 : using Type = CustomIndexArray<UncertainValue<>, MaskType>;
267 909 : static Type get_default(AgeGroup /*size*/)
268 : {
269 909 : Type defaut_value = Type(MaskType::Count, 0.0);
270 : // Initial values according to http://dx.doi.org/10.15585/mmwr.mm7106e1
271 909 : defaut_value[MaskType::FFP2] = 0.83;
272 909 : defaut_value[MaskType::Surgical] = 0.66;
273 909 : defaut_value[MaskType::Community] = 0.56;
274 1818 : return defaut_value;
275 909 : }
276 27 : static std::string name()
277 : {
278 27 : return "MaskProtection";
279 : }
280 : };
281 :
282 : /**
283 : * @brief Aerosol transmission rates.
284 : */
285 : struct AerosolTransmissionRates {
286 : using Type = CustomIndexArray<ScalarType, VirusVariant>;
287 909 : static Type get_default(AgeGroup /*size*/)
288 : {
289 909 : return Type({VirusVariant::Count}, 1.0);
290 : }
291 27 : static std::string name()
292 : {
293 27 : return "AerosolTransmissionRates";
294 : }
295 : };
296 :
297 : /**
298 : * @brief Personal protection factor against #Infection% after #Infection and vaccination, which depends on #ProtectionType,
299 : * #AgeGroup and #VirusVariant. Its value is between 0 and 1.
300 : */
301 : struct InfectionProtectionFactor {
302 : using Type = CustomIndexArray<TimeSeriesFunctor<ScalarType>, ProtectionType, AgeGroup, VirusVariant>;
303 909 : static auto get_default(AgeGroup size)
304 : {
305 909 : return Type({ProtectionType::Count, size, VirusVariant::Count}, TimeSeriesFunctor<ScalarType>());
306 : }
307 27 : static std::string name()
308 : {
309 27 : return "InfectionProtectionFactor";
310 : }
311 : };
312 :
313 : /**
314 : * @brief Personal protective factor against severe symptoms after #Infection and vaccination, which depends on #ProtectionType,
315 : * #AgeGroup and #VirusVariant. Its value is between 0 and 1.
316 : */
317 : struct SeverityProtectionFactor {
318 : using Type = CustomIndexArray<TimeSeriesFunctor<ScalarType>, ProtectionType, AgeGroup, VirusVariant>;
319 909 : static auto get_default(AgeGroup size)
320 : {
321 909 : return Type({ProtectionType::Count, size, VirusVariant::Count}, TimeSeriesFunctor<ScalarType>());
322 : }
323 27 : static std::string name()
324 : {
325 27 : return "SeverityProtectionFactor";
326 : }
327 : };
328 :
329 : /**
330 : * @brief Personal protective factor against high viral load, which depends on #ProtectionType,
331 : * #AgeGroup and #VirusVariant. Its value is between 0 and 1.
332 : */
333 : struct HighViralLoadProtectionFactor {
334 : using Type = CustomIndexArray<TimeSeriesFunctor<ScalarType>, ProtectionType, AgeGroup, VirusVariant>;
335 909 : static auto get_default(AgeGroup size)
336 : {
337 909 : return Type({ProtectionType::Count, size, VirusVariant::Count}, TimeSeriesFunctor<ScalarType>());
338 : }
339 27 : static std::string name()
340 : {
341 27 : return "HighViralLoadProtectionFactor";
342 : }
343 : };
344 :
345 : /**
346 : * @brief Parameters that describe the reliability of a test.
347 : */
348 : struct TestParameters {
349 : UncertainValue<> sensitivity;
350 : UncertainValue<> specificity;
351 : TimeSpan required_time;
352 : TestType type;
353 :
354 : /// This method is used by the default serialization feature.
355 99 : auto default_serialize()
356 : {
357 198 : return Members("TestParameters")
358 297 : .add("sensitivity", sensitivity)
359 297 : .add("specificity", specificity)
360 297 : .add("required_time", required_time)
361 297 : .add("test_type", type);
362 : }
363 : };
364 :
365 : /**
366 : * @brief Store a map from the TestTypes to their TestParameters.
367 : */
368 : struct TestData {
369 : using Type = CustomIndexArray<TestParameters, TestType>;
370 909 : static auto get_default(AgeGroup /*size*/)
371 : {
372 909 : Type default_val = Type({TestType::Count});
373 909 : default_val[{TestType::Generic}] = TestParameters{0.9, 0.99, hours(48), TestType::Generic};
374 909 : default_val[{TestType::Antigen}] = TestParameters{0.8, 0.88, minutes(30), TestType::Antigen};
375 909 : default_val[{TestType::PCR}] = TestParameters{0.9, 0.99, hours(48), TestType::PCR};
376 1818 : return default_val;
377 909 : }
378 27 : static std::string name()
379 : {
380 27 : return "TestData";
381 : }
382 : };
383 :
384 : /**
385 : * @brief Starting date of interventions.
386 : */
387 : struct LockdownDate {
388 : using Type = TimePoint;
389 909 : static auto get_default(AgeGroup /*size*/)
390 : {
391 909 : return TimePoint(std::numeric_limits<int>::max());
392 : }
393 27 : static std::string name()
394 : {
395 27 : return "LockdownDate";
396 : }
397 : };
398 :
399 : /**
400 : * @brief Duration of quarantine.
401 : */
402 : struct QuarantineDuration {
403 : using Type = TimeSpan;
404 909 : static auto get_default(AgeGroup /*size*/)
405 : {
406 909 : return days(10);
407 : }
408 27 : static std::string name()
409 : {
410 27 : return "QuarantineDuration";
411 : }
412 : };
413 :
414 : /**
415 : * @brief Parameter for the exponential distribution to decide if a Person goes shopping.
416 : */
417 : struct BasicShoppingRate {
418 : using Type = CustomIndexArray<UncertainValue<>, AgeGroup>;
419 909 : static auto get_default(AgeGroup size)
420 : {
421 1818 : return Type({size}, 1.0);
422 : }
423 27 : static std::string name()
424 : {
425 27 : return "BasicShoppingRate";
426 : }
427 : };
428 :
429 : /**
430 : * @brief Percentage of Person%s of the respective age going to work.
431 : */
432 : struct WorkRatio {
433 : using Type = DampingMatrixExpression<Dampings<Damping<ColumnVectorShape>>>;
434 909 : static auto get_default(AgeGroup /*size*/)
435 : {
436 1818 : return Type(Eigen::VectorXd::Constant(1, 1.0));
437 : }
438 27 : static std::string name()
439 : {
440 27 : return "WorkRatio";
441 : }
442 : };
443 :
444 : /**
445 : * @brief Percentage of Person%s of the respective age going to school.
446 : */
447 : struct SchoolRatio {
448 : using Type = DampingMatrixExpression<Dampings<Damping<ColumnVectorShape>>>;
449 909 : static auto get_default(AgeGroup /*size*/)
450 : {
451 1818 : return Type(Eigen::VectorXd::Constant(1, 1.0));
452 : }
453 27 : static std::string name()
454 : {
455 27 : return "SchoolRatio";
456 : }
457 : };
458 :
459 : /**
460 : * @brief Parameter for the exponential distribution to decide if a Person goes to a social event.
461 : */
462 : struct SocialEventRate {
463 : using Type = DampingMatrixExpression<Dampings<Damping<ColumnVectorShape>>>;
464 909 : static auto get_default(AgeGroup size)
465 : {
466 1818 : return Type(Eigen::VectorXd::Constant((size_t)size, 1.0));
467 : }
468 27 : static std::string name()
469 : {
470 27 : return "SocialEventRate";
471 : }
472 : };
473 :
474 : /**
475 : * @brief Earliest time that a Person can go to work.
476 : */
477 : struct GotoWorkTimeMinimum {
478 : using Type = CustomIndexArray<TimeSpan, AgeGroup>;
479 909 : static auto get_default(AgeGroup size)
480 : {
481 1818 : return CustomIndexArray<TimeSpan, AgeGroup>(size, hours(6));
482 : }
483 27 : static std::string name()
484 : {
485 27 : return "GotoWorkTimeMinimum";
486 : }
487 : };
488 :
489 : /**
490 : * @brief Latest time that a Person can go to work.
491 : */
492 : struct GotoWorkTimeMaximum {
493 : using Type = CustomIndexArray<TimeSpan, AgeGroup>;
494 909 : static auto get_default(AgeGroup size)
495 : {
496 1818 : return CustomIndexArray<TimeSpan, AgeGroup>(size, hours(9));
497 : }
498 27 : static std::string name()
499 : {
500 27 : return "GotoWorkTimeMaximum";
501 : }
502 : };
503 :
504 : /**
505 : * @brief Earliest time that a Person can go to school.
506 : */
507 : struct GotoSchoolTimeMinimum {
508 : using Type = CustomIndexArray<TimeSpan, AgeGroup>;
509 909 : static auto get_default(AgeGroup size)
510 : {
511 1818 : return CustomIndexArray<TimeSpan, AgeGroup>(size, hours(6));
512 : }
513 27 : static std::string name()
514 : {
515 27 : return "GotoSchoolTimeMinimum";
516 : }
517 : };
518 :
519 : /**
520 : * @brief Latest time that a Person can go to school.
521 : */
522 : struct GotoSchoolTimeMaximum {
523 : using Type = CustomIndexArray<TimeSpan, AgeGroup>;
524 909 : static auto get_default(AgeGroup size)
525 : {
526 1818 : return CustomIndexArray<TimeSpan, AgeGroup>(size, hours(9));
527 : }
528 27 : static std::string name()
529 : {
530 27 : return "GotoSchoolTimeMaximum";
531 : }
532 : };
533 :
534 : /**
535 : * @brief The set of AgeGroups that can go to school.
536 : */
537 : struct AgeGroupGotoSchool {
538 : using Type = CustomIndexArray<bool, AgeGroup>;
539 909 : static Type get_default(AgeGroup num_agegroups)
540 : {
541 909 : return Type(num_agegroups, false);
542 : }
543 27 : static std::string name()
544 : {
545 27 : return "AgeGroupGotoSchool";
546 : }
547 : };
548 :
549 : /**
550 : * @brief The set of AgeGroups that can go to work.
551 : */
552 : struct AgeGroupGotoWork {
553 : using Type = CustomIndexArray<bool, AgeGroup>;
554 909 : static Type get_default(AgeGroup num_agegroups)
555 : {
556 909 : return Type(num_agegroups, false);
557 : }
558 27 : static std::string name()
559 : {
560 27 : return "AgeGroupGotoWork";
561 : }
562 : };
563 :
564 : using ParametersBase =
565 : ParameterSet<IncubationPeriod, InfectedNoSymptomsToSymptoms, InfectedNoSymptomsToRecovered,
566 : InfectedSymptomsToRecovered, InfectedSymptomsToSevere, SevereToCritical, SevereToRecovered, SevereToDead,
567 : CriticalToDead, CriticalToRecovered, RecoveredToSusceptible, ViralLoadDistributions,
568 : InfectivityDistributions, DetectInfection, MaskProtection, AerosolTransmissionRates, LockdownDate,
569 : QuarantineDuration, SocialEventRate, BasicShoppingRate, WorkRatio, SchoolRatio, GotoWorkTimeMinimum,
570 : GotoWorkTimeMaximum, GotoSchoolTimeMinimum, GotoSchoolTimeMaximum, AgeGroupGotoSchool,
571 : AgeGroupGotoWork, InfectionProtectionFactor, SeverityProtectionFactor, HighViralLoadProtectionFactor,
572 : TestData>;
573 :
574 : /**
575 : * @brief Maximum number of Person%s an infectious Person can infect at the respective Location.
576 : */
577 : struct MaximumContacts {
578 : using Type = ScalarType;
579 1426 : static Type get_default(AgeGroup /*size*/)
580 : {
581 1426 : return std::numeric_limits<ScalarType>::max();
582 : }
583 18 : static std::string name()
584 : {
585 18 : return "MaximumContacts";
586 : }
587 : };
588 :
589 : /**
590 : * contact rates
591 : */
592 : struct ContactRates {
593 : using Type = CustomIndexArray<ScalarType, AgeGroup, AgeGroup>;
594 1435 : static Type get_default(AgeGroup size)
595 : {
596 : return Type({size, size},
597 1435 : 1.0); // amount of contacts from AgeGroup a to AgeGroup b per day
598 : }
599 18 : static std::string name()
600 : {
601 18 : return "ContactRates";
602 : }
603 : };
604 :
605 : // If true, consider the capacity of the Cell%s of this Location for the computation of relative transmission risk.
606 : struct UseLocationCapacityForTransmissions {
607 : using Type = bool;
608 1426 : static Type get_default(AgeGroup)
609 : {
610 1426 : return false;
611 : }
612 18 : static std::string name()
613 : {
614 18 : return "UseLocationCapacityForTransmissions";
615 : }
616 : };
617 :
618 : /**
619 : * @brief Parameters of the Infection that depend on the Location.
620 : */
621 : using LocalInfectionParameters = ParameterSet<MaximumContacts, ContactRates, UseLocationCapacityForTransmissions>;
622 :
623 : /**
624 : * @brief Parameters of the simulation that are the same everywhere within the Model.
625 : */
626 : class Parameters : public ParametersBase
627 : {
628 : public:
629 909 : Parameters(size_t num_agegroups)
630 1818 : : ParametersBase(AgeGroup(num_agegroups))
631 2727 : , m_num_groups(num_agegroups)
632 : {
633 909 : }
634 :
635 : private:
636 9 : Parameters(ParametersBase&& base)
637 9 : : ParametersBase(std::move(base))
638 18 : , m_num_groups(this->get<AgeGroupGotoWork>().size<AgeGroup>().get())
639 : {
640 9 : }
641 :
642 : public:
643 : /**
644 : * @brief Get the number of the age groups.
645 : */
646 8516 : size_t get_num_groups() const
647 : {
648 8516 : return m_num_groups;
649 : }
650 :
651 : /**
652 : * @brief Checks whether all Parameters satisfy their corresponding constraints and logs an error
653 : * if constraints are not satisfied.
654 : * @return Returns true if one (or more) constraint(s) are not satisfied, otherwise false.
655 : */
656 189 : bool check_constraints() const
657 : {
658 513 : for (auto age_group : make_index_range(AgeGroup{m_num_groups})) {
659 828 : for (auto virus_variant : enum_members<VirusVariant>()) {
660 :
661 468 : if (this->get<IncubationPeriod>()[{virus_variant, age_group}] < 0) {
662 9 : log_error("Constraint check: Parameter IncubationPeriod of age group {:.0f} smaller than {:.4f}",
663 18 : (size_t)age_group, 0);
664 9 : return true;
665 : }
666 :
667 459 : if (this->get<InfectedNoSymptomsToSymptoms>()[{virus_variant, age_group}] < 0.0) {
668 9 : log_error("Constraint check: Parameter InfectedNoSymptomsToSymptoms of age group {:.0f} smaller "
669 : "than {:d}",
670 18 : (size_t)age_group, 0);
671 9 : return true;
672 : }
673 :
674 450 : if (this->get<InfectedNoSymptomsToRecovered>()[{virus_variant, age_group}] < 0.0) {
675 9 : log_error("Constraint check: Parameter InfectedNoSymptomsToRecovered of age group {:.0f} smaller "
676 : "than {:d}",
677 18 : (size_t)age_group, 0);
678 9 : return true;
679 : }
680 :
681 441 : if (this->get<InfectedSymptomsToRecovered>()[{virus_variant, age_group}] < 0.0) {
682 9 : log_error(
683 : "Constraint check: Parameter InfectedSymptomsToRecovered of age group {:.0f} smaller than {:d}",
684 18 : (size_t)age_group, 0);
685 9 : return true;
686 : }
687 :
688 432 : if (this->get<InfectedSymptomsToSevere>()[{virus_variant, age_group}] < 0.0) {
689 9 : log_error(
690 : "Constraint check: Parameter InfectedSymptomsToSevere of age group {:.0f} smaller than {:d}",
691 18 : (size_t)age_group, 0);
692 9 : return true;
693 : }
694 :
695 423 : if (this->get<SevereToCritical>()[{virus_variant, age_group}] < 0.0) {
696 9 : log_error("Constraint check: Parameter SevereToCritical of age group {:.0f} smaller than {:d}",
697 18 : (size_t)age_group, 0);
698 9 : return true;
699 : }
700 :
701 414 : if (this->get<SevereToRecovered>()[{virus_variant, age_group}] < 0.0) {
702 9 : log_error("Constraint check: Parameter SevereToRecovered of age group {:.0f} smaller than {:d}",
703 18 : (size_t)age_group, 0);
704 9 : return true;
705 : }
706 :
707 405 : if (this->get<SevereToDead>()[{VirusVariant::Wildtype, age_group}] < 0.0) {
708 9 : log_error("Constraint check: Parameter SevereToDead of age group {:.0f} smaller than {:d}",
709 18 : (size_t)age_group, 0);
710 9 : return true;
711 : }
712 :
713 396 : if (this->get<CriticalToDead>()[{virus_variant, age_group}] < 0.0) {
714 9 : log_error("Constraint check: Parameter CriticalToDead of age group {:.0f} smaller than {:d}",
715 18 : (size_t)age_group, 0);
716 9 : return true;
717 : }
718 :
719 387 : if (this->get<CriticalToRecovered>()[{virus_variant, age_group}] < 0.0) {
720 9 : log_error("Constraint check: Parameter CriticalToRecovered of age group {:.0f} smaller than {:d}",
721 18 : (size_t)age_group, 0);
722 9 : return true;
723 : }
724 :
725 378 : if (this->get<RecoveredToSusceptible>()[{virus_variant, age_group}] < 0.0) {
726 9 : log_error(
727 : "Constraint check: Parameter RecoveredToSusceptible of age group {:.0f} smaller than {:d}",
728 18 : (size_t)age_group, 0);
729 9 : return true;
730 : }
731 :
732 1107 : if (this->get<DetectInfection>()[{virus_variant, age_group}] < 0.0 ||
733 738 : this->get<DetectInfection>()[{virus_variant, age_group}] > 1.0) {
734 9 : log_error("Constraint check: Parameter DetectInfection of age group {:.0f} smaller than {:d} or "
735 : "larger than {:d}",
736 18 : (size_t)age_group, 0, 1);
737 9 : return true;
738 : }
739 : }
740 :
741 720 : if (this->get<GotoWorkTimeMinimum>()[age_group].seconds() < 0.0 ||
742 360 : this->get<GotoWorkTimeMinimum>()[age_group].seconds() >
743 360 : this->get<GotoWorkTimeMaximum>()[age_group].seconds()) {
744 9 : log_error("Constraint check: Parameter GotoWorkTimeMinimum of age group {:.0f} smaller {:d} or "
745 : "larger {:d}",
746 18 : (size_t)age_group, 0, this->get<GotoWorkTimeMaximum>()[age_group].seconds());
747 9 : return true;
748 : }
749 :
750 1053 : if (this->get<GotoWorkTimeMaximum>()[age_group].seconds() <
751 1053 : this->get<GotoWorkTimeMinimum>()[age_group].seconds() ||
752 1053 : this->get<GotoWorkTimeMaximum>()[age_group] > days(1)) {
753 9 : log_error("Constraint check: Parameter GotoWorkTimeMaximum of age group {:.0f} smaller {:d} or larger "
754 : "than one day time span",
755 18 : (size_t)age_group, this->get<GotoWorkTimeMinimum>()[age_group].seconds());
756 9 : return true;
757 : }
758 :
759 684 : if (this->get<GotoSchoolTimeMinimum>()[age_group].seconds() < 0.0 ||
760 342 : this->get<GotoSchoolTimeMinimum>()[age_group].seconds() >
761 342 : this->get<GotoSchoolTimeMaximum>()[age_group].seconds()) {
762 9 : log_error("Constraint check: Parameter GotoSchoolTimeMinimum of age group {:.0f} smaller {:d} or "
763 : "larger {:d}",
764 18 : (size_t)age_group, 0, this->get<GotoWorkTimeMaximum>()[age_group].seconds());
765 9 : return true;
766 : }
767 :
768 999 : if (this->get<GotoSchoolTimeMaximum>()[age_group].seconds() <
769 999 : this->get<GotoSchoolTimeMinimum>()[age_group].seconds() ||
770 999 : this->get<GotoSchoolTimeMaximum>()[age_group] > days(1)) {
771 9 : log_error("Constraint check: Parameter GotoWorkTimeMaximum of age group {:.0f} smaller {:d} or larger "
772 : "than one day time span",
773 18 : (size_t)age_group, this->get<GotoSchoolTimeMinimum>()[age_group].seconds());
774 9 : return true;
775 : }
776 : }
777 :
778 135 : if (this->get<MaskProtection>()[MaskType::Community] < 0.0 ||
779 90 : this->get<MaskProtection>()[MaskType::Community] > 1.0) {
780 9 : log_error(
781 18 : "Constraint check: Parameter MaskProtection for MaskType Community is smaller {:d} or larger {:d}", 0,
782 18 : 1);
783 9 : return true;
784 : }
785 :
786 36 : if (this->get<MaskProtection>()[MaskType::FFP2] < 0.0 || this->get<MaskProtection>()[MaskType::FFP2] > 1.0) {
787 9 : log_error("Constraint check: Parameter MaskProtection for MaskType FFP2 is smaller {:d} or larger {:d}", 0,
788 18 : 1);
789 9 : return true;
790 : }
791 :
792 81 : if (this->get<MaskProtection>()[MaskType::Surgical] < 0.0 ||
793 54 : this->get<MaskProtection>()[MaskType::Surgical] > 1.0) {
794 9 : log_error("Constraint check: Parameter MaskProtection for MaskType Surgical smaller {:d} or larger {:d}", 0,
795 18 : 1);
796 9 : return true;
797 : }
798 :
799 18 : if (this->get<LockdownDate>().seconds() < 0.0) {
800 9 : log_error("Constraint check: Parameter LockdownDate smaller {:d}", 0);
801 9 : return true;
802 : }
803 :
804 9 : return false;
805 : }
806 :
807 : /**
808 : * deserialize an object of this class.
809 : * @see epi::deserialize
810 : */
811 : template <class IOContext>
812 9 : static IOResult<Parameters> deserialize(IOContext& io)
813 : {
814 9 : BOOST_OUTCOME_TRY(auto&& base, ParametersBase::deserialize(io));
815 9 : return success(Parameters(std::move(base)));
816 9 : }
817 :
818 : private:
819 : size_t m_num_groups;
820 : };
821 :
822 : } // namespace abm
823 : } // namespace mio
824 : #endif
|