Skip to content

Commit

Permalink
Make LMR optional with new option (#1247)
Browse files Browse the repository at this point in the history
* Make LMR optional with new option

* [FIX] Compile errors

* [DEV] Add exception for LMR disabled

* [DEV] Add function prepareAdqPatchParams

* [DEV] Move functions to AdqPatchParams

* [DEV] Read enable-first-step, update doc

* [FIX] Arg

* [TESTS] Unit tests for lmr and other adq params check

* [TESTS] Use BOOST_CHECK_THROW

* Fix bound on unsupplied energy when local matching is disabled (#1264)

* Fix bound on unsupplied energy when local matching is disabled

* Add forgotten localMatching.enabled in setNTCbounds

* Add write for new parameter

---------

Co-authored-by: Vincent Payet <[email protected]>
  • Loading branch information
flomnes and payetvin authored Apr 28, 2023
1 parent d8c21b1 commit f49f912
Show file tree
Hide file tree
Showing 11 changed files with 136 additions and 52 deletions.
3 changes: 3 additions & 0 deletions docs/reference-guide/13-file-format.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ A few changes related to the introduction of short-term storage objects.

In files **input/thermal/cluster/area/list.ini** add properties `nh3`, `nox`, `pm2_5`, `pm5`, `pm10`, `nmvoc`, `op1`, `op2`, `op3`, `op4`, `op5` [double]. These properties are emission factors similar to the existing one for CO2.

In file **settings/generaldata.ini**, in section `adequacy patch` add property
* `enable-first-step` [bool]. Default value = `true` Enable or disable DENS column

### Output
* For every short-term storage group, add 3 columns in files **values-&lt;period&gt;.txt** (mc-all & mc-ind)
* `ST-<group id>-withdrawal`
Expand Down
5 changes: 5 additions & 0 deletions src/libs/antares/exception/LoadingError.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,11 @@ IncompatibleHurdleCostCSR::IncompatibleHurdleCostCSR() :
{
}

AdqPatchDisabledLMR::AdqPatchDisabledLMR() :
LoadingError("Incompatible options LMR disabled and priceTakingOrder equal Dens")
{
}

IncompatibleOutputOptions::IncompatibleOutputOptions(const std::string& text) : LoadingError(text)
{
}
Expand Down
6 changes: 6 additions & 0 deletions src/libs/antares/exception/LoadingError.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,12 @@ class IncompatibleHurdleCostCSR : public LoadingError
IncompatibleHurdleCostCSR();
};

class AdqPatchDisabledLMR : public LoadingError
{
public:
AdqPatchDisabledLMR();
};

class IncompatibleOutputOptions : public LoadingError
{
public:
Expand Down
2 changes: 1 addition & 1 deletion src/libs/antares/study/parameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,7 @@ static bool SGDIntLoadFamily_VariablesSelection(Parameters& d,
}
if (key == "select_var +" || key == "select_var -")
{
// Check if the read output variable exists
// Check if the read output variable exists
if (not d.variablesPrintInfo.exists(value.to<std::string>()))
return false;

Expand Down
57 changes: 56 additions & 1 deletion src/libs/antares/study/parameters/adq-patch-params.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#include "adq-patch-params.h"
#include "antares/logs.h"

#include <antares/study.h>

#include <antares/exception/LoadingError.hpp>

namespace Antares::Data::AdequacyPatch
{

Expand All @@ -20,13 +24,16 @@ bool LocalMatching::updateFromKeyValue(const String& key, const String& value)
return value.to<bool>(setToZeroOutsideInsideLinks);
if (key == "set-to-null-ntc-between-physical-out-for-first-step")
return value.to<bool>(setToZeroOutsideOutsideLinks);
if (key == "enable-first-step")
return value.to<bool>(enabled);
return false;
}

void LocalMatching::addProperties(IniFile::Section* section) const
{
section->add("set-to-null-ntc-from-physical-out-to-physical-in-for-first-step", setToZeroOutsideInsideLinks);
section->add("set-to-null-ntc-between-physical-out-for-first-step", setToZeroOutsideOutsideLinks);
section->add("enable-first-step", enabled);
}

// -----------------------
Expand Down Expand Up @@ -136,6 +143,12 @@ void AdqPatchParams::addExcludedVariables(std::vector<std::string>& out) const
out.emplace_back("SPIL. ENRG. CSR");
out.emplace_back("DTG MRG CSR");
}

// If the adequacy patch is enabled, but the LMR is disabled, the DENS variable shouldn't exist
if (enabled && !localMatching.enabled)
{
out.emplace_back("DENS");
}
}


Expand All @@ -156,5 +169,47 @@ void AdqPatchParams::saveToINI(IniFile& ini) const
curtailmentSharing.addProperties(section);
}

bool AdqPatchParams::checkAdqPatchParams(const StudyMode studyMode,
const AreaList& areas,
const bool includeHurdleCostParameters) const
{
checkAdqPatchStudyModeEconomyOnly(studyMode);
checkAdqPatchContainsAdqPatchArea(areas);
checkAdqPatchIncludeHurdleCost(includeHurdleCostParameters);
checkAdqPatchDisabledLocalMatching();

return true;
}

// Adequacy Patch can only be used with Economy Study/Simulation Mode.
void AdqPatchParams::checkAdqPatchStudyModeEconomyOnly(const StudyMode studyMode) const
{
if (studyMode != StudyMode::stdmEconomy)
throw Error::IncompatibleStudyModeForAdqPatch();
}

// When Adequacy Patch is on at least one area must be inside Adequacy patch mode.
void AdqPatchParams::checkAdqPatchContainsAdqPatchArea(const Antares::Data::AreaList& areas) const
{
const bool containsAdqArea
= std::any_of(areas.cbegin(), areas.cend(), [](const std::pair<AreaName, Area*>& area) {
return area.second->adequacyPatchMode == physicalAreaInsideAdqPatch;
});

if (!containsAdqArea)
throw Error::NoAreaInsideAdqPatchMode();
}

void AdqPatchParams::checkAdqPatchIncludeHurdleCost(const bool includeHurdleCostParameters) const
{
if (curtailmentSharing.includeHurdleCost && !includeHurdleCostParameters)
throw Error::IncompatibleHurdleCostCSR();
}

void AdqPatchParams::checkAdqPatchDisabledLocalMatching() const
{
if (!localMatching.enabled && curtailmentSharing.priceTakingOrder == AdqPatchPTO::isDens)
throw Error::AdqPatchDisabledLMR();
}

} // Antares::Data::AdequacyPatch
} // Antares::Data::AdequacyPatch
17 changes: 14 additions & 3 deletions src/libs/antares/study/parameters/adq-patch-params.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <vector>
#include <string>

#include <antares/study/fwd.h>
#include <yuni/core/string.h>
#include "antares/inifile/inifile.h"

Expand Down Expand Up @@ -62,6 +63,7 @@ enum class AdqPatchPTO

struct LocalMatching
{
bool enabled = true;
//! Transmission capacities from physical areas outside adequacy patch (area type 1) to
//! physical areas inside adequacy patch (area type 2). NTC is set to null (if true)
//! only in the first step of adequacy patch local matching rule.
Expand Down Expand Up @@ -97,7 +99,7 @@ class CurtailmentSharing

bool updateFromKeyValue(const String& key, const String& value);
void addProperties(IniFile::Section* section) const;

void reset();

private:
Expand All @@ -107,7 +109,7 @@ class CurtailmentSharing

struct AdqPatchParams
{

bool enabled;
LocalMatching localMatching;
CurtailmentSharing curtailmentSharing;
Expand All @@ -116,6 +118,15 @@ struct AdqPatchParams
void addExcludedVariables(std::vector<std::string>&) const;
bool updateFromKeyValue(const String& key, const String& value);
void saveToINI(IniFile& ini) const;
bool checkAdqPatchParams(const StudyMode studyMode,
const AreaList& areas,
const bool includeHurdleCostParameters) const;


void checkAdqPatchStudyModeEconomyOnly(const StudyMode studyMode) const;
void checkAdqPatchContainsAdqPatchArea(const Antares::Data::AreaList& areas) const;
void checkAdqPatchIncludeHurdleCost(const bool includeHurdleCost) const;
void checkAdqPatchDisabledLocalMatching() const;
};

} // Antares::Data
} // namespace Antares::Data::AdequacyPatch
46 changes: 4 additions & 42 deletions src/solver/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,42 +91,6 @@ void checkSimplexRangeHydroHeuristic(Antares::Data::SimplexOptimization optRange
}
}

// Adequacy Patch can only be used with Economy Study/Simulation Mode.
void checkAdqPatchStudyModeEconomyOnly(const bool adqPatchOn,
const Antares::Data::StudyMode studyMode)
{
if ((studyMode != Antares::Data::StudyMode::stdmEconomy) && adqPatchOn)
{
throw Error::IncompatibleStudyModeForAdqPatch();
}
}
// When Adequacy Patch is on at least one area must be inside Adequacy patch mode.
void checkAdqPatchContainsAdqPatchArea(const bool adqPatchOn, const Antares::Data::AreaList& areas)
{
using namespace Antares::Data;
if (adqPatchOn)
{
const bool containsAdqArea
= std::any_of(areas.cbegin(), areas.cend(), [](const std::pair<AreaName, Area*>& area) {
return area.second->adequacyPatchMode == AdequacyPatch::physicalAreaInsideAdqPatch;
});
if (!containsAdqArea)
throw Error::NoAreaInsideAdqPatchMode();
}
}

void checkAdqPatchIncludeHurdleCost(const bool adqPatchOn,
const bool includeHurdleCost,
const bool includeHurdleCostCsr)
{
// No need to check if adq-patch is disabled
if (!adqPatchOn)
return;

if (includeHurdleCostCsr && !includeHurdleCost)
throw Error::IncompatibleHurdleCostCSR();
}

void checkMinStablePower(bool tsGenThermal, const Antares::Data::AreaList& areas)
{
if (tsGenThermal)
Expand Down Expand Up @@ -293,12 +257,10 @@ void Application::prepare(int argc, char* argv[])

checkSimplexRangeHydroHeuristic(pParameters->simplexOptimizationRange, pStudy->areas);

checkAdqPatchStudyModeEconomyOnly(pParameters->adqPatchParams.enabled, pParameters->mode);

checkAdqPatchContainsAdqPatchArea(pParameters->adqPatchParams.enabled, pStudy->areas);
checkAdqPatchIncludeHurdleCost(pParameters->adqPatchParams.enabled,
pParameters->include.hurdleCosts,
pParameters->adqPatchParams.curtailmentSharing.includeHurdleCost);
if (pParameters->adqPatchParams.enabled)
pParameters->adqPatchParams.checkAdqPatchParams(pParameters->mode,
pStudy->areas,
pParameters->include.hurdleCosts);

bool tsGenThermal
= (0 != (pParameters->timeSeriesToGenerate & Antares::Data::TimeSeries::timeSeriesThermal));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ void setNTCbounds(double& Xmax,
Xmin = -(ValeursDeNTC->ValeurDeNTCExtremiteVersOrigine[Interco]);

// set for adq patch first step
if (adqPatchParams.enabled && problemeHebdo->adequacyPatchRuntimeData->AdequacyFirstStep)
if (adqPatchParams.enabled && adqPatchParams.localMatching.enabled
&& problemeHebdo->adequacyPatchRuntimeData->AdequacyFirstStep)
{
ntcToZeroStatusForAdqPatch = getNTCtoZeroStatus(problemeHebdo, adqPatchParams, Interco);

Expand Down
2 changes: 1 addition & 1 deletion src/solver/optimisation/base_weekly_optimization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ std::unique_ptr<WeeklyOptimization> WeeklyOptimization::create(
PROBLEME_HEBDO* problemeHebdo,
uint thread_number)
{
if (adqPatchParams.enabled)
if (adqPatchParams.enabled && adqPatchParams.localMatching.enabled)
return std::make_unique<AdequacyPatchOptimization>(problemeHebdo, adqPatchParams, thread_number);
else
return std::make_unique<DefaultWeeklyOptimization>(problemeHebdo, adqPatchParams, thread_number);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ void setBoundsForUnsuppliedEnergy(PROBLEME_HEBDO* problemeHebdo,
Xmax[var] = 0.;

// adq patch: update ENS <= DENS in 2nd run
if (adqPatchParams.enabled &&
! problemeHebdo->adequacyPatchRuntimeData->AdequacyFirstStep &&
problemeHebdo->adequacyPatchRuntimeData->areaMode[pays]
if (adqPatchParams.enabled && adqPatchParams.localMatching.enabled
&& !problemeHebdo->adequacyPatchRuntimeData->AdequacyFirstStep
&& problemeHebdo->adequacyPatchRuntimeData->areaMode[pays]
== Data::AdequacyPatch::physicalAreaInsideAdqPatch)
Xmax[var] = std::min(
Xmax[var], problemeHebdo->ResultatsHoraires[pays]->ValeursHorairesDENS[pdtHebdo]);
Expand Down
41 changes: 41 additions & 0 deletions src/tests/src/solver/optimisation/adequacy_patch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "adequacy_patch_csr/adq_patch_curtailment_sharing.h"
#include <adequacy_patch_runtime_data.h>
#include "antares/study/parameters/adq-patch-params.h"
#include <antares/exception/LoadingError.hpp>
#include <fstream>

#include <vector>
#include <tuple>
Expand Down Expand Up @@ -130,6 +132,17 @@ std::pair<double, double> calculateAreaFlowBalanceForOneTimeStep(
return std::make_pair(netPositionInit, densNew);
}

AdqPatchParams createParams()
{
AdqPatchParams p;
p.enabled = true;
p.curtailmentSharing.includeHurdleCost = true;
p.localMatching.enabled = true;
p.curtailmentSharing.priceTakingOrder = AdqPatchPTO::isDens;

return p;
}

// Virtual -> Virtual (0 -> 0)
// No change in bounds is expected
BOOST_AUTO_TEST_CASE(setNTCboundsForOneTimeStep_virtual_virtual_no_change_expected)
Expand Down Expand Up @@ -487,3 +500,31 @@ BOOST_AUTO_TEST_CASE(calculateAreaFlowBalanceForOneTimeStep_outside_inside_Inclu
BOOST_CHECK_EQUAL(netPositionInit, -flowArea0toArea1_positive + flowArea2toArea0_negative);
BOOST_CHECK_EQUAL(densNew, 0.0);
}

BOOST_AUTO_TEST_CASE(check_valid_adq_param)
{
auto p = createParams();
BOOST_CHECK_NO_THROW(p.checkAdqPatchStudyModeEconomyOnly(Antares::Data::stdmEconomy));
BOOST_CHECK_NO_THROW(p.checkAdqPatchIncludeHurdleCost(true));
BOOST_CHECK_NO_THROW(p.checkAdqPatchDisabledLocalMatching());
}

BOOST_AUTO_TEST_CASE(check_adq_param_wrong_mode)
{
auto p = createParams();
BOOST_CHECK_THROW(p.checkAdqPatchStudyModeEconomyOnly(Antares::Data::stdmAdequacy),
Error::IncompatibleStudyModeForAdqPatch);
}

BOOST_AUTO_TEST_CASE(check_adq_param_wrong_hurdle_cost)
{
auto p = createParams();
BOOST_CHECK_THROW(p.checkAdqPatchIncludeHurdleCost(false), Error::IncompatibleHurdleCostCSR);
}

BOOST_AUTO_TEST_CASE(check_adq_param_wrong_lmr_disabled)
{
auto p = createParams();
p.localMatching.enabled = false;
BOOST_CHECK_THROW(p.checkAdqPatchDisabledLocalMatching(), Error::AdqPatchDisabledLMR);
}

0 comments on commit f49f912

Please sign in to comment.