diff --git a/cpp/memilio/compartments/flow_model.h b/cpp/memilio/compartments/flow_model.h index 1c59d42d1b..bbb1e240a7 100644 --- a/cpp/memilio/compartments/flow_model.h +++ b/cpp/memilio/compartments/flow_model.h @@ -82,6 +82,7 @@ class FlowModel : public CompartmentalModel // Enforce that Comp is a unique Category of PopIndex, since we use Flows (via their source/target) to provide // Comp indices for the population. static_assert(FlowIndex::size == PopIndex::size - 1, "Compartments must be used exactly once as population index."); + static_assert(!Flows::has_duplicates, "Flow duplicates detected. Flows must be unique."); public: using Base = CompartmentalModel; diff --git a/cpp/memilio/utils/type_list.h b/cpp/memilio/utils/type_list.h index bb3ef29a95..6c5d3e4e61 100644 --- a/cpp/memilio/utils/type_list.h +++ b/cpp/memilio/utils/type_list.h @@ -49,6 +49,9 @@ struct TypeList { { return sizeof...(Types); } + + /// @brief Checks whether TypeList contains any type multiple times. + static constexpr bool has_duplicates = has_duplicates_v; }; /// Specialization of type_at_index for TypeList. @see type_at_index. diff --git a/cpp/models/ode_secirts/model.h b/cpp/models/ode_secirts/model.h index 76ea3743a2..721293fe44 100644 --- a/cpp/models/ode_secirts/model.h +++ b/cpp/models/ode_secirts/model.h @@ -54,7 +54,6 @@ using Flows = TypeList< Flow, Flow, Flow, - Flow, //partial immunity Flow, Flow, diff --git a/cpp/tests/test_odesecirts.cpp b/cpp/tests/test_odesecirts.cpp index cde7f108d9..4041e6c3b6 100755 --- a/cpp/tests/test_odesecirts.cpp +++ b/cpp/tests/test_odesecirts.cpp @@ -125,17 +125,17 @@ TEST(TestOdeSECIRTS, get_flows) model.get_flows(y, y, 0.0, flows); - std::vector expected_values = {0.09375, 0.90625, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0, 0.5, 0.5, 1, 0.046875, 0.953125, 1, 0.5, 0.5, - 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0.5, 0.5, - 0.046875, 0.953125, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 0.5, 0, 0.5, 0.5, 0, 1, 1, 1}; + std::vector expected_values = { + 0.09375, 0.90625, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0, 0.5, 0.5, 0.046875, 0.953125, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0, 0.5, 0.5, 0.046875, 0.953125, 1, 0.5, 0.5, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0.5, 0.5, 1, 1, 1, 1}; - EXPECT_EQ(flows.size(), 53); + EXPECT_EQ(flows.size(), 52); // Compare expected with actual values - for (size_t i = 0; i < expected_values.size(); i++) { - EXPECT_NEAR(flows(i), expected_values[i], 1e-10); + for (auto i = 0; i < flows.size(); i++) { + EXPECT_NEAR(flows(i), expected_values[i], 1e-5); } } @@ -148,8 +148,8 @@ TEST(TestOdeSECIRTS, Simulation) EXPECT_EQ(sim.get_result().get_num_time_points(), 2); // stores initial value and single step Eigen::VectorXd expected_result(29); - expected_result << 1.0, 2.0, 0.09375, 0.046875, 0.046875, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 1.0, 1.0, 1.0, 0.5, 0.5, 0.5, 0.0, 1.5, 1.5, 1.5, 2.90625, 7.90625; + expected_result << 1, 1, 0.09375, 0.046875, 0.046875, 1, 1, 1, 0, 0, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 0.5, + 0.5, 0.5, 0, 1.5, 1.5, 1.5, 3.90625, 7.90625; EXPECT_EQ(sim.get_result().get_last_value(), expected_result); } @@ -165,14 +165,14 @@ TEST(TestOdeSECIRTS, FlowSimulation) EXPECT_EQ(sim.get_result().get_num_time_points(), 2); // stores initial value and single step Eigen::VectorXd expected_result(29); - expected_result << 1.0, 2.0, 0.09375, 0.046875, 0.046875, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 0.5, 0.5, - 0.5, 1.0, 1.0, 1.0, 0.5, 0.5, 0.5, 0.0, 1.5, 1.5, 1.5, 2.90625, 7.90625; + expected_result << 1, 1, 0.09375, 0.046875, 0.046875, 1, 1, 1, 0, 0, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 0.5, + 0.5, 0.5, 0, 1.5, 1.5, 1.5, 3.90625, 7.90625; EXPECT_EQ(sim.get_result().get_last_value(), expected_result); - Eigen::VectorXd expected_flows(53); - expected_flows << 0.09375, 0.90625, 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0, 0.5, 0.5, 1.0, - 0.046875, 0.953125, 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0, 0.5, 0.5, 0.046875, 0.953125, - 1.0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.0, 0.5, 0.5, 0.0, 1.0, 1.0, 1.0; + Eigen::VectorXd expected_flows(52); + expected_flows << 0.09375, 0.90625, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0.5, 0.5, 0.046875, + 0.953125, 1, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0.5, 0.5, 0.046875, 0.953125, 1, 0.5, 0.5, + 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0, 0.5, 0.5, 1, 1, 1, 1; EXPECT_EQ(sim.get_flows().get_last_value(), expected_flows); }