From e40b32f6173f4e52c1890ec9a2856d20f70924b7 Mon Sep 17 00:00:00 2001 From: Guillaume PIERRE Date: Fri, 13 Dec 2024 17:23:17 +0100 Subject: [PATCH] New hydro remix : unit tests on input data --- src/solver/simulation/hydro-remix-new.cpp | 67 +++++++++++++++---- .../src/solver/simulation/CMakeLists.txt | 1 + .../solver/simulation/test-hydro-remix.cpp | 47 ++++++++++++- 3 files changed, 100 insertions(+), 15 deletions(-) diff --git a/src/solver/simulation/hydro-remix-new.cpp b/src/solver/simulation/hydro-remix-new.cpp index 76e9e9f90c..80c7530b73 100644 --- a/src/solver/simulation/hydro-remix-new.cpp +++ b/src/solver/simulation/hydro-remix-new.cpp @@ -1,4 +1,6 @@ #include +#include +#include #include namespace Antares::Solver::Simulation @@ -13,7 +15,7 @@ int find_min_index(const std::vector& G_plus_H, { double min_val = top; int min_idx = -1; - for (size_t i = 0; i < G_plus_H.size(); ++i) + for (int i = 0; i < G_plus_H.size(); ++i) { if (new_D[i] > 0 && new_H[i] < P_max[i] && tried_creux[i] == 0) { @@ -36,7 +38,7 @@ int find_max_index(const std::vector& G_plus_H, { double max_val = 0; int max_idx = -1; - for (size_t i = 0; i < G_plus_H.size(); ++i) + for (int i = 0; i < G_plus_H.size(); ++i) { if (new_H[i] > P_min[i] && G_plus_H[i] >= ref_value + eps && tried_pic[i] == 0) { @@ -50,6 +52,41 @@ int find_max_index(const std::vector& G_plus_H, return max_idx; } +static void checkInputCorrectness(const std::vector& G, + const std::vector& H, + const std::vector& D, + const std::vector& P_max, + const std::vector& P_min, + double initial_level, + double capa, + const std::vector& inflows) +{ + std::string msg_prefix = "Remix hydro input : "; + + // Initial level smaller than capacity + if (initial_level > capa) + { + throw std::invalid_argument(msg_prefix + "initial level > reservoir capacity"); + } + // Arrays sizes must be identical + std::vector sizes = {G.size(), + H.size(), + D.size(), + P_max.size(), + P_min.size(), + inflows.size()}; + if (std::ranges::adjacent_find(sizes, std::not_equal_to()) != sizes.end()) + { + throw std::invalid_argument(msg_prefix + "arrays of different sizes"); + } + + // Arrays are of size 0 + if (!G.size()) + { + throw std::invalid_argument(msg_prefix + "all arrays of sizes 0"); + } +} + std::pair, std::vector> new_remix_hydro( const std::vector& G, const std::vector& H, @@ -58,24 +95,26 @@ std::pair, std::vector> new_remix_hydro( const std::vector& P_min, double initial_level, double capa, - const std::vector& inflow) + const std::vector& inflows) { + checkInputCorrectness(G, H, D, P_max, P_min, initial_level, capa, inflows); + std::vector new_H = H; std::vector new_D = D; int loop = 1000; double eps = 1e-2; - double top = *max_element(G.begin(), G.end()) + *max_element(H.begin(), H.end()) - + *max_element(D.begin(), D.end()) + 1; + double top = *std::max_element(G.begin(), G.end()) + *std::max_element(H.begin(), H.end()) + + *std::max_element(D.begin(), D.end()) + 1; std::vector G_plus_H(G.size()); - transform(G.begin(), G.end(), new_H.begin(), G_plus_H.begin(), std::plus<>()); + std::transform(G.begin(), G.end(), new_H.begin(), G_plus_H.begin(), std::plus<>()); std::vector level(G.size()); - level[0] = initial_level + inflow[0] - new_H[0]; + level[0] = initial_level + inflows[0] - new_H[0]; for (size_t i = 1; i < level.size(); ++i) { - level[i] = level[i - 1] + inflow[i] - new_H[i]; + level[i] = level[i - 1] + inflows[i] - new_H[i]; } while (loop-- > 0) @@ -111,12 +150,12 @@ std::pair, std::vector> new_remix_hydro( double max_pic = std::min(new_H[idx_pic] - P_min[idx_pic], capa - - *max_element(intermediate_level.begin(), - intermediate_level.end())); + - *std::max_element(intermediate_level.begin(), + intermediate_level.end())); double max_creux = std::min( {P_max[idx_creux] - new_H[idx_creux], new_D[idx_creux], - *min_element(intermediate_level.begin(), intermediate_level.end())}); + *std::min_element(intermediate_level.begin(), intermediate_level.end())}); double dif_pic_creux = std::max(G_plus_H[idx_pic] - G_plus_H[idx_creux], 0.0); delta = std::max(std::min({max_pic, max_creux, dif_pic_creux / 2.0}), 0.0); @@ -147,11 +186,11 @@ std::pair, std::vector> new_remix_hydro( break; } - transform(G.begin(), G.end(), new_H.begin(), G_plus_H.begin(), std::plus<>()); - level[0] = initial_level + inflow[0] - new_H[0]; + std::transform(G.begin(), G.end(), new_H.begin(), G_plus_H.begin(), std::plus<>()); + level[0] = initial_level + inflows[0] - new_H[0]; for (size_t i = 1; i < level.size(); ++i) { - level[i] = level[i - 1] + inflow[i] - new_H[i]; + level[i] = level[i - 1] + inflows[i] - new_H[i]; } } diff --git a/src/tests/src/solver/simulation/CMakeLists.txt b/src/tests/src/solver/simulation/CMakeLists.txt index 10ef79b619..be2285170d 100644 --- a/src/tests/src/solver/simulation/CMakeLists.txt +++ b/src/tests/src/solver/simulation/CMakeLists.txt @@ -133,6 +133,7 @@ add_executable(test-hydro-remix target_link_libraries(test-hydro-remix PRIVATE Boost::unit_test_framework + test_utils_unit ) # gp : do we need this ? diff --git a/src/tests/src/solver/simulation/test-hydro-remix.cpp b/src/tests/src/solver/simulation/test-hydro-remix.cpp index 3f90756f0d..e846113bf3 100644 --- a/src/tests/src/solver/simulation/test-hydro-remix.cpp +++ b/src/tests/src/solver/simulation/test-hydro-remix.cpp @@ -2,6 +2,7 @@ #define WIN32_LEAN_AND_MEAN +#include #include #include @@ -21,7 +22,7 @@ std::pair, std::vector> new_remix_hydro( using namespace Antares::Solver::Simulation; -BOOST_AUTO_TEST_CASE(my_first_unit_test) +BOOST_AUTO_TEST_CASE(first_dummy_unit_test___will_be_removed) { std::vector G = {1.0, 2.0, 3.0, 4.0, 5.0}; std::vector H = {2.0, 3.0, 4.0, 5.0, 6.0}; @@ -36,3 +37,47 @@ BOOST_AUTO_TEST_CASE(my_first_unit_test) BOOST_CHECK(true); } + +BOOST_AUTO_TEST_CASE(input_arrays_of_different_sizes__exception_raised) +{ + std::vector G, D, P_max, P_min, inflows; + std::vector H = {0., 0.}; + double initial_level = 0.; + double capa = 0.; + + BOOST_CHECK_EXCEPTION(new_remix_hydro(G, H, D, P_max, P_min, initial_level, capa, inflows), + std::invalid_argument, + checkMessage("Remix hydro input : arrays of different sizes")); +} + +BOOST_AUTO_TEST_CASE(input_init_level_exceeds_capacity__exception_raised) +{ + std::vector G, D, P_max, P_min, inflows; + std::vector H = {0., 0.}; + double initial_level = 2.; + double capa = 1.; + + BOOST_CHECK_EXCEPTION(new_remix_hydro(G, H, D, P_max, P_min, initial_level, capa, inflows), + std::invalid_argument, + checkMessage("Remix hydro input : initial level > reservoir capacity")); +} + +BOOST_AUTO_TEST_CASE(all_input_arrays_of_size_0__exception_raised) +{ + std::vector G, H, D, P_max, P_min, inflows; + double initial_level = 0.; + double capa = 1.; + + BOOST_CHECK_EXCEPTION(new_remix_hydro(G, H, D, P_max, P_min, initial_level, capa, inflows), + std::invalid_argument, + checkMessage("Remix hydro input : all arrays of sizes 0")); +} + +BOOST_AUTO_TEST_CASE(input_is_acceptable__no_exception_raised) +{ + std::vector G = {0.}, H = {0.}, D = {0.}, P_max = {0.}, P_min = {0.}, inflows = {0.}; + double initial_level = 0.; + double capa = 1.; + + BOOST_CHECK_NO_THROW(new_remix_hydro(G, H, D, P_max, P_min, initial_level, capa, inflows)); +}