-
Notifications
You must be signed in to change notification settings - Fork 24
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
Merged
Merged
Changes from all commits
Commits
Show all changes
45 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 da27cb9
New hydro remix : adding test on invariance where S + DTG_MRG > 0
guilpier-code 91e0a0a
New hydro remix : renaming algorithm input data
guilpier-code c02210a
New hydro remix : renaming algorithm input data (part 2)
guilpier-code 7d71f04
New hydro remix : unit tests - renaming algorithm input data
guilpier-code 237940e
New hydro remix : unit tests - renaming algorithm input data (part 2)
guilpier-code 47af157
Merge remote-tracking branch 'remotes/origin/develop' into feature/ne…
guilpier-code 8ce9f25
New hydro remix : some more renaming
guilpier-code 65102e2
fix vcpkg
flomnes 41a811a
New hydro remix : more renaming
guilpier-code bd8d62d
New hydro remix : small correction on algorithm initialization
guilpier-code 511435a
New hydro remix : renaming the algorithm itself
guilpier-code 37bb2be
New hydro remix : create a cmake target for remix hydro algorithm
guilpier-code a4a68ac
New hydro remix : renaming locally in algorithm
guilpier-code 2309099
New hydro remix : more algorithm local renaming
guilpier-code 1e51fa2
New hydro remix : renaming
guilpier-code b7107fa
[skip ci] New hydro remix : tiny correction due to review
guilpier-code d06eeae
New hydro remix : adding a test for comparison with python script
guilpier-code 42352d1
[skip ci] New hydro remix : renaming mainly
guilpier-code 35c4800
Small improvements for hydro remix (#2570)
flomnes 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
29 changes: 29 additions & 0 deletions
29
src/solver/simulation/include/antares/solver/simulation/shave-peaks-by-remix-hydro.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> HydroGen; | ||
std::vector<double> UnsupE; | ||
std::vector<double> levels; | ||
}; | ||
|
||
RemixHydroOutput shavePeaksByRemixingHydro(const std::vector<double>& DispatchGen, | ||
const std::vector<double>& HydroGen, | ||
const std::vector<double>& UnsupE, | ||
const std::vector<double>& HydroPmax, | ||
const std::vector<double>& HydroPmin, | ||
double init_level, | ||
double capacity, | ||
const std::vector<double>& inflow, | ||
const std::vector<double>& overflow, | ||
const std::vector<double>& pump, | ||
const std::vector<double>& Spillage, | ||
const std::vector<double>& DTG_MRG); | ||
|
||
} // namespace Antares::Solver::Simulation |
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,309 @@ | ||
#include "include/antares/solver/simulation/shave-peaks-by-remix-hydro.h" | ||
|
||
#include <algorithm> | ||
#include <ranges> | ||
#include <stdexcept> | ||
#include <vector> | ||
|
||
namespace Antares::Solver::Simulation | ||
{ | ||
|
||
int find_min_index(const std::vector<double>& TotalGen, | ||
const std::vector<double>& OutUnsupE, | ||
const std::vector<double>& OutHydroGen, | ||
const std::vector<bool>& triedBottom, | ||
const std::vector<double>& HydroPmax, | ||
const std::vector<bool>& enabledHours, | ||
double top) | ||
{ | ||
double min_val = top; | ||
int min_hour = -1; | ||
for (unsigned int h = 0; h < TotalGen.size(); ++h) | ||
{ | ||
if (OutUnsupE[h] > 0 && OutHydroGen[h] < HydroPmax[h] && !triedBottom[h] && enabledHours[h]) | ||
{ | ||
if (TotalGen[h] < min_val) | ||
{ | ||
min_val = TotalGen[h]; | ||
min_hour = h; | ||
} | ||
} | ||
} | ||
return min_hour; | ||
} | ||
|
||
int find_max_index(const std::vector<double>& TotalGen, | ||
const std::vector<double>& OutHydroGen, | ||
const std::vector<bool>& triedPeak, | ||
const std::vector<double>& HydroPmin, | ||
const std::vector<bool>& enabledHours, | ||
double ref_value, | ||
double eps) | ||
{ | ||
double max_val = 0; | ||
int max_hour = -1; | ||
for (unsigned int h = 0; h < TotalGen.size(); ++h) | ||
{ | ||
if (OutHydroGen[h] > HydroPmin[h] && TotalGen[h] >= ref_value + eps && !triedPeak[h] | ||
&& enabledHours[h]) | ||
{ | ||
if (TotalGen[h] > max_val) | ||
{ | ||
max_val = TotalGen[h]; | ||
max_hour = h; | ||
} | ||
} | ||
} | ||
return max_hour; | ||
} | ||
|
||
static bool operator<=(const std::vector<double>& a, const std::vector<double>& b) | ||
{ | ||
return a.size() == b.size() | ||
&& std::ranges::all_of(std::views::iota(size_t{0}, a.size()), | ||
[&](size_t i) { return a[i] <= b[i]; }); | ||
} | ||
|
||
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>& DispatchGen, | ||
const std::vector<double>& HydroGen, | ||
const std::vector<double>& UnsupE, | ||
const std::vector<double>& levels, | ||
const std::vector<double>& HydroPmax, | ||
const std::vector<double>& HydroPmin, | ||
double initial_level, | ||
double capacity, | ||
const std::vector<double>& inflows, | ||
const std::vector<double>& overflow, | ||
const std::vector<double>& pump, | ||
const std::vector<double>& Spillage, | ||
const std::vector<double>& DTG_MRG) | ||
{ | ||
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 = {DispatchGen.size(), | ||
HydroGen.size(), | ||
UnsupE.size(), | ||
levels.size(), | ||
HydroPmax.size(), | ||
HydroPmin.size(), | ||
inflows.size(), | ||
overflow.size(), | ||
pump.size(), | ||
Spillage.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 (!DispatchGen.size()) | ||
{ | ||
throw std::invalid_argument(msg_prefix + "all arrays of sizes 0"); | ||
} | ||
|
||
// Hydro production < Pmax | ||
if (!(HydroGen <= HydroPmax)) | ||
{ | ||
throw std::invalid_argument(msg_prefix | ||
+ "Hydro generation not smaller than Pmax everywhere"); | ||
} | ||
|
||
// Hydro production > Pmin | ||
if (!(HydroPmin <= HydroGen)) | ||
{ | ||
throw std::invalid_argument(msg_prefix | ||
+ "Hydro generation 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 shavePeaksByRemixingHydro(const std::vector<double>& DispatchGen, | ||
const std::vector<double>& HydroGen, | ||
const std::vector<double>& UnsupE, | ||
const std::vector<double>& HydroPmax, | ||
const std::vector<double>& HydroPmin, | ||
double initial_level, | ||
double capa, | ||
const std::vector<double>& inflows, | ||
const std::vector<double>& overflow, | ||
const std::vector<double>& pump, | ||
const std::vector<double>& Spillage, | ||
const std::vector<double>& DTG_MRG) | ||
{ | ||
std::vector<double> levels(DispatchGen.size()); | ||
if (!levels.empty()) | ||
{ | ||
levels[0] = initial_level + inflows[0] - overflow[0] + pump[0] - HydroGen[0]; | ||
for (size_t h = 1; h < levels.size(); ++h) | ||
{ | ||
levels[h] = levels[h - 1] + inflows[h] - overflow[h] + pump[h] - HydroGen[h]; | ||
} | ||
} | ||
|
||
checkInputCorrectness(DispatchGen, | ||
HydroGen, | ||
UnsupE, | ||
levels, | ||
HydroPmax, | ||
HydroPmin, | ||
initial_level, | ||
capa, | ||
inflows, | ||
overflow, | ||
pump, | ||
Spillage, | ||
DTG_MRG); | ||
|
||
std::vector<double> OutHydroGen = HydroGen; | ||
std::vector<double> OutUnsupE = UnsupE; | ||
|
||
int loop = 1000; | ||
double eps = 1e-3; | ||
double top = *std::max_element(DispatchGen.begin(), DispatchGen.end()) | ||
+ *std::max_element(HydroGen.begin(), HydroGen.end()) | ||
+ *std::max_element(UnsupE.begin(), UnsupE.end()) + 1; | ||
|
||
std::vector<bool> enabledHours(DispatchGen.size(), false); | ||
for (unsigned int h = 0; h < enabledHours.size(); h++) | ||
{ | ||
if (Spillage[h] + DTG_MRG[h] == 0. && HydroGen[h] + UnsupE[h] > 0.) | ||
{ | ||
enabledHours[h] = true; | ||
} | ||
} | ||
|
||
std::vector<double> TotalGen(DispatchGen.size()); | ||
std::transform(DispatchGen.begin(), | ||
DispatchGen.end(), | ||
HydroGen.begin(), | ||
TotalGen.begin(), | ||
std::plus<>()); | ||
|
||
while (loop-- > 0) | ||
{ | ||
std::vector<bool> triedBottom(DispatchGen.size(), false); | ||
double delta = 0; | ||
|
||
while (true) | ||
{ | ||
int hourBottom = find_min_index(TotalGen, | ||
OutUnsupE, | ||
OutHydroGen, | ||
triedBottom, | ||
HydroPmax, | ||
enabledHours, | ||
top); | ||
if (hourBottom == -1) | ||
{ | ||
break; | ||
} | ||
|
||
std::vector<bool> triedPeak(DispatchGen.size(), false); | ||
while (true) | ||
{ | ||
int hourPeak = find_max_index(TotalGen, | ||
OutHydroGen, | ||
triedPeak, | ||
HydroPmin, | ||
enabledHours, | ||
TotalGen[hourBottom], | ||
eps); | ||
if (hourPeak == -1) | ||
{ | ||
break; | ||
} | ||
|
||
std::vector<double> intermediate_level(levels.begin() | ||
+ std::min(hourBottom, hourPeak), | ||
levels.begin() | ||
+ std::max(hourBottom, hourPeak)); | ||
double max_pic, max_creux; | ||
if (hourBottom < hourPeak) | ||
{ | ||
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(OutHydroGen[hourPeak] - HydroPmin[hourPeak], max_pic); | ||
max_creux = std::min({HydroPmax[hourBottom] - OutHydroGen[hourBottom], | ||
OutUnsupE[hourBottom], | ||
max_creux}); | ||
|
||
double dif_pic_creux = std::max(TotalGen[hourPeak] - TotalGen[hourBottom], 0.); | ||
|
||
delta = std::max(std::min({max_pic, max_creux, dif_pic_creux / 2.}), 0.); | ||
|
||
if (delta > 0) | ||
{ | ||
OutHydroGen[hourPeak] -= delta; | ||
OutHydroGen[hourBottom] += delta; | ||
OutUnsupE[hourPeak] = HydroGen[hourPeak] + UnsupE[hourPeak] | ||
- OutHydroGen[hourPeak]; | ||
OutUnsupE[hourBottom] = HydroGen[hourBottom] + UnsupE[hourBottom] | ||
- OutHydroGen[hourBottom]; | ||
break; | ||
} | ||
else | ||
{ | ||
triedPeak[hourPeak] = true; | ||
} | ||
} | ||
|
||
if (delta > 0) | ||
{ | ||
break; | ||
} | ||
triedBottom[hourBottom] = true; | ||
} | ||
|
||
if (delta == 0) | ||
{ | ||
break; | ||
} | ||
|
||
std::transform(DispatchGen.begin(), | ||
DispatchGen.end(), | ||
OutHydroGen.begin(), | ||
TotalGen.begin(), | ||
std::plus<>()); | ||
levels[0] = initial_level + inflows[0] - overflow[0] + pump[0] - OutHydroGen[0]; | ||
for (size_t h = 1; h < levels.size(); ++h) | ||
{ | ||
levels[h] = levels[h - 1] + inflows[h] - overflow[h] + pump[h] - OutHydroGen[h]; | ||
} | ||
} | ||
return {OutHydroGen, OutUnsupE, levels}; | ||
} | ||
|
||
} // End 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.
🥇