Skip to content
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

[ANT-992] Add ramping for thermal clusters #1817

Draft
wants to merge 26 commits into
base: develop
Choose a base branch
from

Conversation

bencamus
Copy link
Collaborator

@bencamus bencamus commented Dec 11, 2023

This code implement the thermal ramping model in Antares.
The remaining works are:

  • validate the equation of the constraints (the specification might be improved).
  • validate the constraint implementation for the first hour of each week (currently it is cyclical as the evolution of the production for the first hour is constrained the production of the last hour).
  • initialise by default the upward and downward power ramp to +inf (or any large value compliant with the optimization solver).
  • define and integrate unit tests for the thermal ramping.
  • validate the implementation with a sound use case.
  • validate the integration with the Antares Web GUI.

Copy link

watermelon-copilot-for-code-review bot commented Dec 11, 2023

Watermelon AI Summary

AI Summary deactivated by bencamus

GitHub PRs

Antares_Simulator is an open repo and Watermelon will serve it for free.
🍉🫶

{
logs.error() << "Thermal cluster: " << parentArea->name << '/' << pName
<< ": The maximum upward power ramping rate must greater than zero.";
maxUpwardPowerRampingRate = 1.;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would be helpful to print the fallback value;
also it seems that the return value is never used

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, with commit 8133150, the ramping is disabled in this case, and this information is printed.

@@ -58,6 +58,25 @@ ConstraintBuilder& ConstraintBuilder::DispatchableProduction(unsigned int index,
int delta)
{
AddVariable(GetVariableManager(offset, delta).DispatchableProduction(index), coeff);
// logs.info() << "dispatchable production idx " << GetVariableManager(offset, delta).DispatchableProduction(index);
return *this;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove debug comments

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed in commit 624f2ce

src/libs/antares/study/parts/thermal/cluster.cpp Outdated Show resolved Hide resolved
src/libs/antares/study/parts/thermal/cluster.cpp Outdated Show resolved Hide resolved
src/libs/antares/study/parts/thermal/cluster.cpp Outdated Show resolved Hide resolved
src/libs/antares/study/parts/thermal/cluster.cpp Outdated Show resolved Hide resolved
Comment on lines 423 to 424
s->add("max-upward-power-ramping-rate", Math::Round(c.maxUpwardPowerRampingRate, 3));
if (not Math::Zero(c.maxDownwardPowerRampingRate))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Math is part of Yuni, which is deprecated. Please use STL functions instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed by commit 915e0c7

Comment on lines 43 to 46
int add = (pdt == 0) ? 4 : 5;
problemeHebdo->NbTermesContraintesPourLesRampes += add;
problemeHebdo->ProblemeAResoudre->NombreDeContraintes++;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be checked carefully

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with commit 624f2ce, the ramping constraints become cyclical (the evolution of the production for the first hour is constrained the production of the last hour). Then, we don't need to use a constraint for the first time step that is different from the other time steps anymore. This code is now removed.

Comment on lines 11 to 20
if (pdt > 0)
{
builder.updateHourWithinWeek(pdt)
.DispatchableProduction(cluster, 1.0)
.DispatchableProduction(cluster, -1.0, -1, problemeHebdo->NombreDePasDeTempsPourUneOptimisation)
.NumberOfDispatchableUnits(cluster, maxDownwardPowerRampingRate)
.NumberStoppingDispatchableUnits(cluster, pmaxDUnGroupeDuPalierThermique)
.NumberBreakingDownDispatchableUnits(cluster, pmaxDUnGroupeDuPalierThermique)
.greaterThan();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need this if..else since DispatchableProduction has arguments to take this into account.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, commit 624f2ce fixed this.

@@ -0,0 +1,47 @@
#include "RampingIncreaseRate.h"

void RampingIncreaseRate::add(int pays, int cluster, int clusterIndex, int pdt, bool Simulation)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may define a class both for RampingIncreaseRate and RampingDecreaseRate. With a pure virtual method for behaviors that differ, e.g

-.NumberOfDispatchableUnits(cluster, -maxUpwardPowerRampingRate)
-.NumberStartingDispatchableUnits(cluster, -pminDUnGroupeDuPalierThermique)
+.NumberStoppingDispatchableUnits(cluster, pmaxDUnGroupeDuPalierThermique)
+.NumberBreakingDownDispatchableUnits(cluster, pmaxDUnGroupeDuPalierThermique)

See https://refactoring.guru/design-patterns/template-method

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pending until the constraint equations are validated

Copy link
Member

@flomnes flomnes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that 0 is not a suitable value for maxDownwardPowerRampingRate, consider choosing a different default value.

Copy link
Member

@flomnes flomnes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggestion : add ON/OFF (bool, default = OFF) for ramping in every cluster

@a-zakir
Copy link
Contributor

a-zakir commented Dec 13, 2023

Please add test(s) for the newly constraints at least in "named-mps" tests, let me know if i can be of any help

@flomnes flomnes force-pushed the feature/ramping_model_scalian branch from c4cd709 to 09a2ca9 Compare December 18, 2023 20:55
@@ -137,7 +137,8 @@ Data::ThermalCluster::ThermalCluster(Area* parent) :
forcedLaw(thermalLawUniform),
plannedLaw(thermalLawUniform),
PthetaInf(HOURS_PER_YEAR, 0),
costsTimeSeries(1, CostsTimeSeries())
costsTimeSeries(1, CostsTimeSeries()),
ramping()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constructor is called by default, there is no need to call it explicitly here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed in commit 77daa36

bool checkValidity(Area* area, Data::ClusterName clusterName);
friend std::ostream& operator<<(std::ostream&, const Ramping& ramping);
};
Ramping ramping;
Copy link
Member

@flomnes flomnes Dec 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Ramping ramping;
std::optional<Ramping> ramping;

By default, the ramping constraints are not enabled for a given cluster. They are enabled only if an object exists within this std::optional.

Possible justification : there is no good default value for maxUpwardPowerRampingRate and maxDownwardPowerRampingRate, ie we can't keep the existing behavior by default, which is very important.

This induces a small difficulty in the variable/constraint counting process, in the sense that we must only take into account cluster for which ramping is enabled.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commit 8133150 implements now is feature

@flomnes flomnes modified the milestones: 9.0, Sprint 2 Feb 9, 2024
bool rampingEnabled = false;
bool attributeOK = rampingEnabledProperty->value.to<bool>(rampingEnabled);
if (rampingEnabled && attributeOK)
cluster.ramping = ThermalCluster::Ramping();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
cluster.ramping = ThermalCluster::Ramping();
cluster.ramping.emplace();

Otherwise the temporary object is constructed and destructed immediately. In-place construction saves one Construction/Destruction, see https://en.cppreference.com/w/cpp/utility/optional/emplace

ProblemeAResoudre->NombreDeVariables
+= problemeHebdo->PaliersThermiquesDuPays[pays].NombreDePaliersThermiques;

ProblemeAResoudre->NombreDeVariables += problemeHebdo->PaliersThermiquesDuPays[pays].NombreDePaliersThermiques;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting, see .clang-format

Comment on lines 309 to 318
pbPalier.upwardRampingCost[nRampingCluster]
= cluster.ramping.value().powerIncreaseCost;
pbPalier.downwardRampingCost[nRampingCluster]
= cluster.ramping.value().powerDecreaseCost;
pbPalier.maxDownwardPowerRampingRate[nRampingCluster]
= cluster.ramping.value().maxDownwardPowerRampingRate;
pbPalier.maxUpwardPowerRampingRate[nRampingCluster]
= cluster.ramping.value().maxUpwardPowerRampingRate;
pbPalier.clusterRampingVariablesIndex[clusterIndex] = nRampingCluster;
nRampingCluster++;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pbPalier.upwardRampingCost[nRampingCluster]
= cluster.ramping.value().powerIncreaseCost;
pbPalier.downwardRampingCost[nRampingCluster]
= cluster.ramping.value().powerDecreaseCost;
pbPalier.maxDownwardPowerRampingRate[nRampingCluster]
= cluster.ramping.value().maxDownwardPowerRampingRate;
pbPalier.maxUpwardPowerRampingRate[nRampingCluster]
= cluster.ramping.value().maxUpwardPowerRampingRate;
pbPalier.clusterRampingVariablesIndex[clusterIndex] = nRampingCluster;
nRampingCluster++;
const auto& ramping = cluster.ramping.value();
pbPalier.upwardRampingCost[nRampingCluster]
= ramping.powerIncreaseCost;
pbPalier.downwardRampingCost[nRampingCluster]
= ramping.powerDecreaseCost;
pbPalier.maxDownwardPowerRampingRate[nRampingCluster]
= ramping.maxDownwardPowerRampingRate;
pbPalier.maxUpwardPowerRampingRate[nRampingCluster]
= ramping.maxUpwardPowerRampingRate;
pbPalier.clusterRampingVariablesIndex[clusterIndex] = nRampingCluster;
nRampingCluster++;

Comment on lines +187 to 190
variablesMapping.powerRampingIncreaseIndex
.assign(study.runtime->thermalPlantTotalCount, 0);
variablesMapping.powerRampingDecreaseIndex
.assign(study.runtime->thermalPlantTotalCount, 0);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default, the variable doesn't exist

Suggested change
variablesMapping.powerRampingIncreaseIndex
.assign(study.runtime->thermalPlantTotalCount, 0);
variablesMapping.powerRampingDecreaseIndex
.assign(study.runtime->thermalPlantTotalCount, 0);
variablesMapping.powerRampingIncreaseIndex
.assign(study.runtime->thermalPlantTotalCount, -1);
variablesMapping.powerRampingDecreaseIndex
.assign(study.runtime->thermalPlantTotalCount, -1);

@flomnes flomnes changed the title Feature/ramping model scalian [ANT-992] Add ramping for thermal clusters Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants