Skip to content
1 change: 1 addition & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ if(MEMILIO_BUILD_MODELS)
add_subdirectory(models/ide_secir)
add_subdirectory(models/ide_seir)
add_subdirectory(models/ode_seir)
add_subdirectory(models/ode_seirv)
add_subdirectory(models/ode_seair)
add_subdirectory(models/ode_sir)
add_subdirectory(models/sde_sir)
Expand Down
4 changes: 4 additions & 0 deletions cpp/examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ add_executable(seir_flows_example ode_seir_flows.cpp)
target_link_libraries(seir_flows_example PRIVATE memilio ode_seir)
target_compile_options(seir_flows_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})

add_executable(ode_seirv_example ode_seirv_example.cpp)
target_link_libraries(ode_seirv_example PRIVATE memilio ode_seirv)
target_compile_options(ode_seirv_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})

add_executable(ode_secir_example ode_secir.cpp)
target_link_libraries(ode_secir_example PRIVATE memilio ode_secir)
target_compile_options(ode_secir_example PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
Expand Down
120 changes: 120 additions & 0 deletions cpp/examples/ode_seirv_example.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright (C) 2020-2025 MEmilio
*
* Authors: Henrik Zunker
*
* Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "ode_seirv/model.h"
#include "memilio/compartments/simulation.h"
#include "memilio/utils/logging.h"

/**
* @brief set_initial_population sets the initial population of the model
*
* We assume that no one is initially infected or exposed at the beginning of the season.
* Infections are seeded later via the OutsideFoI parameter.
* The destinction into the 2 layers of susceptibility is done via the parameters.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* The destinction into the 2 layers of susceptibility is done via the parameters.
* The distinction into the 2 layers of susceptibility is done via the parameters.

* @tparam FP floating point type
* @param[in, out] model SEIRV model
* @param[in] total_pop total population size
*/
template <class FP>
void set_initial_population(mio::oseirv::Model<FP>& model, const FP total_pop)
{
auto& params = model.parameters;
auto& pop = model.populations;
const size_t num_groups = (size_t)params.get_num_groups();

for (size_t i = 0; i < num_groups; ++i) {
pop.template set_difference_from_group_total<mio::AgeGroup>(
{mio::AgeGroup(i), mio::oseirv::InfectionState::Susceptible}, total_pop / num_groups);

// Total population N_i as currently stored in group totals
FP Ni = pop.get_group_total(mio::AgeGroup(i));

FP s_age = params.template get<mio::oseirv::SusceptibilityByAge<FP>>()[mio::AgeGroup(i)];
FP s_frac = params.template get<mio::oseirv::SusceptibleFraction<FP>>();
FP vc = params.template get<mio::oseirv::VaccineCoverage<FP>>()[mio::AgeGroup(i)];
FP ve = params.template get<mio::oseirv::VaccineEffectiveness<FP>>()[mio::AgeGroup(i)];

pop[{mio::AgeGroup(i), mio::oseirv::InfectionState::Exposed}] = 0;
pop[{mio::AgeGroup(i), mio::oseirv::InfectionState::ExposedVaccinated}] = 0;
pop[{mio::AgeGroup(i), mio::oseirv::InfectionState::Infected}] = 0;
pop[{mio::AgeGroup(i), mio::oseirv::InfectionState::InfectedVaccinated}] = 0;

pop[{mio::AgeGroup(i), mio::oseirv::InfectionState::Susceptible}] = s_frac * s_age * (FP(1) - vc) * Ni;
pop[{mio::AgeGroup(i), mio::oseirv::InfectionState::SusceptibleVaccinated}] =
s_frac * s_age * (FP(1) - ve) * vc * Ni;

pop[{mio::AgeGroup(i), mio::oseirv::InfectionState::Recovered}] = (FP(1) - s_frac * s_age) * (FP(1) - vc) * Ni;
pop[{mio::AgeGroup(i), mio::oseirv::InfectionState::RecoveredVaccinated}] =
(FP(1) - s_frac * s_age * (FP(1) - ve)) * vc * Ni;
}
}

// Example usage of the SEIRV ODE model presented in https://doi.org/10.1186/s12879-017-2344-6
int main()
{
using FP = double;
mio::set_log_level(mio::LogLevel::debug);

const FP t0 = 0., tmax = 42.;
const FP dt = 0.1;

const size_t num_groups = 1;
const auto total_pop = 1e5;
mio::oseirv::Model<FP> model((int)num_groups);
auto& parameters = model.parameters;

FP cont_freq = 10.0;
FP cont_freq_group = FP(1) / FP(num_groups);

// Healthy contacts
mio::ContactMatrixGroup<ScalarType>& contacts_healthy = parameters.get<mio::oseirv::ContactPatternsHealthy<FP>>();
contacts_healthy[0] = mio::ContactMatrix<FP>(
Eigen::MatrixXd::Constant((Eigen::Index)num_groups, (Eigen::Index)num_groups, cont_freq_group * cont_freq));

// Sick contacts (here 20% reduced)
mio::ContactMatrixGroup<ScalarType>& contacts_sick = parameters.get<mio::oseirv::ContactPatternsSick<FP>>();
contacts_sick[0] = mio::ContactMatrix<FP>(Eigen::MatrixXd::Constant(
(Eigen::Index)num_groups, (Eigen::Index)num_groups, cont_freq_group * cont_freq * 0.8));

// Parameters
parameters.get<mio::oseirv::BaselineTransmissibility<FP>>() = 1.2;
parameters.get<mio::oseirv::RecoveryRate<FP>>() = 1.0 / 2.0;
parameters.get<mio::oseirv::SeasonalityAmplitude<FP>>() = 1.0;
parameters.get<mio::oseirv::SeasonalityShiftPerSubtype<FP>>() = 0.0;
parameters.get<mio::oseirv::SeasonalityShiftPerSeason<FP>>() = 0.0;
parameters.get<mio::oseirv::OutsideFoI<FP>>() = 1e-6;
parameters.get<mio::oseirv::ClusteringExponent<FP>>() = 0.9;
parameters.get<mio::oseirv::SickMixing<FP>>() = 2.0;

for (size_t i = 0; i < num_groups; ++i) {
parameters.get<mio::oseirv::SusceptibilityByAge<FP>>()[mio::AgeGroup(i)] = 1.0;
parameters.get<mio::oseirv::VaccineCoverage<FP>>()[mio::AgeGroup(i)] = 0.3;
parameters.get<mio::oseirv::VaccineEffectiveness<FP>>()[mio::AgeGroup(i)] = 0.5;
model.populations.set_difference_from_group_total<mio::AgeGroup>(
{mio::AgeGroup(i), mio::oseirv::InfectionState::Susceptible}, 1e5 / num_groups);
}

set_initial_population(model, total_pop);

auto seirv = mio::simulate<FP>(t0, tmax, dt, model);

std::vector<std::string> vars = {"S", "SV", "E", "EV", "I", "IV", "R", "RV"};
seirv.print_table(vars);
}
12 changes: 12 additions & 0 deletions cpp/models/ode_seirv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
add_library(ode_seirv
infection_state.h
model.h
model.cpp
parameters.h
)
target_link_libraries(ode_seirv PUBLIC memilio)
target_include_directories(ode_seirv PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/..>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
target_compile_options(ode_seirv PRIVATE ${MEMILIO_CXX_FLAGS_ENABLE_WARNING_ERRORS})
23 changes: 23 additions & 0 deletions cpp/models/ode_seirv/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ODE SEIRV (seasonal influenza)

A age‑structured **SEIRV** model implemented into the MEmilio ODE framework.
It extends the classic SEIR by a vaccinated layer (Sᵛ, Eᵛ, Iᵛ, Rᵛ) and follows the seasonal influenza
model structure from:

> **Weidemann, F., Remschmidt, C., Buda, S. et al.**
> *Is the impact of childhood influenza vaccination less than expected: a transmission modelling study.*
> **BMC Infectious Diseases** 17, 258 (2017).
> https://doi.org/10.1186/s12879-017-2344-6

## Get started

To get started, check out the
[official documentation](https://memilio.readthedocs.io/en/latest/cpp/models/oseirv.html)
or the [code example](../../examples/ode_seirv_example.cpp).

## Reference

Please cite the original study if you use this model:

> Weidemann, F., Remschmidt, C., Buda, S. et al. *Is the impact of childhood influenza vaccination less than expected: a transmission modelling study.* **BMC Infect Dis** 17, 258 (2017).
> https://doi.org/10.1186/s12879-017-2344-6
42 changes: 42 additions & 0 deletions cpp/models/ode_seirv/infection_state.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* Copyright (C) 2020-2025 MEmilio
*
* Authors: Henrik Zunker
*
* Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef SEIRV_INFECTIONSTATE_H
#define SEIRV_INFECTIONSTATE_H
namespace mio
{
namespace oseirv
{

enum class InfectionState
{
Susceptible,
SusceptibleVaccinated,
Exposed,
ExposedVaccinated,
Infected,
InfectedVaccinated,
Recovered,
RecoveredVaccinated,
Count
};

} // namespace oseirv
} // namespace mio
#endif
20 changes: 20 additions & 0 deletions cpp/models/ode_seirv/model.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright (C) 2020-2025 MEmilio
*
* Authors: Henrik Zunker
*
* Contact: Martin J. Kuehn <Martin.Kuehn@DLR.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "ode_seirv/model.h"
Loading