Skip to content

Commit a0e3a4f

Browse files
authored
1382 Fix incorrect overload detection and type mismatch in test_commuters (#1394)
1 parent d871c54 commit a0e3a4f

File tree

4 files changed

+42
-43
lines changed

4 files changed

+42
-43
lines changed

cpp/memilio/mobility/metapopulation_mobility_instant.h

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ void calculate_mobility_returns(Eigen::Ref<typename TimeSeries<FP>::Vector> mobi
478478
* detect a get_infections_relative function for the Model type.
479479
*/
480480
template <typename FP, class Sim>
481-
using get_infections_relative_expr_t = decltype(get_infections_relative(
481+
using get_infections_relative_expr_t = decltype(get_infections_relative<FP>(
482482
std::declval<const Sim&>(), std::declval<FP>(), std::declval<const Eigen::Ref<const Eigen::VectorX<FP>>&>()));
483483

484484
/**
@@ -490,26 +490,25 @@ using get_infections_relative_expr_t = decltype(get_infections_relative(
490490
* @param y the current value of the simulation.
491491
* @param t the current simulation time
492492
*/
493-
template <typename FP, class Sim,
494-
std::enable_if_t<!is_expression_valid<get_infections_relative_expr_t, Sim>::value, void*> = nullptr>
495-
FP get_infections_relative(const SimulationNode<FP, Sim>& /*node*/, FP /*t*/,
496-
const Eigen::Ref<const Eigen::VectorX<FP>>& /*y*/)
497-
{
498-
assert(false && "Overload get_infections_relative for your own model/simulation if you want to use dynamic NPIs.");
499-
return 0;
500-
}
501-
template <typename FP, class Sim,
502-
std::enable_if_t<is_expression_valid<get_infections_relative_expr_t, Sim>::value, void*> = nullptr>
493+
template <typename FP, class Sim>
503494
FP get_infections_relative(const SimulationNode<FP, Sim>& node, FP t, const Eigen::Ref<const Eigen::VectorX<FP>>& y)
504495
{
505-
return get_infections_relative<FP, Sim>(node.get_simulation(), t, y);
496+
if constexpr (is_expression_valid<get_infections_relative_expr_t, FP, Sim>::value) {
497+
return get_infections_relative<FP>(node.get_simulation(), t, y);
498+
}
499+
else {
500+
mio::unused(node, t, y);
501+
mio::log_debug("get_infections_relative called without specialization for this simulation type. "
502+
"Implement an overload in your model if you intend to use dynamic NPIs.");
503+
return FP{0};
504+
}
506505
}
507506

508507
/**
509508
* detect a get_mobility_factors function for the Model type.
510509
*/
511510
template <typename FP, class Sim>
512-
using get_mobility_factors_expr_t = decltype(get_mobility_factors(
511+
using get_mobility_factors_expr_t = decltype(get_mobility_factors<FP>(
513512
std::declval<const Sim&>(), std::declval<FP>(), std::declval<const Eigen::Ref<const Eigen::VectorX<FP>>&>()));
514513

515514
/**
@@ -523,26 +522,26 @@ using get_mobility_factors_expr_t = decltype(get_mobility_factors(
523522
* @param t the current simulation time
524523
* @return a vector expression, same size as y, with the factor for each compartment.
525524
*/
526-
template <typename FP, class Sim,
527-
std::enable_if_t<!is_expression_valid<get_mobility_factors_expr_t, Sim>::value, void*> = nullptr>
528-
auto get_mobility_factors(const SimulationNode<FP, Sim>& /*node*/, FP /*t*/,
529-
const Eigen::Ref<const Eigen::VectorX<FP>>& y)
530-
{
531-
return Eigen::VectorX<FP>::Ones(y.rows());
532-
}
533-
template <typename FP, class Sim,
534-
std::enable_if_t<is_expression_valid<get_mobility_factors_expr_t, Sim>::value, void*> = nullptr>
525+
template <typename FP, class Sim>
535526
auto get_mobility_factors(const SimulationNode<FP, Sim>& node, FP t, const Eigen::Ref<const Eigen::VectorX<FP>>& y)
536527
{
537-
return get_mobility_factors<FP, Sim>(node.get_simulation(), t, y);
528+
if constexpr (is_expression_valid<get_mobility_factors_expr_t, FP, Sim>::value) {
529+
return get_mobility_factors<FP>(node.get_simulation(), t, y);
530+
}
531+
else {
532+
mio::unused(node, t);
533+
mio::log_debug("get_mobility_factors called without specialization for this simulation type. "
534+
"Using default mobility factor (1.0) for all compartments.");
535+
return Eigen::VectorX<FP>::Ones(y.rows());
536+
}
538537
}
539538

540539
/**
541540
* detect a get_mobility_factors function for the Model type.
542541
*/
543542
template <typename FP, class Sim>
544-
using test_commuters_expr_t = decltype(test_commuters(
545-
std::declval<Sim&>(), std::declval<Eigen::Ref<const Eigen::VectorX<FP>>&>(), std::declval<FP>()));
543+
using test_commuters_expr_t = decltype(test_commuters<FP>(
544+
std::declval<Sim&>(), std::declval<Eigen::Ref<Eigen::VectorX<FP>>>(), std::declval<FP>()));
546545

547546
/**
548547
* Test persons when moving from their source node.
@@ -554,17 +553,17 @@ using test_commuters_expr_t = decltype(test_commuters(
554553
* @param mobile_population mutable reference to vector of persons per compartment that change nodes.
555554
* @param t the current simulation time.
556555
*/
557-
template <typename FP, class Sim,
558-
std::enable_if_t<!is_expression_valid<test_commuters_expr_t, Sim>::value, void*> = nullptr>
559-
void test_commuters(SimulationNode<FP, Sim>& /*node*/, Eigen::Ref<Eigen::VectorX<FP>> /*mobile_population*/,
560-
FP /*time*/)
561-
{
562-
}
563-
template <typename FP, class Sim,
564-
std::enable_if_t<is_expression_valid<test_commuters_expr_t, Sim>::value, void*> = nullptr>
556+
template <typename FP, class Sim>
565557
void test_commuters(SimulationNode<FP, Sim>& node, Eigen::Ref<Eigen::VectorX<FP>> mobile_population, FP time)
566558
{
567-
return test_commuters<FP, Sim>(node.get_simulation(), mobile_population, time);
559+
if constexpr (is_expression_valid<test_commuters_expr_t, FP, Sim>::value) {
560+
test_commuters<FP>(node.get_simulation(), mobile_population, time);
561+
}
562+
else {
563+
mio::unused(node, mobile_population, time);
564+
mio::log_debug("test_commuters called without specialization for this simulation type. "
565+
"Implement an overload in your model if you intend to use commuter testing.");
566+
}
568567
}
569568

570569
template <typename FP>
@@ -581,7 +580,7 @@ void mio::MobilityEdge<FP>::apply_mobility(FP t, FP dt, SimulationNode<FP, Sim>&
581580
if (dyn_npis.get_thresholds().size() > 0 &&
582581
floating_point_greater_equal<FP>(t, m_t_last_dynamic_npi_check + dyn_npis.get_interval().get())) {
583582
auto inf_rel =
584-
get_infections_relative<FP, Sim>(node_from, t, node_from.get_last_state()) * dyn_npis.get_base_value();
583+
get_infections_relative<FP>(node_from, t, node_from.get_last_state()) * dyn_npis.get_base_value();
585584
auto exceeded_threshold = dyn_npis.get_max_exceeded_threshold(inf_rel);
586585
if (exceeded_threshold != dyn_npis.get_thresholds().end() &&
587586
(exceeded_threshold->first > m_dynamic_npi.first ||
@@ -602,8 +601,8 @@ void mio::MobilityEdge<FP>::apply_mobility(FP t, FP dt, SimulationNode<FP, Sim>&
602601
if (m_return_times.get_time(i) <= t) {
603602
auto v0 = find_value_reverse<FP>(node_to.get_result(), m_mobile_population.get_time(i), 1e-10, 1e-10);
604603
assert(v0 != node_to.get_result().rend() && "unexpected error.");
605-
calculate_mobility_returns<FP, Sim>(m_mobile_population[i], node_to.get_simulation(), *v0,
606-
m_mobile_population.get_time(i), dt);
604+
calculate_mobility_returns<FP>(m_mobile_population[i], node_to.get_simulation(), *v0,
605+
m_mobile_population.get_time(i), dt);
607606

608607
//the lower-order return calculation may in rare cases produce negative compartments,
609608
//especially at the beginning of the simulation.

cpp/models/ode_secir/model.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ IOResult<FP> get_reproduction_number(FP t_value, const Simulation<FP, Base>& sim
659659
* @tparam FP floating point type, e.g., double.
660660
* @tparam Base simulation type that uses a secir compartment model; see Simulation.
661661
*/
662-
template <typename FP, class Base = mio::Simulation<Model<FP>, FP>>
662+
template <typename FP, class Base = mio::Simulation<FP, Model<FP>>>
663663
auto get_mobility_factors(const Simulation<FP, Base>& sim, FP /*t*/, const Eigen::Ref<const Eigen::VectorX<FP>>& y)
664664
{
665665
auto& params = sim.get_model().parameters;
@@ -689,7 +689,7 @@ auto get_mobility_factors(const Simulation<FP, Base>& sim, FP /*t*/, const Eigen
689689
return factors;
690690
}
691691

692-
template <typename FP, class Base = mio::Simulation<Model<FP>, FP>>
692+
template <typename FP, class Base = mio::Simulation<FP, Model<FP>>>
693693
auto test_commuters(Simulation<FP, Base>& sim, Eigen::Ref<Eigen::VectorX<FP>> mobile_population, FP time)
694694
{
695695
auto& model = sim.get_model();

cpp/models/ode_secirts/model.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -896,7 +896,7 @@ FP get_infections_relative(const Simulation<FP, Base>& sim, FP /*t*/, const Eige
896896
* @return vector expression, same size as y, with migration factors per compartment.
897897
* @tparam Base simulation type that uses a SECIRS-type compartment model. see Simulation.
898898
*/
899-
template <typename FP, class Base = mio::Simulation<Model<FP>, FP>>
899+
template <typename FP, class Base = mio::Simulation<FP, Model<FP>>>
900900
auto get_migration_factors(const Simulation<Base>& sim, FP /*t*/, const Eigen::Ref<const Eigen::VectorX<FP>>& y)
901901
{
902902
auto& params = sim.get_model().parameters;
@@ -943,7 +943,7 @@ auto get_migration_factors(const Simulation<Base>& sim, FP /*t*/, const Eigen::R
943943
* @param[in,out] migrated Vector representing the number of commuters in each state.
944944
* @param[in] time Current simulation time, used to determine the commuter detection period.
945945
*/
946-
template <typename FP, class Base = mio::Simulation<Model<FP>, FP>>
946+
template <typename FP, class Base = mio::Simulation<FP, Model<FP>>>
947947
auto test_commuters(Simulation<FP, Base>& sim, Eigen::Ref<Eigen::VectorX<FP>> migrated, FP time)
948948
{
949949
auto& model = sim.get_model();

cpp/models/ode_secirvvs/model.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,7 @@ FP get_infections_relative(const Simulation<FP, Base>& sim, FP /*t*/, const Eige
825825
* @return vector expression, same size as y, with mobility factors per compartment.
826826
* @tparam Base simulation type that uses a secir compartment model. see Simulation.
827827
*/
828-
template <typename FP, class Base = mio::Simulation<Model<FP>, FP>>
828+
template <typename FP, class Base = mio::Simulation<FP, Model<FP>>>
829829
auto get_mobility_factors(const Simulation<Base>& sim, FP /*t*/, const Eigen::Ref<const Eigen::VectorX<FP>>& y)
830830

831831
{
@@ -866,7 +866,7 @@ auto get_mobility_factors(const Simulation<Base>& sim, FP /*t*/, const Eigen::Re
866866
return factors;
867867
}
868868

869-
template <typename FP, class Base = mio::Simulation<Model<FP>, FP>>
869+
template <typename FP, class Base = mio::Simulation<FP, Model<FP>>>
870870
auto test_commuters(Simulation<FP, Base>& sim, Eigen::Ref<Eigen::VectorX<FP>> mobile_population, FP time)
871871
{
872872
auto& model = sim.get_model();

0 commit comments

Comments
 (0)