|
| 1 | +/* |
| 2 | +* Copyright (C) 2020-2025 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 | +#ifndef SEIRDB_MODEL_H |
| 21 | +#define SEIRDB_MODEL_H |
| 22 | + |
| 23 | +#include "memilio/compartments/flow_model.h" |
| 24 | +#include "memilio/config.h" |
| 25 | +#include "memilio/epidemiology/age_group.h" |
| 26 | +#include "memilio/epidemiology/populations.h" |
| 27 | +#include "memilio/math/interpolation.h" |
| 28 | +#include "memilio/utils/time_series.h" |
| 29 | +#include "ode_seirdb/infection_state.h" |
| 30 | +#include "ode_seirdb/parameters.h" |
| 31 | + |
| 32 | +GCC_CLANG_DIAGNOSTIC(push) |
| 33 | +GCC_CLANG_DIAGNOSTIC(ignored "-Wshadow") |
| 34 | +#include <Eigen/Dense> |
| 35 | +GCC_CLANG_DIAGNOSTIC(pop) |
| 36 | + |
| 37 | +namespace mio |
| 38 | +{ |
| 39 | +namespace oseirdb |
| 40 | +{ |
| 41 | + |
| 42 | +/******************** |
| 43 | + * define the model * |
| 44 | + ********************/ |
| 45 | + |
| 46 | +// clang-format off |
| 47 | +using Flows = TypeList<Flow<InfectionState::Susceptible, InfectionState::Exposed>, |
| 48 | + Flow<InfectionState::Exposed, InfectionState::Infected>, |
| 49 | + Flow<InfectionState::Infected, InfectionState::Recovered>, |
| 50 | + Flow<InfectionState::Infected, InfectionState::Dead>, |
| 51 | + Flow<InfectionState::Dead, InfectionState::Buried>>; |
| 52 | +// clang-format on |
| 53 | +template <typename FP> |
| 54 | +class Model |
| 55 | + : public FlowModel<FP, InfectionState, mio::Populations<FP, AgeGroup, InfectionState>, Parameters<FP>, Flows> |
| 56 | +{ |
| 57 | + using Base = FlowModel<FP, InfectionState, mio::Populations<FP, AgeGroup, InfectionState>, Parameters<FP>, Flows>; |
| 58 | + |
| 59 | +public: |
| 60 | + using typename Base::ParameterSet; |
| 61 | + using typename Base::Populations; |
| 62 | + |
| 63 | + Model(const Populations& pop, const ParameterSet& params) |
| 64 | + : Base(pop, params) |
| 65 | + { |
| 66 | + } |
| 67 | + |
| 68 | + Model(int num_agegroups) |
| 69 | + : Base(Populations({AgeGroup(num_agegroups), InfectionState::Count}), ParameterSet(AgeGroup(num_agegroups))) |
| 70 | + { |
| 71 | + } |
| 72 | + |
| 73 | + void get_flows(Eigen::Ref<const Eigen::VectorX<FP>> pop, Eigen::Ref<const Eigen::VectorX<FP>> y, FP t, |
| 74 | + Eigen::Ref<Eigen::VectorX<FP>> flows) const override |
| 75 | + { |
| 76 | + const Index<AgeGroup> age_groups = reduce_index<Index<AgeGroup>>(this->populations.size()); |
| 77 | + const auto& params = this->parameters; |
| 78 | + |
| 79 | + for (auto i : make_index_range(age_groups)) { |
| 80 | + const size_t Si = this->populations.get_flat_index({i, InfectionState::Susceptible}); |
| 81 | + const size_t Ei = this->populations.get_flat_index({i, InfectionState::Exposed}); |
| 82 | + const size_t Ii = this->populations.get_flat_index({i, InfectionState::Infected}); |
| 83 | + const size_t Di = this->populations.get_flat_index({i, InfectionState::Dead}); |
| 84 | + |
| 85 | + for (auto j : make_index_range(age_groups)) { |
| 86 | + const size_t Sj = this->populations.get_flat_index({j, InfectionState::Susceptible}); |
| 87 | + const size_t Ej = this->populations.get_flat_index({j, InfectionState::Exposed}); |
| 88 | + const size_t Ij = this->populations.get_flat_index({j, InfectionState::Infected}); |
| 89 | + const size_t Rj = this->populations.get_flat_index({j, InfectionState::Recovered}); |
| 90 | + const size_t Dj = this->populations.get_flat_index({j, InfectionState::Dead}); |
| 91 | + const size_t Bj = this->populations.get_flat_index({j, InfectionState::Buried}); |
| 92 | + |
| 93 | + const FP Nj = pop[Sj] + pop[Ej] + pop[Ij] + pop[Rj] + pop[Dj] + pop[Bj]; |
| 94 | + const FP divNj = (Nj < Limits<FP>::zero_tolerance()) ? FP(0.0) : FP(1.0 / Nj); |
| 95 | + const FP contact_rate = params.template get<ContactPatterns<FP>>().get_cont_freq_mat().get_matrix_at( |
| 96 | + SimulationTime<FP>(t))(i.get(), j.get()) * |
| 97 | + divNj; |
| 98 | + const FP coeffStoE = contact_rate * params.template get<TransmissionProbabilityOnContact<FP>>()[i]; |
| 99 | + const FP coeffStoEDead = contact_rate * params.template get<TransmissionProbabilityFromDead<FP>>()[i]; |
| 100 | + |
| 101 | + flows[Base::template get_flat_flow_index<InfectionState::Susceptible, InfectionState::Exposed>(i)] += |
| 102 | + y[Si] * (coeffStoE * pop[Ij] + coeffStoEDead * pop[Dj]); |
| 103 | + } |
| 104 | + flows[Base::template get_flat_flow_index<InfectionState::Exposed, InfectionState::Infected>(i)] = |
| 105 | + (1.0 / params.template get<TimeExposed<FP>>()[i]) * y[Ei]; |
| 106 | + |
| 107 | + const FP inv_time_infected = 1.0 / params.template get<TimeInfected<FP>>()[i]; |
| 108 | + const FP prob_recover = params.template get<ProbabilityToRecover<FP>>()[i]; |
| 109 | + const FP prob_die = 1.0 - prob_recover; |
| 110 | + flows[Base::template get_flat_flow_index<InfectionState::Infected, InfectionState::Recovered>(i)] = |
| 111 | + inv_time_infected * prob_recover * y[Ii]; |
| 112 | + flows[Base::template get_flat_flow_index<InfectionState::Infected, InfectionState::Dead>(i)] = |
| 113 | + inv_time_infected * prob_die * y[Ii]; |
| 114 | + flows[Base::template get_flat_flow_index<InfectionState::Dead, InfectionState::Buried>(i)] = |
| 115 | + (1.0 / params.template get<TimeToBurial<FP>>()[i]) * y[Di]; |
| 116 | + } |
| 117 | + } |
| 118 | + |
| 119 | + /** |
| 120 | + * serialize this. |
| 121 | + * @see mio::serialize |
| 122 | + */ |
| 123 | + template <class IOContext> |
| 124 | + void serialize(IOContext& io) const |
| 125 | + { |
| 126 | + auto obj = io.create_object("Model"); |
| 127 | + obj.add_element("Parameters", this->parameters); |
| 128 | + obj.add_element("Populations", this->populations); |
| 129 | + } |
| 130 | + |
| 131 | + /** |
| 132 | + * deserialize an object of this class. |
| 133 | + * @see mio::deserialize |
| 134 | + */ |
| 135 | + template <class IOContext> |
| 136 | + static IOResult<Model> deserialize(IOContext& io) |
| 137 | + { |
| 138 | + auto obj = io.expect_object("Model"); |
| 139 | + auto par = obj.expect_element("Parameters", Tag<ParameterSet>{}); |
| 140 | + auto pop = obj.expect_element("Populations", Tag<Populations>{}); |
| 141 | + return apply( |
| 142 | + io, |
| 143 | + [](auto&& par_, auto&& pop_) { |
| 144 | + return Model{pop_, par_}; |
| 145 | + }, |
| 146 | + par, pop); |
| 147 | + } |
| 148 | +}; |
| 149 | + |
| 150 | +} // namespace oseirdb |
| 151 | +} // namespace mio |
| 152 | + |
| 153 | +#endif // SEIRDB_MODEL_H |
0 commit comments