-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New hydro remix algorithm #2532
Draft
guilpier-code
wants to merge
26
commits into
develop
Choose a base branch
from
feature/new-hydro-remix
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+1,001
−49
Draft
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
6871e98
New hydro remix : setting unit tests environment
guilpier-code 33a96ea
New hydro remix : some cleaning
guilpier-code e40b32f
New hydro remix : unit tests on input data
guilpier-code 34f0ed7
New hydro remix : add unit test > pmax is supposed to limit hydro gen…
guilpier-code cba01ee
New hydro remix : adding tests on Pmax respect
guilpier-code 9f41dc1
New hydro remix : Hydro must respect condition H <= Pmax in input of …
guilpier-code a52aa7b
New hydro remix : adding a test on influence of Pmax
guilpier-code 52b04e0
New hydro remix : adding a test on influence of Pmin
guilpier-code 56ab22d
New hydro remix : Pmin & Pmax unit tests enhancement
guilpier-code 548fc1f
New hydro remix : change the algorithm due to new specifications
guilpier-code f3708e2
New hydro remix : adding 2 unit tests on levels computation
guilpier-code 4c8d407
New hydro remix : improve comparison between 2 std::vector<double>
guilpier-code 88dd5ae
New hydro remix : make a test rightfully fail
guilpier-code d3a24ef
New hydro remix : adding unit tests on levels computed from input data
guilpier-code cd35bdb
New hydro remix : adding a failing test about of impact reservoir cap…
guilpier-code f7757b1
New hydro remix : change algorithm to try to fix a test failure
guilpier-code ea7e23f
New hydro remix : oops, tiny fix
guilpier-code 6ed6f62
New hydro remix : fix the previous fix
guilpier-code adb89a7
New hydro remix : adding a unit test on getting a sub optimal solutio…
guilpier-code 72f75e4
New hydro remix : adding a unit test about the effect of lowering ini…
guilpier-code 08bbd70
New hydro remix : adding test that case where initial level has no in…
guilpier-code f0854dd
New hydro remix : creating a header for remix hydro algorithm
guilpier-code 4685abb
New hydro remix : define and use proper comparison operator when chec…
guilpier-code 957cd5b
[skip ci] New hydro remix : replace use of std::adjacent_find with us…
guilpier-code 6157f34
[skip ci] New hydro remix : make code comment more clear
guilpier-code 889b982
New hydro remix : improve unit tests by use of a fixture
guilpier-code File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,295 @@ | ||
#include "include/antares/solver/simulation/hydro-remix-new.h" | ||
|
||
#include <algorithm> | ||
#include <ranges> | ||
#include <stdexcept> | ||
#include <vector> | ||
|
||
namespace Antares::Solver::Simulation | ||
{ | ||
|
||
int find_min_index(const std::vector<double>& G_plus_H, | ||
const std::vector<double>& new_D, | ||
const std::vector<double>& new_H, | ||
const std::vector<int>& tried_creux, | ||
const std::vector<double>& P_max, | ||
const std::vector<bool>& filter_hours_remix, | ||
double top) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unclear naming |
||
{ | ||
double min_val = top; | ||
int min_idx = -1; | ||
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 && filter_hours_remix[i]) | ||
{ | ||
if (G_plus_H[i] < min_val) | ||
{ | ||
min_val = G_plus_H[i]; | ||
min_idx = i; | ||
} | ||
} | ||
} | ||
return min_idx; | ||
} | ||
|
||
int find_max_index(const std::vector<double>& G_plus_H, | ||
const std::vector<double>& new_H, | ||
const std::vector<int>& tried_pic, | ||
const std::vector<double>& P_min, | ||
const std::vector<bool>& filter_hours_remix, | ||
double ref_value, | ||
double eps) | ||
{ | ||
double max_val = 0; | ||
int max_idx = -1; | ||
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 | ||
&& filter_hours_remix[i]) | ||
{ | ||
if (G_plus_H[i] > max_val) | ||
{ | ||
max_val = G_plus_H[i]; | ||
max_idx = i; | ||
} | ||
} | ||
} | ||
return max_idx; | ||
} | ||
|
||
static bool operator<=(const std::vector<double>& a, const std::vector<double>& b) | ||
{ | ||
std::vector<double> a_minus_b; | ||
std::ranges::transform(a, b, std::back_inserter(a_minus_b), std::minus<double>()); | ||
return std::ranges::all_of(a_minus_b, [](const double& e) { return e <= 0.; }); | ||
} | ||
|
||
static bool operator<=(const std::vector<double>& v, const double c) | ||
{ | ||
return std::ranges::all_of(v, [&c](const double& e) { return e <= c; }); | ||
} | ||
|
||
static bool operator>=(const std::vector<double>& v, const double c) | ||
{ | ||
return std::ranges::all_of(v, [&c](const double& e) { return e >= c; }); | ||
} | ||
|
||
static void checkInputCorrectness(const std::vector<double>& G, | ||
const std::vector<double>& H, | ||
const std::vector<double>& D, | ||
const std::vector<double>& levels, | ||
const std::vector<double>& P_max, | ||
const std::vector<double>& P_min, | ||
double initial_level, | ||
double capacity, | ||
const std::vector<double>& inflows, | ||
const std::vector<double>& overflow, | ||
const std::vector<double>& pump, | ||
const std::vector<double>& S, | ||
const std::vector<double>& DTG_MRG) | ||
Comment on lines
+77
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
std::string msg_prefix = "Remix hydro input : "; | ||
|
||
// Initial level smaller than capacity | ||
if (initial_level > capacity) | ||
{ | ||
throw std::invalid_argument(msg_prefix + "initial level > reservoir capacity"); | ||
} | ||
// Arrays sizes must be identical | ||
std::vector<size_t> sizes = {G.size(), | ||
H.size(), | ||
D.size(), | ||
levels.size(), | ||
P_max.size(), | ||
P_min.size(), | ||
inflows.size(), | ||
overflow.size(), | ||
pump.size(), | ||
S.size(), | ||
DTG_MRG.size()}; | ||
|
||
if (!std::ranges::all_of(sizes, [&sizes](const size_t s) { return s == sizes.front(); })) | ||
{ | ||
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"); | ||
} | ||
|
||
// Hydro production < Pmax | ||
if (!(H <= P_max)) | ||
{ | ||
throw std::invalid_argument(msg_prefix + "H not smaller than Pmax everywhere"); | ||
} | ||
|
||
// Hydro production > Pmin | ||
if (!(P_min <= H)) | ||
{ | ||
throw std::invalid_argument(msg_prefix + "H not greater than Pmin everywhere"); | ||
} | ||
|
||
if (!(levels <= capacity) || !(levels >= 0.)) | ||
{ | ||
throw std::invalid_argument(msg_prefix | ||
+ "levels computed from input don't respect reservoir bounds"); | ||
} | ||
} | ||
|
||
RemixHydroOutput new_remix_hydro(const std::vector<double>& G, | ||
const std::vector<double>& H, | ||
const std::vector<double>& D, | ||
const std::vector<double>& P_max, | ||
const std::vector<double>& P_min, | ||
double initial_level, | ||
double capa, | ||
const std::vector<double>& inflows, | ||
const std::vector<double>& overflow, | ||
const std::vector<double>& pump, | ||
const std::vector<double>& S, | ||
const std::vector<double>& DTG_MRG) | ||
{ | ||
std::vector<double> levels(G.size()); | ||
if (levels.size()) | ||
{ | ||
levels[0] = initial_level + inflows[0] - overflow[0] + pump[0] - H[0]; | ||
for (size_t i = 1; i < levels.size(); ++i) | ||
{ | ||
levels[i] = levels[i - 1] + inflows[i] - overflow[i] + pump[i] - H[i]; | ||
} | ||
} | ||
|
||
checkInputCorrectness(G, | ||
H, | ||
D, | ||
levels, | ||
P_max, | ||
P_min, | ||
initial_level, | ||
capa, | ||
inflows, | ||
overflow, | ||
pump, | ||
S, | ||
DTG_MRG); | ||
|
||
std::vector<double> new_H = H; | ||
std::vector<double> new_D = D; | ||
|
||
int loop = 1000; | ||
double eps = 1e-3; | ||
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<bool> filter_hours_remix(G.size(), false); | ||
for (unsigned int h = 0; h < filter_hours_remix.size(); h++) | ||
{ | ||
if (S[h] + DTG_MRG[h] == 0. && H[h] + D[h] > 0.) | ||
{ | ||
filter_hours_remix[h] = true; | ||
} | ||
} | ||
|
||
std::vector<double> G_plus_H(G.size()); | ||
std::transform(G.begin(), G.end(), new_H.begin(), G_plus_H.begin(), std::plus<>()); | ||
|
||
while (loop-- > 0) | ||
{ | ||
std::vector<int> tried_creux(G.size(), 0); | ||
double delta = 0; | ||
|
||
while (true) | ||
{ | ||
int idx_creux = find_min_index(G_plus_H, | ||
new_D, | ||
new_H, | ||
tried_creux, | ||
P_max, | ||
filter_hours_remix, | ||
top); | ||
if (idx_creux == -1) | ||
{ | ||
break; | ||
} | ||
|
||
std::vector<int> tried_pic(G.size(), 0); | ||
while (true) | ||
{ | ||
int idx_pic = find_max_index(G_plus_H, | ||
new_H, | ||
tried_pic, | ||
P_min, | ||
filter_hours_remix, | ||
G_plus_H[idx_creux], | ||
eps); | ||
if (idx_pic == -1) | ||
{ | ||
break; | ||
} | ||
|
||
std::vector<double> intermediate_level(levels.begin() | ||
+ std::min(idx_creux, idx_pic), | ||
levels.begin() | ||
+ std::max(idx_creux, idx_pic)); | ||
double max_pic, max_creux; | ||
if (idx_creux < idx_pic) | ||
{ | ||
max_pic = capa; | ||
max_creux = *std::min_element(intermediate_level.begin(), | ||
intermediate_level.end()); | ||
} | ||
else | ||
{ | ||
max_pic = capa | ||
- *std::max_element(intermediate_level.begin(), | ||
intermediate_level.end()); | ||
max_creux = capa; | ||
} | ||
|
||
max_pic = std::min(new_H[idx_pic] - P_min[idx_pic], max_pic); | ||
max_creux = std::min( | ||
{P_max[idx_creux] - new_H[idx_creux], new_D[idx_creux], max_creux}); | ||
|
||
double dif_pic_creux = std::max(G_plus_H[idx_pic] - G_plus_H[idx_creux], 0.); | ||
|
||
delta = std::max(std::min({max_pic, max_creux, dif_pic_creux / 2.}), 0.); | ||
|
||
if (delta > 0) | ||
{ | ||
new_H[idx_pic] -= delta; | ||
new_H[idx_creux] += delta; | ||
new_D[idx_pic] = H[idx_pic] + D[idx_pic] - new_H[idx_pic]; | ||
new_D[idx_creux] = H[idx_creux] + D[idx_creux] - new_H[idx_creux]; | ||
break; | ||
} | ||
else | ||
{ | ||
tried_pic[idx_pic] = 1; | ||
} | ||
} | ||
|
||
if (delta > 0) | ||
{ | ||
break; | ||
} | ||
tried_creux[idx_creux] = 1; | ||
} | ||
|
||
if (delta == 0) | ||
{ | ||
break; | ||
} | ||
|
||
std::transform(G.begin(), G.end(), new_H.begin(), G_plus_H.begin(), std::plus<>()); | ||
levels[0] = initial_level + inflows[0] - overflow[0] + pump[0] - new_H[0]; | ||
for (size_t i = 1; i < levels.size(); ++i) | ||
{ | ||
levels[i] = levels[i - 1] + inflows[i] - overflow[i] + pump[i] - new_H[i]; | ||
} | ||
} | ||
return {new_H, new_D, levels}; | ||
} | ||
|
||
} // End namespace Antares::Solver::Simulation |
29 changes: 29 additions & 0 deletions
29
src/solver/simulation/include/antares/solver/simulation/hydro-remix-new.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
|
||
#pragma once | ||
|
||
#include <vector> | ||
|
||
namespace Antares::Solver::Simulation | ||
{ | ||
|
||
struct RemixHydroOutput | ||
{ | ||
std::vector<double> new_H; | ||
std::vector<double> new_D; | ||
std::vector<double> levels; | ||
}; | ||
|
||
RemixHydroOutput new_remix_hydro(const std::vector<double>& G, | ||
const std::vector<double>& H, | ||
const std::vector<double>& D, | ||
const std::vector<double>& P_max, | ||
const std::vector<double>& P_min, | ||
double init_level, | ||
double capacity, | ||
const std::vector<double>& inflow, | ||
const std::vector<double>& overflow, | ||
const std::vector<double>& pump, | ||
const std::vector<double>& S, | ||
const std::vector<double>& DTG_MRG); | ||
|
||
} // namespace Antares::Solver::Simulation |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unclear naming