diff --git a/src/libs/antares/study/parts/thermal/cluster.cpp b/src/libs/antares/study/parts/thermal/cluster.cpp index 25297fedda..4ade08ae1f 100644 --- a/src/libs/antares/study/parts/thermal/cluster.cpp +++ b/src/libs/antares/study/parts/thermal/cluster.cpp @@ -138,10 +138,7 @@ Data::ThermalCluster::ThermalCluster(Area* parent) : plannedLaw(thermalLawUniform), PthetaInf(HOURS_PER_YEAR, 0), costsTimeSeries(1, CostsTimeSeries()), - maxUpwardPowerRampingRate(0.), - maxDownwardPowerRampingRate(0.), - powerIncreaseCost(0.), - powerDecreaseCost(0.) + ramping() { // assert assert(parent and "A parent for a thermal dispatchable cluster can not be null"); @@ -187,10 +184,7 @@ void Data::ThermalCluster::copyFrom(const ThermalCluster& cluster) minDownTime = cluster.minDownTime; // ramping - maxUpwardPowerRampingRate = cluster.maxUpwardPowerRampingRate; - maxDownwardPowerRampingRate = cluster.maxDownwardPowerRampingRate; - powerDecreaseCost = cluster.powerDecreaseCost; - powerIncreaseCost = cluster.powerIncreaseCost; + ramping = cluster.ramping; // spinning spinning = cluster.spinning; @@ -489,11 +483,9 @@ void Data::ThermalCluster::reset() marketBidCost = 0.; variableomcost = 0.; costsTimeSeries.resize(1, CostsTimeSeries()); - powerIncreaseCost = 0; - powerDecreaseCost = 0; - - maxUpwardPowerRampingRate = 0; - maxDownwardPowerRampingRate = 0; + + // ramping + ramping.reset(); // modulation modulation.resize(thermalModulationMax, HOURS_PER_YEAR); @@ -624,34 +616,7 @@ bool Data::ThermalCluster::integrityCheck() }*/ // ramping - if (maxUpwardPowerRampingRate <= 0) - { - logs.error() << "Thermal cluster: " << parentArea->name << '/' << pName - << ": The maximum upward power ramping rate must greater than zero."; - maxUpwardPowerRampingRate = 1.; - ret = false; - } - if (maxDownwardPowerRampingRate <= 0) - { - logs.error() << "Thermal cluster: " << parentArea->name << '/' << pName - << ": The maximum downward power ramping rate must greater than zero."; - maxDownwardPowerRampingRate = 1.; - ret = false; - } - if (powerIncreaseCost < 0) - { - logs.error() << "Thermal cluster: " << parentArea->name << '/' << pName - << ": The ramping power increase cost must be positive or null."; - powerIncreaseCost = 0.; - ret = false; - } - if (powerDecreaseCost < 0) - { - logs.error() << "Thermal cluster: " << parentArea->name << '/' << pName - << ": The ramping power decrease cost must be positive or null."; - powerDecreaseCost = 0.; - ret = false; - } + ret = ramping.checkValidity(parentArea, pName) && ret; return ret; } @@ -867,5 +832,48 @@ bool ThermalCluster::isActive() const { return enabled && !mustrun; } +void ThermalCluster::Ramping::reset() +{ + powerIncreaseCost = 0; + powerDecreaseCost = 0; + maxUpwardPowerRampingRate = 0; + maxDownwardPowerRampingRate = 0; +} + +bool ThermalCluster::Ramping::checkValidity(Area* parentArea, Data::ClusterName clusterName) +{ + bool ret = true; + + if (maxUpwardPowerRampingRate <= 0) + { + logs.error() << "Thermal cluster: " << parentArea->name << '/' << clusterName + << ": The maximum upward power ramping rate must greater than zero."; + maxUpwardPowerRampingRate = 1.; + ret = false; + } + if (maxDownwardPowerRampingRate <= 0) + { + logs.error() << "Thermal cluster: " << parentArea->name << '/' << clusterName + << ": The maximum downward power ramping rate must greater than zero."; + maxDownwardPowerRampingRate = 1.; + ret = false; + } + if (powerIncreaseCost < 0) + { + logs.error() << "Thermal cluster: " << parentArea->name << '/' << clusterName + << ": The ramping power increase cost must be positive or null."; + powerIncreaseCost = 0.; + ret = false; + } + if (powerDecreaseCost < 0) + { + logs.error() << "Thermal cluster: " << parentArea->name << '/' << clusterName + << ": The ramping power decrease cost must be positive or null."; + powerDecreaseCost = 0.; + ret = false; + } + return ret; +} + } // namespace Data } // namespace Antares diff --git a/src/libs/antares/study/parts/thermal/cluster.h b/src/libs/antares/study/parts/thermal/cluster.h index a9a9705363..c27e70473d 100644 --- a/src/libs/antares/study/parts/thermal/cluster.h +++ b/src/libs/antares/study/parts/thermal/cluster.h @@ -340,15 +340,30 @@ class ThermalCluster final : public Cluster, public std::enable_shared_from_this double marketBidCost = 0; //! Variable O&M cost (euros/MWh) double variableomcost = 0; - //! Cost of power increase (euros/MW) - double powerIncreaseCost = 0; - //! Cost of power decrease (euros/MW) - double powerDecreaseCost = 0; - - //! Maximum hourly upward power ramping rate (MW/hour) - double maxUpwardPowerRampingRate = 0; - //! Maximum hourly downward power ramping rate (MW/hour) - double maxDownwardPowerRampingRate = 0; + + struct Ramping + { + //! Cost of power increase (euros/MW) + double powerIncreaseCost; + //! Cost of power decrease (euros/MW) + double powerDecreaseCost; + //! Maximum hourly upward power ramping rate (MW/hour) + double maxUpwardPowerRampingRate; + //! Maximum hourly downward power ramping rate (MW/hour) + double maxDownwardPowerRampingRate; + + Ramping() : + powerIncreaseCost(0.), + powerDecreaseCost(0.), + maxUpwardPowerRampingRate(0.), + maxDownwardPowerRampingRate(0.) + { + } + + void reset(); + bool checkValidity(Area* area, Data::ClusterName clusterName); + }; + Ramping ramping; //@} diff --git a/src/libs/antares/study/parts/thermal/cluster_list.cpp b/src/libs/antares/study/parts/thermal/cluster_list.cpp index b5320be9d8..9ba5d025fd 100644 --- a/src/libs/antares/study/parts/thermal/cluster_list.cpp +++ b/src/libs/antares/study/parts/thermal/cluster_list.cpp @@ -223,13 +223,13 @@ static bool ThermalClusterLoadFromProperty(ThermalCluster& cluster, const IniFil return p->value.to(cluster.startupCost); if (p->key == "power-increase-cost") - return p->value.to(cluster.powerIncreaseCost); + return p->value.to(cluster.ramping.powerIncreaseCost); if (p->key == "power-decrease-cost") - return p->value.to(cluster.powerDecreaseCost); + return p->value.to(cluster.ramping.powerDecreaseCost); if (p->key == "max-upward-power-ramping-rate") - return p->value.to(cluster.maxUpwardPowerRampingRate); + return p->value.to(cluster.ramping.maxUpwardPowerRampingRate); if (p->key == "max-downward-power-ramping-rate") - return p->value.to(cluster.maxDownwardPowerRampingRate); + return p->value.to(cluster.ramping.maxDownwardPowerRampingRate); if (p->key == "unitcount") return p->value.to(cluster.unitCount); @@ -415,14 +415,16 @@ bool ThermalClusterList::saveToFolder(const AnyString& folder) const s->add("variableomcost", Math::Round(c.variableomcost,3)); // ramping - if (c.powerIncreaseCost != 0) - s->add("power-increase-cost", Math::Round(c.powerIncreaseCost, 3)); - if (c.powerDecreaseCost != 0) - s->add("power-decrease-cost", Math::Round(c.powerDecreaseCost, 3)); - if (c.maxUpwardPowerRampingRate != 0) - s->add("max-upward-power-ramping-rate", Math::Round(c.maxUpwardPowerRampingRate, 3)); - if (c.maxDownwardPowerRampingRate != 0) - s->add("max-downward-power-ramping-rate", Math::Round(c.maxDownwardPowerRampingRate, 3)); + if (c.ramping.powerIncreaseCost != 0) + s->add("power-increase-cost", Math::Round(c.ramping.powerIncreaseCost, 3)); + if (c.ramping.powerDecreaseCost != 0) + s->add("power-decrease-cost", Math::Round(c.ramping.powerDecreaseCost, 3)); + if (c.ramping.maxUpwardPowerRampingRate != 0) + s->add("max-upward-power-ramping-rate", + Math::Round(c.ramping.maxUpwardPowerRampingRate, 3)); + if (c.ramping.maxDownwardPowerRampingRate != 0) + s->add("max-downward-power-ramping-rate", + Math::Round(c.ramping.maxDownwardPowerRampingRate, 3)); //pollutant factor for (auto const& [key, val] : Pollutant::namesToEnum) diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index d545917625..839917cd5d 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -302,10 +302,10 @@ void SIM_InitialisationProblemeHebdo(Data::Study& study, = cluster.minDownTime; pbPalier.upwardRampingCost[clusterIndex] - = cluster.powerIncreaseCost; - pbPalier.downwardRampingCost[clusterIndex] = cluster.powerDecreaseCost; - pbPalier.maxDownwardPowerRampingRate[clusterIndex] = cluster.maxDownwardPowerRampingRate; - pbPalier.maxUpwardPowerRampingRate[clusterIndex] = cluster.maxUpwardPowerRampingRate; + = cluster.ramping.powerIncreaseCost; + pbPalier.downwardRampingCost[clusterIndex] = cluster.ramping.powerDecreaseCost; + pbPalier.maxDownwardPowerRampingRate[clusterIndex] = cluster.ramping.maxDownwardPowerRampingRate; + pbPalier.maxUpwardPowerRampingRate[clusterIndex] = cluster.ramping.maxUpwardPowerRampingRate; diff --git a/src/solver/variable/surveyresults/surveyresults.cpp b/src/solver/variable/surveyresults/surveyresults.cpp index 2a86dff42b..45558ab172 100644 --- a/src/solver/variable/surveyresults/surveyresults.cpp +++ b/src/solver/variable/surveyresults/surveyresults.cpp @@ -159,10 +159,10 @@ static void ExportGridInfosAreas(const Data::Study& study, outThermal << cluster.startupCost << '\t'; outThermal << cluster.marketBidCost << '\t'; outThermal << cluster.spreadCost << '\n'; - outThermal << cluster.powerIncreaseCost << '\n'; - outThermal << cluster.powerDecreaseCost << '\n'; - outThermal << cluster.maxUpwardPowerRampingRate << '\n'; - outThermal << cluster.maxDownwardPowerRampingRate << '\n'; + outThermal << cluster.ramping.powerIncreaseCost << '\n'; + outThermal << cluster.ramping.powerDecreaseCost << '\n'; + outThermal << cluster.ramping.maxUpwardPowerRampingRate << '\n'; + outThermal << cluster.ramping.maxDownwardPowerRampingRate << '\n'; } // each thermal cluster }); // each area