|
| 1 | +#include "ode_secir/model.h" |
| 2 | +#include "memilio/compartments/simulation.h" |
| 3 | +#include "memilio/data/analyze_result.h" |
| 4 | + |
| 5 | +int main() |
| 6 | +{ |
| 7 | + // MEmilio implements various models based on ordinary differential equations (ODEs). ODE-based models are a subclass of compartmental models in which individuals are grouped into subpopulations called compartments. |
| 8 | + |
| 9 | + // In this tutorial we will setup and run MEmilio's ODE-based SECIR-type model. This model is particularly suited for pathogens with pre- or asymptomatic infection states and when severe or critical symptoms are possible. The model assumes perfect immunity after recovery. The used infection states or compartments are Susceptible (S), Exposed(E), Non-symptomatically Infected (Ins), Symptomatically Infected (Isy), Severely Infected (Isev), Critically Infected (Icri), Dead (D) and Recovered (R). The transitions are depicted in the following figure. |
| 10 | + |
| 11 | + // *** Set up model. *** |
| 12 | + // We need to specify basic parameters. In this tutorial, we use a simple model without spatial resolution and with only one age group. |
| 13 | + size_t num_agegroups = 1; |
| 14 | + // We first define the `total_population` size and the simulation horizong through the start day `t0`, and the simulation's end point `tmax`. By default, the ODE is solved with adaptive time stepping and the initial time step is `dt`. |
| 15 | + ScalarType total_population = 100000; |
| 16 | + ScalarType t0 = 0; |
| 17 | + ScalarType tmax = 100; |
| 18 | + ScalarType dt = 0.1; |
| 19 | + |
| 20 | + // Create model |
| 21 | + mio::osecir::Model<ScalarType> model(num_agegroups); |
| 22 | + |
| 23 | + // Next, we have to set the epidemiological model parameters which include the average stay times per infection state, the state transition probabilities, and the contact frequency. A list of all parameters can be found at https://memilio.readthedocs.io/en/latest/cpp/models/osecir.html. The parameters can be set as follows: |
| 24 | + // Set infection state stay times (in days) |
| 25 | + model.parameters.get<mio::osecir::TimeInfectedNoSymptoms<ScalarType>>() = 2.; |
| 26 | + model.parameters.get<mio::osecir::TimeInfectedSymptoms<ScalarType>>() = 6.; |
| 27 | + model.parameters.get<mio::osecir::TimeInfectedSevere<ScalarType>>() = 12.; |
| 28 | + model.parameters.get<mio::osecir::TimeInfectedCritical<ScalarType>>() = 8.; |
| 29 | + // Set infection state transition probabilities |
| 30 | + model.parameters.get<mio::osecir::RelativeTransmissionNoSymptoms<ScalarType>>() = 0.67; |
| 31 | + model.parameters.get<mio::osecir::TransmissionProbabilityOnContact<ScalarType>>() = 0.1; |
| 32 | + model.parameters.get<mio::osecir::RecoveredPerInfectedNoSymptoms<ScalarType>>() = 0.2; |
| 33 | + model.parameters.get<mio::osecir::RiskOfInfectionFromSymptomatic<ScalarType>>() = 0.25; |
| 34 | + model.parameters.get<mio::osecir::SeverePerInfectedSymptoms<ScalarType>>() = 0.2; |
| 35 | + model.parameters.get<mio::osecir::CriticalPerSevere<ScalarType>>() = 0.25; |
| 36 | + model.parameters.get<mio::osecir::DeathsPerCritical<ScalarType>>() = 0.3; |
| 37 | + //Set contact frequency |
| 38 | + ScalarType contact_frequency = 10; |
| 39 | + mio::ContactMatrixGroup<ScalarType>& contact_matrix = |
| 40 | + model.parameters.get<mio::osecir::ContactPatterns<ScalarType>>(); |
| 41 | + contact_matrix[0] = mio::ContactMatrix<ScalarType>(Eigen::MatrixX<ScalarType>::Constant(1, 1, contact_frequency)); |
| 42 | + |
| 43 | + // EXERCISE: Please set the average time individuals spend in the exposed state (TimeExposed) to 4 days |
| 44 | + |
| 45 | + // In addition to the parameters, the initial number of individuals in each compartment has to be set. If a compartment is not set, its initial value is zero by default. In this example, we start our simulation with 1 % of the population initially infected, distributing them equally to the `Exposed` and the `InfectedNoSymptoms` state, where the latter contains pre- and asymptomatic infectious individuals. With the last line, we set the remaining part of the population (99%) to be susceptible. |
| 46 | + model.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::Exposed}] = 0.005 * total_population; |
| 47 | + model.populations[{mio::AgeGroup(0), mio::osecir::InfectionState::InfectedNoSymptoms}] = 0.005 * total_population; |
| 48 | + model.populations.set_difference_from_total({mio::AgeGroup(0), mio::osecir::InfectionState::Susceptible}, |
| 49 | + total_population); |
| 50 | + |
| 51 | + // EXERCISE: Please set 2% of the population initially infected. The initially infected should be distributed to the compartpartments as follows: 0.5% is initially exposed (state `Exposed`), 0.5% is non-symptomatically infected (state `InfectedNosymptoms`) and 1% is symptomatically infected (state `InfectedSymptoms`). |
| 52 | + |
| 53 | + // To check that all initial parameter and compartmental values are in a meaningful range, MEmilio provides the `check_constraints` function. If a value exceeds its meaningful range, a warning is printed and the function returns `True`, otherwise it returns `False`. |
| 54 | + model.check_constraints(); |
| 55 | + |
| 56 | + // *** Simulate model. *** |
| 57 | + mio::TimeSeries<ScalarType> result = mio::osecir::simulate<ScalarType>(t0, tmax, dt, model); |
| 58 | + // Interpolate time series to full days. |
| 59 | + auto interpolated_result = mio::interpolate_simulation_result(result); |
| 60 | + |
| 61 | + // *** Print results. *** |
| 62 | + interpolated_result.print_table({"S", "E", "C", "C_confirmed", "I", "I_confirmed", "H", "U", "R", "D"}, 12, 4); |
| 63 | +} |
0 commit comments