Skip to content

Commit

Permalink
Increase coverage on hydro common data (hydro.ini) [ANT-1825] (#2634)
Browse files Browse the repository at this point in the history
# Description
- Split large loading function (time-series / INI file)
- Add coverage on new property `overflow spilled cost difference`

# Summary
```cpp
void CommonFixture::writeValidFile()
{
    std::ofstream outfile(hydroIni);
    outfile <<
      R"([overflow spilled cost difference]
east = 1.00000
west = 2.31000
[reservoir]
east = true)";
}

BOOST_FIXTURE_TEST_CASE(test_read_valid_file, CommonFixture)
{
    writeValidFile();
    BOOST_CHECK(load());
    BOOST_CHECK_EQUAL(east->hydro.overflowSpilledCostDifference, 1.0);
    BOOST_CHECK_EQUAL(west->hydro.overflowSpilledCostDifference, 2.31000);
}
```
  • Loading branch information
flomnes authored Feb 21, 2025
1 parent 8ccec91 commit e5af225
Show file tree
Hide file tree
Showing 4 changed files with 232 additions and 97 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ class PartHydro
pumpMod,
};

static bool LoadIniFile(Study& study, const std::filesystem::path& folder);

/*!
** \brief Load data for hydro container from a folder
**
Expand Down
199 changes: 102 additions & 97 deletions src/libs/antares/study/parts/hydro/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,105 +132,9 @@ static bool loadProperties(Study& study,
return ret;
}

bool PartHydro::LoadFromFolder(Study& study, const fs::path& folder)
bool PartHydro::LoadIniFile(Study& study, const std::filesystem::path& folder)
{
bool ret = true;

// Initialize all alpha values to 0
study.areas.each(
[&ret, &study, &folder](Data::Area& area)
{
area.hydro.interDailyBreakdown = 1.;
area.hydro.intraDailyModulation = 24.;
area.hydro.intermonthlyBreakdown = 1.;
area.hydro.reservoirManagement = false;
area.hydro.followLoadModulations = true;
area.hydro.useWaterValue = false;
area.hydro.hardBoundsOnRuleCurves = false;
area.hydro.useHeuristicTarget = true;
area.hydro.useLeeway = false;
area.hydro.powerToLevel = false;
area.hydro.leewayLowerBound = 1.;
area.hydro.leewayUpperBound = 1.;
area.hydro.initializeReservoirLevelDate = 0;
area.hydro.reservoirCapacity = 0.;
area.hydro.pumpingEfficiency = 1.;
area.hydro.deltaBetweenFinalAndInitialLevels.resize(study.parameters.nbYears);

if (study.parameters.compatibility.hydroPmax
== Parameters::Compatibility::HydroPmax::Hourly)
{
// GUI part patch :
// We need to know, when estimating the RAM required by the solver, if the current
// area is hydro modulable. Therefore, reading the area's daily max power at this
// stage is necessary.

if (!study.usedByTheSolver)
{
bool enabledModeIsChanged = false;
if (JIT::enabled)
{
JIT::enabled = false; // Allowing to read the area's daily max power
enabledModeIsChanged = true;
}

ret = area.hydro.LoadDailyMaxEnergy(folder.string(), area.id) && ret;

if (enabledModeIsChanged)
{
JIT::enabled = true; // Back to the previous loading mode.
}
}
else
{
ret = area.hydro.LoadDailyMaxEnergy(folder.string(), area.id) && ret;

// Check is moved here, because in case of old study
// dailyNbHoursAtGenPmax and dailyNbHoursAtPumpPmax are not yet initialized.

ret = area.hydro.CheckDailyMaxEnergy(area.name) && ret;
}
}

fs::path capacityPath = folder / "common" / "capacity";

std::string creditId = "creditmodulations_" + area.id + ".txt";
fs::path creditPath = capacityPath / creditId;
ret = area.hydro.creditModulation.loadFromCSVFile(creditPath.string(),
101,
2,
Matrix<>::optFixedSize,
&study.dataBuffer)
&& ret;

std::string reservoirId = "reservoir_" + area.id + ".txt";
fs::path reservoirPath = capacityPath / reservoirId;
ret = area.hydro.reservoirLevel.loadFromCSVFile(reservoirPath.string(),
3,
DAYS_PER_YEAR,
Matrix<>::optFixedSize,
&study.dataBuffer)
&& ret;

std::string waterValueId = "waterValues_" + area.id + ".txt";
fs::path waterValuePath = capacityPath / waterValueId;
ret = area.hydro.waterValues.loadFromCSVFile(waterValuePath.string(),
101,
DAYS_PER_YEAR,
Matrix<>::optFixedSize,
&study.dataBuffer)
&& ret;

std::string inflowId = "inflowPattern_" + area.id + ".txt";
fs::path inflowPath = capacityPath / inflowId;
ret = area.hydro.inflowPattern.loadFromCSVFile(inflowPath.string(),
1,
DAYS_PER_YEAR,
Matrix<>::optFixedSize,
&study.dataBuffer)
&& ret;
});

IniFile ini;
auto path = folder / "hydro.ini";
if (not ini.open(path))
Expand Down Expand Up @@ -333,7 +237,108 @@ bool PartHydro::LoadFromFolder(Study& study, const fs::path& folder)
&PartHydro::overflowSpilledCostDifference)
&& ret;
}
return ret;
}

bool PartHydro::LoadFromFolder(Study& study, const fs::path& folder)
{
bool ret = true;

// Initialize all alpha values to 0
study.areas.each(
[&ret, &study, &folder](Data::Area& area)
{
area.hydro.interDailyBreakdown = 1.;
area.hydro.intraDailyModulation = 24.;
area.hydro.intermonthlyBreakdown = 1.;
area.hydro.reservoirManagement = false;
area.hydro.followLoadModulations = true;
area.hydro.useWaterValue = false;
area.hydro.hardBoundsOnRuleCurves = false;
area.hydro.useHeuristicTarget = true;
area.hydro.useLeeway = false;
area.hydro.powerToLevel = false;
area.hydro.leewayLowerBound = 1.;
area.hydro.leewayUpperBound = 1.;
area.hydro.initializeReservoirLevelDate = 0;
area.hydro.reservoirCapacity = 0.;
area.hydro.pumpingEfficiency = 1.;
area.hydro.deltaBetweenFinalAndInitialLevels.resize(study.parameters.nbYears);

if (study.parameters.compatibility.hydroPmax
== Parameters::Compatibility::HydroPmax::Hourly)
{
// GUI part patch :
// We need to know, when estimating the RAM required by the solver, if the current
// area is hydro modulable. Therefore, reading the area's daily max power at this
// stage is necessary.

if (!study.usedByTheSolver)
{
bool enabledModeIsChanged = false;
if (JIT::enabled)
{
JIT::enabled = false; // Allowing to read the area's daily max power
enabledModeIsChanged = true;
}

ret = area.hydro.LoadDailyMaxEnergy(folder.string(), area.id) && ret;

if (enabledModeIsChanged)
{
JIT::enabled = true; // Back to the previous loading mode.
}
}
else
{
ret = area.hydro.LoadDailyMaxEnergy(folder.string(), area.id) && ret;

// Check is moved here, because in case of old study
// dailyNbHoursAtGenPmax and dailyNbHoursAtPumpPmax are not yet initialized.

ret = area.hydro.CheckDailyMaxEnergy(area.name) && ret;
}
}

fs::path capacityPath = folder / "common" / "capacity";

std::string creditId = "creditmodulations_" + area.id + ".txt";
fs::path creditPath = capacityPath / creditId;
ret = area.hydro.creditModulation.loadFromCSVFile(creditPath.string(),
101,
2,
Matrix<>::optFixedSize,
&study.dataBuffer)
&& ret;

std::string reservoirId = "reservoir_" + area.id + ".txt";
fs::path reservoirPath = capacityPath / reservoirId;
ret = area.hydro.reservoirLevel.loadFromCSVFile(reservoirPath.string(),
3,
DAYS_PER_YEAR,
Matrix<>::optFixedSize,
&study.dataBuffer)
&& ret;

std::string waterValueId = "waterValues_" + area.id + ".txt";
fs::path waterValuePath = capacityPath / waterValueId;
ret = area.hydro.waterValues.loadFromCSVFile(waterValuePath.string(),
101,
DAYS_PER_YEAR,
Matrix<>::optFixedSize,
&study.dataBuffer)
&& ret;

std::string inflowId = "inflowPattern_" + area.id + ".txt";
fs::path inflowPath = capacityPath / inflowId;
ret = area.hydro.inflowPattern.loadFromCSVFile(inflowPath.string(),
1,
DAYS_PER_YEAR,
Matrix<>::optFixedSize,
&study.dataBuffer)
&& ret;
});
ret = PartHydro::LoadIniFile(study, folder) && ret;
return ret;
}

Expand Down
7 changes: 7 additions & 0 deletions src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,10 @@ add_boost_test(test-hydro-series
LIBS
Antares::study
test_utils_unit)

# Hydro series
add_boost_test(test-hydro-common
SRC test-hydro-common.cpp
LIBS
Antares::study
test_utils_unit)
121 changes: 121 additions & 0 deletions src/tests/src/libs/antares/study/parts/hydro/test-hydro-common.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/*
* 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/>.
*/

#define BOOST_TEST_MODULE test hydro common

#define WIN32_LEAN_AND_MEAN

#include <files-system.h>
#include <memory>

#include <boost/test/unit_test.hpp>

#include <antares/study/study.h>

#define SEP "/"

using namespace Antares::Data;
namespace fs = std::filesystem;

// =================
// The fixture
// =================
struct CommonFixture
{
std::filesystem::path path;
StudyLoadOptions options;
StudyVersion version = StudyVersion::latest();

CommonFixture():
tmp(fs::temp_directory_path()),
hydroIni(tmp / "hydro.ini"),
study(std::make_unique<Study>())
{
east = new Area("east"); // freed by ~AreaList
study->areas.add(east);
west = new Area("west"); // freed by ~AreaList
study->areas.add(west);
}

bool load()
{
return east->hydro.LoadIniFile(*study, tmp) && west->hydro.LoadIniFile(*study, tmp);
}

~CommonFixture()
{
fs::remove(hydroIni);
}

void writeValidFile();
void writeInvalidFile();

public:
Area* east;
Area* west;

private:
fs::path tmp;
fs::path hydroIni;
std::unique_ptr<Study> study;
};

void CommonFixture::writeValidFile()
{
std::ofstream outfile(hydroIni);
outfile <<
R"([overflow spilled cost difference]
east = 1.00000
west = 2.31000
[reservoir]
east = true)";
}

void CommonFixture::writeInvalidFile()
{
std::ofstream outfile(hydroIni);
outfile <<
R"([overflow spilled cost difference]
east = 1.00000
west = 2.31000
wrongarea = 1.414
[reservoir]
east = true)";
}

BOOST_AUTO_TEST_SUITE(s)

BOOST_FIXTURE_TEST_CASE(test_read_valid_file, CommonFixture)
{
writeValidFile();
BOOST_CHECK(load());
BOOST_CHECK_EQUAL(east->hydro.overflowSpilledCostDifference, 1.0);
BOOST_CHECK_EQUAL(west->hydro.overflowSpilledCostDifference, 2.31000);
}

BOOST_FIXTURE_TEST_CASE(test_read_invalid_file, CommonFixture)
{
writeInvalidFile();
BOOST_CHECK(!load());
}
BOOST_AUTO_TEST_SUITE_END()

0 comments on commit e5af225

Please sign in to comment.