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