parameters_io.h Source File

CPP API: parameters_io.h Source File
models/ode_secirts/parameters_io.h
Go to the documentation of this file.
1 /*
2 * Copyright (C) 2020-2026 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_PARAMETERS_IO_H
21 #define MIO_ODE_SECIRTS_PARAMETERS_IO_H
22 
23 #include "memilio/config.h"
24 
25 #ifdef MEMILIO_HAS_JSONCPP
26 
27 #include "ode_secirts/model.h"
31 #include "memilio/mobility/graph.h"
33 #include "memilio/io/epi_data.h"
35 #include "memilio/io/io.h"
37 #include "memilio/io/result_io.h"
38 #include "memilio/utils/logging.h"
39 #include "memilio/utils/date.h"
40 
41 namespace mio
42 {
43 namespace osecirts
44 {
45 
46 namespace details
47 {
73 template <typename FP, class Model>
74 IOResult<void> compute_confirmed_cases_data(
75  const std::vector<ConfirmedCasesDataEntry>& case_data, std::vector<std::vector<FP>>& vnum_Exposed,
76  std::vector<std::vector<FP>>& vnum_InfectedNoSymptoms, std::vector<std::vector<FP>>& vnum_InfectedSymptoms,
77  std::vector<std::vector<FP>>& vnum_InfectedSevere, std::vector<std::vector<FP>>& vnum_icu,
78  std::vector<std::vector<FP>>& vnum_death, std::vector<std::vector<FP>>& vnum_timm_i,
79  std::vector<int> const& vregion, Date date, const std::vector<Model>& model,
80  const std::vector<FP>& scaling_factor_inf, const size_t layer)
81 {
82  auto max_date_entry = std::max_element(case_data.begin(), case_data.end(), [](auto&& a, auto&& b) {
83  return a.date < b.date;
84  });
85  if (max_date_entry == case_data.end()) {
86  log_error("Case data file is empty.");
87  return failure(StatusCode::InvalidValue, "Case data is empty.");
88  }
89  auto max_date = max_date_entry->date;
90  if (max_date < date) {
91  log_error("Specified date does not exist in case data");
92  return failure(StatusCode::OutOfRange, "Case data does not contain specified date.");
93  }
94 
95  // shifts the initilization to the recent past if simulation starts
96  // around current day and data of the future would be required.
97  // Only needed for preinfection compartments, exposed and InfectedNoSymptoms.
98  auto days_surplus = get_offset_in_days(max_date, date) - 6; // 6 > T_E + T_C
99  if (days_surplus > 0) {
100  days_surplus = 0;
101  }
102 
103  for (auto&& entry : case_data) {
104  auto it = std::find_if(vregion.begin(), vregion.end(), [&entry](auto r) {
105  return r == 0 || get_region_id(entry) == r;
106  });
107  if (it != vregion.end()) {
108  auto region_idx = size_t(it - vregion.begin());
109 
110  auto params_region = model[region_idx].parameters;
111  auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx];
112  auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx];
113  auto& num_Exposed = vnum_Exposed[region_idx];
114  auto& num_InfectedSevere = vnum_InfectedSevere[region_idx];
115  auto& num_death = vnum_death[region_idx];
116  auto& num_icu = vnum_icu[region_idx];
117  auto& num_imm = vnum_timm_i[region_idx];
118 
119  auto age = (size_t)entry.age_group;
120  // (rounded) transition times
121  const int t_exposed =
122  static_cast<int>(std::round(params_region.template get<TimeExposed<FP>>()[entry.age_group]));
123  int t_InfectedNoSymptoms =
124  static_cast<int>(std::round(params_region.template get<TimeInfectedNoSymptoms<FP>>()[entry.age_group]));
125  int t_InfectedSymptoms =
126  static_cast<int>(std::round(params_region.template get<TimeInfectedSymptoms<FP>>()[entry.age_group]));
127  const int t_InfectedSevere =
128  static_cast<int>(std::round(params_region.template get<TimeInfectedSevere<FP>>()[entry.age_group]));
129  const int t_InfectedCritical =
130  static_cast<int>(std::round(params_region.template get<TimeInfectedCritical<FP>>()[entry.age_group]));
131  const int t_imm_interval_i = static_cast<int>(
132  std::round(params_region.template get<TimeTemporaryImmunityPI<FP>>()[entry.age_group]));
133 
134  // transition probabilities
135  FP recoveredPerInfectedNoSymptoms =
136  params_region.template get<RecoveredPerInfectedNoSymptoms<FP>>()[entry.age_group];
137  FP severePerInfectedSymptoms = params_region.template get<SeverePerInfectedSymptoms<FP>>()[entry.age_group];
138  FP criticalPerSevere = params_region.template get<CriticalPerSevere<FP>>()[entry.age_group];
139 
140  // if we select a layer with better immunity (layer > 0), we need to adjust the times and transition rates
141  if (layer > 0) {
142  t_InfectedNoSymptoms = static_cast<int>(std::round(
143  t_InfectedNoSymptoms * params_region.template get<ReducTimeInfectedMild<FP>>()[entry.age_group]));
144  t_InfectedSymptoms = static_cast<int>(std::round(
145  t_InfectedSymptoms * params_region.template get<ReducTimeInfectedMild<FP>>()[entry.age_group]));
146 
147  const FP red_fact_exp =
148  layer == 1 ? params_region.template get<ReducExposedPartialImmunity<FP>>()[entry.age_group]
149  : params_region.template get<ReducExposedImprovedImmunity<FP>>()[entry.age_group];
150 
151  const FP red_fact_inf =
152  layer == 1
153  ? params_region.template get<ReducInfectedSymptomsPartialImmunity<FP>>()[entry.age_group]
154  : params_region.template get<ReducInfectedSymptomsImprovedImmunity<FP>>()[entry.age_group];
155 
156  const FP red_fact_sev =
157  layer == 1
158  ? params_region
159  .template get<ReducInfectedSevereCriticalDeadPartialImmunity<FP>>()[entry.age_group]
160  : params_region
161  .template get<ReducInfectedSevereCriticalDeadImprovedImmunity<FP>>()[entry.age_group];
162 
163  recoveredPerInfectedNoSymptoms = 1 - red_fact_inf / red_fact_exp * (1 - recoveredPerInfectedNoSymptoms);
164  severePerInfectedSymptoms = red_fact_sev / red_fact_inf * severePerInfectedSymptoms;
165  }
166 
167  if (entry.date == offset_date_by_days(date, 0)) {
168  num_InfectedSymptoms[age] += scaling_factor_inf[age] * entry.num_confirmed;
169  num_imm[age] += entry.num_confirmed;
170  }
171  if (entry.date == offset_date_by_days(date, t_InfectedNoSymptoms + days_surplus)) {
172  num_InfectedNoSymptoms[age] +=
173  1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed;
174  num_Exposed[age] -=
175  1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed;
176  }
177  if (entry.date == offset_date_by_days(date, days_surplus)) {
178  num_InfectedNoSymptoms[age] -=
179  1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed;
180  }
181  if (entry.date == offset_date_by_days(date, t_exposed + t_InfectedNoSymptoms + days_surplus)) {
182  num_Exposed[age] +=
183  1 / (1 - recoveredPerInfectedNoSymptoms) * scaling_factor_inf[age] * entry.num_confirmed;
184  }
185  if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms)) {
186  num_InfectedSymptoms[age] -= scaling_factor_inf[age] * entry.num_confirmed;
187  num_InfectedSevere[age] += severePerInfectedSymptoms * scaling_factor_inf[age] * entry.num_confirmed;
188  }
189  if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms - t_InfectedSevere)) {
190  num_InfectedSevere[age] -= severePerInfectedSymptoms * scaling_factor_inf[age] * entry.num_confirmed;
191  num_icu[age] +=
192  severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * entry.num_confirmed;
193  }
194  if (entry.date == offset_date_by_days(date, -t_InfectedSymptoms - t_InfectedSevere - t_InfectedCritical)) {
195  num_death[age] += entry.num_deaths;
196  num_icu[age] -=
197  severePerInfectedSymptoms * criticalPerSevere * scaling_factor_inf[age] * entry.num_confirmed;
198  }
199  if (entry.date == offset_date_by_days(date, 0 - t_imm_interval_i)) {
200  num_imm[age] -= entry.num_confirmed;
201  }
202  }
203  }
204 
205  for (size_t region_idx = 0; region_idx < vregion.size(); ++region_idx) {
206  auto region = vregion[region_idx];
207 
208  auto& num_InfectedNoSymptoms = vnum_InfectedNoSymptoms[region_idx];
209  auto& num_InfectedSymptoms = vnum_InfectedSymptoms[region_idx];
210  auto& num_Exposed = vnum_Exposed[region_idx];
211  auto& num_InfectedSevere = vnum_InfectedSevere[region_idx];
212  auto& num_death = vnum_death[region_idx];
213  auto& num_icu = vnum_icu[region_idx];
214  auto& num_timm_i = vnum_timm_i[region_idx];
215 
216  size_t num_groups = ConfirmedCasesDataEntry::age_group_names.size();
217  for (size_t i = 0; i < num_groups; i++) {
218  auto try_fix_constraints = [region, i](FP& value, FP error, auto str) {
219  if (value < error) {
220  // this should probably return a failure
221  // but the algorithm is not robust enough to avoid large negative
222  // values and there are tests that rely on it
223  log_error("{:s} for age group {:s} is {:.4f} for region {:d}, "
224  "exceeds expected negative value.",
225  str, ConfirmedCasesDataEntry::age_group_names[i], value, region);
226  value = 0.0;
227  }
228  else if (value < 0) {
229  log_info("{:s} for age group {:s} is {:.4f} for region {:d}, "
230  "automatically corrected",
231  str, ConfirmedCasesDataEntry::age_group_names[i], value, region);
232  value = 0.0;
233  }
234  };
235 
236  const FP tol_error = -1e-8;
237  try_fix_constraints(num_InfectedSymptoms[i], tol_error, "InfectedSymptoms");
238  try_fix_constraints(num_InfectedNoSymptoms[i], tol_error, "InfectedNoSymptoms");
239  try_fix_constraints(num_Exposed[i], tol_error, "Exposed");
240  try_fix_constraints(num_InfectedSevere[i], tol_error, "InfectedSevere");
241  try_fix_constraints(num_death[i], tol_error, "Dead");
242  try_fix_constraints(num_icu[i], tol_error, "InfectedCritical");
243  try_fix_constraints(num_timm_i[i], tol_error, "Recently Recovered or Vaccinated");
244  }
245  }
246 
247  return success();
248 }
249 
275 template <typename FP, class Model>
276 IOResult<void> read_confirmed_cases_data(
277  std::string const& path, std::vector<int> const& vregion, Date date, std::vector<std::vector<FP>>& vnum_Exposed,
278  std::vector<std::vector<FP>>& vnum_InfectedNoSymptoms, std::vector<std::vector<FP>>& vnum_InfectedSymptoms,
279  std::vector<std::vector<FP>>& vnum_InfectedSevere, std::vector<std::vector<FP>>& vnum_icu,
280  std::vector<std::vector<FP>>& vnum_death, std::vector<std::vector<FP>>& vnum_timm_i,
281  const std::vector<Model>& model, const std::vector<FP>& scaling_factor_inf, const size_t layer)
282 {
283  BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path));
284  return compute_confirmed_cases_data(case_data, vnum_Exposed, vnum_InfectedNoSymptoms, vnum_InfectedSymptoms,
285  vnum_InfectedSevere, vnum_icu, vnum_death, vnum_timm_i, vregion, date, model,
286  scaling_factor_inf, layer);
287 }
288 
307 template <typename FP, class Model>
308 IOResult<void>
309 set_confirmed_cases_data(std::vector<Model>& model, const std::vector<ConfirmedCasesDataEntry>& case_data,
310  std::vector<int> const& region, Date date, const std::vector<FP>& scaling_factor_inf,
311  const std::vector<std::vector<FP>> immunity_population)
312 {
313  auto num_age_groups = (size_t)model[0].parameters.get_num_groups();
314  assert(scaling_factor_inf.size() == num_age_groups); //TODO: allow vector or scalar valued scaling factors
315  assert(ConfirmedCasesDataEntry::age_group_names.size() == num_age_groups);
316 
317  std::vector<std::vector<FP>> num_InfectedSymptoms(model.size());
318  std::vector<std::vector<FP>> num_death(model.size());
319  std::vector<std::vector<FP>> num_Exposed(model.size());
320  std::vector<std::vector<FP>> num_InfectedNoSymptoms(model.size());
321  std::vector<std::vector<FP>> num_InfectedSevere(model.size());
322  std::vector<std::vector<FP>> num_icu(model.size());
323  std::vector<std::vector<FP>> num_timm1(model.size());
324  std::vector<std::vector<FP>> num_timm2(model.size());
325 
326  std::vector<FP> denom_E(num_age_groups, 0.0);
327  std::vector<FP> denom_I_NS(num_age_groups, 0.0);
328  std::vector<FP> denom_I_Sy(num_age_groups, 0.0);
329  std::vector<FP> denom_I_Sev_Cr(num_age_groups, 0.0);
330 
331  /*----------- Naive immunity -----------*/
332  for (size_t county = 0; county < model.size(); county++) {
333  num_InfectedSymptoms[county] = std::vector<FP>(num_age_groups, 0.0);
334  num_death[county] = std::vector<FP>(num_age_groups, 0.0);
335  num_Exposed[county] = std::vector<FP>(num_age_groups, 0.0);
336  num_InfectedNoSymptoms[county] = std::vector<FP>(num_age_groups, 0.0);
337  num_InfectedSevere[county] = std::vector<FP>(num_age_groups, 0.0);
338  num_icu[county] = std::vector<FP>(num_age_groups, 0.0);
339  num_timm1[county] = std::vector<FP>(num_age_groups, 0.0);
340  num_timm2[county] = std::vector<FP>(num_age_groups, 0.0);
341  for (size_t group = 0; group < num_age_groups; group++) {
342  // calculate the denominators to split the reported case numbers to the different immunity layers.
343  denom_E[group] =
344  1 / (immunity_population[0][group] +
345  immunity_population[1][group] *
346  model[county].parameters.template get<ReducExposedPartialImmunity<FP>>()[(AgeGroup)group] +
347  immunity_population[2][group] *
348  model[county].parameters.template get<ReducExposedImprovedImmunity<FP>>()[(AgeGroup)group]);
349 
350  denom_I_NS[group] =
351  1 / (immunity_population[0][group] +
352  immunity_population[1][group] *
353  model[county].parameters.template get<ReducExposedPartialImmunity<FP>>()[(AgeGroup)group] +
354  immunity_population[2][group] *
355  model[county].parameters.template get<ReducExposedImprovedImmunity<FP>>()[(AgeGroup)group]);
356 
357  denom_I_Sy[group] =
358  1 / (immunity_population[0][group] +
359  immunity_population[1][group] *
360  model[county]
361  .parameters.template get<ReducInfectedSymptomsPartialImmunity<FP>>()[(AgeGroup)group] +
362  immunity_population[2][group] *
363  model[county]
364  .parameters.template get<ReducInfectedSymptomsImprovedImmunity<FP>>()[(AgeGroup)group]);
365 
366  denom_I_Sev_Cr[group] =
367  1 / (immunity_population[0][group] +
368  immunity_population[1][group] *
369  model[county].parameters.template get<ReducInfectedSevereCriticalDeadPartialImmunity<FP>>()[(
370  AgeGroup)group] +
371  immunity_population[2][group] *
372  model[county].parameters.template get<ReducInfectedSevereCriticalDeadImprovedImmunity<FP>>()[(
373  AgeGroup)group]);
374  }
375  }
376 
377  BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms,
378  num_InfectedSevere, num_icu, num_death, num_timm1, region, date,
379  model, scaling_factor_inf, 0));
380 
381  for (size_t county = 0; county < model.size(); county++) {
382  size_t num_groups = (size_t)model[county].parameters.get_num_groups();
383  for (size_t i = 0; i < num_groups; i++) {
384  model[county].populations[{AgeGroup(i), InfectionState::ExposedNaive}] =
385  immunity_population[0][i] * denom_E[i] * num_Exposed[county][i];
386  model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaive}] =
387  immunity_population[0][i] * denom_I_NS[i] * num_InfectedNoSymptoms[county][i];
388  model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsNaiveConfirmed}] = 0;
389  model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaive}] =
390  immunity_population[0][i] * denom_I_Sy[i] * num_InfectedSymptoms[county][i];
391  model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsNaiveConfirmed}] = 0;
392  model[county].populations[{AgeGroup(i), InfectionState::InfectedSevereNaive}] =
393  immunity_population[0][i] * denom_I_Sev_Cr[i] * num_InfectedSevere[county][i];
394  // Only set the number of ICU patients here, if the date is not available in the data.
395  if (!is_divi_data_available(date)) {
396  model[county].populations[{AgeGroup(i), InfectionState::InfectedCriticalNaive}] =
397  immunity_population[0][i] * denom_I_Sev_Cr[i] * num_icu[county][i];
398  }
399  }
400  if (std::accumulate(num_InfectedSymptoms[county].begin(), num_InfectedSymptoms[county].end(), FP(0.0),
401  [](const FP& a, const FP& b) {
402  return evaluate_intermediate<FP>(a + b);
403  }) == 0) {
404  log_warning(
405  "No infections for unvaccinated reported on date {} for region {}. Population data has not been set.",
406  date, region[county]);
407  }
408  }
409 
410  /*----------- PARTIAL Immunity -----------*/
411  for (size_t county = 0; county < model.size(); county++) {
412  num_InfectedSymptoms[county] = std::vector<FP>(num_age_groups, 0.0);
413  num_death[county] = std::vector<FP>(num_age_groups, 0.0);
414  num_Exposed[county] = std::vector<FP>(num_age_groups, 0.0);
415  num_InfectedNoSymptoms[county] = std::vector<FP>(num_age_groups, 0.0);
416  num_InfectedSevere[county] = std::vector<FP>(num_age_groups, 0.0);
417  num_icu[county] = std::vector<FP>(num_age_groups, 0.0);
418  }
419 
420  BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms,
421  num_InfectedSevere, num_icu, num_death, num_timm1, region, date,
422  model, scaling_factor_inf, 1));
423 
424  for (size_t county = 0; county < model.size(); county++) {
425  size_t num_groups = (size_t)model[county].parameters.get_num_groups();
426  for (size_t i = 0; i < num_groups; i++) {
427  model[county].populations[{AgeGroup(i), InfectionState::ExposedPartialImmunity}] =
428  immunity_population[1][i] *
429  model[county].parameters.template get<ReducExposedPartialImmunity<FP>>()[(AgeGroup)i] * denom_E[i] *
430  num_Exposed[county][i];
431  model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunity}] =
432  immunity_population[1][i] *
433  model[county].parameters.template get<ReducExposedPartialImmunity<FP>>()[(AgeGroup)i] * denom_I_NS[i] *
434  num_InfectedNoSymptoms[county][i];
435  model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] = 0;
436  model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunity}] =
437  immunity_population[1][i] *
438  model[county].parameters.template get<ReducInfectedSymptomsPartialImmunity<FP>>()[(AgeGroup)i] *
439  denom_I_Sy[i] * num_InfectedSymptoms[county][i];
440  model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsPartialImmunityConfirmed}] = 0;
441  model[county].populations[{AgeGroup(i), InfectionState::InfectedSeverePartialImmunity}] =
442  immunity_population[1][i] *
443  model[county]
444  .parameters.template get<ReducInfectedSevereCriticalDeadPartialImmunity<FP>>()[(AgeGroup)i] *
445  denom_I_Sev_Cr[i] * num_InfectedSevere[county][i];
446  // Only set the number of ICU patients here, if the date is not available in the data.
447  if (!is_divi_data_available(date)) {
448  model[county].populations[{AgeGroup(i), InfectionState::InfectedCriticalPartialImmunity}] =
449  immunity_population[1][i] *
450  model[county]
451  .parameters.template get<ReducInfectedSevereCriticalDeadPartialImmunity<FP>>()[(AgeGroup)i] *
452  denom_I_Sev_Cr[i] * num_icu[county][i];
453  }
454  // the += is necessary because we already set the previous vaccinated individuals
455  model[county].populations[{AgeGroup(i), InfectionState::TemporaryImmunePartialImmunity}] +=
456  immunity_population[1][i] *
457  model[county].parameters.template get<ReducExposedPartialImmunity<FP>>()[(AgeGroup)i] * denom_E[i] *
458  num_timm1[county][i];
459  }
460  if (std::accumulate(num_InfectedSymptoms[county].begin(), num_InfectedSymptoms[county].end(), FP(0.0),
461  [](const FP& a, const FP& b) {
462  return evaluate_intermediate<FP>(a + b);
463  }) == 0) {
464 
465  log_warning("No infections for partially vaccinated reported on date {} for region {}. "
466  "Population data has not been set.",
467  date, region[county]);
468  }
469  }
470 
471  /*----------- Improved Immunity -----------*/
472  for (size_t county = 0; county < model.size(); county++) {
473  num_InfectedSymptoms[county] = std::vector<FP>(num_age_groups, 0.0);
474  num_death[county] = std::vector<FP>(num_age_groups, 0.0);
475  num_Exposed[county] = std::vector<FP>(num_age_groups, 0.0);
476  num_InfectedNoSymptoms[county] = std::vector<FP>(num_age_groups, 0.0);
477  num_InfectedSevere[county] = std::vector<FP>(num_age_groups, 0.0);
478  num_icu[county] = std::vector<FP>(num_age_groups, 0.0);
479  }
480 
481  BOOST_OUTCOME_TRY(compute_confirmed_cases_data(case_data, num_Exposed, num_InfectedNoSymptoms, num_InfectedSymptoms,
482  num_InfectedSevere, num_icu, num_death, num_timm2, region, date,
483  model, scaling_factor_inf, 2));
484 
485  for (size_t county = 0; county < model.size(); county++) {
486  size_t num_groups = (size_t)model[county].parameters.get_num_groups();
487  for (size_t i = 0; i < num_groups; i++) {
488  model[county].populations[{AgeGroup(i), InfectionState::ExposedImprovedImmunity}] =
489  immunity_population[2][i] *
490  model[county].parameters.template get<ReducExposedImprovedImmunity<FP>>()[(AgeGroup)i] * denom_E[i] *
491  num_Exposed[county][i];
492  model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunity}] =
493  immunity_population[2][i] *
494  model[county].parameters.template get<ReducExposedImprovedImmunity<FP>>()[(AgeGroup)i] * denom_I_NS[i] *
495  num_InfectedNoSymptoms[county][i];
496  model[county].populations[{AgeGroup(i), InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] = 0;
497  model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunity}] =
498  immunity_population[2][i] *
499  model[county].parameters.template get<ReducInfectedSymptomsImprovedImmunity<FP>>()[(AgeGroup)i] *
500  denom_I_Sy[i] * num_InfectedSymptoms[county][i];
501  model[county].populations[{AgeGroup(i), InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] = 0;
502  model[county].populations[{AgeGroup(i), InfectionState::InfectedSevereImprovedImmunity}] =
503  immunity_population[2][i] *
504  model[county]
505  .parameters.template get<ReducInfectedSevereCriticalDeadImprovedImmunity<FP>>()[(AgeGroup)i] *
506  denom_I_Sev_Cr[i] * num_InfectedSevere[county][i];
507  // Only set the number of ICU patients here, if the date is not available in the data.
508  if (!is_divi_data_available(date)) {
509  model[county].populations[{AgeGroup(i), InfectionState::InfectedCriticalImprovedImmunity}] =
510  immunity_population[2][i] *
511  model[county]
512  .parameters.template get<ReducInfectedSevereCriticalDeadImprovedImmunity<FP>>()[(AgeGroup)i] *
513  denom_I_Sev_Cr[i] * num_icu[county][i];
514  }
515 
516  // the += is necessary because we already set the previous vaccinated individuals
517  model[county].populations[{AgeGroup(i), InfectionState::TemporaryImmuneImprovedImmunity}] +=
518  immunity_population[2][i] *
519  model[county].parameters.template get<ReducExposedImprovedImmunity<FP>>()[(AgeGroup)i] * denom_E[i] *
520  num_timm2[county][i];
521  }
522  if (std::accumulate(num_InfectedSymptoms[county].begin(), num_InfectedSymptoms[county].end(), FP(0.0),
523  [](const FP& a, const FP& b) {
524  return evaluate_intermediate<FP>(a + b);
525  }) == 0) {
526  log_warning("No infections for vaccinated reported on date {} for region {}. "
527  "Population data has not been set.",
528  date, region[county]);
529  }
530  }
531  return success();
532 }
533 
553 template <typename FP, class Model>
554 IOResult<void> set_confirmed_cases_data(std::vector<Model>& model, const std::string& path,
555  std::vector<int> const& region, Date date,
556  const std::vector<FP>& scaling_factor_inf,
557  const std::vector<std::vector<FP>> immunity_population)
558 {
559  BOOST_OUTCOME_TRY(auto&& case_data, mio::read_confirmed_cases_data(path));
560  BOOST_OUTCOME_TRY(
561  set_confirmed_cases_data(model, case_data, region, date, scaling_factor_inf, immunity_population));
562  return success();
563 }
564 
583 template <typename FP, class Model>
584 IOResult<void> set_divi_data(std::vector<Model>& model, const std::string& path, const std::vector<int>& vregion,
585  Date date, FP scaling_factor_icu)
586 {
587  // DIVI dataset will no longer be updated from CW29 2024 on.
588  if (!is_divi_data_available(date)) {
589  log_warning("No DIVI data available for date: {}. "
590  "ICU compartment will be set based on Case data.",
591  date);
592  return success();
593  }
594  std::vector<FP> sum_mu_I_U(vregion.size(), 0);
595  std::vector<std::vector<FP>> mu_I_U{model.size()};
596  for (size_t region = 0; region < vregion.size(); region++) {
597  auto num_groups = model[region].parameters.get_num_groups();
598  for (auto i = AgeGroup(0); i < num_groups; i++) {
599  sum_mu_I_U[region] += model[region].parameters.template get<CriticalPerSevere<FP>>()[i] *
600  model[region].parameters.template get<SeverePerInfectedSymptoms<FP>>()[i];
601  mu_I_U[region].push_back(model[region].parameters.template get<CriticalPerSevere<FP>>()[i] *
602  model[region].parameters.template get<SeverePerInfectedSymptoms<FP>>()[i]);
603  }
604  }
605  std::vector<FP> num_icu(model.size(), 0.0);
606  BOOST_OUTCOME_TRY(read_divi_data(path, vregion, date, num_icu));
607 
608  for (size_t region = 0; region < vregion.size(); region++) {
609  auto num_groups = model[region].parameters.get_num_groups();
610  for (auto i = AgeGroup(0); i < num_groups; i++) {
611  model[region].populations[{i, InfectionState::InfectedCriticalNaive}] =
612  scaling_factor_icu * num_icu[region] * mu_I_U[region][(size_t)i] / sum_mu_I_U[region];
613  }
614  }
615 
616  return success();
617 }
618 
633 template <typename FP, class Model>
634 IOResult<void> set_population_data(std::vector<Model>& model, const std::vector<std::vector<FP>>& num_population,
635  const std::vector<int>& vregion,
636  const std::vector<std::vector<FP>> immunity_population)
637 {
638  for (size_t region = 0; region < vregion.size(); region++) {
639  if (std::accumulate(num_population[region].begin(), num_population[region].end(), FP(0.0),
640  [](const FP& a, const FP& b) {
641  return evaluate_intermediate<FP>(a + b);
642  }) > 0.0) {
643  auto num_groups = model[region].parameters.get_num_groups();
644  for (auto i = AgeGroup(0); i < num_groups; i++) {
645 
646  FP SN = num_population[region][size_t(i)] * immunity_population[0][size_t(i)];
647  FP SPI = num_population[region][size_t(i)] * immunity_population[1][size_t(i)];
648  FP SII = num_population[region][size_t(i)] - SN - SPI;
649 
650  model[region].populations[{i, InfectionState::SusceptibleImprovedImmunity}] = std::max(
651  0.0,
652  FP(SII -
653  (model[region].populations[{i, InfectionState::ExposedImprovedImmunity}] +
654  model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunity}] +
655  model[region].populations[{i, InfectionState::InfectedNoSymptomsImprovedImmunityConfirmed}] +
656  model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunity}] +
657  model[region].populations[{i, InfectionState::InfectedSymptomsImprovedImmunityConfirmed}] +
658  model[region].populations[{i, InfectionState::InfectedSevereImprovedImmunity}] +
659  model[region].populations[{i, InfectionState::InfectedCriticalImprovedImmunity}] +
660  model[region].populations[{i, InfectionState::DeadImprovedImmunity}] +
661  model[region].populations[{i, InfectionState::TemporaryImmuneImprovedImmunity}])));
662 
663  model[region].populations[{i, InfectionState::SusceptiblePartialImmunity}] = std::max(
664  0.0,
665  SPI - model[region].populations[{i, InfectionState::ExposedPartialImmunity}] -
666  model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunity}] -
667  model[region].populations[{i, InfectionState::InfectedNoSymptomsPartialImmunityConfirmed}] -
668  model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunity}] -
669  model[region].populations[{i, InfectionState::InfectedSymptomsPartialImmunityConfirmed}] -
670  model[region].populations[{i, InfectionState::InfectedSeverePartialImmunity}] -
671  model[region].populations[{i, InfectionState::InfectedCriticalPartialImmunity}] -
672  model[region].populations[{i, InfectionState::DeadPartialImmunity}] -
673  model[region].populations[{i, InfectionState::TemporaryImmunePartialImmunity}]);
674 
675  model[region].populations.template set_difference_from_group_total<AgeGroup>(
676  {i, InfectionState::SusceptibleNaive}, num_population[region][size_t(i)]);
677  }
678 
679  for (auto i = AgeGroup(0); i < AgeGroup(6); i++) {
680  for (auto j = Index<InfectionState>(0); j < InfectionState::Count; ++j) {
681  if (model[region].populations[{i, j}] < 0) {
682  log_warning("Compartment at age group {}, infection state {}, is negative: {}", size_t(i),
683  size_t(j), model[region].populations[{i, j}]);
684  }
685  }
686  }
687  }
688  else {
689  log_warning("No population data available for region " + std::to_string(region) +
690  ". Population data has not been set.");
691  }
692  }
693 
694  return success();
695 }
696 
710 template <class Model>
711 IOResult<void> set_population_data(std::vector<Model>& model, const std::string& path, const std::vector<int>& vregion,
712  const std::vector<std::vector<double>> immunity_population)
713 {
714  BOOST_OUTCOME_TRY(auto&& num_population, mio::read_population_data(path, vregion));
715  BOOST_OUTCOME_TRY(set_population_data(model, num_population, vregion, immunity_population));
716  return success();
717 }
718 
733 template <typename FP>
734 IOResult<void> set_vaccination_data(std::vector<Model<FP>>& model, const std::vector<VaccinationDataEntry>& vacc_data,
735  Date date, const std::vector<int>& vregion, int num_days)
736 {
737  auto num_groups = model[0].parameters.get_num_groups();
738 
739  auto days_until_effective_n =
740  (int)(double)model[0].parameters.template get<DaysUntilEffectivePartialVaccination<FP>>()[AgeGroup(0)];
741  auto days_until_effective_pi =
742  (int)(double)model[0].parameters.template get<DaysUntilEffectiveImprovedVaccination<FP>>()[AgeGroup(0)];
743  auto days_until_effective_ii =
744  (int)(double)model[0].parameters.template get<DaysUntilEffectiveBoosterImmunity<FP>>()[AgeGroup(0)];
745  // iterate over regions (e.g., counties)
746  for (size_t i = 0; i < model.size(); ++i) {
747  // iterate over age groups in region
748  for (auto g = AgeGroup(0); g < num_groups; ++g) {
749 
750  model[i].parameters.template get<DailyPartialVaccinations<FP>>().resize(SimulationDay(num_days + 1));
751  model[i].parameters.template get<DailyFullVaccinations<FP>>().resize(SimulationDay(num_days + 1));
752  model[i].parameters.template get<DailyBoosterVaccinations<FP>>().resize(SimulationDay(num_days + 1));
753  for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) {
754  model[i].parameters.template get<DailyPartialVaccinations<FP>>()[{g, d}] = 0.0;
755  model[i].parameters.template get<DailyFullVaccinations<FP>>()[{g, d}] = 0.0;
756  model[i].parameters.template get<DailyBoosterVaccinations<FP>>()[{g, d}] = 0.0;
757  }
758  }
759  }
760 
761  auto max_date_entry = std::max_element(vacc_data.begin(), vacc_data.end(), [](auto&& a, auto&& b) {
762  return a.date < b.date;
763  });
764  if (max_date_entry == vacc_data.end()) {
765  return failure(StatusCode::InvalidFileFormat, "Vaccination data file is empty.");
766  }
767  auto max_date = max_date_entry->date;
768  auto min_date_entry = std::min_element(vacc_data.begin(), vacc_data.end(), [](auto&& a, auto&& b) {
769  return a.date < b.date;
770  });
771  auto min_date = min_date_entry->date;
772  if (min_date > date || max_date < offset_date_by_days(date, num_days)) {
773  log_warning("Vaccination data only available from {} to {}. "
774  "For days before and after, vaccinations will be set to 0.",
775  min_date, max_date);
776  }
777 
778  for (auto&& vacc_data_entry : vacc_data) {
779  auto it = std::find_if(vregion.begin(), vregion.end(), [&vacc_data_entry](auto&& r) {
780  return r == 0 || (vacc_data_entry.county_id && vacc_data_entry.county_id == regions::CountyId(r)) ||
781  (vacc_data_entry.state_id && vacc_data_entry.state_id == regions::StateId(r)) ||
782  (vacc_data_entry.district_id && vacc_data_entry.district_id == regions::DistrictId(r));
783  });
784  auto date_df = vacc_data_entry.date;
785  if (it != vregion.end()) {
786  auto region_idx = size_t(it - vregion.begin());
787  AgeGroup age = vacc_data_entry.age_group;
788 
789  // get daily vaccinations for each layer
790  for (size_t d = 0; d < (size_t)num_days + 1; ++d) {
791  auto offset_first_date = offset_date_by_days(date, (int)d - days_until_effective_n);
792  if (max_date >= offset_first_date) {
793  if (date_df == offset_first_date) {
794  model[region_idx]
795  .parameters.template get<DailyPartialVaccinations<FP>>()[{age, SimulationDay(d)}] =
796  vacc_data_entry.num_vaccinations_partial;
797  }
798  }
799  else {
800  if (date_df == offset_first_date) {
801  model[region_idx]
802  .parameters.template get<DailyPartialVaccinations<FP>>()[{age, SimulationDay(d)}] = 0;
803  }
804  }
805 
806  auto offset_full_date = offset_date_by_days(date, (int)d - days_until_effective_pi);
807  if (max_date >= offset_full_date) {
808  if (date_df == offset_full_date) {
809  model[region_idx]
810  .parameters.template get<DailyFullVaccinations<FP>>()[{age, SimulationDay(d)}] =
811  vacc_data_entry.num_vaccinations_completed;
812  }
813  }
814  else {
815  if (date_df == offset_first_date) {
816  model[region_idx]
817  .parameters.template get<DailyFullVaccinations<FP>>()[{age, SimulationDay(d)}] = 0;
818  }
819  }
820 
821  auto offset_booster_date = offset_date_by_days(date, (int)d - days_until_effective_ii);
822  if (max_date >= offset_booster_date) {
823  if (date_df == offset_booster_date) {
824  model[region_idx]
825  .parameters.template get<DailyBoosterVaccinations<FP>>()[{age, SimulationDay(d)}] =
826  vacc_data_entry.num_vaccinations_refreshed_first +
827  vacc_data_entry.num_vaccinations_refreshed_additional;
828  }
829  }
830  else {
831  if (date_df == offset_first_date) {
832  model[region_idx]
833  .parameters.template get<DailyBoosterVaccinations<FP>>()[{age, SimulationDay(d)}] = 0;
834  }
835  }
836  }
837  }
838  }
839  return success();
840 }
841 
858 template <typename FP>
859 IOResult<void> set_vaccination_data(std::vector<Model<FP>>& model, const std::string& path, Date date,
860  const std::vector<int>& vregion, int num_days)
861 {
862  // Check if vaccination data is available for the given date range
863  auto end_date = offset_date_by_days(date, num_days);
864  if (!is_vaccination_data_available(date, end_date)) {
865  log_warning("No vaccination data available in range from {} to {}. "
866  "Vaccination data will be set to 0.",
867  date, end_date);
868  // Set vaccination data to 0 for all models
869  for (auto& m : model) {
870  m.parameters.template get<DailyPartialVaccinations<FP>>().resize(SimulationDay(num_days + 1));
871  m.parameters.template get<DailyFullVaccinations<FP>>().resize(SimulationDay(num_days + 1));
872  m.parameters.template get<DailyBoosterVaccinations<FP>>().resize(SimulationDay(num_days + 1));
873  for (auto d = SimulationDay(0); d < SimulationDay(num_days + 1); ++d) {
874  for (auto a = AgeGroup(0); a < m.parameters.get_num_groups(); ++a) {
875  m.parameters.template get<DailyPartialVaccinations<FP>>()[{a, d}] = 0.0;
876  m.parameters.template get<DailyFullVaccinations<FP>>()[{a, d}] = 0.0;
877  m.parameters.template get<DailyBoosterVaccinations<FP>>()[{a, d}] = 0.0;
878  }
879  }
880  }
881  return success();
882  }
883  BOOST_OUTCOME_TRY(auto&& vacc_data, read_vaccination_data(path));
884  BOOST_OUTCOME_TRY(set_vaccination_data(model, vacc_data, date, vregion, num_days));
885  return success();
886 }
887 
888 } // namespace details
889 
890 #ifdef MEMILIO_HAS_HDF5
891 
916 template <class Model>
917 IOResult<void> export_input_data_county_timeseries(
918  std::vector<Model> models, const std::string& results_dir, const std::vector<int>& counties, Date date,
919  const std::vector<double>& scaling_factor_inf, const double scaling_factor_icu, const int num_days,
920  const std::string& divi_data_path, const std::string& confirmed_cases_path, const std::string& population_data_path,
921  const std::vector<std::vector<double>> immunity_population, const std::string& vaccination_data_path = "")
922 {
923  const auto num_groups = (size_t)models[0].parameters.get_num_groups();
924  assert(scaling_factor_inf.size() == num_groups);
925  assert(num_groups == ConfirmedCasesDataEntry::age_group_names.size());
926  assert(models.size() == counties.size());
927  std::vector<TimeSeries<double>> extrapolated_data(
928  models.size(), TimeSeries<double>::zero(num_days + 1, (size_t)InfectionState::Count * num_groups));
929 
930  BOOST_OUTCOME_TRY(auto&& case_data, read_confirmed_cases_data(confirmed_cases_path));
931  BOOST_OUTCOME_TRY(auto&& population_data, read_population_data(population_data_path, counties));
932 
933  // empty vector if set_vaccination_data is not set
934  std::vector<VaccinationDataEntry> vacc_data;
935  if (!vaccination_data_path.empty()) {
936  BOOST_OUTCOME_TRY(vacc_data, read_vaccination_data(vaccination_data_path));
937  }
938 
939  for (int t = 0; t <= num_days; ++t) {
940  auto offset_day = offset_date_by_days(date, t);
941 
942  if (!vaccination_data_path.empty()) {
943  BOOST_OUTCOME_TRY(details::set_vaccination_data(models, vacc_data, offset_day, counties, num_days));
944  }
945 
946  // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType.
947  // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available.
948  BOOST_OUTCOME_TRY(details::set_divi_data(models, divi_data_path, counties, offset_day, scaling_factor_icu));
949 
950  BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(models, case_data, counties, offset_day, scaling_factor_inf,
951  immunity_population));
952 
953  BOOST_OUTCOME_TRY(details::set_population_data(models, population_data, counties, immunity_population));
954 
955  for (size_t r = 0; r < counties.size(); r++) {
956  extrapolated_data[r][t] = models[r].get_initial_values();
957  // in set_population_data the number of death individuals is subtracted from the SusceptibleImprovedImmunity compartment.
958  // Since we should be independent whether we consider them or not, we add them back here before we save the data.
959  for (size_t age = 0; age < num_groups; age++) {
960  extrapolated_data[r][t][(size_t)InfectionState::SusceptibleImprovedImmunity +
961  age * (size_t)InfectionState::Count] +=
962  extrapolated_data[r][t][(size_t)InfectionState::DeadNaive + age * (size_t)InfectionState::Count];
963  }
964  }
965  }
966  BOOST_OUTCOME_TRY(save_result(extrapolated_data, counties, static_cast<int>(num_groups),
967  path_join(results_dir, "Results_rki.h5")));
968 
969  auto extrapolated_rki_data_sum = sum_nodes(std::vector<std::vector<TimeSeries<double>>>{extrapolated_data});
970  BOOST_OUTCOME_TRY(save_result({extrapolated_rki_data_sum[0][0]}, {0}, static_cast<int>(num_groups),
971  path_join(results_dir, "Results_rki_sum.h5")));
972 
973  return success();
974 }
975 
976 #else
977 template <class Model>
978 IOResult<void> export_input_data_county_timeseries(std::vector<Model>, const std::string&, const std::vector<int>&,
979  Date, const std::vector<double>&, const double, const int,
980  const std::string&, const std::string&, const std::string&,
981  const std::vector<std::vector<double>>, const std::string&)
982 {
983  mio::log_warning("HDF5 not available. Cannot export time series of extrapolated real data.");
984  return success();
985 }
986 
987 #endif //MEMILIO_HAS_HDF5
988 
1010 template <class Model>
1011 IOResult<void> read_input_data_county(std::vector<Model>& model, Date date, const std::vector<int>& county,
1012  const std::vector<double>& scaling_factor_inf, double scaling_factor_icu,
1013  const std::string& pydata_dir, int num_days,
1014  const std::vector<std::vector<double>> immunity_population,
1015  bool export_time_series = false)
1016 {
1017  BOOST_OUTCOME_TRY(details::set_vaccination_data(model, path_join(pydata_dir, "vacc_county_ageinf_ma7.json"), date,
1018  county, num_days));
1019 
1020  // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType.
1021  // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available.
1022  BOOST_OUTCOME_TRY(
1023  details::set_divi_data(model, path_join(pydata_dir, "county_divi_ma7.json"), county, date, scaling_factor_icu));
1024 
1025  BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "cases_all_county_age_ma7.json"),
1026  county, date, scaling_factor_inf, immunity_population));
1027  BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, "county_current_population.json"),
1028  county, immunity_population));
1029 
1030  if (export_time_series) {
1031  // Use only if extrapolated real data is needed for comparison. EXPENSIVE !
1032  // Run time equals run time of the previous functions times the num_days !
1033  // (This only represents the vectorization of the previous function over all simulation days...)
1034  log_info("Exporting time series of extrapolated real data. This may take some minutes. "
1035  "For simulation runs over the same time period, deactivate it.");
1036  BOOST_OUTCOME_TRY(export_input_data_county_timeseries(
1037  model, pydata_dir, county, date, scaling_factor_inf, scaling_factor_icu, num_days,
1038  path_join(pydata_dir, "county_divi_ma7.json"), path_join(pydata_dir, "cases_all_county_age_ma7.json"),
1039  path_join(pydata_dir, "county_current_population.json"), immunity_population,
1040  path_join(pydata_dir, "vacc_county_ageinf_ma7.json")));
1041  }
1042 
1043  return success();
1044 }
1045 
1065 template <class Model>
1066 IOResult<void> read_input_data(std::vector<Model>& model, Date date, const std::vector<int>& node_ids,
1067  const std::vector<double>& scaling_factor_inf, double scaling_factor_icu,
1068  const std::string& pydata_dir, int num_days,
1069  const std::vector<std::vector<double>> immunity_population,
1070  bool export_time_series = false)
1071 {
1072 
1073  BOOST_OUTCOME_TRY(
1074  details::set_vaccination_data(model, path_join(pydata_dir, "vaccination_data.json"), date, node_ids, num_days));
1075 
1076  // TODO: Reuse more code, e.g., set_divi_data (in secir) and a set_divi_data (here) only need a different ModelType.
1077  // TODO: add option to set ICU data from confirmed cases if DIVI or other data is not available.
1078  BOOST_OUTCOME_TRY(details::set_divi_data(model, path_join(pydata_dir, "critical_cases.json"), node_ids, date,
1079  scaling_factor_icu));
1080 
1081  BOOST_OUTCOME_TRY(details::set_confirmed_cases_data(model, path_join(pydata_dir, "confirmed_cases.json"), node_ids,
1082  date, scaling_factor_inf, immunity_population));
1083  BOOST_OUTCOME_TRY(details::set_population_data(model, path_join(pydata_dir, "population_data.json"), node_ids,
1084  immunity_population));
1085 
1086  if (export_time_series) {
1087  // Use only if extrapolated real data is needed for comparison. EXPENSIVE !
1088  // Run time equals run time of the previous functions times the num_days !
1089  // (This only represents the vectorization of the previous function over all simulation days...)
1090  log_info("Exporting time series of extrapolated real data. This may take some minutes. "
1091  "For simulation runs over the same time period, deactivate it.");
1092  BOOST_OUTCOME_TRY(export_input_data_county_timeseries(
1093  model, pydata_dir, node_ids, date, scaling_factor_inf, scaling_factor_icu, num_days,
1094  path_join(pydata_dir, "critical_cases.json"), path_join(pydata_dir, "confirmed_cases.json"),
1095  path_join(pydata_dir, "population_data.json"), immunity_population,
1096  path_join(pydata_dir, "vaccination_data.json")));
1097  }
1098 
1099  return success();
1100 }
1101 
1102 } // namespace osecirts
1103 } // namespace mio
1104 
1105 #endif // MEMILIO_HAS_JSONCPP
1106 
1107 #endif // MIO_ODE_SECIRTS_PARAMETERS_IO_H
static TimeSeries zero(Eigen::Index num_time_points, Eigen::Index num_elements)
constructs TimeSeries instance and initializes it with zeros
Definition: time_series.h:152
static min_max_return_type< ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 >, ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > >::type max(const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &a, const ad::internal::active_type< AD_TAPE_REAL, DATA_HANDLER_1 > &b)
Definition: ad.hpp:2596
trait_value< T >::RETURN_TYPE & value(T &x)
Definition: ad.hpp:3308
int size(Comm comm)
Return the size of the given communicator.
Definition: miompi.cpp:75
A collection of classes to simplify handling of matrix shapes in meta programming.
Definition: models/abm/analyze_result.h:30
requires details::IsElementReference< M > RowMajorIterator< M, false > end(M &m)
create a non-const end iterator for the matrix m.
Definition: eigen_util.h:449
auto failure(const IOStatus &s)
Create an object that is implicitly convertible to an error IOResult<T>.
Definition: io.h:380
auto i
Definition: io.h:809
void log_warning(spdlog::string_view_t fmt, const Args &... args)
Definition: logging.h:112
auto success()
Create an object that is implicitly convertible to a succesful IOResult<void>.
Definition: io.h:359
int get_offset_in_days(Date date1, Date date2)
Computes the offset in days given two dates: first date minus second date.
Definition: date.h:310
void log_error(spdlog::string_view_t fmt, const Args &... args)
Definition: logging.h:100
requires details::IsElementReference< M > RowMajorIterator< M, false > begin(M &m)
create a non-const iterator to first element of the matrix m.
Definition: eigen_util.h:421
Date offset_date_by_days(Date date, int offset_days)
Computes the new date corresponding to a given date and a offset in days.
Definition: date.h:242
std::string path_join(String &&base, Strings &&... app)
join one ore more strings with path separators.
Definition: stl_util.h:268
constexpr std::tuple_element< I, std::tuple< Index< CategoryTags >... > >::type & get(Index< CategoryTags... > &i) noexcept
Retrieves the Index (by reference) at the Ith position of a MultiIndex.
Definition: index.h:294
std::vector< std::vector< TimeSeries< FP > > > sum_nodes(const std::vector< std::vector< TimeSeries< FP >>> &ensemble_result)
Definition: memilio/data/analyze_result.h:268
void log_info(spdlog::string_view_t fmt, const Args &... args)
Definition: logging.h:94