Skip to content

Commit

Permalink
Split
Browse files Browse the repository at this point in the history
  • Loading branch information
flomnes committed Dec 6, 2024
1 parent 1de8150 commit 06526a2
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 149 deletions.
2 changes: 2 additions & 0 deletions src/libs/antares/study/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ set(SRC_STUDY_PART_THERMAL
include/antares/study/parts/thermal/cluster.h
include/antares/study/parts/thermal/cluster.hxx
parts/thermal/cluster.cpp
parts/thermal/scenarized_cost_provider.cpp
parts/thermal/constant_cost_provider.cpp
include/antares/study/parts/thermal/cluster_list.h
parts/thermal/cluster_list.cpp
include/antares/study/parts/thermal/pollutant.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,6 @@ class ThermalCluster final: public Cluster, public std::enable_shared_from_this<
// Marginal_Cost[€/MWh] = Market_Bid_Cost[€/MWh] = (Fuel_Cost[€/GJ] * 3.6 * 100 / Efficiency[%])
// CO2_emission_factor[tons/MWh] * C02_cost[€/tons] + Variable_O&M_cost[€/MWh]

void initializeCostProvider();

std::unique_ptr<CostProvider> costProvider;

}; // class ThermalCluster
Expand Down
154 changes: 11 additions & 143 deletions src/libs/antares/study/parts/thermal/cluster.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,148 +272,6 @@ void Data::ThermalCluster::markAsModified() const
ecoInput.markAsModified();
}

ConstantCostProvider::ConstantCostProvider(ThermalCluster* cluster):
cluster(cluster)
{
}

double ConstantCostProvider::getOperatingCost(uint serieIndex, uint hourInTheYear) const
{
const auto* modCost = cluster->modulation[thermalModulationCost];
return cluster->marginalCost * modCost[hourInTheYear];
}

double ConstantCostProvider::getMarginalCost(uint serieIndex, uint hourInTheYear) const
{
const double mod = cluster->modulation[Data::thermalModulationCost][hourInTheYear];
return cluster->marginalCost * mod;
}

double ConstantCostProvider::getMarketBidCost(uint hourInTheYear, uint year) const
{
const double mod = cluster->modulation[thermalModulationMarketBid][hourInTheYear];
return cluster->marketBidCost * mod;
}

ScenarizedCostProvider::ScenarizedCostProvider(ThermalCluster* cluster):
cluster(cluster)
{
resizeCostTS();
ComputeMarketBidTS();
MarginalCostEqualsMarketBid();
ComputeProductionCostTS();
}

void ScenarizedCostProvider::ComputeProductionCostTS()
{
if (cluster->modulation.width == 0)
{
return;
}

for (auto& timeSeries: costsTimeSeries)
{
auto& productionCostTS = timeSeries.productionCostTs;
auto& marginalCostTS = timeSeries.marginalCostTS;

for (uint hour = 0; hour < HOURS_PER_YEAR; ++hour)
{
double hourlyModulation = cluster->modulation[Data::thermalModulationCost][hour];
productionCostTS[hour] = marginalCostTS[hour] * hourlyModulation;
}
}
}

void ScenarizedCostProvider::resizeCostTS()
{
const uint fuelCostWidth = cluster->ecoInput.fuelcost.width;
const uint co2CostWidth = cluster->ecoInput.co2cost.width;
const uint tsCount = std::max(fuelCostWidth, co2CostWidth);

costsTimeSeries.resize(tsCount, CostsTimeSeries());
}

void ScenarizedCostProvider::MarginalCostEqualsMarketBid()
{
for (auto& timeSeries: costsTimeSeries)
{
auto& source = timeSeries.marketBidCostTS;
auto& destination = timeSeries.marginalCostTS;
std::copy(source.begin(), source.end(), destination.begin());
}
}

double computeMarketBidCost(double fuelCost,
double fuelEfficiency,
double co2EmissionFactor,
double co2cost,
double variableomcost)
{
return fuelCost * 360.0 / fuelEfficiency + co2EmissionFactor * co2cost + variableomcost;
}

void ScenarizedCostProvider::ComputeMarketBidTS()
{
const uint fuelCostWidth = cluster->ecoInput.fuelcost.width;
const uint co2CostWidth = cluster->ecoInput.co2cost.width;

double co2EmissionFactor = cluster->emissions.factors[Pollutant::CO2];

for (uint tsIndex = 0; tsIndex < costsTimeSeries.size(); ++tsIndex)
{
uint tsIndexFuel = std::min(fuelCostWidth - 1, tsIndex);
uint tsIndexCo2 = std::min(co2CostWidth - 1, tsIndex);
for (uint hour = 0; hour < HOURS_PER_YEAR; ++hour)
{
double fuelcost = cluster->ecoInput.fuelcost[tsIndexFuel][hour];
double co2cost = cluster->ecoInput.co2cost[tsIndexCo2][hour];

costsTimeSeries[tsIndex].marketBidCostTS[hour] = computeMarketBidCost(
fuelcost,
cluster->fuelEfficiency,
co2EmissionFactor,
co2cost,
cluster->variableomcost);
}
}
}

double ScenarizedCostProvider::getOperatingCost(uint serieIndex, uint hourInTheYear) const
{
const uint tsIndex = std::min(serieIndex, (uint)costsTimeSeries.size() - 1);
return costsTimeSeries[tsIndex].productionCostTs[hourInTheYear];
}

double ScenarizedCostProvider::getMarginalCost(uint serieIndex, uint hourInTheYear) const
{
const double mod = cluster->modulation[thermalModulationMarketBid][hourInTheYear];
const uint tsIndex = std::min(serieIndex, (uint)costsTimeSeries.size() - 1);
return costsTimeSeries[tsIndex].marginalCostTS[hourInTheYear] * mod;
}

double ScenarizedCostProvider::getMarketBidCost(uint hourInTheYear, uint year) const
{
const double mod = cluster->modulation[thermalModulationMarketBid][hourInTheYear];
const uint serieIndex = cluster->series.getSeriesIndex(year);
const uint tsIndex = std::min(serieIndex, (uint)costsTimeSeries.size() - 1);
return costsTimeSeries[tsIndex].marketBidCostTS[hourInTheYear] * mod;
}

void Data::ThermalCluster::initializeCostProvider()
{
switch (costgeneration)
{
case Data::setManually:
costProvider = std::make_unique<ConstantCostProvider>(this);
break;
case Data::useCostTimeseries:
costProvider = std::make_unique<ScenarizedCostProvider>(this);
break;
default:
throw std::string("Invalid parameter");
}
}

void Data::ThermalCluster::calculationOfSpinning()
{
// nominal capacity (for solver)
Expand Down Expand Up @@ -756,7 +614,17 @@ CostProvider& ThermalCluster::getCostProvider()
{
if (!costProvider)
{
initializeCostProvider();
switch (costgeneration)
{
case Data::setManually:
costProvider = std::make_unique<ConstantCostProvider>(this);
break;
case Data::useCostTimeseries:
costProvider = std::make_unique<ScenarizedCostProvider>(this);
break;
default:
throw std::runtime_error("Invalid costgeneration parameter");
}
}
return *costProvider;
}
Expand Down
47 changes: 47 additions & 0 deletions src/libs/antares/study/parts/thermal/constant_cost_provider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2007-2024, RTE (https://www.rte-france.com)
* See AUTHORS.txt
* SPDX-License-Identifier: MPL-2.0
* This file is part of Antares-Simulator,
* Adequacy and Performance assessment for interconnected energy networks.
*
* Antares_Simulator is free software: you can redistribute it and/or modify
* it under the terms of the Mozilla Public Licence 2.0 as published by
* the Mozilla Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Antares_Simulator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Mozilla Public Licence 2.0 for more details.
*
* You should have received a copy of the Mozilla Public Licence 2.0
* along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
*/
#include "antares/study/parts/thermal/cluster.h"

namespace Antares::Data
{
ConstantCostProvider::ConstantCostProvider(ThermalCluster* cluster):
cluster(cluster)
{
}

double ConstantCostProvider::getOperatingCost(uint serieIndex, uint hourInTheYear) const
{
const auto* modCost = cluster->modulation[thermalModulationCost];
return cluster->marginalCost * modCost[hourInTheYear];
}

double ConstantCostProvider::getMarginalCost(uint serieIndex, uint hourInTheYear) const
{
const double mod = cluster->modulation[Data::thermalModulationCost][hourInTheYear];
return cluster->marginalCost * mod;
}

double ConstantCostProvider::getMarketBidCost(uint hourInTheYear, uint year) const
{
const double mod = cluster->modulation[thermalModulationMarketBid][hourInTheYear];
return cluster->marketBidCost * mod;
}
} // namespace Antares::Data
131 changes: 131 additions & 0 deletions src/libs/antares/study/parts/thermal/scenarized_cost_provider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/*
* Copyright 2007-2024, RTE (https://www.rte-france.com)
* See AUTHORS.txt
* SPDX-License-Identifier: MPL-2.0
* This file is part of Antares-Simulator,
* Adequacy and Performance assessment for interconnected energy networks.
*
* Antares_Simulator is free software: you can redistribute it and/or modify
* it under the terms of the Mozilla Public Licence 2.0 as published by
* the Mozilla Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Antares_Simulator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Mozilla Public Licence 2.0 for more details.
*
* You should have received a copy of the Mozilla Public Licence 2.0
* along with Antares_Simulator. If not, see <https://opensource.org/license/mpl-2-0/>.
*/

#include "antares/study/parts/thermal/cluster.h"

namespace Antares::Data
{

ScenarizedCostProvider::ScenarizedCostProvider(ThermalCluster* cluster):
cluster(cluster)
{
resizeCostTS();
ComputeMarketBidTS();
MarginalCostEqualsMarketBid();
ComputeProductionCostTS();
}

void ScenarizedCostProvider::ComputeProductionCostTS()
{
if (cluster->modulation.width == 0)
{
return;
}

for (auto& timeSeries: costsTimeSeries)
{
auto& productionCostTS = timeSeries.productionCostTs;
auto& marginalCostTS = timeSeries.marginalCostTS;

for (uint hour = 0; hour < HOURS_PER_YEAR; ++hour)
{
double hourlyModulation = cluster->modulation[Data::thermalModulationCost][hour];
productionCostTS[hour] = marginalCostTS[hour] * hourlyModulation;
}
}
}

void ScenarizedCostProvider::resizeCostTS()
{
const uint fuelCostWidth = cluster->ecoInput.fuelcost.width;
const uint co2CostWidth = cluster->ecoInput.co2cost.width;
const uint tsCount = std::max(fuelCostWidth, co2CostWidth);

costsTimeSeries.resize(tsCount, CostsTimeSeries());
}

void ScenarizedCostProvider::MarginalCostEqualsMarketBid()
{
for (auto& timeSeries: costsTimeSeries)
{
auto& source = timeSeries.marketBidCostTS;
auto& destination = timeSeries.marginalCostTS;
std::copy(source.begin(), source.end(), destination.begin());
}
}

double computeMarketBidCost(double fuelCost,
double fuelEfficiency,
double co2EmissionFactor,
double co2cost,
double variableomcost)
{
return fuelCost * 360.0 / fuelEfficiency + co2EmissionFactor * co2cost + variableomcost;
}

void ScenarizedCostProvider::ComputeMarketBidTS()
{
const uint fuelCostWidth = cluster->ecoInput.fuelcost.width;
const uint co2CostWidth = cluster->ecoInput.co2cost.width;

double co2EmissionFactor = cluster->emissions.factors[Pollutant::CO2];

for (uint tsIndex = 0; tsIndex < costsTimeSeries.size(); ++tsIndex)
{
uint tsIndexFuel = std::min(fuelCostWidth - 1, tsIndex);
uint tsIndexCo2 = std::min(co2CostWidth - 1, tsIndex);
for (uint hour = 0; hour < HOURS_PER_YEAR; ++hour)
{
double fuelcost = cluster->ecoInput.fuelcost[tsIndexFuel][hour];
double co2cost = cluster->ecoInput.co2cost[tsIndexCo2][hour];

costsTimeSeries[tsIndex].marketBidCostTS[hour] = computeMarketBidCost(
fuelcost,
cluster->fuelEfficiency,
co2EmissionFactor,
co2cost,
cluster->variableomcost);
}
}
}

double ScenarizedCostProvider::getOperatingCost(uint serieIndex, uint hourInTheYear) const
{
const uint tsIndex = std::min(serieIndex, (uint)costsTimeSeries.size() - 1);
return costsTimeSeries[tsIndex].productionCostTs[hourInTheYear];
}

double ScenarizedCostProvider::getMarginalCost(uint serieIndex, uint hourInTheYear) const
{
const double mod = cluster->modulation[thermalModulationMarketBid][hourInTheYear];
const uint tsIndex = std::min(serieIndex, (uint)costsTimeSeries.size() - 1);
return costsTimeSeries[tsIndex].marginalCostTS[hourInTheYear] * mod;
}

double ScenarizedCostProvider::getMarketBidCost(uint hourInTheYear, uint year) const
{
const double mod = cluster->modulation[thermalModulationMarketBid][hourInTheYear];
const uint serieIndex = cluster->series.getSeriesIndex(year);
const uint tsIndex = std::min(serieIndex, (uint)costsTimeSeries.size() - 1);
return costsTimeSeries[tsIndex].marketBidCostTS[hourInTheYear] * mod;
}

} // namespace Antares::Data
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,9 @@ BOOST_FIXTURE_TEST_CASE(ThermalCluster_costGenManualCalculationOfMarketBidAndMar

cluster->costgeneration = Data::setManually;

BOOST_CHECK_EQUAL(cluster->getCostProvider().getMarketBidCost(2637, 0), 35);
BOOST_CHECK_EQUAL(cluster->getCostProvider().getMarginalCost(6737, 0), 23);
auto& cp = cluster->getCostProvider();
BOOST_CHECK_EQUAL(cp.getMarketBidCost(2637, 0), 35);
BOOST_CHECK_EQUAL(cp.getMarginalCost(6737, 0), 23);
}

BOOST_FIXTURE_TEST_CASE(
Expand All @@ -250,8 +251,9 @@ BOOST_FIXTURE_TEST_CASE(

cluster->tsNumbers.reset(1);

BOOST_CHECK_CLOSE(cluster->getCostProvider().getMarginalCost(0, 0), 24.12, 0.001);
BOOST_CHECK_CLOSE(cluster->getCostProvider().getMarketBidCost(2637, 0), 24.12, 0.001);
auto& cp = cluster->getCostProvider();
BOOST_CHECK_CLOSE(cp.getMarginalCost(0, 0), 24.12, 0.001);
BOOST_CHECK_CLOSE(cp.getMarketBidCost(2637, 0), 24.12, 0.001);
}

BOOST_FIXTURE_TEST_CASE(computeMarketBidCost_useTimeSeries, FixtureFull)
Expand Down

0 comments on commit 06526a2

Please sign in to comment.