Line data Source code
1 : /* 2 : * Copyright (C) 2020-2024 MEmilio 3 : * 4 : * Authors: Daniel Abele, Jan Kleinert, Martin J. Kuehn 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 : 21 : #ifndef SIR_PARAMETERS_H 22 : #define SIR_PARAMETERS_H 23 : 24 : #include "memilio/epidemiology/age_group.h" 25 : #include "memilio/epidemiology/uncertain_matrix.h" 26 : #include "memilio/utils/custom_index_array.h" 27 : #include "memilio/utils/parameter_set.h" 28 : #include "memilio/utils/uncertain_value.h" 29 : 30 : namespace mio 31 : { 32 : namespace osir 33 : { 34 : 35 : /************************************** 36 : * Define Parameters of the SIR model * 37 : **************************************/ 38 : 39 : /** 40 : * @brief probability of getting infected from a contact 41 : */ 42 : template <typename FP = ScalarType> 43 : struct TransmissionProbabilityOnContact { 44 : using Type = CustomIndexArray<UncertainValue<FP>, AgeGroup>; 45 72 : static Type get_default(AgeGroup size) 46 : { 47 144 : return Type(size, 1.0); 48 : } 49 : static std::string name() 50 : { 51 : return "TransmissionProbabilityOnContact"; 52 : } 53 : }; 54 : 55 : /** 56 : * @brief the infectious time in day unit 57 : */ 58 : template <typename FP = ScalarType> 59 : struct TimeInfected { 60 : using Type = CustomIndexArray<UncertainValue<FP>, AgeGroup>; 61 72 : static Type get_default(AgeGroup size) 62 : { 63 144 : return Type(size, 6.0); 64 : } 65 : static std::string name() 66 : { 67 : return "TimeInfected"; 68 : } 69 : }; 70 : 71 : /** 72 : * @brief the contact patterns within the society are modelled using a ContactMatrix 73 : */ 74 : template <typename FP = ScalarType> 75 : struct ContactPatterns { 76 : using Type = UncertainContactMatrix<FP>; 77 72 : static Type get_default(AgeGroup size) 78 : { 79 72 : return Type(1, static_cast<Eigen::Index>((size_t)size)); 80 : } 81 : static std::string name() 82 : { 83 : return "ContactPatterns"; 84 : } 85 : }; 86 : 87 : template <typename FP = ScalarType> 88 : using ParametersBase = ParameterSet<TransmissionProbabilityOnContact<FP>, TimeInfected<FP>, ContactPatterns<FP>>; 89 : 90 : /** 91 : * @brief Parameters of SIR model. 92 : */ 93 : template <typename FP = ScalarType> 94 : class Parameters : public ParametersBase<FP> 95 : { 96 : public: 97 72 : Parameters(AgeGroup num_agegroups) 98 : : ParametersBase<FP>(num_agegroups) 99 72 : , m_num_groups{num_agegroups} 100 : { 101 72 : } 102 : 103 4077 : AgeGroup get_num_groups() 104 : { 105 4077 : return m_num_groups; 106 : } 107 : 108 : /** 109 : * @brief Checks whether all Parameters satisfy their corresponding constraints and applies them, if they do not. 110 : * Time spans cannot be negative and probabilities can only take values between [0,1]. 111 : * 112 : * Attention: This function should be used with care. It is necessary for some test problems to run through quickly, 113 : * but in a manual execution of an example, check_constraints() may be preferred. Note that the apply_constraints() 114 : * function can and will not set Parameters to meaningful values in an epidemiological or virological context, 115 : * as all models are designed to be transferable to multiple diseases. Consequently, only acceptable 116 : * (like 0 or 1 for probabilities or small positive values for time spans) values are set here and a manual adaptation 117 : * may often be necessary to have set meaningful values. 118 : * 119 : * @return Returns true if one ore more constraint were corrected, false otherwise. 120 : */ 121 27 : bool apply_constraints() 122 : { 123 27 : double tol_times = 1e-1; 124 : 125 27 : int corrected = false; 126 : 127 54 : for (auto i = AgeGroup(0); i < AgeGroup(m_num_groups); i++) { 128 27 : if (this->template get<TimeInfected<FP>>()[i] < tol_times) { 129 18 : log_warning( 130 : "Constraint check: Parameter TimeInfected changed from {:.4f} to {:.4f}. Please note that " 131 : "unreasonably small compartment stays lead to massively increased run time. Consider to cancel " 132 : "and reset parameters.", 133 9 : this->template get<TimeInfected<FP>>()[i], tol_times); 134 9 : this->template get<TimeInfected<FP>>()[i] = tol_times; 135 9 : corrected = true; 136 : } 137 54 : if (this->template get<TransmissionProbabilityOnContact<FP>>()[i] < 0.0 || 138 27 : this->template get<TransmissionProbabilityOnContact<FP>>()[i] > 1.0) { 139 18 : log_warning( 140 : "Constraint check: Parameter TransmissionProbabilityOnContact changed from {:0.4f} to {:d} ", 141 18 : this->template get<TransmissionProbabilityOnContact<FP>>()[i], 0.0); 142 9 : this->template get<TransmissionProbabilityOnContact<FP>>() = 0.0; 143 9 : corrected = true; 144 : } 145 : } 146 27 : return corrected; 147 : } 148 : 149 : /** 150 : * @brief Checks whether all Parameters satisfy their corresponding constraints and logs an error 151 : * if constraints are not satisfied. 152 : * @return Returns true if one constraint is not satisfied, otherwise false. 153 : */ 154 81 : bool check_constraints() const 155 : { 156 81 : double tol_times = 1e-1; 157 : 158 144 : for (auto i = AgeGroup(0); i < AgeGroup(m_num_groups); i++) { 159 : 160 81 : if (this->template get<TimeInfected<FP>>()[i] < tol_times) { 161 18 : log_error( 162 : "Constraint check: Parameter TimeInfected {:.4f} smaller or equal {:.4f}. Please note that " 163 : "unreasonably small compartment stays lead to massively increased run time. Consider to cancel " 164 : "and reset parameters.", 165 18 : this->template get<TimeInfected<FP>>()[i], 0.0); 166 9 : return true; 167 : } 168 144 : if (this->template get<TransmissionProbabilityOnContact<FP>>()[i] < 0.0 || 169 72 : this->template get<TransmissionProbabilityOnContact<FP>>()[i] > 1.0) { 170 18 : log_error("Constraint check: Parameter TransmissionProbabilityOnContact {:.4f} smaller {:.4f} or " 171 : "greater {:.4f}", 172 18 : this->template get<TransmissionProbabilityOnContact<FP>>()[i], 0.0, 1.0); 173 9 : return true; 174 : } 175 : } 176 63 : return false; 177 : } 178 : 179 : private: 180 : Parameters(ParametersBase<FP>&& base) 181 : : ParametersBase<FP>(std::move(base)) 182 : , m_num_groups(this->template get<ContactPatterns<FP>>().get_cont_freq_mat().get_num_groups()) 183 : { 184 : } 185 : 186 : public: 187 : /** 188 : * deserialize an object of this class. 189 : * @see mio::deserialize 190 : */ 191 : template <class IOContext> 192 : static IOResult<Parameters> deserialize(IOContext& io) 193 : { 194 : BOOST_OUTCOME_TRY(auto&& base, ParametersBase<FP>::deserialize(io)); 195 : return success(Parameters(std::move(base))); 196 : } 197 : 198 : private: 199 : AgeGroup m_num_groups; 200 : }; 201 : 202 : } // namespace osir 203 : } // namespace mio 204 : 205 : #endif // SIR_PARAMETERS_H