LCOV - code coverage report
Current view: top level - models/ode_secirts - model.h (source / functions) Hit Total Coverage
Test: coverage.info Lines: 516 516 100.0 %
Date: 2025-01-17 12:16:22 Functions: 15 17 88.2 %

          Line data    Source code
       1             : /* 
       2             : * * Copyright (C) 2020-2025 MEmilio
       3             : *
       4             : * Authors: Henrik Zunker, Wadim Koslow, Daniel Abele, Martin J. Kühn
       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_ODE_SECIRTS_MODEL_H
      21             : #define MIO_ODE_SECIRTS_MODEL_H
      22             : 
      23             : #include "memilio/compartments/flow_model.h"
      24             : #include "memilio/compartments/simulation.h"
      25             : #include "memilio/compartments/flow_simulation.h"
      26             : #include "memilio/epidemiology/populations.h"
      27             : #include "ode_secirts/infection_state.h"
      28             : #include "ode_secirts/parameters.h"
      29             : #include "memilio/math/smoother.h"
      30             : #include "memilio/math/eigen_util.h"
      31             : 
      32             : namespace mio
      33             : {
      34             : namespace osecirts
      35             : {
      36             : // clang-format off
      37             : using Flows = TypeList<
      38             :     //naive
      39             :     Flow<InfectionState::SusceptibleNaive,                            InfectionState::ExposedNaive>, 
      40             :     Flow<InfectionState::SusceptibleNaive,                            InfectionState::TemporaryImmunePartialImmunity>, 
      41             :     Flow<InfectionState::ExposedNaive,                                InfectionState::InfectedNoSymptomsNaive>,
      42             :     Flow<InfectionState::InfectedNoSymptomsNaive,                     InfectionState::InfectedSymptomsNaive>,
      43             :     Flow<InfectionState::InfectedNoSymptomsNaive,                     InfectionState::TemporaryImmunePartialImmunity>,
      44             :     Flow<InfectionState::InfectedNoSymptomsNaiveConfirmed,            InfectionState::InfectedSymptomsNaiveConfirmed>,
      45             :     Flow<InfectionState::InfectedNoSymptomsNaiveConfirmed,            InfectionState::TemporaryImmunePartialImmunity>,
      46             :     Flow<InfectionState::InfectedSymptomsNaive,                       InfectionState::InfectedSevereNaive>,
      47             :     Flow<InfectionState::InfectedSymptomsNaive,                       InfectionState::TemporaryImmunePartialImmunity>,
      48             :     Flow<InfectionState::InfectedSymptomsNaiveConfirmed,              InfectionState::InfectedSevereNaive>,
      49             :     Flow<InfectionState::InfectedSymptomsNaiveConfirmed,              InfectionState::TemporaryImmunePartialImmunity>,
      50             :     Flow<InfectionState::InfectedSevereNaive,                         InfectionState::InfectedCriticalNaive>,
      51             :     Flow<InfectionState::InfectedSevereNaive,                         InfectionState::TemporaryImmunePartialImmunity>, 
      52             :     Flow<InfectionState::InfectedSevereNaive,                         InfectionState::DeadNaive>,
      53             :     Flow<InfectionState::InfectedCriticalNaive,                       InfectionState::DeadNaive>,
      54             :     Flow<InfectionState::InfectedCriticalNaive,                       InfectionState::TemporaryImmunePartialImmunity>,
      55             :     Flow<InfectionState::TemporaryImmunePartialImmunity,              InfectionState::SusceptiblePartialImmunity>,
      56             :     //partial immunity
      57             :     Flow<InfectionState::SusceptiblePartialImmunity,                  InfectionState::ExposedPartialImmunity>,
      58             :     Flow<InfectionState::SusceptiblePartialImmunity,                  InfectionState::TemporaryImmuneImprovedImmunity>,
      59             :     Flow<InfectionState::ExposedPartialImmunity,                      InfectionState::InfectedNoSymptomsPartialImmunity>,
      60             :     Flow<InfectionState::InfectedNoSymptomsPartialImmunity,           InfectionState::InfectedSymptomsPartialImmunity>,
      61             :     Flow<InfectionState::InfectedNoSymptomsPartialImmunity,           InfectionState::TemporaryImmuneImprovedImmunity>,
      62             :     Flow<InfectionState::InfectedNoSymptomsPartialImmunityConfirmed,  InfectionState::InfectedSymptomsPartialImmunityConfirmed>,
      63             :     Flow<InfectionState::InfectedNoSymptomsPartialImmunityConfirmed,  InfectionState::TemporaryImmuneImprovedImmunity>,
      64             :     Flow<InfectionState::InfectedSymptomsPartialImmunity,             InfectionState::InfectedSeverePartialImmunity>,
      65             :     Flow<InfectionState::InfectedSymptomsPartialImmunity,             InfectionState::TemporaryImmuneImprovedImmunity>,
      66             :     Flow<InfectionState::InfectedSymptomsPartialImmunityConfirmed,    InfectionState::InfectedSeverePartialImmunity>,
      67             :     Flow<InfectionState::InfectedSymptomsPartialImmunityConfirmed,    InfectionState::TemporaryImmuneImprovedImmunity>,
      68             :     Flow<InfectionState::InfectedSeverePartialImmunity,               InfectionState::InfectedCriticalPartialImmunity>,
      69             :     Flow<InfectionState::InfectedSeverePartialImmunity,               InfectionState::TemporaryImmuneImprovedImmunity>,
      70             :     Flow<InfectionState::InfectedSeverePartialImmunity,               InfectionState::DeadPartialImmunity>,
      71             :     Flow<InfectionState::InfectedCriticalPartialImmunity,             InfectionState::DeadPartialImmunity>,
      72             :     Flow<InfectionState::InfectedCriticalPartialImmunity,             InfectionState::TemporaryImmuneImprovedImmunity>,
      73             :     //improved immunity
      74             :     Flow<InfectionState::SusceptibleImprovedImmunity,                 InfectionState::ExposedImprovedImmunity>,
      75             :     Flow<InfectionState::SusceptibleImprovedImmunity,                 InfectionState::TemporaryImmuneImprovedImmunity>,
      76             :     Flow<InfectionState::ExposedImprovedImmunity,                     InfectionState::InfectedNoSymptomsImprovedImmunity>,
      77             :     Flow<InfectionState::InfectedNoSymptomsImprovedImmunity,          InfectionState::InfectedSymptomsImprovedImmunity>,
      78             :     Flow<InfectionState::InfectedNoSymptomsImprovedImmunity,          InfectionState::TemporaryImmuneImprovedImmunity>,
      79             :     Flow<InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed, InfectionState::InfectedSymptomsImprovedImmunityConfirmed>,
      80             :     Flow<InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed, InfectionState::TemporaryImmuneImprovedImmunity>,
      81             :     Flow<InfectionState::InfectedSymptomsImprovedImmunity,            InfectionState::InfectedSevereImprovedImmunity>,
      82             :     Flow<InfectionState::InfectedSymptomsImprovedImmunity,            InfectionState::TemporaryImmuneImprovedImmunity>,
      83             :     Flow<InfectionState::InfectedSymptomsImprovedImmunityConfirmed,   InfectionState::InfectedSevereImprovedImmunity>,
      84             :     Flow<InfectionState::InfectedSymptomsImprovedImmunityConfirmed,   InfectionState::TemporaryImmuneImprovedImmunity>,
      85             :     Flow<InfectionState::InfectedSevereImprovedImmunity,              InfectionState::InfectedCriticalImprovedImmunity>,
      86             :     Flow<InfectionState::InfectedSevereImprovedImmunity,              InfectionState::TemporaryImmuneImprovedImmunity>,
      87             :     Flow<InfectionState::InfectedSevereImprovedImmunity,              InfectionState::DeadImprovedImmunity>,
      88             :     Flow<InfectionState::InfectedCriticalImprovedImmunity,            InfectionState::DeadImprovedImmunity>,
      89             :     Flow<InfectionState::InfectedCriticalImprovedImmunity,            InfectionState::TemporaryImmuneImprovedImmunity>,
      90             :     
      91             :     // waning
      92             :     Flow<InfectionState::TemporaryImmunePartialImmunity,              InfectionState::SusceptiblePartialImmunity>,
      93             :     Flow<InfectionState::TemporaryImmuneImprovedImmunity,             InfectionState::SusceptibleImprovedImmunity>,
      94             :     Flow<InfectionState::SusceptibleImprovedImmunity,                 InfectionState::SusceptiblePartialImmunity>,
      95             :     Flow<InfectionState::SusceptiblePartialImmunity,                  InfectionState::SusceptibleNaive>>;
      96             : // clang-format on
      97             : 
      98             : template <typename FP = ScalarType>
      99             : class Model
     100             :     : public FlowModel<FP, InfectionState, mio::Populations<FP, AgeGroup, InfectionState>, Parameters<FP>, Flows>
     101             : {
     102             :     using Base = FlowModel<FP, InfectionState, mio::Populations<FP, AgeGroup, InfectionState>, Parameters<FP>, Flows>;
     103             : 
     104             : public:
     105             :     using typename Base::ParameterSet;
     106             :     using typename Base::Populations;
     107             : 
     108         208 :     Model(const Populations& pop, const ParameterSet& params)
     109         208 :         : Base(pop, params)
     110             :     {
     111         208 :     }
     112             : 
     113         208 :     Model(int num_agegroups)
     114         208 :         : Model(Populations({AgeGroup(num_agegroups), InfectionState::Count}), ParameterSet(AgeGroup(num_agegroups)))
     115             :     {
     116         208 :     }
     117             : 
     118        3933 :     void get_flows(Eigen::Ref<const Eigen::VectorX<FP>> pop, Eigen::Ref<const Eigen::VectorX<FP>> y, FP t,
     119             :                    Eigen::Ref<Eigen::VectorX<FP>> flows) const override
     120             :     {
     121        3933 :         auto const& params   = this->parameters;
     122        3933 :         AgeGroup n_agegroups = params.get_num_groups();
     123             : 
     124        3933 :         ContactMatrixGroup const& contact_matrix = params.template get<ContactPatterns<FP>>();
     125             : 
     126        3933 :         auto icu_occupancy           = 0.0;
     127        3933 :         auto test_and_trace_required = 0.0;
     128       11376 :         for (auto i = AgeGroup(0); i < n_agegroups; ++i) {
     129             :             // naive flow to symptomatic in unit time
     130        7443 :             test_and_trace_required +=
     131       14886 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     132        7443 :                 params.template get<TimeInfectedNoSymptoms<FP>>()[i] *
     133       14886 :                 (this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsNaive}) +
     134        7443 :                  this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsNaiveConfirmed}));
     135             :             // partial immunity flow to symptomatic in unit time
     136        7443 :             test_and_trace_required +=
     137       14886 :                 (params.template get<ReducInfectedSymptomsPartialImmunity<FP>>()[i] /
     138        7443 :                  params.template get<ReducExposedPartialImmunity<FP>>()[i]) *
     139        7443 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     140       14886 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] *
     141        7443 :                  params.template get<ReducTimeInfectedMild<FP>>()[i]) *
     142       14886 :                 (this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsPartialImmunity}) +
     143        7443 :                  this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}));
     144             :             // improved immunity flow to symptomatic in unit time
     145        7443 :             test_and_trace_required +=
     146       14886 :                 (params.template get<ReducInfectedSymptomsImprovedImmunity<FP>>()[i] /
     147        7443 :                  params.template get<ReducExposedImprovedImmunity<FP>>()[i]) *
     148        7443 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     149       14886 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] *
     150        7443 :                  params.template get<ReducTimeInfectedMild<FP>>()[i]) *
     151       14886 :                 (this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsImprovedImmunity}) +
     152        7443 :                  this->populations.get_from(pop, {i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}));
     153       14886 :             icu_occupancy += this->populations.get_from(pop, {i, InfectionState::InfectedCriticalNaive}) +
     154       14886 :                              this->populations.get_from(pop, {i, InfectionState::InfectedCriticalPartialImmunity}) +
     155        7443 :                              this->populations.get_from(pop, {i, InfectionState::InfectedCriticalImprovedImmunity});
     156             :         }
     157             : 
     158             :         // get vaccinations
     159        3933 :         auto const partial_vaccination = vaccinations_at(t, params.template get<DailyPartialVaccinations<FP>>());
     160        3933 :         auto const full_vaccination    = vaccinations_at(t, params.template get<DailyFullVaccinations<FP>>());
     161        3933 :         auto const booster_vaccination = vaccinations_at(t, params.template get<DailyBoosterVaccinations<FP>>());
     162             : 
     163       11376 :         for (auto i = AgeGroup(0); i < n_agegroups; i++) {
     164             : 
     165        7443 :             size_t SNi    = this->populations.get_flat_index({i, InfectionState::SusceptibleNaive});
     166        7443 :             size_t ENi    = this->populations.get_flat_index({i, InfectionState::ExposedNaive});
     167        7443 :             size_t INSNi  = this->populations.get_flat_index({i, InfectionState::InfectedNoSymptomsNaive});
     168        7443 :             size_t ISyNi  = this->populations.get_flat_index({i, InfectionState::InfectedSymptomsNaive});
     169        7443 :             size_t ISevNi = this->populations.get_flat_index({i, InfectionState::InfectedSevereNaive});
     170        7443 :             size_t ICrNi  = this->populations.get_flat_index({i, InfectionState::InfectedCriticalNaive});
     171             : 
     172        7443 :             size_t INSNCi = this->populations.get_flat_index({i, InfectionState::InfectedNoSymptomsNaiveConfirmed});
     173        7443 :             size_t ISyNCi = this->populations.get_flat_index({i, InfectionState::InfectedSymptomsNaiveConfirmed});
     174             : 
     175        7443 :             size_t SPIi    = this->populations.get_flat_index({i, InfectionState::SusceptiblePartialImmunity});
     176        7443 :             size_t EPIi    = this->populations.get_flat_index({i, InfectionState::ExposedPartialImmunity});
     177        7443 :             size_t INSPIi  = this->populations.get_flat_index({i, InfectionState::InfectedNoSymptomsPartialImmunity});
     178        7443 :             size_t ISyPIi  = this->populations.get_flat_index({i, InfectionState::InfectedSymptomsPartialImmunity});
     179        7443 :             size_t ISevPIi = this->populations.get_flat_index({i, InfectionState::InfectedSeverePartialImmunity});
     180        7443 :             size_t ICrPIi  = this->populations.get_flat_index({i, InfectionState::InfectedCriticalPartialImmunity});
     181             : 
     182             :             size_t INSPICi =
     183        7443 :                 this->populations.get_flat_index({i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed});
     184             :             size_t ISyPICi =
     185        7443 :                 this->populations.get_flat_index({i, InfectionState::InfectedSymptomsPartialImmunityConfirmed});
     186             : 
     187        7443 :             size_t EIIi    = this->populations.get_flat_index({i, InfectionState::ExposedImprovedImmunity});
     188        7443 :             size_t INSIIi  = this->populations.get_flat_index({i, InfectionState::InfectedNoSymptomsImprovedImmunity});
     189        7443 :             size_t ISyIIi  = this->populations.get_flat_index({i, InfectionState::InfectedSymptomsImprovedImmunity});
     190        7443 :             size_t ISevIIi = this->populations.get_flat_index({i, InfectionState::InfectedSevereImprovedImmunity});
     191        7443 :             size_t ICrIIi  = this->populations.get_flat_index({i, InfectionState::InfectedCriticalImprovedImmunity});
     192             : 
     193             :             size_t INSIICi =
     194        7443 :                 this->populations.get_flat_index({i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed});
     195             :             size_t ISyIICi =
     196        7443 :                 this->populations.get_flat_index({i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed});
     197        7443 :             size_t TImm1 = this->populations.get_flat_index({i, InfectionState::TemporaryImmunePartialImmunity});
     198        7443 :             size_t TImm2 = this->populations.get_flat_index({i, InfectionState::TemporaryImmuneImprovedImmunity});
     199             : 
     200        7443 :             size_t SIIi = this->populations.get_flat_index({i, InfectionState::SusceptibleImprovedImmunity});
     201             : 
     202        7443 :             FP reducExposedPartialImmunity  = params.template get<ReducExposedPartialImmunity<FP>>()[i];
     203        7443 :             FP reducExposedImprovedImmunity = params.template get<ReducExposedImprovedImmunity<FP>>()[i];
     204        7443 :             FP reducInfectedSymptomsPartialImmunity =
     205        7443 :                 params.template get<ReducInfectedSymptomsPartialImmunity<FP>>()[i];
     206        7443 :             FP reducInfectedSymptomsImprovedImmunity =
     207        7443 :                 params.template get<ReducInfectedSymptomsImprovedImmunity<FP>>()[i];
     208        7443 :             FP reducInfectedSevereCriticalDeadPartialImmunity =
     209        7443 :                 params.template get<ReducInfectedSevereCriticalDeadPartialImmunity<FP>>()[i];
     210        7443 :             FP reducInfectedSevereCriticalDeadImprovedImmunity =
     211        7443 :                 params.template get<ReducInfectedSevereCriticalDeadImprovedImmunity<FP>>()[i];
     212        7443 :             FP reducTimeInfectedMild = params.template get<ReducTimeInfectedMild<FP>>()[i];
     213             : 
     214             :             //symptomatic are less well quarantined when testing and tracing is overwhelmed so they infect more people
     215             :             auto riskFromInfectedSymptomatic =
     216       29772 :                 smoother_cosine(test_and_trace_required, params.template get<TestAndTraceCapacity<FP>>(),
     217       14886 :                                 params.template get<TestAndTraceCapacity<FP>>() *
     218        7443 :                                     params.template get<TestAndTraceCapacityMaxRiskSymptoms<FP>>(),
     219        7443 :                                 params.template get<RiskOfInfectionFromSymptomatic<FP>>()[i],
     220        7443 :                                 params.template get<MaxRiskOfInfectionFromSymptomatic<FP>>()[i]);
     221             : 
     222             :             auto riskFromInfectedNoSymptoms =
     223       22329 :                 smoother_cosine(test_and_trace_required, params.template get<TestAndTraceCapacity<FP>>(),
     224       14886 :                                 params.template get<TestAndTraceCapacity<FP>>() *
     225        7443 :                                     params.template get<TestAndTraceCapacityMaxRiskNoSymptoms<FP>>(),
     226        7443 :                                 params.template get<RelativeTransmissionNoSymptoms<FP>>()[i], 1.0);
     227             : 
     228       21906 :             for (auto j = AgeGroup(0); j < n_agegroups; j++) {
     229       14463 :                 size_t SNj    = this->populations.get_flat_index({j, InfectionState::SusceptibleNaive});
     230       14463 :                 size_t ENj    = this->populations.get_flat_index({j, InfectionState::ExposedNaive});
     231       14463 :                 size_t INSNj  = this->populations.get_flat_index({j, InfectionState::InfectedNoSymptomsNaive});
     232       14463 :                 size_t ISyNj  = this->populations.get_flat_index({j, InfectionState::InfectedSymptomsNaive});
     233       14463 :                 size_t ISevNj = this->populations.get_flat_index({j, InfectionState::InfectedSevereNaive});
     234       14463 :                 size_t ICrNj  = this->populations.get_flat_index({j, InfectionState::InfectedCriticalNaive});
     235       14463 :                 size_t SIIj   = this->populations.get_flat_index({j, InfectionState::SusceptibleImprovedImmunity});
     236             : 
     237       14463 :                 size_t INSNCj = this->populations.get_flat_index({j, InfectionState::InfectedNoSymptomsNaiveConfirmed});
     238       14463 :                 size_t ISyNCj = this->populations.get_flat_index({j, InfectionState::InfectedSymptomsNaiveConfirmed});
     239             : 
     240       14463 :                 size_t SPIj = this->populations.get_flat_index({j, InfectionState::SusceptiblePartialImmunity});
     241       14463 :                 size_t EPIj = this->populations.get_flat_index({j, InfectionState::ExposedPartialImmunity});
     242             :                 size_t INSPIj =
     243       14463 :                     this->populations.get_flat_index({j, InfectionState::InfectedNoSymptomsPartialImmunity});
     244       14463 :                 size_t ISyPIj  = this->populations.get_flat_index({j, InfectionState::InfectedSymptomsPartialImmunity});
     245       14463 :                 size_t ISevPIj = this->populations.get_flat_index({j, InfectionState::InfectedSeverePartialImmunity});
     246       14463 :                 size_t ICrPIj  = this->populations.get_flat_index({j, InfectionState::InfectedCriticalPartialImmunity});
     247             : 
     248             :                 size_t INSPICj =
     249       14463 :                     this->populations.get_flat_index({j, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed});
     250             :                 size_t ISyPICj =
     251       14463 :                     this->populations.get_flat_index({j, InfectionState::InfectedSymptomsPartialImmunityConfirmed});
     252             : 
     253       14463 :                 size_t EIIj = this->populations.get_flat_index({j, InfectionState::ExposedImprovedImmunity});
     254             :                 size_t INSIIj =
     255       14463 :                     this->populations.get_flat_index({j, InfectionState::InfectedNoSymptomsImprovedImmunity});
     256       14463 :                 size_t ISyIIj = this->populations.get_flat_index({j, InfectionState::InfectedSymptomsImprovedImmunity});
     257       14463 :                 size_t ISevIIj = this->populations.get_flat_index({j, InfectionState::InfectedSevereImprovedImmunity});
     258       14463 :                 size_t ICrIIj = this->populations.get_flat_index({j, InfectionState::InfectedCriticalImprovedImmunity});
     259             : 
     260             :                 size_t INSIICj =
     261       14463 :                     this->populations.get_flat_index({j, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed});
     262             :                 size_t ISyIICj =
     263       14463 :                     this->populations.get_flat_index({j, InfectionState::InfectedSymptomsImprovedImmunityConfirmed});
     264             : 
     265             :                 // effective contact rate by contact rate between groups i and j and damping j
     266       14463 :                 FP season_val    = (1 + params.template get<Seasonality<FP>>() *
     267       14463 :                                          sin(3.141592653589793 *
     268       14463 :                                                 (std::fmod((params.template get<StartDay>() + t), 365.0) / 182.5 + 0.5)));
     269       28926 :                 FP cont_freq_eff = season_val * contact_matrix.get_matrix_at(t)(static_cast<Eigen::Index>((size_t)i),
     270       14463 :                                                                                 static_cast<Eigen::Index>((size_t)j));
     271             :                 // without died people
     272       14463 :                 FP Nj = pop[SNj] + pop[ENj] + pop[INSNj] + pop[ISyNj] + pop[ISevNj] + pop[ICrNj] + pop[INSNCj] +
     273       14463 :                         pop[ISyNCj] + pop[SPIj] + pop[EPIj] + pop[INSPIj] + pop[ISyPIj] + pop[ISevPIj] + pop[ICrPIj] +
     274       14463 :                         pop[INSPICj] + pop[ISyPICj] + pop[SIIj] + pop[EIIj] + pop[INSIIj] + pop[ISyIIj] + pop[ISevIIj] +
     275       14463 :                         pop[ICrIIj] + pop[INSIICj] + pop[ISyIICj];
     276             : 
     277       14463 :                 const FP divNj = (Nj < Limits<FP>::zero_tolerance()) ? 0.0 : 1.0 / Nj;
     278             : 
     279       14463 :                 FP ext_inf_force_dummy = cont_freq_eff * divNj *
     280       14463 :                                          params.template get<TransmissionProbabilityOnContact<FP>>()[(AgeGroup)i] *
     281       14463 :                                          (riskFromInfectedNoSymptoms * (pop[INSNj] + pop[INSPIj] + pop[INSIIj]) +
     282       14463 :                                           riskFromInfectedSymptomatic * (pop[ISyNj] + pop[ISyPIj] + pop[ISyIIj]));
     283             : 
     284       14463 :                 FP dummy_SN = y[SNi] * ext_inf_force_dummy;
     285             : 
     286       14463 :                 FP dummy_SPI = y[SPIi] * reducExposedPartialImmunity * ext_inf_force_dummy;
     287             : 
     288       14463 :                 FP dummy_SII = y[SIIi] * reducExposedImprovedImmunity * ext_inf_force_dummy;
     289             : 
     290       28926 :                 flows[this->template get_flat_flow_index<InfectionState::SusceptibleNaive,
     291       14463 :                                                          InfectionState::ExposedNaive>({i})] += dummy_SN;
     292       28926 :                 flows[this->template get_flat_flow_index<InfectionState::SusceptiblePartialImmunity,
     293       14463 :                                                          InfectionState::ExposedPartialImmunity>({i})] += dummy_SPI;
     294       28926 :                 flows[this->template get_flat_flow_index<InfectionState::SusceptibleImprovedImmunity,
     295       14463 :                                                          InfectionState::ExposedImprovedImmunity>({i})] += dummy_SII;
     296             :             }
     297             : 
     298             :             // vaccinations
     299       14886 :             flows[this->template get_flat_flow_index<InfectionState::SusceptibleNaive,
     300        7443 :                                                      InfectionState::TemporaryImmunePartialImmunity>({i})] =
     301       22329 :                 std::min(y[SNi] - flows[this->template get_flat_flow_index<InfectionState::SusceptibleNaive,
     302        7443 :                                                                            InfectionState::ExposedNaive>({i})],
     303        7443 :                          partial_vaccination[static_cast<size_t>(i)]);
     304             : 
     305       14886 :             flows[this->template get_flat_flow_index<InfectionState::SusceptiblePartialImmunity,
     306        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     307       22329 :                 std::min(y[SPIi] -
     308        7443 :                              flows[this->template get_flat_flow_index<InfectionState::SusceptiblePartialImmunity,
     309        7443 :                                                                       InfectionState::ExposedPartialImmunity>({i})],
     310        7443 :                          full_vaccination[static_cast<size_t>(i)]);
     311             : 
     312       14886 :             flows[this->template get_flat_flow_index<InfectionState::SusceptibleImprovedImmunity,
     313        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     314       22329 :                 std::min(y[SIIi] -
     315        7443 :                              flows[this->template get_flat_flow_index<InfectionState::SusceptibleImprovedImmunity,
     316        7443 :                                                                       InfectionState::ExposedImprovedImmunity>({i})],
     317        7443 :                          booster_vaccination[static_cast<size_t>(i)]);
     318             : 
     319             :             // ICU capacity shortage is close
     320             :             // TODO: if this is used with vaccination model, it has to be adapted if CriticalPerSevere
     321             :             // is different for different vaccination status. This is not the case here and in addition, ICUCapacity
     322             :             // is set to infinity and this functionality is deactivated, so this is OK for the moment.
     323       14886 :             FP criticalPerSevereAdjusted = smoother_cosine(icu_occupancy, 0.90 * params.template get<ICUCapacity<FP>>(),
     324        7443 :                                                            params.template get<ICUCapacity<FP>>(),
     325        7443 :                                                            params.template get<CriticalPerSevere<FP>>()[i], 0);
     326             : 
     327        7443 :             FP deathsPerSevereAdjusted = params.template get<CriticalPerSevere<FP>>()[i] - criticalPerSevereAdjusted;
     328             : 
     329             :             /**** path of immune-naive ***/
     330             :             // Exposed
     331       14886 :             flows[this->template get_flat_flow_index<InfectionState::ExposedNaive,
     332        7443 :                                                      InfectionState::InfectedNoSymptomsNaive>({i})] +=
     333        7443 :                 y[ENi] / params.template get<TimeExposed<FP>>()[i];
     334             : 
     335             :             // InfectedNoSymptoms
     336       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsNaive,
     337        7443 :                                                      InfectionState::TemporaryImmunePartialImmunity>({i})] =
     338        7443 :                 params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i] *
     339        7443 :                 (1 / params.template get<TimeInfectedNoSymptoms<FP>>()[i]) * y[INSNi];
     340       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsNaive,
     341        7443 :                                                      InfectionState::InfectedSymptomsNaive>({i})] =
     342       14886 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     343       14886 :                 params.template get<TimeInfectedNoSymptoms<FP>>()[i] * y[INSNi];
     344       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsNaiveConfirmed,
     345        7443 :                                                      InfectionState::InfectedSymptomsNaiveConfirmed>({i})] =
     346       14886 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     347       14886 :                 params.template get<TimeInfectedNoSymptoms<FP>>()[i] * y[INSNCi];
     348       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsNaiveConfirmed,
     349        7443 :                                                      InfectionState::TemporaryImmunePartialImmunity>({i})] =
     350        7443 :                 params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i] *
     351        7443 :                 (1 / params.template get<TimeInfectedNoSymptoms<FP>>()[i]) * y[INSNCi];
     352             : 
     353             :             // // InfectedSymptoms
     354       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsNaive,
     355        7443 :                                                      InfectionState::InfectedSevereNaive>({i})] =
     356       14886 :                 params.template get<SeverePerInfectedSymptoms<FP>>()[i] /
     357       14886 :                 params.template get<TimeInfectedSymptoms<FP>>()[i] * y[ISyNi];
     358             : 
     359       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsNaive,
     360        7443 :                                                      InfectionState::TemporaryImmunePartialImmunity>({i})] =
     361       14886 :                 (1 - params.template get<SeverePerInfectedSymptoms<FP>>()[i]) /
     362       14886 :                 params.template get<TimeInfectedSymptoms<FP>>()[i] * y[ISyNi];
     363             : 
     364       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsNaiveConfirmed,
     365        7443 :                                                      InfectionState::InfectedSevereNaive>({i})] =
     366       14886 :                 params.template get<SeverePerInfectedSymptoms<FP>>()[i] /
     367       14886 :                 params.template get<TimeInfectedSymptoms<FP>>()[i] * y[ISyNCi];
     368             : 
     369       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsNaiveConfirmed,
     370        7443 :                                                      InfectionState::TemporaryImmunePartialImmunity>({i})] =
     371       14886 :                 (1 - params.template get<SeverePerInfectedSymptoms<FP>>()[i]) /
     372       14886 :                 params.template get<TimeInfectedSymptoms<FP>>()[i] * y[ISyNCi];
     373             : 
     374             :             // InfectedSevere
     375       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSevereNaive,
     376        7443 :                                                      InfectionState::InfectedCriticalNaive>({i})] =
     377        7443 :                 criticalPerSevereAdjusted / params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevNi];
     378             : 
     379       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSevereNaive,
     380        7443 :                                                      InfectionState::TemporaryImmunePartialImmunity>({i})] =
     381       14886 :                 (1 - params.template get<CriticalPerSevere<FP>>()[i]) /
     382       14886 :                 params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevNi];
     383             : 
     384        7443 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSevereNaive, InfectionState::DeadNaive>(
     385       14886 :                 {i})] = deathsPerSevereAdjusted / params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevNi];
     386             :             // InfectedCritical
     387        7443 :             flows[this->template get_flat_flow_index<InfectionState::InfectedCriticalNaive, InfectionState::DeadNaive>(
     388       22329 :                 {i})] = params.template get<DeathsPerCritical<FP>>()[i] /
     389       14886 :                         params.template get<TimeInfectedCritical<FP>>()[i] * y[ICrNi];
     390             : 
     391       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedCriticalNaive,
     392        7443 :                                                      InfectionState::TemporaryImmunePartialImmunity>({i})] =
     393       14886 :                 (1 - params.template get<DeathsPerCritical<FP>>()[i]) /
     394       14886 :                 params.template get<TimeInfectedCritical<FP>>()[i] * y[ICrNi];
     395             : 
     396             :             // Waning immunity
     397       14886 :             flows[this->template get_flat_flow_index<InfectionState::SusceptiblePartialImmunity,
     398        7443 :                                                      InfectionState::SusceptibleNaive>({i})] =
     399        7443 :                 1 / params.template get<TimeWaningPartialImmunity<FP>>()[i] * y[SPIi];
     400       14886 :             flows[this->template get_flat_flow_index<InfectionState::TemporaryImmunePartialImmunity,
     401        7443 :                                                      InfectionState::SusceptiblePartialImmunity>({i})] =
     402        7443 :                 1 / params.template get<TimeTemporaryImmunityPI<FP>>()[i] * y[TImm1];
     403             : 
     404             :             // /**** path of partially immune ***/
     405             : 
     406             :             // Exposed
     407       14886 :             flows[this->template get_flat_flow_index<InfectionState::ExposedPartialImmunity,
     408        7443 :                                                      InfectionState::InfectedNoSymptomsPartialImmunity>({i})] +=
     409        7443 :                 y[EPIi] / params.template get<TimeExposed<FP>>()[i];
     410             : 
     411             :             // InfectedNoSymptoms
     412       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsPartialImmunity,
     413        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     414       14886 :                 (1 - (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) *
     415        7443 :                          (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i])) /
     416        7443 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[INSPIi];
     417       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsPartialImmunity,
     418        7443 :                                                      InfectionState::InfectedSymptomsPartialImmunity>({i})] =
     419       14886 :                 (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) *
     420        7443 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     421        7443 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[INSPIi];
     422       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsPartialImmunityConfirmed,
     423        7443 :                                                      InfectionState::InfectedSymptomsPartialImmunityConfirmed>({i})] =
     424       14886 :                 (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) *
     425        7443 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     426        7443 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[INSPICi];
     427       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsPartialImmunityConfirmed,
     428        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     429       14886 :                 (1 - (reducInfectedSymptomsPartialImmunity / reducExposedPartialImmunity) *
     430        7443 :                          (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i])) /
     431        7443 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[INSPICi];
     432             : 
     433             :             // InfectedSymptoms
     434       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsPartialImmunity,
     435        7443 :                                                      InfectionState::InfectedSeverePartialImmunity>({i})] =
     436        7443 :                 reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSymptomsPartialImmunity *
     437        7443 :                 params.template get<SeverePerInfectedSymptoms<FP>>()[i] /
     438        7443 :                 (params.template get<TimeInfectedSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[ISyPIi];
     439             : 
     440       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsPartialImmunity,
     441        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     442        7443 :                 (1 - (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSymptomsPartialImmunity) *
     443        7443 :                          params.template get<SeverePerInfectedSymptoms<FP>>()[i]) /
     444        7443 :                 (params.template get<TimeInfectedSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[ISyPIi];
     445             : 
     446       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsPartialImmunityConfirmed,
     447        7443 :                                                      InfectionState::InfectedSeverePartialImmunity>({i})] =
     448        7443 :                 reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSymptomsPartialImmunity *
     449        7443 :                 params.template get<SeverePerInfectedSymptoms<FP>>()[i] /
     450        7443 :                 (params.template get<TimeInfectedSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[ISyPICi];
     451             : 
     452       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsPartialImmunityConfirmed,
     453        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     454        7443 :                 (1 - (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSymptomsPartialImmunity) *
     455        7443 :                          params.template get<SeverePerInfectedSymptoms<FP>>()[i]) /
     456        7443 :                 (params.template get<TimeInfectedSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[ISyPICi];
     457             : 
     458             :             // InfectedSevere
     459       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSeverePartialImmunity,
     460        7443 :                                                      InfectionState::InfectedCriticalPartialImmunity>({i})] =
     461        7443 :                 reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity *
     462        7443 :                 criticalPerSevereAdjusted / params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevPIi];
     463             : 
     464       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSeverePartialImmunity,
     465        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     466        7443 :                 (1 - (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity) *
     467       14886 :                          params.template get<CriticalPerSevere<FP>>()[i]) /
     468       14886 :                 params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevPIi];
     469             : 
     470       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSeverePartialImmunity,
     471        7443 :                                                      InfectionState::DeadPartialImmunity>({i})] =
     472        7443 :                 (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity) *
     473        7443 :                 deathsPerSevereAdjusted / params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevPIi];
     474             :             // InfectedCritical
     475       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedCriticalPartialImmunity,
     476        7443 :                                                      InfectionState::DeadPartialImmunity>({i})] =
     477        7443 :                 (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity) *
     478       14886 :                 params.template get<DeathsPerCritical<FP>>()[i] / params.template get<TimeInfectedCritical<FP>>()[i] *
     479        7443 :                 y[ICrPIi];
     480             : 
     481       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedCriticalPartialImmunity,
     482        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     483        7443 :                 (1 - (reducInfectedSevereCriticalDeadPartialImmunity / reducInfectedSevereCriticalDeadPartialImmunity) *
     484       14886 :                          params.template get<DeathsPerCritical<FP>>()[i]) /
     485       14886 :                 params.template get<TimeInfectedCritical<FP>>()[i] * y[ICrPIi];
     486             : 
     487             :             // /**** path of improved immunity ***/
     488             :             // Exposed
     489       14886 :             flows[this->template get_flat_flow_index<InfectionState::ExposedImprovedImmunity,
     490        7443 :                                                      InfectionState::InfectedNoSymptomsImprovedImmunity>({i})] +=
     491        7443 :                 y[EIIi] / params.template get<TimeExposed<FP>>()[i];
     492             : 
     493             :             // InfectedNoSymptoms
     494       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsImprovedImmunity,
     495        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     496       14886 :                 (1 - (reducInfectedSymptomsImprovedImmunity / reducExposedImprovedImmunity) *
     497        7443 :                          (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i])) /
     498        7443 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[INSIIi];
     499       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsImprovedImmunity,
     500        7443 :                                                      InfectionState::InfectedSymptomsImprovedImmunity>({i})] =
     501       14886 :                 (reducInfectedSymptomsImprovedImmunity / reducExposedImprovedImmunity) *
     502        7443 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     503        7443 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[INSIIi];
     504       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed,
     505        7443 :                                                      InfectionState::InfectedSymptomsImprovedImmunityConfirmed>({i})] =
     506       14886 :                 (reducInfectedSymptomsImprovedImmunity / reducExposedImprovedImmunity) *
     507        7443 :                 (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i]) /
     508        7443 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[INSIICi];
     509       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed,
     510        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     511       14886 :                 (1 - (reducInfectedSymptomsImprovedImmunity / reducExposedImprovedImmunity) *
     512        7443 :                          (1 - params.template get<RecoveredPerInfectedNoSymptoms<FP>>()[i])) /
     513        7443 :                 (params.template get<TimeInfectedNoSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[INSIICi];
     514             : 
     515             :             // InfectedSymptoms
     516       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsImprovedImmunity,
     517        7443 :                                                      InfectionState::InfectedSevereImprovedImmunity>({i})] =
     518        7443 :                 reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSymptomsImprovedImmunity *
     519        7443 :                 params.template get<SeverePerInfectedSymptoms<FP>>()[i] /
     520        7443 :                 (params.template get<TimeInfectedSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[ISyIIi];
     521             : 
     522       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsImprovedImmunity,
     523        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     524        7443 :                 (1 - (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSymptomsImprovedImmunity) *
     525        7443 :                          params.template get<SeverePerInfectedSymptoms<FP>>()[i]) /
     526        7443 :                 (params.template get<TimeInfectedSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[ISyIIi];
     527             : 
     528       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsImprovedImmunityConfirmed,
     529        7443 :                                                      InfectionState::InfectedSevereImprovedImmunity>({i})] =
     530        7443 :                 reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSymptomsImprovedImmunity *
     531        7443 :                 params.template get<SeverePerInfectedSymptoms<FP>>()[i] /
     532        7443 :                 (params.template get<TimeInfectedSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[ISyIICi];
     533             : 
     534       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSymptomsImprovedImmunityConfirmed,
     535        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     536        7443 :                 (1 - (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSymptomsImprovedImmunity) *
     537        7443 :                          params.template get<SeverePerInfectedSymptoms<FP>>()[i]) /
     538        7443 :                 (params.template get<TimeInfectedSymptoms<FP>>()[i] * reducTimeInfectedMild) * y[ISyIICi];
     539             : 
     540             :             // InfectedSevere
     541       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSevereImprovedImmunity,
     542        7443 :                                                      InfectionState::InfectedCriticalImprovedImmunity>({i})] =
     543        7443 :                 reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity *
     544        7443 :                 criticalPerSevereAdjusted / params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevIIi];
     545             : 
     546       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSevereImprovedImmunity,
     547        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     548        7443 :                 (1 -
     549        7443 :                  (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity) *
     550       14886 :                      params.template get<CriticalPerSevere<FP>>()[i]) /
     551       14886 :                 params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevIIi];
     552             : 
     553       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedSevereImprovedImmunity,
     554        7443 :                                                      InfectionState::DeadImprovedImmunity>({i})] =
     555        7443 :                 (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity) *
     556        7443 :                 deathsPerSevereAdjusted / params.template get<TimeInfectedSevere<FP>>()[i] * y[ISevIIi];
     557             : 
     558             :             // InfectedCritical
     559       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedCriticalImprovedImmunity,
     560        7443 :                                                      InfectionState::DeadImprovedImmunity>({i})] =
     561        7443 :                 (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity) *
     562       14886 :                 params.template get<DeathsPerCritical<FP>>()[i] / params.template get<TimeInfectedCritical<FP>>()[i] *
     563        7443 :                 y[ICrIIi];
     564             : 
     565       14886 :             flows[this->template get_flat_flow_index<InfectionState::InfectedCriticalImprovedImmunity,
     566        7443 :                                                      InfectionState::TemporaryImmuneImprovedImmunity>({i})] =
     567        7443 :                 (1 -
     568        7443 :                  (reducInfectedSevereCriticalDeadImprovedImmunity / reducInfectedSevereCriticalDeadImprovedImmunity) *
     569       14886 :                      params.template get<DeathsPerCritical<FP>>()[i]) /
     570       14886 :                 params.template get<TimeInfectedCritical<FP>>()[i] * y[ICrIIi];
     571             : 
     572             :             // Waning immunity
     573       14886 :             flows[this->template get_flat_flow_index<InfectionState::TemporaryImmuneImprovedImmunity,
     574        7443 :                                                      InfectionState::SusceptibleImprovedImmunity>({i})] =
     575        7443 :                 1 / params.template get<TimeTemporaryImmunityII<FP>>()[i] * y[TImm2];
     576             : 
     577       14886 :             flows[this->template get_flat_flow_index<InfectionState::SusceptibleImprovedImmunity,
     578        7443 :                                                      InfectionState::SusceptiblePartialImmunity>({i})] =
     579        7443 :                 1 / params.template get<TimeWaningImprovedImmunity<FP>>()[i] * y[SIIi];
     580             :         }
     581        7866 :     }
     582             : 
     583             :     /**
     584             :     * @brief Calculates smoothed vaccinations for a given time point.
     585             :     *
     586             :     * This function calculates the number of vaccinations for each age group at a given time t, 
     587             :     * based on daily vaccinations data. The smoothing is done using a cosine function.
     588             :     *
     589             :     * @param t The time in the simulation.
     590             :     * @param daily_vaccinations The daily vaccinations data, indexed by age group and simulation day.
     591             :     * @param eps [Default: 0.15] The smoothing factor used in the cosine smoothing function.
     592             :     * @return A vector containing the number of vaccinations for each age group at time t.
     593             :     */
     594       11898 :     Eigen::VectorXd vaccinations_at(const FP t,
     595             :                                     const CustomIndexArray<ScalarType, AgeGroup, SimulationDay>& daily_vaccinations,
     596             :                                     const FP eps = 0.15) const
     597             :     {
     598       11898 :         auto const& params = this->parameters;
     599       11898 :         const FP ub        = (size_t)t + 1.0;
     600       11898 :         const FP lb        = ub - eps;
     601             : 
     602       11898 :         const auto max_time = static_cast<size_t>(daily_vaccinations.size<SimulationDay>()) - 1;
     603             : 
     604       11898 :         Eigen::VectorXd smoothed_vaccinations((size_t)params.get_num_groups());
     605       11898 :         smoothed_vaccinations.setZero();
     606             : 
     607             :         // if daily_vaccinations is not available for the current time point, we return zero vaccinations.
     608       11898 :         if (max_time <= (size_t)t) {
     609           9 :             mio::log_warning("Vaccination data not available for time point ", t, ". Returning zero vaccinations.");
     610           9 :             return smoothed_vaccinations;
     611             :         }
     612       11889 :         if (t >= lb) {
     613       10476 :             for (AgeGroup age = AgeGroup(0); age < params.get_num_groups(); age++) {
     614             :                 // if ub + 1 is out of bounds, we use the value at ub
     615        6912 :                 auto ubp1 = static_cast<size_t>(ub + 1);
     616        6912 :                 if (max_time < ubp1) {
     617           9 :                     ubp1 = static_cast<size_t>(ub);
     618             :                 }
     619       20736 :                 const auto num_vaccinations_ub = daily_vaccinations[{age, SimulationDay(static_cast<size_t>(ubp1))}] -
     620       13824 :                                                  daily_vaccinations[{age, SimulationDay(static_cast<size_t>(ub))}];
     621       20736 :                 const auto num_vaccinations_lb = daily_vaccinations[{age, SimulationDay(static_cast<size_t>(lb + 1))}] -
     622       13824 :                                                  daily_vaccinations[{age, SimulationDay(static_cast<size_t>(lb))}];
     623        6912 :                 smoothed_vaccinations[(size_t)age] =
     624        6912 :                     smoother_cosine(t, lb, ub, num_vaccinations_lb, num_vaccinations_ub);
     625             :             }
     626             :         }
     627             :         else {
     628       23832 :             for (auto age = AgeGroup(0); age < params.get_num_groups(); age++) {
     629       46521 :                 smoothed_vaccinations[(size_t)age] = daily_vaccinations[{age, SimulationDay((size_t)t + 1)}] -
     630       31014 :                                                      daily_vaccinations[{age, SimulationDay((size_t)t)}];
     631             :             }
     632             :         }
     633       11889 :         return smoothed_vaccinations;
     634       11898 :     }
     635             : 
     636             :     /**
     637             :     * serialize this. 
     638             :     * @see mio::serialize
     639             :     */
     640             :     template <class IOContext>
     641             :     void serialize(IOContext& io) const
     642             :     {
     643             :         auto obj = io.create_object("Model");
     644             :         obj.add_element("Parameters", this->parameters);
     645             :         obj.add_element("Populations", this->populations);
     646             :     }
     647             : 
     648             :     /**
     649             :     * deserialize an object of this class.
     650             :     * @see mio::deserialize
     651             :     */
     652             :     template <class IOContext>
     653             :     static IOResult<Model> deserialize(IOContext& io)
     654             :     {
     655             :         auto obj = io.expect_object("Model");
     656             :         auto par = obj.expect_element("Parameters", Tag<ParameterSet>{});
     657             :         auto pop = obj.expect_element("Populations", Tag<Populations>{});
     658             :         return apply(
     659             :             io,
     660             :             [](auto&& par_, auto&& pop_) {
     661             :                 return Model{pop_, par_};
     662             :             },
     663             :             par, pop);
     664             :     }
     665             : }; // namespace osecirts
     666             : 
     667             : //forward declaration, see below.
     668             : template <typename FP = ScalarType, class Base = mio::Simulation<FP, Model<FP>>>
     669             : class Simulation;
     670             : 
     671             : /**
     672             : * get percentage of infections per total population.
     673             : * @param model the compartment model with initial values.
     674             : * @param t current simulation time.
     675             : * @param y current value of compartments.
     676             : * @tparam Base simulation type that uses the SECIRS-type compartment model. see Simulation.
     677             : */
     678             : template <typename FP = ScalarType, class Base = mio::Simulation<FP, Model<FP>>>
     679             : FP get_infections_relative(const Simulation<FP, Base>& model, FP t, const Eigen::Ref<const Eigen::VectorX<FP>>& y);
     680             : 
     681             : /**
     682             :  * specialization of compartment model simulation for the SECIRTS model.
     683             :  * @tparam FP floating point type, e.g., double.
     684             :  * @tparam BaseT simulation type, default mio::Simulation. For testing purposes only!
     685             :  */
     686             : template <typename FP, class BaseT>
     687             : class Simulation : public BaseT
     688             : {
     689             : public:
     690             :     /**
     691             :      * construct a simulation.
     692             :      * @param model the model to simulate.
     693             :      * @param t0 start time
     694             :      * @param dt time steps
     695             :      */
     696          63 :     Simulation(mio::osecirts::Model<FP> const& model, FP t0 = 0., FP dt = 0.1)
     697             :         : BaseT(model, t0, dt)
     698          63 :         , m_t_last_npi_check(t0)
     699             :     {
     700          63 :     }
     701             : 
     702             :     /**
     703             :     * @brief Applies the effect of a new variant of a disease to the transmission probability of the model.
     704             :     * 
     705             :     * This function adjusts the transmission probability of the disease for each age group based on the share of the new variant.
     706             :     * The share of the new variant is calculated based on the time `t` and the start day of the new variant.
     707             :     * The transmission probability is then updated for each age group in the model.
     708             :     * 
     709             :     * Based on Equation (35) and (36) in doi.org/10.1371/journal.pcbi.1010054
     710             :     * 
     711             :     * @param [in] t The current time.
     712             :     * @param [in] base_infectiousness The base infectiousness of the old variant for each age group.
     713             :     */
     714             : 
     715         333 :     void apply_variant(const FP t, const CustomIndexArray<UncertainValue<FP>, AgeGroup> base_infectiousness)
     716             :     {
     717         333 :         auto start_day             = this->get_model().parameters.template get<StartDay>();
     718         333 :         auto start_day_new_variant = this->get_model().parameters.template get<StartDayNewVariant>();
     719             : 
     720         333 :         if (start_day + t >= start_day_new_variant - 1e-10) {
     721          27 :             const FP days_variant      = t - (start_day_new_variant - start_day);
     722          27 :             const FP share_new_variant = std::min(1.0, 0.01 * pow(2, (1. / 7) * days_variant));
     723          27 :             const auto num_groups      = this->get_model().parameters.get_num_groups();
     724          54 :             for (auto i = AgeGroup(0); i < num_groups; ++i) {
     725          27 :                 FP new_transmission = (1 - share_new_variant) * base_infectiousness[i] +
     726          27 :                                       share_new_variant * base_infectiousness[i] *
     727          27 :                                           this->get_model().parameters.template get<InfectiousnessNewVariant<FP>>()[i];
     728          27 :                 this->get_model().parameters.template get<TransmissionProbabilityOnContact<FP>>()[i] = new_transmission;
     729             :             }
     730             :         }
     731         333 :     }
     732             : 
     733             :     /**
     734             :      * @brief advance simulation to tmax.
     735             :      * Overwrites Simulation::advance and includes a check for dynamic NPIs in regular intervals.
     736             :      * @see Simulation::advance
     737             :      * @param tmax next stopping point of simulation
     738             :      * @return value at tmax
     739             :      */
     740          36 :     Eigen::Ref<Eigen::VectorXd> advance(FP tmax)
     741             :     {
     742          36 :         auto& t_end_dyn_npis   = this->get_model().parameters.get_end_dynamic_npis();
     743          36 :         auto& dyn_npis         = this->get_model().parameters.template get<DynamicNPIsInfectedSymptoms<FP>>();
     744          36 :         auto& contact_patterns = this->get_model().parameters.template get<ContactPatterns<FP>>();
     745             :         // const size_t num_groups = (size_t)this->get_model().parameters.get_num_groups();
     746             : 
     747             :         // in the apply_variant function, we adjust the TransmissionProbabilityOnContact parameter. We need to store
     748             :         // the base value to use it in the apply_variant function and also to reset the parameter after the simulation.
     749          36 :         auto base_infectiousness = this->get_model().parameters.template get<TransmissionProbabilityOnContact<FP>>();
     750             : 
     751             :         FP delay_npi_implementation;
     752          36 :         auto t        = BaseT::get_result().get_last_time();
     753          36 :         const auto dt = dyn_npis.get_interval().get();
     754         333 :         while (t < tmax) {
     755             : 
     756         297 :             auto dt_eff = std::min({dt, tmax - t, m_t_last_npi_check + dt - t});
     757         297 :             if (dt_eff >= 1.0) {
     758         288 :                 dt_eff = 1.0;
     759             :             }
     760             : 
     761         297 :             BaseT::advance(t + dt_eff);
     762         297 :             if (t + 0.5 + dt_eff - std::floor(t + 0.5) >= 1) {
     763         288 :                 this->apply_variant(t, base_infectiousness);
     764             :             }
     765             : 
     766         297 :             if (t > 0) {
     767         261 :                 delay_npi_implementation =
     768         261 :                     this->get_model().parameters.template get<DynamicNPIsImplementationDelay<FP>>();
     769             :             }
     770             :             else {
     771             :                 // DynamicNPIs for t=0 are 'misused' to be from-start NPIs. I.e., do not enforce delay.
     772          36 :                 delay_npi_implementation = 0;
     773             :             }
     774         297 :             t = t + dt_eff;
     775             : 
     776         297 :             if (dyn_npis.get_thresholds().size() > 0) {
     777         270 :                 if (floating_point_greater_equal(t, m_t_last_npi_check + dt)) {
     778          90 :                     if (t < t_end_dyn_npis) {
     779          54 :                         auto inf_rel = get_infections_relative<FP>(*this, t, this->get_result().get_last_value()) *
     780          27 :                                        dyn_npis.get_base_value();
     781          27 :                         auto exceeded_threshold = dyn_npis.get_max_exceeded_threshold(inf_rel);
     782          54 :                         if (exceeded_threshold != dyn_npis.get_thresholds().end() &&
     783          45 :                             (exceeded_threshold->first > m_dynamic_npi.first ||
     784          18 :                              t > FP(m_dynamic_npi.second))) { //old npi was weaker or is expired
     785             : 
     786           9 :                             auto t_start = SimulationTime(t + delay_npi_implementation);
     787           9 :                             auto t_end   = t_start + SimulationTime(dyn_npis.get_duration());
     788           9 :                             this->get_model().parameters.get_start_commuter_detection() = (FP)t_start;
     789           9 :                             this->get_model().parameters.get_end_commuter_detection()   = (FP)t_end;
     790           9 :                             m_dynamic_npi = std::make_pair(exceeded_threshold->first, t_end);
     791           9 :                             implement_dynamic_npis(contact_patterns.get_cont_freq_mat(), exceeded_threshold->second,
     792           9 :                                                    t_start, t_end, [](auto& g) {
     793           9 :                                                        return make_contact_damping_matrix(g);
     794             :                                                    });
     795             :                         }
     796             :                     }
     797          90 :                     m_t_last_npi_check = t;
     798             :                 }
     799             :             }
     800             :             else {
     801          27 :                 m_t_last_npi_check = t;
     802             :             }
     803             :         }
     804             :         // reset TransmissionProbabilityOnContact. This is important for the graph simulation where the advance
     805             :         // function is called multiple times for the same model.
     806          36 :         this->get_model().parameters.template get<TransmissionProbabilityOnContact<FP>>() = base_infectiousness;
     807             : 
     808          72 :         return this->get_result().get_last_value();
     809          36 :     }
     810             : 
     811             : private:
     812             :     FP m_t_last_npi_check;
     813             :     std::pair<FP, SimulationTime> m_dynamic_npi = {-std::numeric_limits<FP>::max(), SimulationTime(0)};
     814             : };
     815             : 
     816             : /**
     817             :  * @brief Specialization of simulate for SECIRS-type models using Simulation.
     818             :  * 
     819             :  * @param[in] t0 start time.
     820             :  * @param[in] tmax end time.
     821             :  * @param[in] dt time step.
     822             :  * @param[in] model SECIRS-type model to simulate.
     823             :  * @param[in] integrator optional integrator, uses rk45 if nullptr.
     824             :  * 
     825             :  * @return Returns the result of the simulation.
     826             :  */
     827             : template <typename FP = ScalarType>
     828           9 : inline auto simulate(FP t0, FP tmax, FP dt, const Model<FP>& model,
     829             :                      std::shared_ptr<IntegratorCore<FP>> integrator = nullptr)
     830             : {
     831           9 :     return mio::simulate<FP, Model<FP>, Simulation<FP>>(t0, tmax, dt, model, integrator);
     832             : }
     833             : 
     834             : /**
     835             :  * @brief Specialization of simulate for SECIRS-type models using the FlowSimulation.
     836             :  * 
     837             :  * @param[in] t0 start time.
     838             :  * @param[in] tmax end time.
     839             :  * @param[in] dt time step.
     840             :  * @param[in] model SECIRS-type model to simulate.
     841             :  * @param[in] integrator optional integrator, uses rk45 if nullptr.
     842             :  * 
     843             :  * @return Returns the result of the Flowsimulation.
     844             :   */
     845             : template <typename FP = ScalarType>
     846             : inline auto simulate_flows(FP t0, FP tmax, FP dt, const Model<FP>& model,
     847             :                            std::shared_ptr<IntegratorCore<FP>> integrator = nullptr)
     848             : {
     849             :     return mio::simulate_flows<FP, Model<FP>, Simulation<FP, mio::FlowSimulation<FP, Model<FP>>>>(t0, tmax, dt, model,
     850             :                                                                                                   integrator);
     851             : }
     852             : 
     853             : //see declaration above.
     854             : template <typename FP, class Base>
     855          36 : FP get_infections_relative(const Simulation<FP, Base>& sim, FP /*t*/, const Eigen::Ref<const Eigen::VectorX<FP>>& y)
     856             : {
     857          36 :     FP sum_inf = 0;
     858         108 :     for (auto i = AgeGroup(0); i < sim.get_model().parameters.get_num_groups(); ++i) {
     859          72 :         sum_inf += sim.get_model().populations.get_from(y, {i, InfectionState::InfectedSymptomsNaive});
     860          72 :         sum_inf += sim.get_model().populations.get_from(y, {i, InfectionState::InfectedSymptomsNaiveConfirmed});
     861          72 :         sum_inf += sim.get_model().populations.get_from(y, {i, InfectionState::InfectedSymptomsPartialImmunity});
     862          72 :         sum_inf += sim.get_model().populations.get_from(y, {i, InfectionState::InfectedSymptomsImprovedImmunity});
     863          72 :         sum_inf +=
     864          72 :             sim.get_model().populations.get_from(y, {i, InfectionState::InfectedSymptomsPartialImmunityConfirmed});
     865          72 :         sum_inf +=
     866          72 :             sim.get_model().populations.get_from(y, {i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed});
     867             :     }
     868          36 :     auto inf_rel = sum_inf / sim.get_model().populations.get_total();
     869             : 
     870          36 :     return inf_rel;
     871             : }
     872             : 
     873             : /**
     874             :  * Get migration factors.
     875             :  * Used by migration graph simulation.
     876             :  * Like infection risk, migration of infected individuals is reduced if they are well isolated.
     877             :  * @param model the compartment model with initial values.
     878             :  * @param t current simulation time.
     879             :  * @param y current value of compartments.
     880             :  * @return vector expression, same size as y, with migration factors per compartment.
     881             :  * @tparam Base simulation type that uses a SECIRS-type compartment model. see Simulation.
     882             :  */
     883             : template <typename FP = double, class Base = mio::Simulation<Model<FP>, FP>>
     884           9 : auto get_migration_factors(const Simulation<Base>& sim, FP /*t*/, const Eigen::Ref<const Eigen::VectorX<FP>>& y)
     885             : {
     886           9 :     auto& params = sim.get_model().parameters;
     887             :     //parameters as arrays
     888           9 :     auto& p_asymp   = params.template get<RecoveredPerInfectedNoSymptoms<FP>>().array().template cast<double>();
     889           9 :     auto& p_inf     = params.template get<RiskOfInfectionFromSymptomatic<FP>>().array().template cast<double>();
     890           9 :     auto& p_inf_max = params.template get<MaxRiskOfInfectionFromSymptomatic<FP>>().array().template cast<double>();
     891             :     //slice of InfectedNoSymptoms
     892          54 :     auto y_INS = slice(y, {Eigen::Index(InfectionState::InfectedNoSymptomsNaive),
     893          18 :                            Eigen::Index(size_t(params.get_num_groups())), Eigen::Index(InfectionState::Count)}) +
     894             :                  slice(y, {Eigen::Index(InfectionState::InfectedNoSymptomsPartialImmunity),
     895          18 :                            Eigen::Index(size_t(params.get_num_groups())), Eigen::Index(InfectionState::Count)}) +
     896             :                  slice(y, {Eigen::Index(InfectionState::InfectedNoSymptomsImprovedImmunity),
     897          18 :                            Eigen::Index(size_t(params.get_num_groups())), Eigen::Index(InfectionState::Count)});
     898             : 
     899             :     //compute isolation, same as infection risk from main model
     900           9 :     auto test_and_trace_required =
     901          27 :         ((1 - p_asymp) / params.template get<TimeInfectedNoSymptoms<FP>>().array().template cast<double>() *
     902             :          y_INS.array())
     903          36 :             .sum();
     904          27 :     auto riskFromInfectedSymptomatic =
     905           9 :         smoother_cosine(test_and_trace_required, double(params.template get<TestAndTraceCapacity<FP>>()),
     906           9 :                         params.template get<TestAndTraceCapacity<FP>>() * 5, p_inf.matrix(), p_inf_max.matrix());
     907             : 
     908             :     //set factor for infected
     909           9 :     auto factors = Eigen::VectorXd::Ones(y.rows()).eval();
     910          27 :     slice(factors, {Eigen::Index(InfectionState::InfectedSymptomsNaive), Eigen::Index(size_t(params.get_num_groups())),
     911             :                     Eigen::Index(InfectionState::Count)})
     912          18 :         .array() = riskFromInfectedSymptomatic;
     913           9 :     slice(factors, {Eigen::Index(InfectionState::InfectedSymptomsPartialImmunity),
     914          18 :                     Eigen::Index(size_t(params.get_num_groups())), Eigen::Index(InfectionState::Count)})
     915          18 :         .array() = riskFromInfectedSymptomatic;
     916           9 :     slice(factors, {Eigen::Index(InfectionState::InfectedSymptomsImprovedImmunity),
     917          18 :                     Eigen::Index(size_t(params.get_num_groups())), Eigen::Index(InfectionState::Count)})
     918          18 :         .array() = riskFromInfectedSymptomatic;
     919          18 :     return factors;
     920           9 : }
     921             : 
     922             : /**
     923             :  * @brief Adjusts the state of commuters in a model, accounting for detection and mobility effects.
     924             :  * 
     925             :  * @tparam FP Floating-point type, e.g., double.
     926             :  * @tparam Base Simulation type that uses the SECIRTS-type model. see Simulation.
     927             :  * @param[in,out] sim Simulation object containing the model and result data.
     928             :  * @param[in,out] migrated Vector representing the number of commuters in each state.
     929             :  * @param[in] time Current simulation time, used to determine the commuter detection period.
     930             :  */
     931             : template <typename FP = double, class Base = mio::Simulation<Model<FP>, FP>>
     932           9 : auto test_commuters(Simulation<FP, Base>& sim, Eigen::Ref<Eigen::VectorX<FP>> migrated, FP time)
     933             : {
     934           9 :     auto& model       = sim.get_model();
     935           9 :     auto nondetection = 1.0;
     936          18 :     if (time >= model.parameters.get_start_commuter_detection() &&
     937           9 :         time < model.parameters.get_end_commuter_detection()) {
     938           9 :         nondetection = (double)model.parameters.get_commuter_nondetection();
     939             :     }
     940          27 :     for (auto i = AgeGroup(0); i < model.parameters.get_num_groups(); ++i) {
     941          18 :         auto ISyNi  = model.populations.get_flat_index({i, InfectionState::InfectedSymptomsNaive});
     942          18 :         auto ISyNCi = model.populations.get_flat_index({i, InfectionState::InfectedSymptomsNaiveConfirmed});
     943          18 :         auto INSNi  = model.populations.get_flat_index({i, InfectionState::InfectedNoSymptomsNaive});
     944          18 :         auto INSNCi = model.populations.get_flat_index({i, InfectionState::InfectedNoSymptomsNaiveConfirmed});
     945             : 
     946          18 :         auto ISPIi  = model.populations.get_flat_index({i, InfectionState::InfectedSymptomsPartialImmunity});
     947          18 :         auto ISPICi = model.populations.get_flat_index({i, InfectionState::InfectedSymptomsPartialImmunityConfirmed});
     948          18 :         auto INSPIi = model.populations.get_flat_index({i, InfectionState::InfectedNoSymptomsPartialImmunity});
     949             :         auto INSPICi =
     950          18 :             model.populations.get_flat_index({i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed});
     951             : 
     952          18 :         auto ISyIIi  = model.populations.get_flat_index({i, InfectionState::InfectedSymptomsImprovedImmunity});
     953          18 :         auto ISyIICi = model.populations.get_flat_index({i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed});
     954          18 :         auto INSIIi  = model.populations.get_flat_index({i, InfectionState::InfectedNoSymptomsImprovedImmunity});
     955             :         auto INSIICi =
     956          18 :             model.populations.get_flat_index({i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed});
     957             : 
     958             :         //put detected commuters in their own compartment so they don't contribute to infections in their home node
     959          18 :         sim.get_result().get_last_value()[ISyNi] -= migrated[ISyNi] * (1 - nondetection);
     960          18 :         sim.get_result().get_last_value()[ISyNCi] += migrated[ISyNi] * (1 - nondetection);
     961          18 :         sim.get_result().get_last_value()[INSNi] -= migrated[INSNi] * (1 - nondetection);
     962          18 :         sim.get_result().get_last_value()[INSNCi] += migrated[INSNi] * (1 - nondetection);
     963             : 
     964          18 :         sim.get_result().get_last_value()[ISPIi] -= migrated[ISPIi] * (1 - nondetection);
     965          18 :         sim.get_result().get_last_value()[ISPICi] += migrated[ISPIi] * (1 - nondetection);
     966          18 :         sim.get_result().get_last_value()[INSPIi] -= migrated[INSPIi] * (1 - nondetection);
     967          18 :         sim.get_result().get_last_value()[INSPICi] += migrated[INSPIi] * (1 - nondetection);
     968             : 
     969          18 :         sim.get_result().get_last_value()[ISyIIi] -= migrated[ISyIIi] * (1 - nondetection);
     970          18 :         sim.get_result().get_last_value()[ISyIICi] += migrated[ISyIIi] * (1 - nondetection);
     971          18 :         sim.get_result().get_last_value()[INSIIi] -= migrated[INSIIi] * (1 - nondetection);
     972          18 :         sim.get_result().get_last_value()[INSIICi] += migrated[INSIIi] * (1 - nondetection);
     973             : 
     974             :         //reduce the number of commuters
     975          18 :         migrated[ISyNi] *= nondetection;
     976          18 :         migrated[INSNi] *= nondetection;
     977             : 
     978          18 :         migrated[ISPIi] *= nondetection;
     979          18 :         migrated[INSPIi] *= nondetection;
     980             : 
     981          18 :         migrated[ISyIIi] *= nondetection;
     982          18 :         migrated[INSIIi] *= nondetection;
     983             :     }
     984           9 : }
     985             : 
     986             : } // namespace osecirts
     987             : } // namespace mio
     988             : 
     989             : #endif //MIO_ODE_SECIRTS_MODEL_H

Generated by: LCOV version 1.14