From 61bb933924754070d4a2e0da9bb17ee8ff8dfab8 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Mon, 16 Dec 2024 16:20:13 +0100 Subject: [PATCH 01/14] Add a warning if sts group property is empty [ANT-2026] (#2534) --- .../antares/study/parts/short-term-storage/properties.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libs/antares/study/parts/short-term-storage/properties.cpp b/src/libs/antares/study/parts/short-term-storage/properties.cpp index 3805b239a2..cbed02122e 100644 --- a/src/libs/antares/study/parts/short-term-storage/properties.cpp +++ b/src/libs/antares/study/parts/short-term-storage/properties.cpp @@ -213,6 +213,12 @@ bool Properties::validate() << " should be inferior to 1, value has been set to " << initialLevel; } + if (groupName.empty()) + { + logs.warning() << "Group name is empty for short term storage " << name; + return false; + } + return true; } From 7ead326b284a027398ef9ece7cc6c9e81e9356fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Mon, 16 Dec 2024 17:06:20 +0100 Subject: [PATCH 02/14] Use sirius-solver@antares-integration-v1.6 (#2533) --- src/ports/sirius-solver/portfile.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ports/sirius-solver/portfile.cmake b/src/ports/sirius-solver/portfile.cmake index 287994c152..bf6ac68a36 100644 --- a/src/ports/sirius-solver/portfile.cmake +++ b/src/ports/sirius-solver/portfile.cmake @@ -1,8 +1,8 @@ vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO "rte-france/sirius-solver" - REF "antares-integration-v1.5" - SHA512 19c6c156861bdeb58c2f17f703124d52020c79f9b81734057bf1bc5dff3dbc464179f99aeab6c8c44a84de1f84ed8f4929f9a919d2bf8bd49ac737f656088e19 + REF "antares-integration-v1.6" + SHA512 8d5992f036f35b73c11261e68e030c58c3ffe22b411921c7e08e62274feeed41227b59365a00a4e32e49f35cdaa733b079cfc0a7d98347825253ae67d9c69e4a HEAD_REF main ) From ce061834cd596744f30eab2919b5207be55bde84 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:06:28 +0100 Subject: [PATCH 03/14] Modeler 4.6: system import [ANT-2207] (#2530) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR add the ability to read a YAML file containing all the infos about the electric system and which models they're related to, converting it into system-model structures. --------- Co-authored-by: Florian Omnès --- src/solver/CMakeLists.txt | 1 + src/solver/systemParser/CMakeLists.txt | 32 ++ src/solver/systemParser/converter.cpp | 131 ++++++++ src/solver/systemParser/encoders.hxx | 95 ++++++ .../antares/solver/systemParser/converter.h | 35 +++ .../antares/solver/systemParser/parser.h | 32 ++ .../antares/solver/systemParser/system.h | 55 ++++ src/solver/systemParser/parser.cpp | 40 +++ src/study/system-model/component.cpp | 4 +- .../antares/study/system-model/system.h | 2 +- src/study/system-model/system.cpp | 2 +- .../src/solver/modelParser/CMakeLists.txt | 5 +- .../modelParser/testSystemConverter.cpp | 281 ++++++++++++++++++ .../solver/modelParser/testSystemParser.cpp | 184 ++++++++++++ .../src/study/system-model/test_component.cpp | 18 +- .../src/study/system-model/test_system.cpp | 19 +- 16 files changed, 916 insertions(+), 20 deletions(-) create mode 100644 src/solver/systemParser/CMakeLists.txt create mode 100644 src/solver/systemParser/converter.cpp create mode 100644 src/solver/systemParser/encoders.hxx create mode 100644 src/solver/systemParser/include/antares/solver/systemParser/converter.h create mode 100644 src/solver/systemParser/include/antares/solver/systemParser/parser.h create mode 100644 src/solver/systemParser/include/antares/solver/systemParser/system.h create mode 100644 src/solver/systemParser/parser.cpp create mode 100644 src/tests/src/solver/modelParser/testSystemConverter.cpp create mode 100644 src/tests/src/solver/modelParser/testSystemParser.cpp diff --git a/src/solver/CMakeLists.txt b/src/solver/CMakeLists.txt index 5ae822209b..b37cb7f1cf 100644 --- a/src/solver/CMakeLists.txt +++ b/src/solver/CMakeLists.txt @@ -16,6 +16,7 @@ add_subdirectory(lps) add_subdirectory(misc) add_subdirectory(modelConverter) add_subdirectory(modelParser) +add_subdirectory(systemParser) add_subdirectory(modeler) add_subdirectory(optimisation) add_subdirectory(signal-handling) diff --git a/src/solver/systemParser/CMakeLists.txt b/src/solver/systemParser/CMakeLists.txt new file mode 100644 index 0000000000..79e1262644 --- /dev/null +++ b/src/solver/systemParser/CMakeLists.txt @@ -0,0 +1,32 @@ +find_package(yaml-cpp REQUIRED) + +set(SOURCES + parser.cpp + converter.cpp + encoders.hxx + include/antares/solver/systemParser/parser.h + include/antares/solver/systemParser/converter.h + include/antares/solver/systemParser/system.h +) + +# Create the library +add_library(systemParser STATIC ${SOURCES}) +add_library(Antares::systemParser ALIAS systemParser) + +# Specify include directories +target_include_directories(systemParser + PUBLIC + $ +) + +# Link dependencies (if any) +target_link_libraries(systemParser + PUBLIC + Antares::antares-study-system-model + PRIVATE + yaml-cpp +) + +install(DIRECTORY include/antares + DESTINATION "include" +) diff --git a/src/solver/systemParser/converter.cpp b/src/solver/systemParser/converter.cpp new file mode 100644 index 0000000000..b78b8abb8a --- /dev/null +++ b/src/solver/systemParser/converter.cpp @@ -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 . + */ + +#include "antares/solver/systemParser/converter.h" + +#include + +#include "antares/solver/systemParser/system.h" +#include "antares/study/system-model/system.h" + +using namespace Antares::Study; + +namespace Antares::Solver::SystemConverter +{ + +class ErrorWhileSplittingLibraryAndModel: public std::runtime_error +{ +public: + explicit ErrorWhileSplittingLibraryAndModel(const std::string& s): + runtime_error("'.' not found while splitting library and model: " + s) + { + } +}; + +class LibraryNotFound: public std::runtime_error +{ +public: + explicit LibraryNotFound(const std::string& s): + runtime_error("No library found with this name: " + s) + { + } +}; + +class ModelNotFound: public std::runtime_error +{ +public: + explicit ModelNotFound(const std::string& s): + runtime_error("No model found with this name: " + s) + { + } +}; + +static std::pair splitLibraryModelString(const std::string& s) +{ + size_t pos = s.find('.'); + if (pos == std::string::npos) + { + throw ErrorWhileSplittingLibraryAndModel(s); + } + + std::string library = s.substr(0, pos); + std::string model = s.substr(pos + 1); + return {library, model}; +} + +static const SystemModel::Model& getModel(const std::vector& libraries, + const std::string& libraryId, + const std::string& modelId) +{ + auto lib = std::ranges::find_if(libraries, + [&libraryId](const auto& l) { return l.Id() == libraryId; }); + if (lib == libraries.end()) + { + throw LibraryNotFound(libraryId); + } + + auto search = lib->Models().find(modelId); + if (search == lib->Models().end()) + { + throw ModelNotFound(modelId); + } + + return search->second; +} + +static SystemModel::Component createComponent(const SystemParser::Component& c, + const std::vector& libraries) +{ + const auto [libraryId, modelId] = splitLibraryModelString(c.model); + SystemModel::ModelBuilder model_builder; + + const SystemModel::Model& model = getModel(libraries, libraryId, modelId); + + SystemModel::ComponentBuilder component_builder; + + std::map parameters; + for (const auto& p: c.parameters) + { + parameters.try_emplace(p.id, p.value); + } + + auto component = component_builder.withId(c.id) + .withModel(&model) + .withScenarioGroupId(c.scenarioGroup) + .withParameterValues(parameters) + .build(); + return component; +} + +SystemModel::System convert(const SystemParser::System& parserSystem, + const std::vector& libraries) +{ + std::vector components; + for (const auto& c: parserSystem.components) + { + components.push_back(createComponent(c, libraries)); + } + + SystemModel::SystemBuilder builder; + return builder.withId(parserSystem.id).withComponents(components).build(); +} + +} // namespace Antares::Solver::SystemConverter diff --git a/src/solver/systemParser/encoders.hxx b/src/solver/systemParser/encoders.hxx new file mode 100644 index 0000000000..17135195e9 --- /dev/null +++ b/src/solver/systemParser/encoders.hxx @@ -0,0 +1,95 @@ +/* + * 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 . + */ + +#pragma once + +#include "antares/solver/systemParser/system.h" + +#include "yaml-cpp/yaml.h" + +// Implement convert specializations +namespace YAML +{ + +/** + * @brief shortend to default construct a value when node is null + * @tparam T Type to convert the node to + * @param n node + * @return Object of type T + * It's just to simplify repertitve and verbose lines + * as_fallback_default>( +node["parameters"]) is equivalent to + node["parameters"].as>(std::vector()) + */ +template +inline T as_fallback_default(const Node& n) +{ + return n.as(T()); +} + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::SystemParser::Parameter& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.id = node["id"].as(); + rhs.type = node["type"].as(); + rhs.value = node["value"].as(); + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::SystemParser::Component& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.id = node["id"].as(); + rhs.model = node["model"].as(); + rhs.scenarioGroup = node["scenario-group"].as(); + rhs.parameters = as_fallback_default>( + node["parameters"]); + return true; + } +}; + +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::SystemParser::System& rhs) + { + rhs.id = node["id"].as(); + rhs.libraries = as_fallback_default>(node["model-libraries"]); + rhs.components = as_fallback_default>( + node["components"]); + return true; + } +}; + +} // namespace YAML diff --git a/src/solver/systemParser/include/antares/solver/systemParser/converter.h b/src/solver/systemParser/include/antares/solver/systemParser/converter.h new file mode 100644 index 0000000000..32c607b6e8 --- /dev/null +++ b/src/solver/systemParser/include/antares/solver/systemParser/converter.h @@ -0,0 +1,35 @@ +/* + * 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 . + */ + +#pragma once + +#include +#include + +#include "parser.h" + +namespace Antares::Solver::SystemConverter +{ + +Study::SystemModel::System convert(const SystemParser::System& parserSystem, + const std::vector& libraries); + +} // namespace Antares::Solver::SystemConverter diff --git a/src/solver/systemParser/include/antares/solver/systemParser/parser.h b/src/solver/systemParser/include/antares/solver/systemParser/parser.h new file mode 100644 index 0000000000..94aad258be --- /dev/null +++ b/src/solver/systemParser/include/antares/solver/systemParser/parser.h @@ -0,0 +1,32 @@ +/* + * 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 . + */ + +#pragma once +#include "antares/solver/systemParser/system.h" + +namespace Antares::Solver::SystemParser +{ +class Parser +{ +public: + System parse(const std::string& content); +}; +} // namespace Antares::Solver::SystemParser diff --git a/src/solver/systemParser/include/antares/solver/systemParser/system.h b/src/solver/systemParser/include/antares/solver/systemParser/system.h new file mode 100644 index 0000000000..888d136d5a --- /dev/null +++ b/src/solver/systemParser/include/antares/solver/systemParser/system.h @@ -0,0 +1,55 @@ +/* + * 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 . + */ + +#pragma once + +#include +#include + +namespace Antares::Solver::SystemParser +{ + +struct Parameter +{ + std::string id; + std::string type; + double value; +}; + +struct Component +{ + std::string id; + std::string model; + std::string scenarioGroup; + std::vector parameters; +}; + +struct System +{ + std::string id; + std::vector libraries; + std::vector components; + + // will be implemented later + // std::vector connections; +}; + +} // namespace Antares::Solver::SystemParser diff --git a/src/solver/systemParser/parser.cpp b/src/solver/systemParser/parser.cpp new file mode 100644 index 0000000000..76f7fa15d5 --- /dev/null +++ b/src/solver/systemParser/parser.cpp @@ -0,0 +1,40 @@ +/* + * 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 . + */ + +#include "antares/solver/systemParser/parser.h" + +#include "antares/solver/systemParser/system.h" + +#include "encoders.hxx" + +namespace Antares::Solver::SystemParser +{ + +System Parser::parse(const std::string& content) +{ + YAML::Node root = YAML::Load(content); + + System system = root["system"].as(); + + return system; +} + +} // namespace Antares::Solver::SystemParser diff --git a/src/study/system-model/component.cpp b/src/study/system-model/component.cpp index 1c3d360e64..87b9991865 100644 --- a/src/study/system-model/component.cpp +++ b/src/study/system-model/component.cpp @@ -45,14 +45,14 @@ static void checkComponentDataValidity(const ComponentData& data) if (data.model->Parameters().size() != data.parameter_values.size()) { throw std::invalid_argument( - "The component has " + std::to_string(data.parameter_values.size()) + "The component \"" + data.id + "\" has " + std::to_string(data.parameter_values.size()) + " parameter(s), but its model has " + std::to_string(data.model->Parameters().size())); } for (const auto param: data.model->Parameters() | std::views::keys) { if (!data.parameter_values.contains(param)) { - throw std::invalid_argument("The component has no value for parameter '" + param + "'"); + throw std::invalid_argument("The component \"" + data.id + "\" has no value for parameter '" + param + "'"); } } } diff --git a/src/study/system-model/include/antares/study/system-model/system.h b/src/study/system-model/include/antares/study/system-model/system.h index 50fa196399..80b042388e 100644 --- a/src/study/system-model/include/antares/study/system-model/system.h +++ b/src/study/system-model/include/antares/study/system-model/system.h @@ -68,7 +68,7 @@ class SystemBuilder { public: SystemBuilder& withId(std::string_view id); - SystemBuilder& withComponents(std::vector&& components); + SystemBuilder& withComponents(std::vector& components); System build() const; private: diff --git a/src/study/system-model/system.cpp b/src/study/system-model/system.cpp index 20a26287e1..70c1807d30 100644 --- a/src/study/system-model/system.cpp +++ b/src/study/system-model/system.cpp @@ -71,7 +71,7 @@ SystemBuilder& SystemBuilder::withId(std::string_view id) * \param components A vector of components to set. * \return Reference to the SystemBuilder object. */ -SystemBuilder& SystemBuilder::withComponents(std::vector&& components) +SystemBuilder& SystemBuilder::withComponents(std::vector& components) { components_ = std::move(components); return *this; diff --git a/src/tests/src/solver/modelParser/CMakeLists.txt b/src/tests/src/solver/modelParser/CMakeLists.txt index 9f884255d8..9c5fad1f82 100644 --- a/src/tests/src/solver/modelParser/CMakeLists.txt +++ b/src/tests/src/solver/modelParser/CMakeLists.txt @@ -5,6 +5,8 @@ set(SOURCE_FILES testConvertorVisitor.cpp test_full.cpp enum_operators.h + testSystemParser.cpp + testSystemConverter.cpp ) # Add executable @@ -14,9 +16,10 @@ add_executable(TestModelParser ${SOURCE_FILES}) target_link_libraries(TestModelParser PRIVATE Boost::unit_test_framework - Antares::solver-expressions + Antares::solver-expressions Antares::modelConverter Antares::modelParser + Antares::systemParser Antares::antares-study-system-model Antares::antlr-interface ) diff --git a/src/tests/src/solver/modelParser/testSystemConverter.cpp b/src/tests/src/solver/modelParser/testSystemConverter.cpp new file mode 100644 index 0000000000..1ba1bbb1fd --- /dev/null +++ b/src/tests/src/solver/modelParser/testSystemConverter.cpp @@ -0,0 +1,281 @@ +/* + * 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 . + */ + +#define WIN32_LEAN_AND_MEAN + +#include + +#include +#include +#include +#include "antares/solver/modelConverter/modelConverter.h" +#include "antares/solver/modelParser/parser.h" +#include "antares/study/system-model/library.h" + +using namespace std::string_literals; +using namespace Antares::Solver; +using namespace Antares::Study; + +struct LibraryObjects +{ + ModelParser::Model model1{.id = "node", + .description = "description", + .parameters = {{"cost", true, false}}, + .variables = {}, + .ports = {}, + .port_field_definitions = {}, + .constraints = {{"constraint1", "cost"}}, + .objective = ""}; + + SystemParser::Parser parser; + ModelParser::Library library; + std::vector libraries; + + LibraryObjects() + { + library.id = "std"; + library.models = {model1}; + libraries = {ModelConverter::convert(library)}; + } + + ~LibraryObjects() = default; +}; + +BOOST_FIXTURE_TEST_CASE(full_model_system, LibraryObjects) +{ + const auto system = R"( + system: + id: base_system + description: real application model + model-libraries: [std] + components: + - id: N + model: std.node + scenario-group: group-234 + parameters: + - id: cost + type: constant + value: 30 + )"s; + + SystemParser::System systemObj = parser.parse(system); + + auto systemModel = SystemConverter::convert(systemObj, libraries); + + BOOST_CHECK_EQUAL(systemModel.Components().size(), 1); + BOOST_CHECK_EQUAL(systemModel.Components().at("N").Id(), "N"); + BOOST_CHECK_EQUAL(systemModel.Components().at("N").getModel()->Id(), "node"); + BOOST_CHECK_EQUAL(systemModel.Components().at("N").getParameterValue("cost"), 30); +} + +BOOST_FIXTURE_TEST_CASE(bad_param_name_in_component, LibraryObjects) +{ + const auto system = R"( + system: + id: base_system + description: real application model + model-libraries: [std] + components: + - id: N + model: std.node + scenario-group: group-234 + parameters: + - id: param_not_in_model + type: constant + value: 30 + )"s; + + SystemParser::System systemObj = parser.parse(system); + + BOOST_CHECK_THROW(SystemConverter::convert(systemObj, libraries), std::invalid_argument); +} + +BOOST_FIXTURE_TEST_CASE(library_not_existing, LibraryObjects) +{ + const auto system = R"( + system: + id: base_system + model-libraries: [abc] + components: + - id: N + model: abc.node + scenario-group: group-234 + )"s; + + SystemParser::System systemObj = parser.parse(system); + + BOOST_CHECK_THROW(SystemConverter::convert(systemObj, libraries), std::runtime_error); +} + +BOOST_FIXTURE_TEST_CASE(model_not_existing, LibraryObjects) +{ + const auto system = R"( + system: + id: base_system + model-libraries: [std] + components: + - id: N + model: std.abc + scenario-group: group-234 + )"s; + + SystemParser::System systemObj = parser.parse(system); + + BOOST_CHECK_THROW(SystemConverter::convert(systemObj, libraries), std::runtime_error); +} + +BOOST_FIXTURE_TEST_CASE(bad_library_model_format, LibraryObjects) +{ + const auto system = R"( + system: + id: base_system + model-libraries: [std] + components: + - id: N + model: std___node + scenario-group: group-234 + parameters: + - id: cost + type: constant + value: 30 + )"s; + + SystemParser::System systemObj = parser.parse(system); + + BOOST_CHECK_THROW(SystemConverter::convert(systemObj, libraries), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(Full_system_test) +{ + const auto libraryYaml = R"( + library: + id: std + description: Standard library + port-types: [] + + models: + - id: generator + description: A basic generator model + parameters: + - id: cost + time-dependent: false + scenario-dependent: false + - id: p_max + time-dependent: false + scenario-dependent: false + variables: + - id: generation + lower-bound: 0 + upper-bound: p_max + ports: + - id: injection_port + type: flow + port-field-definitions: + - port: injection_port + field: flow + definition: generation + objective: cost * generation + + - id: node + description: A basic balancing node model + ports: + - id: injection_port + type: flow + binding-constraints: + - id: balance + expression: injection_port.flow = 0 + )"s; + + const auto libraryYaml2 = R"( + library: + id: mylib + description: Extra library + port-types: [] + + models: + - id: demand + description: A basic fixed demand model + parameters: + - id: demand + time-dependent: true + scenario-dependent: true + ports: + - id: injection_port + type: flow + port-field-definitions: + - port: injection_port + field: flow + definition: -demand + )"s; + + const auto systemYaml = R"( + system: + id: system1 + description: basic description + model-libraries: [std, mylib] + + components: + - id: N + model: std.node + scenario-group: group-234 + + - id: G + model: std.generator + scenario-group: group-234 + parameters: + - id: cost + type: constant + value: 30 + - id: p_max + type: constant + value: 100 + + - id: D + model: mylib.demand + scenario-group: group-qsf + parameters: + - id: demand + type: constant + value: 100 + )"s; + + ModelParser::Parser parserModel; + SystemParser::Parser parserSystem; + + std::vector libraries; + libraries.push_back(ModelConverter::convert(parserModel.parse(libraryYaml))); + libraries.push_back(ModelConverter::convert(parserModel.parse(libraryYaml2))); + + SystemParser::System systemObj = parserSystem.parse(systemYaml); + auto systemModel = SystemConverter::convert(systemObj, libraries); + + BOOST_CHECK_EQUAL(systemModel.Components().size(), 3); + BOOST_CHECK_EQUAL(systemModel.Components().at("N").Id(), "N"); + BOOST_CHECK_EQUAL(systemModel.Components().at("N").getModel()->Id(), "node"); + BOOST_CHECK_EQUAL(systemModel.Components().at("N").getScenarioGroupId(), "group-234"); + + BOOST_CHECK_EQUAL(systemModel.Components().at("G").getModel()->Id(), "generator"); + BOOST_CHECK_EQUAL(systemModel.Components().at("G").getParameterValue("cost"), 30); + BOOST_CHECK_EQUAL(systemModel.Components().at("G").getParameterValue("p_max"), 100); + + BOOST_CHECK_EQUAL(systemModel.Components().at("D").getModel()->Id(), "demand"); + BOOST_CHECK_EQUAL(systemModel.Components().at("D").getParameterValue("demand"), 100); +} diff --git a/src/tests/src/solver/modelParser/testSystemParser.cpp b/src/tests/src/solver/modelParser/testSystemParser.cpp new file mode 100644 index 0000000000..892e29467d --- /dev/null +++ b/src/tests/src/solver/modelParser/testSystemParser.cpp @@ -0,0 +1,184 @@ +/* + * 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 . + */ + +#define WIN32_LEAN_AND_MEAN + +#include + +#include +#include +#include + +using namespace std::string_literals; +using namespace Antares::Solver; +using namespace Antares::Study; + +BOOST_AUTO_TEST_CASE(empty_system) +{ + SystemParser::Parser parser; + const auto system = R"( + system: + id: "" + description: "" + model-libraries: [] + components: [] + )"s; + SystemParser::System systemObj = parser.parse(system); + BOOST_CHECK(systemObj.id.empty()); + BOOST_CHECK(systemObj.libraries.empty()); + BOOST_CHECK(systemObj.components.empty()); +} + +BOOST_AUTO_TEST_CASE(simple_id) +{ + SystemParser::Parser parser; + const auto system = R"( + system: + id: base_system + description: a basic system + )"s; + SystemParser::System systemObj = parser.parse(system); + BOOST_CHECK_EQUAL(systemObj.id, "base_system"); +} + +BOOST_AUTO_TEST_CASE(libraries_one_model) +{ + SystemParser::Parser parser; + const auto system = R"( + system: + id: base_system + model-libraries: [abc] + )"s; + SystemParser::System systemObj = parser.parse(system); + BOOST_CHECK_EQUAL(systemObj.libraries[0], "abc"); +} + +BOOST_AUTO_TEST_CASE(libraries_list_of_models) +{ + SystemParser::Parser parser; + const auto system = R"( + system: + id: base_system + description: 3 model libraries + model-libraries: [abc, def, 123] + components: [] + )"s; + SystemParser::System systemObj = parser.parse(system); + BOOST_CHECK_EQUAL(systemObj.libraries[0], "abc"); + BOOST_CHECK_EQUAL(systemObj.libraries[1], "def"); + BOOST_CHECK_EQUAL(systemObj.libraries[2], "123"); + BOOST_CHECK(systemObj.components.empty()); +} + +BOOST_AUTO_TEST_CASE(one_component) +{ + SystemParser::Parser parser; + const auto system = R"( + system: + id: base_system + description: one simple component + components: + - id: N + model: abcde + scenario-group: group-234 + )"s; + SystemParser::System systemObj = parser.parse(system); + BOOST_CHECK_EQUAL(systemObj.components[0].id, "N"); + BOOST_CHECK_EQUAL(systemObj.components[0].model, "abcde"); + BOOST_CHECK_EQUAL(systemObj.components[0].scenarioGroup, "group-234"); +} + +BOOST_AUTO_TEST_CASE(two_components) +{ + SystemParser::Parser parser; + const auto system = R"( + system: + id: base_system + description: two components + components: + - id: N + model: std.node + scenario-group: group-234 + - id: G + model: std.generator + scenario-group: group-thermal + )"s; + SystemParser::System systemObj = parser.parse(system); + BOOST_CHECK_EQUAL(systemObj.components[0].id, "N"); + BOOST_CHECK_EQUAL(systemObj.components[0].model, "std.node"); + BOOST_CHECK_EQUAL(systemObj.components[0].scenarioGroup, "group-234"); + BOOST_CHECK_EQUAL(systemObj.components[1].id, "G"); + BOOST_CHECK_EQUAL(systemObj.components[1].model, "std.generator"); + BOOST_CHECK_EQUAL(systemObj.components[1].scenarioGroup, "group-thermal"); +} + +BOOST_AUTO_TEST_CASE(component_parameter) +{ + SystemParser::Parser parser; + const auto system = R"( + system: + id: base_system + description: one component with one parameter + components: + - id: N + model: std.node + scenario-group: group-234 + parameters: + - id: cost + type: constant + value: 30 + )"s; + SystemParser::System systemObj = parser.parse(system); + const auto& param = systemObj.components[0].parameters[0]; + BOOST_CHECK_EQUAL(param.id, "cost"); + BOOST_CHECK_EQUAL(param.type, "constant"); + BOOST_CHECK_EQUAL(param.value, 30); +} + +BOOST_AUTO_TEST_CASE(component_two_parameters) +{ + SystemParser::Parser parser; + const auto system = R"( + system: + id: base_system + description: one component with one parameter + components: + - id: N + model: std.node + scenario-group: group-234 + parameters: + - id: cost + type: constant + value: 30 + - id: p_max + type: constant + value: 100 + )"s; + SystemParser::System systemObj = parser.parse(system); + const auto& param = systemObj.components[0].parameters[0]; + const auto& param2 = systemObj.components[0].parameters[1]; + BOOST_CHECK_EQUAL(param.id, "cost"); + BOOST_CHECK_EQUAL(param.type, "constant"); + BOOST_CHECK_EQUAL(param.value, 30); + BOOST_CHECK_EQUAL(param2.id, "p_max"); + BOOST_CHECK_EQUAL(param2.type, "constant"); + BOOST_CHECK_EQUAL(param2.value, 100); +} diff --git a/src/tests/src/study/system-model/test_component.cpp b/src/tests/src/study/system-model/test_component.cpp index 3f52b33880..ca8e0c93f4 100644 --- a/src/tests/src/study/system-model/test_component.cpp +++ b/src/tests/src/study/system-model/test_component.cpp @@ -159,7 +159,8 @@ BOOST_AUTO_TEST_CASE(fail_on_no_params1) .withScenarioGroupId("scenario_group"); BOOST_CHECK_EXCEPTION(component_builder.build(), std::invalid_argument, - checkMessage("The component has 0 parameter(s), but its model has 2")); + checkMessage( + "The component \"component\" has 0 parameter(s), but its model has 2")); } BOOST_AUTO_TEST_CASE(fail_on_no_params2) @@ -171,7 +172,8 @@ BOOST_AUTO_TEST_CASE(fail_on_no_params2) .withScenarioGroupId("scenario_group"); BOOST_CHECK_EXCEPTION(component_builder.build(), std::invalid_argument, - checkMessage("The component has 0 parameter(s), but its model has 2")); + checkMessage( + "The component \"component\" has 0 parameter(s), but its model has 2")); } BOOST_AUTO_TEST_CASE(fail_on_missing_param) @@ -183,7 +185,8 @@ BOOST_AUTO_TEST_CASE(fail_on_missing_param) .withScenarioGroupId("scenario_group"); BOOST_CHECK_EXCEPTION(component_builder.build(), std::invalid_argument, - checkMessage("The component has 1 parameter(s), but its model has 2")); + checkMessage( + "The component \"component\" has 1 parameter(s), but its model has 2")); } BOOST_AUTO_TEST_CASE(fail_on_missing_wrong_param) @@ -195,7 +198,8 @@ BOOST_AUTO_TEST_CASE(fail_on_missing_wrong_param) .withScenarioGroupId("scenario_group"); BOOST_CHECK_EXCEPTION(component_builder.build(), std::invalid_argument, - checkMessage("The component has no value for parameter 'param1'")); + checkMessage( + "The component \"component\" has no value for parameter 'param1'")); } BOOST_AUTO_TEST_CASE(fail_on_too_many_params1) @@ -207,7 +211,8 @@ BOOST_AUTO_TEST_CASE(fail_on_too_many_params1) .withScenarioGroupId("scenario_group"); BOOST_CHECK_EXCEPTION(component_builder.build(), std::invalid_argument, - checkMessage("The component has 3 parameter(s), but its model has 2")); + checkMessage( + "The component \"component\" has 3 parameter(s), but its model has 2")); } BOOST_AUTO_TEST_CASE(fail_on_too_many_params2) @@ -219,7 +224,8 @@ BOOST_AUTO_TEST_CASE(fail_on_too_many_params2) .withScenarioGroupId("scenario_group"); BOOST_CHECK_EXCEPTION(component_builder.build(), std::invalid_argument, - checkMessage("The component has 1 parameter(s), but its model has 0")); + checkMessage( + "The component \"component\" has 1 parameter(s), but its model has 0")); } BOOST_AUTO_TEST_SUITE_END() diff --git a/src/tests/src/study/system-model/test_system.cpp b/src/tests/src/study/system-model/test_system.cpp index 550ca59693..03436fa365 100644 --- a/src/tests/src/study/system-model/test_system.cpp +++ b/src/tests/src/study/system-model/test_system.cpp @@ -32,6 +32,7 @@ using namespace Antares::Study::SystemModel; struct SystemBuilderCreationFixture { SystemBuilder system_builder; + std::vector components; }; static Component createComponent(std::string id) @@ -50,9 +51,8 @@ BOOST_AUTO_TEST_SUITE(_System_) BOOST_FIXTURE_TEST_CASE(nominal_build, SystemBuilderCreationFixture) { - auto system = system_builder.withId("system") - .withComponents({createComponent("component1"), createComponent("component2")}) - .build(); + components = {createComponent("component1"), createComponent("component2")}; + auto system = system_builder.withId("system").withComponents(components).build(); BOOST_CHECK_EQUAL(system.Id(), "system"); BOOST_CHECK_EQUAL(system.Components().size(), 2); BOOST_CHECK_EQUAL(system.Components().at("component1").Id(), "component1"); @@ -61,7 +61,8 @@ BOOST_FIXTURE_TEST_CASE(nominal_build, SystemBuilderCreationFixture) BOOST_FIXTURE_TEST_CASE(fail_on_no_id, SystemBuilderCreationFixture) { - system_builder.withComponents({createComponent("component1"), createComponent("component2")}); + components = {createComponent("component1"), createComponent("component2")}; + system_builder.withComponents(components); BOOST_CHECK_EXCEPTION(system_builder.build(), std::invalid_argument, checkMessage("A system can't have an empty id")); @@ -77,7 +78,7 @@ BOOST_FIXTURE_TEST_CASE(fail_on_no_component1, SystemBuilderCreationFixture) BOOST_FIXTURE_TEST_CASE(fail_on_no_component2, SystemBuilderCreationFixture) { - system_builder.withId("system").withComponents({}); + system_builder.withId("system").withComponents(components); BOOST_CHECK_EXCEPTION(system_builder.build(), std::invalid_argument, checkMessage("A system must contain at least one component")); @@ -85,10 +86,10 @@ BOOST_FIXTURE_TEST_CASE(fail_on_no_component2, SystemBuilderCreationFixture) BOOST_FIXTURE_TEST_CASE(fail_on_components_with_same_id, SystemBuilderCreationFixture) { - system_builder.withId("system").withComponents({}).withComponents( - {createComponent("component1"), - createComponent("component2"), - createComponent("component2")}); + components = {createComponent("component1"), + createComponent("component2"), + createComponent("component2")}; + system_builder.withId("system").withComponents({components}); BOOST_CHECK_EXCEPTION(system_builder.build(), std::invalid_argument, checkMessage("System has at least two components with the same id " From 5b14f61ccbd4b05356380b074bbf8f73b9477eab Mon Sep 17 00:00:00 2001 From: Abdoulbari Zaher <32519851+a-zakir@users.noreply.github.com> Date: Thu, 19 Dec 2024 14:35:59 +0100 Subject: [PATCH 04/14] Adding constraints on injection-witdrawal cumulation with constant RHS [ANT-1885] (#2535) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This pull request introduces new functionality for handling additional constraints in the short-term storage component of the Antares Simulator. The changes include adding new files, modifying existing classes to support the new constraints, and updating the build configuration to include the new files. Below are the most important changes: ### New Functionality for Additional Constraints * Added `AdditionalConstraint` structure and related methods to handle validation and storage of constraints. (`src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.h`, [src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.hR1-R53](diffhunk://#diff-28f2057f7eba48ae42dec99b653d4022ea6604fa48a13ae8ac1b806315506e27R1-R53)) * Implemented methods to load additional constraints from an INI file and validate them. (`src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cpp`, [src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cppR1-R65](diffhunk://#diff-3621d191c85fb5b66bcbfeaf356663b248edc889bb73333496d195ab52e278f5R1-R65)) ### Modifications to Existing Classes * Updated `STStorageCluster` to include a vector of `AdditionalConstraint` objects and added necessary methods to handle these constraints. (`src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h`, [src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.hR39-R54](diffhunk://#diff-bdfebe31db8d5e9aa119ac2793a107597bca647f65f399d1f408060f4e945ef9R39-R54)) * Modified `STStorageInput` to load constraints from an INI file and calculate the cumulative constraint count. (`src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h`, [[1]](diffhunk://#diff-52dc8a33c0238cd4143e96739e689b64a1723f13f3d09a4aca5ac9f62f21b882R35-R57); `src/libs/antares/study/parts/short-term-storage/container.cpp`, [[2]](diffhunk://#diff-cec1ba69ce05b7ff57b2fa19d1fd601b94db222e9fdd0b784d6be9313ce4f790R78-R154) [[3]](diffhunk://#diff-cec1ba69ce05b7ff57b2fa19d1fd601b94db222e9fdd0b784d6be9313ce4f790R195-R203) ### Build Configuration Updates * Updated `CMakeLists.txt` to include new header and source files for additional constraints. (`src/libs/antares/study/CMakeLists.txt`, [[1]](diffhunk://#diff-8710cc094e1d5a6f4a53b07116cd0d335fe1efb285e154dcd5b3a3c297079647R105-R107); `src/solver/optimisation/CMakeLists.txt`, [[2]](diffhunk://#diff-8d1079b5acad0fbdef8bc452ff03744eae4089d018b72461e91e31eba16ec714R85-R87) ### Solver Integration * Integrated the handling of additional constraints into the solver's optimization process by adding new methods and including the necessary headers. (`src/solver/optimisation/constraints/Group1.cpp`, [[1]](diffhunk://#diff-819577c61bf6475f45b1df04e74fb7d665c6fc52c36f3484a1a0dc1c0421facdR25) [[2]](diffhunk://#diff-819577c61bf6475f45b1df04e74fb7d665c6fc52c36f3484a1a0dc1c0421facdR53-R59) [[3]](diffhunk://#diff-819577c61bf6475f45b1df04e74fb7d665c6fc52c36f3484a1a0dc1c0421facdR100-R104) [[4]](diffhunk://#diff-819577c61bf6475f45b1df04e74fb7d665c6fc52c36f3484a1a0dc1c0421facdR139-R143) ### Runtime Information * Enhanced `StudyRuntimeInfos` to include cumulative constraint counts for short-term storage. (`src/libs/antares/study/runtime/runtime.h`, [[1]](diffhunk://#diff-458433d2f769bbbcbc330ee42ec7258665121c44c7971082cfda8f95bae3b029R113); `src/libs/antares/study/runtime/runtime.cpp`, [[2]](diffhunk://#diff-c5ee413f02cb61b2ec6d93145fcd7254e1d566a391a7ffccf66da9851fc8e746R97-R98) [[3]](diffhunk://#diff-c5ee413f02cb61b2ec6d93145fcd7254e1d566a391a7ffccf66da9851fc8e746R368-R369) These changes collectively add support for additional constraints in the short-term storage component, ensuring they are loaded, validated, and integrated into the simulation and optimization processes. --------- Co-authored-by: Florian Omnès --- src/libs/antares/study/CMakeLists.txt | 10 +- src/libs/antares/study/area/list.cpp | 1 + .../short-term-storage/AdditionalConstraint.h | 53 ++++++ .../study/parts/short-term-storage/cluster.h | 5 + .../parts/short-term-storage/container.h | 12 +- .../include/antares/study/runtime/runtime.h | 1 + .../AdditionalConstraint.cpp | 65 ++++++++ .../parts/short-term-storage/cluster.cpp | 2 - .../parts/short-term-storage/container.cpp | 89 +++++++++- src/libs/antares/study/runtime/runtime.cpp | 4 + src/solver/optimisation/CMakeLists.txt | 2 + .../optimisation/constraints/Group1.cpp | 18 ++ .../ShortTermStorageCumulation.cpp | 157 ++++++++++++++++++ .../constraints/ConstraintBuilder.h | 5 + .../solver/optimisation/constraints/Group1.h | 3 + .../constraints/ShortTermStorageCumulation.h | 39 +++++ .../solver/optimisation/opt_rename_problem.h | 10 ++ .../opt_decompte_variables_et_contraintes.cpp | 36 ++-- ...opt_gestion_second_membre_cas_lineaire.cpp | 25 ++- .../optimisation/opt_rename_problem.cpp | 17 +- .../simulation/sim_alloc_probleme_hebdo.h | 2 + .../sim_structure_probleme_economique.h | 3 +- .../simulation/sim_alloc_probleme_hebdo.cpp | 8 + .../simulation/sim_calcul_economique.cpp | 8 +- 24 files changed, 546 insertions(+), 29 deletions(-) create mode 100644 src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.h create mode 100644 src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cpp create mode 100644 src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp create mode 100644 src/solver/optimisation/include/antares/solver/optimisation/constraints/ShortTermStorageCumulation.h diff --git a/src/libs/antares/study/CMakeLists.txt b/src/libs/antares/study/CMakeLists.txt index 29a89fc631..e7336d020c 100644 --- a/src/libs/antares/study/CMakeLists.txt +++ b/src/libs/antares/study/CMakeLists.txt @@ -74,8 +74,8 @@ set(SRC_STUDY_PART_THERMAL include/antares/study/parts/thermal/cost_provider.h include/antares/study/parts/thermal/cluster.hxx parts/thermal/cluster.cpp - parts/thermal/scenarized_cost_provider.cpp - parts/thermal/constant_cost_provider.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 @@ -102,7 +102,9 @@ set(SRC_STUDY_PART_SHORT_TERM_STORAGE parts/short-term-storage/series.cpp include/antares/study/parts/short-term-storage/series.h include/antares/study/parts/short-term-storage/cluster.h + include/antares/study/parts/short-term-storage/AdditionalConstraint.h parts/short-term-storage/cluster.cpp + parts/short-term-storage/AdditionalConstraint.cpp ) source_group("study\\part\\short-term-storage" FILES ${SRC_STUDY_PART_SHORT_TERM_SOTRAGE}) @@ -306,12 +308,12 @@ target_link_libraries(study ) target_include_directories(study - PUBLIC + PUBLIC $ # Make more than just study visible but it's the lesser evil for now ) -install(DIRECTORY include/antares +install(DIRECTORY include/antares DESTINATION "include" ) diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index cf2624515f..7af3a6a5a7 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -1199,6 +1199,7 @@ bool AreaList::loadFromFolder(const StudyLoadOptions& options) fs::path folder = stsFolder / "clusters" / area->id.c_str(); ret = area->shortTermStorage.createSTStorageClustersFromIniFile(folder) && ret; + ret = area->shortTermStorage.LoadConstraintsFromIniFile(folder) && ret; } } else diff --git a/src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.h b/src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.h new file mode 100644 index 0000000000..e16b991a05 --- /dev/null +++ b/src/libs/antares/study/include/antares/study/parts/short-term-storage/AdditionalConstraint.h @@ -0,0 +1,53 @@ +/* + * 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 . + */ + +#pragma once +#include +#include + +namespace Antares::Data::ShortTermStorage +{ + +struct AdditionalConstraint +{ + std::string name; + std::string cluster_id; + std::string variable; + std::string operatorType; + std::set hours; + double rhs; + + unsigned int globalIndex = 0; + + struct ValidateResult + { + bool ok; + std::string error_msg; + }; + + ValidateResult validate() const; + +private: + bool isValidVariable() const; + bool isValidOperatorType() const; + bool isValidHoursRange() const; +}; +} // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h b/src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h index b4074a28c8..df74a350b0 100644 --- a/src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h +++ b/src/libs/antares/study/include/antares/study/parts/short-term-storage/cluster.h @@ -26,6 +26,7 @@ #include +#include "AdditionalConstraint.h" #include "properties.h" #include "series.h" @@ -35,17 +36,21 @@ class STStorageCluster { public: bool enabled() const; + bool validate() const; bool loadFromSection(const IniFile::Section& section); + bool loadSeries(const std::filesystem::path& folder) const; void saveProperties(IniFile& ini) const; + bool saveSeries(const std::string& path) const; std::string id; std::shared_ptr series = std::make_shared(); mutable Properties properties; + std::vector additional_constraints; }; } // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h b/src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h index 90f8fafbce..d4e0233b5c 100644 --- a/src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h +++ b/src/libs/antares/study/include/antares/study/parts/short-term-storage/container.h @@ -21,9 +21,9 @@ #pragma once #include -#include #include +#include "AdditionalConstraint.h" #include "cluster.h" namespace Antares::Data::ShortTermStorage @@ -32,18 +32,28 @@ class STStorageInput { public: bool validate() const; + /// 1. Read list.ini bool createSTStorageClustersFromIniFile(const std::filesystem::path& path); + /// 2. Read ALL series bool loadSeriesFromFolder(const std::filesystem::path& folder) const; + /// Number of enabled ST storages, ignoring disabled ST storages std::size_t count() const; + + bool LoadConstraintsFromIniFile(const std::filesystem::path& filePath); + /// erase disabled cluster from the vector uint removeDisabledClusters(); bool saveToFolder(const std::string& folder) const; + bool saveDataSeriesToFolder(const std::string& folder) const; std::vector storagesByIndex; + + /// Number cumulative - constraint + std::size_t cumulativeConstraintCount() const; }; } // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/include/antares/study/runtime/runtime.h b/src/libs/antares/study/include/antares/study/runtime/runtime.h index 858719ab27..fe394199df 100644 --- a/src/libs/antares/study/include/antares/study/runtime/runtime.h +++ b/src/libs/antares/study/include/antares/study/runtime/runtime.h @@ -110,6 +110,7 @@ class StudyRuntimeInfos uint thermalPlantTotalCountMustRun; uint shortTermStorageCount = 0; + uint shortTermStorageCumulativeConstraintCount = 0; //! Override enable/disable TS generation per cluster bool thermalTSRefresh = false; diff --git a/src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cpp b/src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cpp new file mode 100644 index 0000000000..2ca904041c --- /dev/null +++ b/src/libs/antares/study/parts/short-term-storage/AdditionalConstraint.cpp @@ -0,0 +1,65 @@ +/* +** 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 . +*/ +#include "antares/study/parts/short-term-storage/AdditionalConstraint.h" + +namespace Antares::Data::ShortTermStorage +{ +AdditionalConstraint::ValidateResult AdditionalConstraint::validate() const +{ + if (cluster_id.empty()) + { + return {false, "Cluster ID is empty."}; + } + + if (!isValidVariable()) + { + return {false, "Invalid variable type. Must be 'injection', 'withdrawal', or 'netting'."}; + } + + if (!isValidOperatorType()) + { + return {false, "Invalid operator type. Must be 'less', 'equal', or 'greater'."}; + } + + if (!isValidHoursRange()) + { + return {false, "Hours set contains invalid values. Must be between 1 and 168."}; + } + + return {true, ""}; +} + +bool AdditionalConstraint::isValidHoursRange() const +{ + // `hours` is a sorted set; begin() gives the smallest and prev(end()) gives the largest. + return !hours.empty() && *hours.begin() >= 1 && *std::prev(hours.end()) <= 168; +} + +bool AdditionalConstraint::isValidVariable() const +{ + return variable == "injection" || variable == "withdrawal" || variable == "netting"; +} + +bool AdditionalConstraint::isValidOperatorType() const +{ + return operatorType == "less" || operatorType == "equal" || operatorType == "greater"; +} +} // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/parts/short-term-storage/cluster.cpp b/src/libs/antares/study/parts/short-term-storage/cluster.cpp index 787d1c85e6..cbfb7e679f 100644 --- a/src/libs/antares/study/parts/short-term-storage/cluster.cpp +++ b/src/libs/antares/study/parts/short-term-storage/cluster.cpp @@ -28,7 +28,6 @@ namespace Antares::Data::ShortTermStorage { - bool STStorageCluster::loadFromSection(const IniFile::Section& section) { if (!section.firstProperty) @@ -92,5 +91,4 @@ bool STStorageCluster::saveSeries(const std::string& path) const { return series->saveToFolder(path); } - } // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/parts/short-term-storage/container.cpp b/src/libs/antares/study/parts/short-term-storage/container.cpp index bee1546ec4..39a958c5c7 100644 --- a/src/libs/antares/study/parts/short-term-storage/container.cpp +++ b/src/libs/antares/study/parts/short-term-storage/container.cpp @@ -22,11 +22,13 @@ #include "antares/study/parts/short-term-storage/container.h" #include +#include #include #include #include +#include #define SEP Yuni::IO::Separator @@ -73,6 +75,83 @@ bool STStorageInput::createSTStorageClustersFromIniFile(const fs::path& path) return true; } +bool STStorageInput::LoadConstraintsFromIniFile(const fs::path& parent_path) +{ + IniFile ini; + const auto pathIni = parent_path / "additional-constraints.ini"; + if (!ini.open(pathIni, false)) + { + logs.info() << "There is no: " << pathIni; + return true; + } + + for (auto* section = ini.firstSection; section; section = section->next) + { + AdditionalConstraint constraint; + constraint.name = section->name.c_str(); + for (auto* property = section->firstProperty; property; property = property->next) + { + const std::string key = property->key; + const auto value = property->value; + + if (key == "cluster") + { + // TODO do i have to transform the name to id? TransformNameIntoID + std::string clusterName; + value.to(clusterName); + constraint.cluster_id = transformNameIntoID(clusterName); + } + else if (key == "variable") + { + value.to(constraint.variable); + } + else if (key == "operator") + { + value.to(constraint.operatorType); + } + else if (key == "hours") + { + std::stringstream ss(value.c_str()); + std::string hour; + while (std::getline(ss, hour, ',')) + { + int hourVal = std::stoi(hour); + constraint.hours.insert(hourVal); + } + } + else if (key == "rhs") + { + property->value.to(constraint.rhs); + } + } + + if (auto ret = constraint.validate(); !ret.ok) + { + logs.error() << "Invalid constraint in section: " << section->name; + logs.error() << ret.error_msg; + return false; + } + + auto it = std::find_if(storagesByIndex.begin(), + storagesByIndex.end(), + [&constraint](const STStorageCluster& cluster) + { return cluster.id == constraint.cluster_id; }); + if (it == storagesByIndex.end()) + { + logs.warning() << " from file " << pathIni; + logs.warning() << "Constraint " << section->name + << " does not reference an existing cluster"; + return false; + } + else + { + it->additional_constraints.push_back(constraint); + } + } + + return true; +} + bool STStorageInput::loadSeriesFromFolder(const fs::path& folder) const { if (folder.empty()) @@ -113,6 +192,15 @@ bool STStorageInput::saveDataSeriesToFolder(const std::string& folder) const { return storage.saveSeries(folder + SEP + storage.id); }); } +std::size_t STStorageInput::cumulativeConstraintCount() const +{ + return std::accumulate(storagesByIndex.begin(), + storagesByIndex.end(), + 0, + [](int acc, const auto& cluster) + { return acc + cluster.additional_constraints.size(); }); +} + std::size_t STStorageInput::count() const { return std::ranges::count_if(storagesByIndex, @@ -123,5 +211,4 @@ uint STStorageInput::removeDisabledClusters() { return std::erase_if(storagesByIndex, [](const auto& c) { return !c.enabled(); }); } - } // namespace Antares::Data::ShortTermStorage diff --git a/src/libs/antares/study/runtime/runtime.cpp b/src/libs/antares/study/runtime/runtime.cpp index 3bca4404a5..32bfb0f28e 100644 --- a/src/libs/antares/study/runtime/runtime.cpp +++ b/src/libs/antares/study/runtime/runtime.cpp @@ -94,6 +94,8 @@ static void StudyRuntimeInfosInitializeAllAreas(Study& study, StudyRuntimeInfos& r.thermalPlantTotalCountMustRun += area.thermal.list.enabledAndMustRunCount(); r.shortTermStorageCount += area.shortTermStorage.count(); + r.shortTermStorageCumulativeConstraintCount += area.shortTermStorage + .cumulativeConstraintCount(); } } @@ -363,6 +365,8 @@ bool StudyRuntimeInfos::loadFromStudy(Study& study) logs.info() << " thermal clusters: " << thermalPlantTotalCount; logs.info() << " thermal clusters (must-run): " << thermalPlantTotalCountMustRun; logs.info() << " short-term storages: " << shortTermStorageCount; + logs.info() << " short-term storage cumulative constraints count: " + << shortTermStorageCumulativeConstraintCount; logs.info() << " binding constraints: " << study.bindingConstraints.activeConstraints().size(); logs.info() << " geographic trimming:" << (gd.geographicTrimming ? "true" : "false"); diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt index 57194b388a..ec98f298e8 100644 --- a/src/solver/optimisation/CMakeLists.txt +++ b/src/solver/optimisation/CMakeLists.txt @@ -82,7 +82,9 @@ set(RTESOLVER_OPT include/antares/solver/optimisation/constraints/ShortTermStorageLevel.h constraints/ShortTermStorageLevel.cpp include/antares/solver/optimisation/constraints/ShortTermStorageCostVariation.h + include/antares/solver/optimisation/constraints/ShortTermStorageCumulation.h constraints/ShortTermStorageCostVariation.cpp + constraints/ShortTermStorageCumulation.cpp constraints/ShortTermStorageCostVariationInjectionForward.cpp constraints/ShortTermStorageCostVariationInjectionBackward.cpp constraints/ShortTermStorageCostVariationWithdrawalForward.cpp diff --git a/src/solver/optimisation/constraints/Group1.cpp b/src/solver/optimisation/constraints/Group1.cpp index 810b957aee..61de7cf2b3 100644 --- a/src/solver/optimisation/constraints/Group1.cpp +++ b/src/solver/optimisation/constraints/Group1.cpp @@ -22,6 +22,7 @@ #include "antares/solver/optimisation/constraints/Group1.h" #include "antares/solver/optimisation/constraints/ShortTermStorageCostVariation.h" +#include "antares/solver/optimisation/constraints/ShortTermStorageCumulation.h" AreaBalanceData Group1::GetAreaBalanceData() { @@ -49,6 +50,13 @@ ShortTermStorageData Group1::GetShortTermStorageData() }; } +ShortTermStorageCumulativeConstraintData Group1::GetShortTermStorageCumulativeConstraintData() +{ + return {problemeHebdo_->CorrespondanceCntNativesCntOptim, + problemeHebdo_->ShortTermStorage, + problemeHebdo_->CorrespondanceCntNativesCntOptimHebdomadaires}; +} + FlowDissociationData Group1::GetFlowDissociationData() { return {.CorrespondanceCntNativesCntOptim = problemeHebdo_->CorrespondanceCntNativesCntOptim, @@ -89,6 +97,11 @@ void Group1::BuildConstraints() ShortTermStorageCostVariationWithdrawalForward shortTermStorageCostVariationWithdrawalForward( builder_, shortTermStorageData); + + auto shortTermStorageCumulativeConstraintData = GetShortTermStorageCumulativeConstraintData(); + ShortTermStorageCumulation shortTermStorageCumulation(builder_, + shortTermStorageCumulativeConstraintData); + auto flowDissociationData = GetFlowDissociationData(); FlowDissociation flowDissociation(builder_, flowDissociationData); @@ -123,4 +136,9 @@ void Group1::BuildConstraints() bindingConstraintHour.add(pdt, cntCouplante); } } + + for (uint32_t pays = 0; pays < problemeHebdo_->NombreDePays; ++pays) + { + shortTermStorageCumulation.add(pays); + } } diff --git a/src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp b/src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp new file mode 100644 index 0000000000..f6e684db83 --- /dev/null +++ b/src/solver/optimisation/constraints/ShortTermStorageCumulation.cpp @@ -0,0 +1,157 @@ +/* + * 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 . + */ + +#include "antares/solver/optimisation/constraints/ShortTermStorageCumulation.h" + +#include +#include + +class CumulationConstraint +{ +public: + virtual void build(ConstraintBuilder& builder, + unsigned int index, + const ::ShortTermStorage::PROPERTIES& input) const + = 0; + virtual std::string name() const = 0; + virtual ~CumulationConstraint() = default; +}; + +class WithdrawalCumulationConstraint: public CumulationConstraint +{ +public: + void build(ConstraintBuilder& builder, + unsigned int index, + const ::ShortTermStorage::PROPERTIES&) const override + { + builder.ShortTermStorageWithdrawal(index, 1.0); + } + + std::string name() const override + { + return "WithdrawalSum"; + } + + ~WithdrawalCumulationConstraint() override = default; +}; + +class InjectionCumulationConstraint: public CumulationConstraint +{ +public: + void build(ConstraintBuilder& builder, + unsigned int index, + const ::ShortTermStorage::PROPERTIES&) const override + { + builder.ShortTermStorageInjection(index, 1.0); + } + + std::string name() const override + { + return "InjectionSum"; + } + + ~InjectionCumulationConstraint() override = default; +}; + +class NettingCumulationConstraint: public CumulationConstraint +{ +public: + void build(ConstraintBuilder& builder, + unsigned int index, + const ::ShortTermStorage::PROPERTIES& input) const override + { + builder.ShortTermStorageInjection(index, input.injectionEfficiency) + .ShortTermStorageWithdrawal(index, -input.withdrawalEfficiency); + } + + std::string name() const override + { + return "NettingSum"; + } + + ~NettingCumulationConstraint() override = default; +}; + +std::unique_ptr cumulationConstraintFromVariable(const std::string& variable) +{ + if (variable == "withdrawal") + { + return std::make_unique(); + } + else if (variable == "injection") + { + return std::make_unique(); + } + else if (variable == "netting") + { + return std::make_unique(); + } + throw std::invalid_argument("Invalid cumulation constraint type"); +} + +char ConvertSense(const std::string& sense) +{ + if (sense == "greater") + { + return '>'; + } + else if (sense == "less") + { + return '<'; + } + else + { + return '='; + } +} + +void ShortTermStorageCumulation::add(int pays) +{ + ConstraintNamer namer(builder.data.NomDesContraintes); + namer.UpdateArea(builder.data.NomsDesPays[pays]); + + for (const auto& storage: data.ShortTermStorage[pays]) + { + for (const auto& constraint: storage.additional_constraints) + { + // sum (var[h]) sign rhs, h in list provided by user where: + // var = injection for InjectionCumulationConstraint + // var = withdrawal for WithdrawalCumulationConstraint + // var = injectionEfficiency * injection - withdrawalEfficiency * withdrawal for Netting + auto constraintHelper = cumulationConstraintFromVariable(constraint.variable); + namer.ShortTermStorageCumulation(constraintHelper->name(), + builder.data.nombreDeContraintes, + storage.name, + constraint.name); + const auto index = storage.clusterGlobalIndex; + data.CorrespondanceCntNativesCntOptimHebdomadaires + .ShortTermStorageCumulation[constraint.globalIndex] + = builder.data.nombreDeContraintes; + + for (const auto& hour: constraint.hours) + { + builder.updateHourWithinWeek(hour - 1); + constraintHelper->build(builder, index, storage); + } + builder.SetOperator(ConvertSense(constraint.operatorType)).build(); + } + } +} diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h index b06af4614d..31019332d3 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/ConstraintBuilder.h @@ -305,3 +305,8 @@ struct ShortTermStorageData const std::vector<::ShortTermStorage::AREA_INPUT>& ShortTermStorage; }; + +struct ShortTermStorageCumulativeConstraintData: ShortTermStorageData +{ + CORRESPONDANCES_DES_CONTRAINTES_HEBDOMADAIRES& CorrespondanceCntNativesCntOptimHebdomadaires; +}; diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/Group1.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/Group1.h index e5134edb6e..c74567716e 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/constraints/Group1.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/Group1.h @@ -38,6 +38,9 @@ class Group1: public ConstraintGroup AreaBalanceData GetAreaBalanceData(); FictitiousLoadData GetFictitiousLoadData(); ShortTermStorageData GetShortTermStorageData(); + + ShortTermStorageCumulativeConstraintData GetShortTermStorageCumulativeConstraintData(); + FlowDissociationData GetFlowDissociationData(); BindingConstraintHourData GetBindingConstraintHourData(); }; diff --git a/src/solver/optimisation/include/antares/solver/optimisation/constraints/ShortTermStorageCumulation.h b/src/solver/optimisation/include/antares/solver/optimisation/constraints/ShortTermStorageCumulation.h new file mode 100644 index 0000000000..2c4c540158 --- /dev/null +++ b/src/solver/optimisation/include/antares/solver/optimisation/constraints/ShortTermStorageCumulation.h @@ -0,0 +1,39 @@ +/* + * 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 . + */ + +#pragma once +#include "ConstraintBuilder.h" + +class ShortTermStorageCumulation: ConstraintFactory +{ +public: + ShortTermStorageCumulation(ConstraintBuilder& builder, + ShortTermStorageCumulativeConstraintData& data): + ConstraintFactory(builder), + data(data) + { + } + + void add(int pays); + +private: + ShortTermStorageCumulativeConstraintData& data; +}; diff --git a/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h b/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h index f05b6eb15a..c7c3dff284 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/opt_rename_problem.h @@ -166,6 +166,11 @@ class ConstraintNamer: public Namer unsigned int constraint, const std::string& short_term_name); + void ShortTermStorageCumulation(const std::string& constraint_type, + unsigned int constraint, + const std::string& short_term_name, + const std::string& constraint_name); + private: void nameWithTimeGranularity(unsigned int constraint, const std::string& name, @@ -177,6 +182,11 @@ inline std::string TimeIdentifier(unsigned int timeStep, const std::string& time return timeStepType + "<" + std::to_string(timeStep) + ">"; } +inline std::string ShortTermStorageCumulationIdentifier(const std::string& name) +{ + return "Constraint<" + name + ">"; +} + inline std::string LocationIdentifier(const std::string& location, const std::string& locationType) { return locationType + "<" + location + ">"; diff --git a/src/solver/optimisation/opt_decompte_variables_et_contraintes.cpp b/src/solver/optimisation/opt_decompte_variables_et_contraintes.cpp index d1a0f00ea2..79c29c58ab 100644 --- a/src/solver/optimisation/opt_decompte_variables_et_contraintes.cpp +++ b/src/solver/optimisation/opt_decompte_variables_et_contraintes.cpp @@ -144,12 +144,12 @@ int OPT_DecompteDesVariablesEtDesContraintesDuProblemeAOptimiser(PROBLEME_HEBDO* ProblemeAResoudre->NombreDeContraintes += 2; /* 2 constraints bounding the overall energy generated over the period (10a in the reference document) */ - ProblemeAResoudre - ->NombreDeContraintes++; /* 1 constraint setting the level variation over the period - (10b in the reference document) */ - ProblemeAResoudre - ->NombreDeContraintes++; /* 1 constraint bounding the overall energy pumped over the - period (10c in the reference document) */ + ProblemeAResoudre->NombreDeContraintes++; + /* 1 constraint setting the level variation over the period + (10b in the reference document) */ + ProblemeAResoudre->NombreDeContraintes++; + /* 1 constraint bounding the overall energy pumped over the + period (10c in the reference document) */ } if (!Pump && TurbEntreBornes && !MonitorHourlyLev) @@ -192,16 +192,16 @@ int OPT_DecompteDesVariablesEtDesContraintesDuProblemeAOptimiser(PROBLEME_HEBDO* ProblemeAResoudre->NombreDeContraintes += 2; /* 2 constraints bounding the overall energy generated over the period (10a in the reference document) */ - ProblemeAResoudre - ->NombreDeContraintes++; /* 1 constraint setting the level variation over the period - (10b in the reference document) */ - ProblemeAResoudre - ->NombreDeContraintes++; /* 1 constraint bounding the overall energy pumped over the - period (10c in the reference document) */ - ProblemeAResoudre->NombreDeContraintes - += nombreDePasDeTempsPourUneOptimisation; /* T constraints expressing the level hourly - variations (14a in the reference - document) */ + ProblemeAResoudre->NombreDeContraintes++; + /* 1 constraint setting the level variation over the period + (10b in the reference document) */ + ProblemeAResoudre->NombreDeContraintes++; + /* 1 constraint bounding the overall energy pumped over the + period (10c in the reference document) */ + ProblemeAResoudre->NombreDeContraintes += nombreDePasDeTempsPourUneOptimisation; + /* T constraints expressing the level hourly + variations (14a in the reference + document) */ } if (!Pump && !TurbEntreBornes && MonitorHourlyLev) { @@ -245,6 +245,10 @@ int OPT_DecompteDesVariablesEtDesContraintesDuProblemeAOptimiser(PROBLEME_HEBDO* ProblemeAResoudre->NombreDeContraintes += 2 * nombreDePasDeTempsPourUneOptimisation; } + if (!storage.additional_constraints.empty()) + { + ProblemeAResoudre->NombreDeContraintes += storage.additional_constraints.size(); + } } } } diff --git a/src/solver/optimisation/opt_gestion_second_membre_cas_lineaire.cpp b/src/solver/optimisation/opt_gestion_second_membre_cas_lineaire.cpp index 36bb303964..c04d416f00 100644 --- a/src/solver/optimisation/opt_gestion_second_membre_cas_lineaire.cpp +++ b/src/solver/optimisation/opt_gestion_second_membre_cas_lineaire.cpp @@ -43,6 +43,26 @@ static void shortTermStorageLevelsRHS( } } +static void shortTermStorageCumulationRHS( + const std::vector<::ShortTermStorage::AREA_INPUT>& shortTermStorageInput, + int numberOfAreas, + std::vector& SecondMembre, + const CORRESPONDANCES_DES_CONTRAINTES_HEBDOMADAIRES& CorrespondancesDesContraintesHebdomadaires) +{ + for (int areaIndex = 0; areaIndex < numberOfAreas; areaIndex++) + { + for (auto& storage: shortTermStorageInput[areaIndex]) + { + for (const auto& constraint: storage.additional_constraints) + { + int cnt = CorrespondancesDesContraintesHebdomadaires + .ShortTermStorageCumulation[constraint.globalIndex]; + SecondMembre[cnt] = constraint.rhs; + } + } + } +} + void OPT_InitialiserLeSecondMembreDuProblemeLineaire(PROBLEME_HEBDO* problemeHebdo, int PremierPdtDeLIntervalle, int DernierPdtDeLIntervalle, @@ -145,7 +165,6 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaire(PROBLEME_HEBDO* problemeHeb ProblemeAResoudre->SecondMembre, CorrespondanceCntNativesCntOptim, hourInTheYear); - for (uint32_t interco = 0; interco < problemeHebdo->NombreDInterconnexions; interco++) { if (const COUTS_DE_TRANSPORT& CoutDeTransport = problemeHebdo->CoutDeTransport[interco]; @@ -377,6 +396,10 @@ void OPT_InitialiserLeSecondMembreDuProblemeLineaire(PROBLEME_HEBDO* problemeHeb } } + shortTermStorageCumulationRHS(problemeHebdo->ShortTermStorage, + problemeHebdo->NombreDePays, + ProblemeAResoudre->SecondMembre, + problemeHebdo->CorrespondanceCntNativesCntOptimHebdomadaires); if (problemeHebdo->OptimisationAvecCoutsDeDemarrage) { OPT_InitialiserLeSecondMembreDuProblemeLineaireCoutsDeDemarrage(problemeHebdo, diff --git a/src/solver/optimisation/opt_rename_problem.cpp b/src/solver/optimisation/opt_rename_problem.cpp index a92553e5e6..b385c0f8f5 100644 --- a/src/solver/optimisation/opt_rename_problem.cpp +++ b/src/solver/optimisation/opt_rename_problem.cpp @@ -35,9 +35,9 @@ const std::string AREA("area"); std::string BuildName(const std::string& name, const std::string& location, - const std::string& timeIdentifier) + const std::string& additional_identifier) { - std::string result = name + SEPARATOR + location + SEPARATOR + timeIdentifier; + std::string result = name + SEPARATOR + location + SEPARATOR + additional_identifier; std::replace(result.begin(), result.end(), ' ', '*'); return result; } @@ -414,3 +414,16 @@ void ConstraintNamer::ShortTermStorageCostVariation(const std::string& constrain TimeIdentifier(timeStep_, HOUR)), constraint); } + +void ConstraintNamer::ShortTermStorageCumulation(const std::string& constraint_type, + unsigned int constraint, + const std::string& short_term_name, + const std::string& constraint_name) +{ + targetUpdater_.UpdateTargetAtIndex( + BuildName(constraint_type, + LocationIdentifier(area_, AREA) + SEPARATOR + "ShortTermStorage" + "<" + + short_term_name + ">", + ShortTermStorageCumulationIdentifier(constraint_name)), + constraint); +} diff --git a/src/solver/simulation/include/antares/solver/simulation/sim_alloc_probleme_hebdo.h b/src/solver/simulation/include/antares/solver/simulation/sim_alloc_probleme_hebdo.h index f1ed9bca0c..a4517115a8 100644 --- a/src/solver/simulation/include/antares/solver/simulation/sim_alloc_probleme_hebdo.h +++ b/src/solver/simulation/include/antares/solver/simulation/sim_alloc_probleme_hebdo.h @@ -39,6 +39,8 @@ void SIM_AllocationLinks(PROBLEME_HEBDO& problem, void SIM_AllocationConstraints(PROBLEME_HEBDO& problem, const Antares::Data::Study& study, unsigned NombreDePasDeTemps); +void SIM_AllocationShortermStorageCumulation(PROBLEME_HEBDO& problem, + const Antares::Data::Study& study); void SIM_AllocateAreas(PROBLEME_HEBDO& problem, const Antares::Data::Study& study, diff --git a/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h b/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h index d24fb25bc4..35051ba2d5 100644 --- a/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h +++ b/src/solver/simulation/include/antares/solver/simulation/sim_structure_probleme_economique.h @@ -111,6 +111,7 @@ struct CORRESPONDANCES_DES_CONTRAINTES_JOURNALIERES struct CORRESPONDANCES_DES_CONTRAINTES_HEBDOMADAIRES { std::vector NumeroDeContrainteDesContraintesCouplantes; + std::vector ShortTermStorageCumulation; }; struct VALEURS_DE_NTC_ET_RESISTANCES @@ -182,7 +183,7 @@ struct PROPERTIES bool penalizeVariationInjection; std::shared_ptr series; - + std::vector additional_constraints; int clusterGlobalIndex; std::string name; }; diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index d735191ff7..78785f0fd3 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -38,6 +38,7 @@ void SIM_AllocationProblemeHebdo(const Data::Study& study, SIM_AllocationProblemePasDeTemps(problem, study, NombreDePasDeTemps); SIM_AllocationLinks(problem, study.runtime.interconnectionsCount(), NombreDePasDeTemps); SIM_AllocationConstraints(problem, study, NombreDePasDeTemps); + SIM_AllocationShortermStorageCumulation(problem, study); SIM_AllocateAreas(problem, study, NombreDePasDeTemps); } catch (const std::bad_alloc& e) @@ -245,6 +246,13 @@ void SIM_AllocationLinks(PROBLEME_HEBDO& problem, const uint linkCount, unsigned } } +void SIM_AllocationShortermStorageCumulation(PROBLEME_HEBDO& problem, + const Antares::Data::Study& study) +{ + problem.CorrespondanceCntNativesCntOptimHebdomadaires.ShortTermStorageCumulation + .assign(study.runtime.shortTermStorageCumulativeConstraintCount, 0); +} + void SIM_AllocationConstraints(PROBLEME_HEBDO& problem, const Antares::Data::Study& study, unsigned NombreDePasDeTemps) diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index 3d29d3ee42..786b1b5aa6 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -39,6 +39,7 @@ static void importShortTermStorages( std::vector<::ShortTermStorage::AREA_INPUT>& ShortTermStorageOut) { int clusterGlobalIndex = 0; + int clusterCumulativeConstraintGlobalIndex = 0; for (uint areaIndex = 0; areaIndex != areas.size(); areaIndex++) { ShortTermStorageOut[areaIndex].resize(areas[areaIndex]->shortTermStorage.count()); @@ -59,7 +60,12 @@ static void importShortTermStorages( toInsert.penalizeVariationInjection = st.properties.penalizeVariationInjection; toInsert.penalizeVariationWithdrawal = st.properties.penalizeVariationWithdrawal; toInsert.name = st.properties.name; - + toInsert.additional_constraints = st.additional_constraints; + for (auto& constraint: toInsert.additional_constraints) + { + constraint.globalIndex = clusterCumulativeConstraintGlobalIndex; + ++clusterCumulativeConstraintGlobalIndex; + } toInsert.series = st.series; // TODO add missing properties, or use the same struct From a570a0ec9b24cdc6f3894e4ec2273314aac6f11e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Thu, 19 Dec 2024 15:21:09 +0100 Subject: [PATCH 05/14] Rebase the 8.8.x branch on top of develop to take multiple fixes into account (#2512) Co-authored-by: Jason Marechal Co-authored-by: payetvin <113102157+payetvin@users.noreply.github.com> Co-authored-by: guilpier-code <62292552+guilpier-code@users.noreply.github.com> Co-authored-by: Abdoulbari Zakir Co-authored-by: Vincent Payet Co-authored-by: Juliette-Gerbaux <130555142+Juliette-Gerbaux@users.noreply.github.com> Co-authored-by: OMNES Florian Co-authored-by: Guillaume PIERRE --- .github/workflows/ubuntu.yml | 30 +- .github/workflows/windows-vcpkg.yml | 8 + sonar-project.properties | 21 + src/CMakeLists.txt | 1 - src/libs/antares/exception/LoadingError.cpp | 5 +- .../antares/exception/LoadingError.hpp | 2 +- .../study/parameters/adq-patch-params.cpp | 4 + .../antares/study/parts/thermal/cluster.cpp | 5 + src/solver/misc/options.cpp | 8 +- src/solver/optimisation/CMakeLists.txt | 2 - .../adq_patch_curtailment_sharing.cpp | 3 +- .../adq_patch_post_process_list.cpp | 9 +- .../adequacy_patch_csr/post_processing.cpp | 62 --- .../adequacy_patch_csr/solve_problem.h | 14 + .../adequacy_patch_csr/hourly_csr_problem.h | 134 +++--- .../adequacy_patch_csr/post_processing.h | 29 -- .../solver/optimisation/opt_fonctions.h | 7 - .../optimisation/post_process_commands.h | 25 +- .../opt_appel_solveur_lineaire.cpp | 3 +- .../optimisation/post_process_commands.cpp | 90 ++-- .../simulation/sim_alloc_probleme_hebdo.cpp | 1 + src/solver/variable/CMakeLists.txt | 4 +- src/solver/variable/economy/max-mrg.cpp | 193 --------- .../antares/solver/variable/economy/all.h | 113 ++--- .../antares/solver/variable/economy/loldCsr.h | 242 +++++++++++ .../antares/solver/variable/economy/lolpCsr.h | 242 +++++++++++ .../solver/variable/economy/max-mrg-csr.h | 243 +++++++++++ .../solver/variable/economy/max-mrg-utils.h | 56 +++ .../antares/solver/variable/economy/max-mrg.h | 15 +- .../solver/variable/economy/overallCostCsr.h | 253 ++++++++++++ .../variable/economy/unsupliedEnergyCsr.h | 2 - src/solver/variable/max-mrg-utils.cpp | 171 ++++++++ .../libs/antares/writer/test_zip_writer.cpp | 127 ++++++ .../solver/optimisation/adequacy_patch.cpp | 386 ++++++++++++++++++ .../adequacy_patch/adequacy_patch.cpp | 73 ---- src/ui/simulator/application/main/create.cpp | 8 +- .../simulator/application/main/internal-ids.h | 10 + src/ui/simulator/application/main/main.cpp | 65 +++ src/ui/simulator/application/main/main.h | 45 ++ src/ui/simulator/application/main/menu.cpp | 15 + .../simulator/application/main/statusbar.cpp | 226 +++++++++- src/ui/simulator/cmake/components.cmake | 1 + .../toolbox/components/datagrid/dbgrid.cpp | 19 + .../components/datagrid/selectionoperation.h | 247 +++++++++++ 44 files changed, 2647 insertions(+), 572 deletions(-) delete mode 100644 src/solver/optimisation/adequacy_patch_csr/post_processing.cpp create mode 100644 src/solver/optimisation/adequacy_patch_csr/solve_problem.h delete mode 100644 src/solver/optimisation/include/antares/solver/optimisation/adequacy_patch_csr/post_processing.h delete mode 100644 src/solver/variable/economy/max-mrg.cpp create mode 100644 src/solver/variable/include/antares/solver/variable/economy/loldCsr.h create mode 100644 src/solver/variable/include/antares/solver/variable/economy/lolpCsr.h create mode 100644 src/solver/variable/include/antares/solver/variable/economy/max-mrg-csr.h create mode 100644 src/solver/variable/include/antares/solver/variable/economy/max-mrg-utils.h create mode 100644 src/solver/variable/include/antares/solver/variable/economy/overallCostCsr.h create mode 100644 src/solver/variable/max-mrg-utils.cpp create mode 100644 src/tests/src/libs/antares/writer/test_zip_writer.cpp create mode 100644 src/tests/src/solver/optimisation/adequacy_patch.cpp create mode 100644 src/ui/simulator/toolbox/components/datagrid/selectionoperation.h diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 2c73097adb..daceabc0ff 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -170,6 +170,7 @@ jobs: run: | cd _build ctest -C Release --output-on-failure -L "unit|end-to-end" + - name: Upload logs for failed tests if: ${{ failure() }} @@ -177,7 +178,7 @@ jobs: with: name: test-log path: ${{ github.workspace }}/_build/Testing/Temporary/LastTest.log - + - name: Run tests about infinity on BCs RHS if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests @@ -185,7 +186,7 @@ jobs: simtest-tag: ${{ env.SIMTEST }} batch-name: valid-v830 os: ${{ env.os }} - + - name: Run MILP with CBC if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests @@ -195,6 +196,23 @@ jobs: variant: "milp-cbc" os: ${{ env.os }} + - name: Run tests on adequacy patch (CSR) + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: adequacy-patch-CSR + os: ${{ env.os }} + + - name: Run parallel tests + if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-parallel + os: ${{ env.os }} + variant: "parallel" + - name: Run tests introduced in 8.6.0 if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests @@ -248,14 +266,6 @@ jobs: batch-name: valid-mps os: ${{ env.os }} - - name: Run tests for adequacy patch (CSR) - if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{ env.SIMTEST }} - batch-name: adequacy-patch-CSR - os: ${{ env.os }} - - name: Run parallel tests if: ${{ env.RUN_EXTENDED_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 5fb4b19603..37d47eaadf 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -188,6 +188,14 @@ jobs: batch-name: adequacy-patch-CSR os: ${{ env.os }} + - name: Run tests about infinity on BCs RHS + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-v830 + os: ${{ env.test-platform }} + - name: Run tests about infinity on BCs RHS if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests diff --git a/sonar-project.properties b/sonar-project.properties index 0c74bd252a..d4ba8cce37 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,3 +1,24 @@ +# +# 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 . +# + sonar.projectName=Antares_Simulator sonar.projectKey=AntaresSimulatorTeam_Antares_Simulator sonar.organization=antaressimulatorteam diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 56dc5e2bf8..13c67fe7a0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,7 +5,6 @@ set(ANTARES_VERSION_HI 9) set(ANTARES_VERSION_LO 2) set(ANTARES_VERSION_REVISION 0) - # Beta release set(ANTARES_BETA 0) set(ANTARES_RC 7) diff --git a/src/libs/antares/exception/LoadingError.cpp b/src/libs/antares/exception/LoadingError.cpp index cea447153e..32f4b3b1c1 100644 --- a/src/libs/antares/exception/LoadingError.cpp +++ b/src/libs/antares/exception/LoadingError.cpp @@ -96,9 +96,8 @@ InvalidSolverSpecificParameters::InvalidSolverSpecificParameters(const std::stri { } -InvalidStudy::InvalidStudy(const Yuni::String& study): - LoadingError(std::string("The folder `") + study.c_str() - + "` does not seem to be a valid study") +InvalidStudy::InvalidStudy(const std::string& study): + LoadingError(std::string("The folder `") + study + "` does not seem to be a valid study") { } diff --git a/src/libs/antares/exception/include/antares/exception/LoadingError.hpp b/src/libs/antares/exception/include/antares/exception/LoadingError.hpp index d70820e5e9..9a5ff14002 100644 --- a/src/libs/antares/exception/include/antares/exception/LoadingError.hpp +++ b/src/libs/antares/exception/include/antares/exception/LoadingError.hpp @@ -140,7 +140,7 @@ class InvalidSolverSpecificParameters: public LoadingError class InvalidStudy: public LoadingError { public: - explicit InvalidStudy(const Yuni::String& study); + explicit InvalidStudy(const std::string& study); }; class NoStudyProvided: public LoadingError diff --git a/src/libs/antares/study/parameters/adq-patch-params.cpp b/src/libs/antares/study/parameters/adq-patch-params.cpp index ebf6de321e..800f2d19f8 100644 --- a/src/libs/antares/study/parameters/adq-patch-params.cpp +++ b/src/libs/antares/study/parameters/adq-patch-params.cpp @@ -146,6 +146,10 @@ void AdqPatchParams::addExcludedVariables(std::vector& out) const out.emplace_back("LMR VIOL."); out.emplace_back("UNSP. ENRG CSR"); out.emplace_back("DTG MRG CSR"); + out.emplace_back("LOLD CSR"); + out.emplace_back("LOLP CSR"); + out.emplace_back("MAX MRG CSR"); + out.emplace_back("OV. COST CSR"); } } diff --git a/src/libs/antares/study/parts/thermal/cluster.cpp b/src/libs/antares/study/parts/thermal/cluster.cpp index 96b2d87826..cfd16f521e 100644 --- a/src/libs/antares/study/parts/thermal/cluster.cpp +++ b/src/libs/antares/study/parts/thermal/cluster.cpp @@ -298,6 +298,11 @@ void Data::ThermalCluster::calculationOfSpinning() void Data::ThermalCluster::reverseCalculationOfSpinning() { + if (tsGenBehavior == LocalTSGenerationBehavior::forceNoGen) + { + return; + } + // Nothing to do if the spinning is equal to zero // because it will the same multiply all entries of the matrix by 1. if (Utils::isZero(spinning)) diff --git a/src/solver/misc/options.cpp b/src/solver/misc/options.cpp index d72bd4c692..00572039a9 100644 --- a/src/solver/misc/options.cpp +++ b/src/solver/misc/options.cpp @@ -82,14 +82,14 @@ std::unique_ptr CreateParser(Settings& settings, StudyLoad "Solver used for simulation\nAvailable solver list : " + availableOrToolsSolversString()); - //--xpress-parameters + //--solver-parameters parser->add( options.optOptions.solverParameters, ' ', "solver-parameters", - "Set xpress solver specific parameters. The specified string must be wrapped into quotes: " - "--solver-parameters=\"param1 value1 param2 value2\". The syntax of parameters is solver " - "specfic, examples are given in Antares-Simulator online documentation."); + "Set solver-specific parameters, for instance --solver-parameters=\"THREADS 1 PRESOLVE 1\"" + "for XPRESS or --solver-parameters=\"parallel/maxnthreads 1, lp/presolving TRUE\" for SCIP." + "Syntax is solver-dependent, and only supported for SCIP & XPRESS."); parser->addParagraph("\nParameters"); // --name diff --git a/src/solver/optimisation/CMakeLists.txt b/src/solver/optimisation/CMakeLists.txt index ec98f298e8..0d64d42e44 100644 --- a/src/solver/optimisation/CMakeLists.txt +++ b/src/solver/optimisation/CMakeLists.txt @@ -47,9 +47,7 @@ set(RTESOLVER_OPT post_process_commands.cpp include/antares/solver/optimisation/adequacy_patch_csr/hourly_csr_problem.h include/antares/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.h - include/antares/solver/optimisation/adequacy_patch_csr/post_processing.h adequacy_patch_csr/adq_patch_post_process_list.cpp - adequacy_patch_csr/post_processing.cpp include/antares/solver/optimisation/adequacy_patch_csr/adq_patch_curtailment_sharing.h adequacy_patch_csr/adq_patch_curtailment_sharing.cpp adequacy_patch_csr/solve_problem.cpp diff --git a/src/solver/optimisation/adequacy_patch_csr/adq_patch_curtailment_sharing.cpp b/src/solver/optimisation/adequacy_patch_csr/adq_patch_curtailment_sharing.cpp index b480108379..731aaac79c 100644 --- a/src/solver/optimisation/adequacy_patch_csr/adq_patch_curtailment_sharing.cpp +++ b/src/solver/optimisation/adequacy_patch_csr/adq_patch_curtailment_sharing.cpp @@ -25,9 +25,10 @@ #include "antares/solver/optimisation/adequacy_patch_csr/count_constraints_variables.h" #include "antares/solver/optimisation/adequacy_patch_csr/csr_quadratic_problem.h" -#include "antares/solver/optimisation/opt_fonctions.h" #include "antares/solver/simulation/adequacy_patch_runtime_data.h" +#include "solve_problem.h" + using namespace Yuni; namespace Antares::Data::AdequacyPatch diff --git a/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp b/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp index 1d54cb0da0..f9f8aa389b 100644 --- a/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp +++ b/src/solver/optimisation/adequacy_patch_csr/adq_patch_post_process_list.cpp @@ -36,7 +36,7 @@ AdqPatchPostProcessList::AdqPatchPostProcessList(const AdqPatchParams& adqPatchP { post_process_list.push_back( std::make_unique(problemeHebdo_, numSpace_, areas)); - + // Here a post process particular to adq patch post_process_list.push_back( std::make_unique(problemeHebdo_, areas, false, false)); post_process_list.push_back(std::make_unique(problemeHebdo_, @@ -44,15 +44,14 @@ AdqPatchPostProcessList::AdqPatchPostProcessList(const AdqPatchParams& adqPatchP sheddingPolicy, splxOptimization, numSpace)); - - // Here a post process particular to adq patch post_process_list.push_back(std::make_unique(adqPatchParams, problemeHebdo_, areas, numSpace_)); - // Here a post process particular to adq patch post_process_list.push_back( - std::make_unique(problemeHebdo_, areas, numSpace)); + std::make_unique(problemeHebdo_, areas, numSpace)); + post_process_list.push_back( + std::make_unique(problemeHebdo_, areas, numSpace)); post_process_list.push_back( std::make_unique(problemeHebdo_, areas, true, false)); post_process_list.push_back( diff --git a/src/solver/optimisation/adequacy_patch_csr/post_processing.cpp b/src/solver/optimisation/adequacy_patch_csr/post_processing.cpp deleted file mode 100644 index bc946a3c57..0000000000 --- a/src/solver/optimisation/adequacy_patch_csr/post_processing.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* -** 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 . -*/ -#include "antares/solver/optimisation/adequacy_patch_csr/post_processing.h" - -#include - -namespace Antares::Data::AdequacyPatch -{ -double recomputeDTG_MRG(bool triggered, double dtgMrg, double ens) -{ - if (triggered) - { - return std::max(0.0, dtgMrg - ens); - } - else - { - return dtgMrg; - } -} - -double recomputeENS_MRG(bool triggered, double dtgMrg, double ens) -{ - if (triggered) - { - return std::max(0.0, ens - dtgMrg); - } - else - { - return ens; - } -} - -double recomputeMRGPrice(double ensCsr, double originalCost, double unsuppliedEnergyCost) -{ - if (ensCsr > 0.5) - { - return -unsuppliedEnergyCost; - } - else - { - return originalCost; - } -} -} // namespace Antares::Data::AdequacyPatch diff --git a/src/solver/optimisation/adequacy_patch_csr/solve_problem.h b/src/solver/optimisation/adequacy_patch_csr/solve_problem.h new file mode 100644 index 0000000000..59b0619ca2 --- /dev/null +++ b/src/solver/optimisation/adequacy_patch_csr/solve_problem.h @@ -0,0 +1,14 @@ + +#pragma once + +#include "antares/solver/optimisation/adequacy_patch_csr/hourly_csr_problem.h" +#include "antares/solver/optimisation/opt_structure_probleme_a_resoudre.h" +#include "antares/study/parameters/adq-patch-params.h" + +using namespace Antares::Data::AdequacyPatch; + +bool ADQ_PATCH_CSR(PROBLEME_ANTARES_A_RESOUDRE&, + HourlyCSRProblem&, + const AdqPatchParams&, + unsigned int week, + int year); diff --git a/src/solver/optimisation/include/antares/solver/optimisation/adequacy_patch_csr/hourly_csr_problem.h b/src/solver/optimisation/include/antares/solver/optimisation/adequacy_patch_csr/hourly_csr_problem.h index c7fb554c22..6ebb9734e4 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/adequacy_patch_csr/hourly_csr_problem.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/adequacy_patch_csr/hourly_csr_problem.h @@ -31,10 +31,69 @@ #include "../variables/VariableManagerUtils.h" +struct LinkVariable +{ + LinkVariable(): + directVar(-1), + indirectVar(-1) + { + } + + LinkVariable(int direct, int indirect): + directVar(direct), + indirectVar(indirect) + { + } + + inline bool check() const + { + if (directVar < 0) + { + Antares::logs.warning() << "directVar < 0 detected, this should not happen"; + } + if (indirectVar < 0) + { + Antares::logs.warning() << "indirectVar < 0 detected, this should not happen"; + } + + return (directVar >= 0) && (indirectVar >= 0); + } + + int directVar; + int indirectVar; +}; + struct PROBLEME_HEBDO; class HourlyCSRProblem { + using AdqPatchParams = Antares::Data::AdequacyPatch::AdqPatchParams; + +public: + explicit HourlyCSRProblem(const AdqPatchParams& adqPatchParams, PROBLEME_HEBDO* p): + adqPatchParams_(adqPatchParams), + variableManager_(p->CorrespondanceVarNativesVarOptim, + p->NumeroDeVariableStockFinal, + p->NumeroDeVariableDeTrancheDeStock, + p->NombreDePasDeTempsPourUneOptimisation), + problemeHebdo_(p) + { + double temp = pow(10, -adqPatchParams.curtailmentSharing.thresholdVarBoundsRelaxation); + belowThisThresholdSetToZero = std::min(temp, 0.1); + + allocateProblem(); + } + + HourlyCSRProblem(const HourlyCSRProblem&) = delete; + HourlyCSRProblem& operator=(const HourlyCSRProblem&) = delete; + + inline void setHour(int hour) + { + triggeredHour = hour; + } + + void run(uint week, uint year); + private: void calculateCsrParameters(); @@ -65,85 +124,26 @@ class HourlyCSRProblem void setQuadraticCost(); void setLinearCost(); -private: - using AdqPatchParams = Antares::Data::AdequacyPatch::AdqPatchParams; +public: + // TODO [gp] : try to make these members private + double belowThisThresholdSetToZero; + std::map numberOfConstraintCsrAreaBalance; + std::set ensVariablesInsideAdqPatch; // place inside only ENS inside adq-patch + std::set varToBeSetToZeroIfBelowThreshold; // place inside only ENS and Spillage variable + int triggeredHour; + const AdqPatchParams& adqPatchParams_; VariableManagement::VariableManager variableManager_; -public: - void run(uint week, uint year); - - // TODO[FOM] Make these members private - int triggeredHour; - double belowThisThresholdSetToZero; PROBLEME_HEBDO* problemeHebdo_; PROBLEME_ANTARES_A_RESOUDRE problemeAResoudre_; - explicit HourlyCSRProblem(const AdqPatchParams& adqPatchParams, PROBLEME_HEBDO* p): - adqPatchParams_(adqPatchParams), - variableManager_(p->CorrespondanceVarNativesVarOptim, - p->NumeroDeVariableStockFinal, - p->NumeroDeVariableDeTrancheDeStock, - p->NombreDePasDeTempsPourUneOptimisation), - problemeHebdo_(p) - { - double temp = pow(10, -adqPatchParams.curtailmentSharing.thresholdVarBoundsRelaxation); - belowThisThresholdSetToZero = std::min(temp, 0.1); - - allocateProblem(); - } - - ~HourlyCSRProblem() = default; - - HourlyCSRProblem(const HourlyCSRProblem&) = delete; - HourlyCSRProblem& operator=(const HourlyCSRProblem&) = delete; - - inline void setHour(int hour) - { - triggeredHour = hour; - } - std::map numberOfConstraintCsrEns; - std::map numberOfConstraintCsrAreaBalance; std::map numberOfConstraintCsrFlowDissociation; std::map numberOfConstraintCsrHourlyBinding; // length is number of binding constraint // contains interco 2-2 std::map rhsAreaBalanceValues; - std::set varToBeSetToZeroIfBelowThreshold; // place inside only ENS and Spillage variable - std::set ensVariablesInsideAdqPatch; // place inside only ENS inside adq-patch - - struct LinkVariable - { - LinkVariable(): - directVar(-1), - indirectVar(-1) - { - } - - LinkVariable(int direct, int indirect): - directVar(direct), - indirectVar(indirect) - { - } - - inline bool check() const - { - if (directVar < 0) - { - Antares::logs.warning() << "directVar < 0 detected, this should not happen"; - } - if (indirectVar < 0) - { - Antares::logs.warning() << "indirectVar < 0 detected, this should not happen"; - } - - return (directVar >= 0) && (indirectVar >= 0); - } - - int directVar; - int indirectVar; - }; // links between two areas inside the adq-patch domain std::map linkInsideAdqPatch; diff --git a/src/solver/optimisation/include/antares/solver/optimisation/adequacy_patch_csr/post_processing.h b/src/solver/optimisation/include/antares/solver/optimisation/adequacy_patch_csr/post_processing.h deleted file mode 100644 index 3ae5ee2d91..0000000000 --- a/src/solver/optimisation/include/antares/solver/optimisation/adequacy_patch_csr/post_processing.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -** 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 . -*/ - -#pragma once - -namespace Antares::Data::AdequacyPatch -{ -double recomputeDTG_MRG(bool triggered, double dtgMrg, double ens); -double recomputeENS_MRG(bool triggered, double dtgMrg, double ens); -double recomputeMRGPrice(double ensCsr, double originalCost, double unsuppliedEnergyCost); -} // namespace Antares::Data::AdequacyPatch diff --git a/src/solver/optimisation/include/antares/solver/optimisation/opt_fonctions.h b/src/solver/optimisation/include/antares/solver/optimisation/opt_fonctions.h index 55cccc4e64..4d761bd558 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/opt_fonctions.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/opt_fonctions.h @@ -56,13 +56,6 @@ void OPT_InitialiserLesCoutsLineaire(PROBLEME_HEBDO*, const int, const int); void OPT_InitialiserLesCoutsQuadratiques(PROBLEME_HEBDO*, int); bool OPT_AppelDuSolveurQuadratique(PROBLEME_ANTARES_A_RESOUDRE*, const int); -using namespace Antares::Data::AdequacyPatch; -bool ADQ_PATCH_CSR(PROBLEME_ANTARES_A_RESOUDRE&, - HourlyCSRProblem&, - const AdqPatchParams&, - uint week, - int year); - bool OPT_PilotageOptimisationLineaire(const OptimizationOptions& options, PROBLEME_HEBDO* problemeHebdo, Solver::IResultWriter& writer, diff --git a/src/solver/optimisation/include/antares/solver/optimisation/post_process_commands.h b/src/solver/optimisation/include/antares/solver/optimisation/post_process_commands.h index 4c3fd49bd1..b7e125ad03 100644 --- a/src/solver/optimisation/include/antares/solver/optimisation/post_process_commands.h +++ b/src/solver/optimisation/include/antares/solver/optimisation/post_process_commands.h @@ -69,16 +69,24 @@ class RemixHydroPostProcessCmd: public basePostProcessCommand SimplexOptimization splx_optimization_; }; -class DTGmarginForAdqPatchPostProcessCmd: public basePostProcessCommand +class UpdateMrgPriceAfterCSRcmd: public basePostProcessCommand { - using AdqPatchParams = Antares::Data::AdequacyPatch::AdqPatchParams; - public: - DTGmarginForAdqPatchPostProcessCmd(PROBLEME_HEBDO* problemeHebdo, - AreaList& areas, - unsigned int numSpace); + UpdateMrgPriceAfterCSRcmd(PROBLEME_HEBDO* problemeHebdo, + AreaList& areas, + unsigned int numSpace); + void execute(const optRuntimeData&) override; - void execute(const optRuntimeData& opt_runtime_data) override; +private: + const AreaList& area_list_; + unsigned int numSpace_ = 0; +}; + +class DTGnettingAfterCSRcmd: public basePostProcessCommand +{ +public: + DTGnettingAfterCSRcmd(PROBLEME_HEBDO* problemeHebdo, AreaList& areas, unsigned int numSpace); + void execute(const optRuntimeData&) override; private: const AreaList& area_list_; @@ -112,8 +120,6 @@ class HydroLevelsFinalUpdatePostProcessCmd: public basePostProcessCommand class CurtailmentSharingPostProcessCmd: public basePostProcessCommand { - using AdqPatchParams = Antares::Data::AdequacyPatch::AdqPatchParams; - public: CurtailmentSharingPostProcessCmd(const AdqPatchParams& adqPatchParams, PROBLEME_HEBDO* problemeHebdo, @@ -128,6 +134,7 @@ class CurtailmentSharingPostProcessCmd: public basePostProcessCommand std::set identifyHoursForCurtailmentSharing(const std::vector& sumENS) const; std::set getHoursRequiringCurtailmentSharing() const; + using AdqPatchParams = Antares::Data::AdequacyPatch::AdqPatchParams; const AreaList& area_list_; const AdqPatchParams& adqPatchParams_; unsigned int numSpace_ = 0; diff --git a/src/solver/optimisation/opt_appel_solveur_lineaire.cpp b/src/solver/optimisation/opt_appel_solveur_lineaire.cpp index 2f6f907c5a..304aab13df 100644 --- a/src/solver/optimisation/opt_appel_solveur_lineaire.cpp +++ b/src/solver/optimisation/opt_appel_solveur_lineaire.cpp @@ -214,10 +214,9 @@ static SimplexResult OPT_TryToCallSimplex(const OptimizationOptions& options, mps_writer->runIfNeeded(writer, filename); TimeMeasurement measure; - const bool keepBasis = (optimizationNumber == PREMIERE_OPTIMISATION); solver = ORTOOLS_Simplexe(&Probleme, solver, keepBasis, options); - if (solver) + if (solver != nullptr) { ProblemeAResoudre->ProblemesSpx[NumIntervalle] = (void*)solver; } diff --git a/src/solver/optimisation/post_process_commands.cpp b/src/solver/optimisation/post_process_commands.cpp index b069050960..3ddc06ddde 100644 --- a/src/solver/optimisation/post_process_commands.cpp +++ b/src/solver/optimisation/post_process_commands.cpp @@ -22,7 +22,6 @@ #include "antares/solver/optimisation/post_process_commands.h" #include "antares/solver/optimisation/adequacy_patch_csr/adq_patch_curtailment_sharing.h" -#include "antares/solver/optimisation/adequacy_patch_csr/post_processing.h" #include "antares/solver/simulation/adequacy_patch_runtime_data.h" #include "antares/solver/simulation/common-eco-adq.h" @@ -116,53 +115,84 @@ void RemixHydroPostProcessCmd::execute(const optRuntimeData& opt_runtime_data) hourInYear); } -// ----------------------------- -// DTG margin for adq patch -// ----------------------------- +// ---------------------------------- +// Update marginal price after CSR +// ---------------------------------- using namespace Antares::Data::AdequacyPatch; -DTGmarginForAdqPatchPostProcessCmd::DTGmarginForAdqPatchPostProcessCmd( - PROBLEME_HEBDO* problemeHebdo, - AreaList& areas, - unsigned int numSpace): +UpdateMrgPriceAfterCSRcmd::UpdateMrgPriceAfterCSRcmd(PROBLEME_HEBDO* problemeHebdo, + AreaList& areas, + unsigned int numSpace): basePostProcessCommand(problemeHebdo), area_list_(areas), numSpace_(numSpace) { } -/*! -** Calculate Dispatchable margin for all areas after CSR optimization and adjust ENS -** values if neccessary. If LOLD=1, Sets MRG COST to the max value (unsupplied energy cost) -** */ -void DTGmarginForAdqPatchPostProcessCmd::execute(const optRuntimeData&) +void UpdateMrgPriceAfterCSRcmd::execute(const optRuntimeData&) { for (uint32_t Area = 0; Area < problemeHebdo_->NombreDePays; Area++) { - if (problemeHebdo_->adequacyPatchRuntimeData->areaMode[Area] != physicalAreaInsideAdqPatch) + auto& hourlyResults = problemeHebdo_->ResultatsHoraires[Area]; + const auto& scratchpad = area_list_[Area]->scratchpad[numSpace_]; + const double unsuppliedEnergyCost = area_list_[Area]->thermal.unsuppliedEnergyCost; + const bool areaInside = problemeHebdo_->adequacyPatchRuntimeData->areaMode[Area] + == physicalAreaInsideAdqPatch; + for (uint hour = 0; hour < nbHoursInWeek; hour++) { - continue; + const bool isHourTriggeredByCsr = problemeHebdo_->adequacyPatchRuntimeData + ->wasCSRTriggeredAtAreaHour(Area, hour); + + if (isHourTriggeredByCsr + && hourlyResults.ValeursHorairesDeDefaillancePositive[hour] > 0.5 && areaInside) + { + hourlyResults.CoutsMarginauxHoraires[hour] = -unsuppliedEnergyCost; + } } + } +} + +// ----------------------------- +// DTG margin for adq patch +// ----------------------------- +DTGnettingAfterCSRcmd::DTGnettingAfterCSRcmd(PROBLEME_HEBDO* problemeHebdo, + AreaList& areas, + unsigned int numSpace): + basePostProcessCommand(problemeHebdo), + area_list_(areas), + numSpace_(numSpace) +{ +} + +void DTGnettingAfterCSRcmd::execute(const optRuntimeData&) +{ + for (uint32_t Area = 0; Area < problemeHebdo_->NombreDePays; Area++) + { + auto& hourlyResults = problemeHebdo_->ResultatsHoraires[Area]; + const auto& scratchpad = area_list_[Area]->scratchpad[numSpace_]; for (uint hour = 0; hour < nbHoursInWeek; hour++) { - auto& hourlyResults = problemeHebdo_->ResultatsHoraires[Area]; - const auto& scratchpad = area_list_[Area]->scratchpad[numSpace_]; + const bool isHourTriggeredByCsr = problemeHebdo_->adequacyPatchRuntimeData + ->wasCSRTriggeredAtAreaHour(Area, hour); + const double dtgMrg = scratchpad.dispatchableGenerationMargin[hour]; const double ens = hourlyResults.ValeursHorairesDeDefaillancePositive[hour]; - const bool triggered = problemeHebdo_->adequacyPatchRuntimeData - ->wasCSRTriggeredAtAreaHour(Area, hour); - hourlyResults.ValeursHorairesDtgMrgCsr[hour] = recomputeDTG_MRG(triggered, dtgMrg, ens); - hourlyResults.ValeursHorairesDeDefaillancePositiveCSR[hour] = recomputeENS_MRG( - triggered, - dtgMrg, - ens); - - const double unsuppliedEnergyCost = area_list_[Area]->thermal.unsuppliedEnergyCost; - hourlyResults.CoutsMarginauxHoraires[hour] = recomputeMRGPrice( - hourlyResults.ValeursHorairesDtgMrgCsr[hour], - hourlyResults.CoutsMarginauxHoraires[hour], - unsuppliedEnergyCost); + const bool areaInside = problemeHebdo_->adequacyPatchRuntimeData->areaMode[Area] + == physicalAreaInsideAdqPatch; + if (isHourTriggeredByCsr && areaInside) + { + hourlyResults.ValeursHorairesDtgMrgCsr[hour] = std::max(0.0, dtgMrg - ens); + hourlyResults.ValeursHorairesDeDefaillancePositiveCSR[hour] = std::max(0.0, + ens + - dtgMrg); + } + else + { + // Default value (when the hour is not triggered by CSR) + hourlyResults.ValeursHorairesDtgMrgCsr[hour] = dtgMrg; + hourlyResults.ValeursHorairesDeDefaillancePositiveCSR[hour] = ens; + } } } } diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index 78785f0fd3..dd7480671c 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -394,6 +394,7 @@ void SIM_AllocateAreas(PROBLEME_HEBDO& problem, problem.ResultatsHoraires[k].ValeursHorairesDeDefaillanceNegative.assign(NombreDePasDeTemps, 0.); + problem.ResultatsHoraires[k].TurbinageHoraire.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].PompageHoraire.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].CoutsMarginauxHoraires.assign(NombreDePasDeTemps, 0.); diff --git a/src/solver/variable/CMakeLists.txt b/src/solver/variable/CMakeLists.txt index 5022d5b542..ed7c017f5b 100644 --- a/src/solver/variable/CMakeLists.txt +++ b/src/solver/variable/CMakeLists.txt @@ -78,8 +78,9 @@ set(SRC_VARIABLE_ECONOMY include/antares/solver/variable/economy/links.h # Variables for Economy + include/antares/solver/variable/economy/max-mrg-utils.h + max-mrg-utils.cpp include/antares/solver/variable/economy/max-mrg.h - economy/max-mrg.cpp include/antares/solver/variable/economy/price.h include/antares/solver/variable/economy/balance.h include/antares/solver/variable/economy/operatingCost.h @@ -127,6 +128,7 @@ set(SRC_VARIABLE_ECONOMY include/antares/solver/variable/economy/links/congestionFeeAbs.h include/antares/solver/variable/economy/links/marginalCost.h include/antares/solver/variable/economy/links/congestionProbability.h + include/antares/solver/variable/economy/overallCostCsr.h # Binding constraints include/antares/solver/variable/economy/bindingConstraints/bindingConstraintsMarginalCost.h diff --git a/src/solver/variable/economy/max-mrg.cpp b/src/solver/variable/economy/max-mrg.cpp deleted file mode 100644 index 7cb565037f..0000000000 --- a/src/solver/variable/economy/max-mrg.cpp +++ /dev/null @@ -1,193 +0,0 @@ -/* -** 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 . -*/ - -#include "antares/solver/variable/economy/max-mrg.h" - -#include - -#include -#include - -using namespace Yuni; - -namespace Antares::Solver::Variable::Economy -{ -template -struct SpillageSelector -{ - template - static auto Value(const State&, - const U& weeklyResults, - uint) -> decltype(weeklyResults.ValeursHorairesDeDefaillanceNegative) - { - return weeklyResults.ValeursHorairesDeDefaillanceNegative; - } -}; - -template<> -struct SpillageSelector -{ - template - static auto Value(const State& state, const U&, uint index) -> decltype(state.resSpilled[index]) - { - return state.resSpilled[index]; - } -}; - -template -inline void PrepareMaxMRGFor(const State& state, double* opmrg, uint numSpace) -{ - assert(168 + state.hourInTheYear <= HOURS_PER_YEAR); - assert(opmrg && "Invalid OP.MRG target"); - - enum - { - offset = 0, - endHour = 168, - }; - - // current area - auto& area = *state.area; - // index of the current area - auto index = area.index; - assert(area.index < 50000 && "seems invalid"); - - // current problem - auto& problem = *state.problemeHebdo; - // Weekly results from solver for the current area - auto& weeklyResults = problem.ResultatsHoraires[index]; - // Unsupplied enery for the current area - auto& D = weeklyResults.ValeursHorairesDeDefaillancePositive; - // Spillage - auto S = SpillageSelector::Value(state, weeklyResults, area.index); - - double OI[168]; - - // H.STOR - std::vector& H = weeklyResults.TurbinageHoraire; - - // energie turbinee de la semaine - { - // DTG MRG - const double* M = area.scratchpad[numSpace].dispatchableGenerationMargin; - - double WH = 0.; - { - // H.STOR - for (uint i = offset; i != endHour; ++i) - { - WH += H[i]; - } - } - - if (Utils::isZero(WH)) // no hydro - { - for (uint i = offset; i != endHour; ++i) - { - opmrg[i] = +S[i] + M[i] - D[i]; - } - return; - } - - // initialisation - for (uint i = offset; i != endHour; ++i) - { - OI[i] = +S[i] + M[i] - D[i]; - } - } - - double bottom = +std::numeric_limits::max(); - double top = 0; - - for (uint i = offset; i != endHour; ++i) - { - double oii = OI[i]; - if (oii > top) - { - top = oii; - } - if (oii < bottom) - { - bottom = oii; - } - } - - double ecart = 1.; - uint loop = 100; // arbitrary - maximum number of iterations - - // Pmax - const uint y = problem.year; - const auto& P = area.hydro.series->maxHourlyGenPower; - - do - { - double niveau = (top + bottom) * 0.5; - double SP = 0; // S+ - double SM = 0; // S- - - for (uint i = offset; i != endHour; ++i) - { - assert(i < HOURS_PER_YEAR && "calendar overflow"); - if (niveau > OI[i]) - { - opmrg[i] = std::min(niveau, - OI[i] + P.getCoefficient(y, i + state.hourInTheYear) - H[i]); - SM += opmrg[i] - OI[i]; - } - else - { - opmrg[i] = std::max(niveau, OI[i] - H[i]); - SP += OI[i] - opmrg[i]; - } - } - - ecart = SP - SM; - if (ecart > 0) - { - bottom = niveau; - } - else - { - top = niveau; - } - - if (!--loop) - { - logs.error() << "OP.MRG: " << area.name - << ": infinite loop detected. please check input data"; - return; - } - } while (ecart * ecart > 0.25); -} - -void PrepareMaxMRG(const State& state, double* opmrg, uint numSpace) -{ - if (state.simplexRunNeeded) - { - PrepareMaxMRGFor(state, opmrg, numSpace); - } - else - { - PrepareMaxMRGFor(state, opmrg, numSpace); - } -} - -} // namespace Antares::Solver::Variable::Economy diff --git a/src/solver/variable/include/antares/solver/variable/economy/all.h b/src/solver/variable/include/antares/solver/variable/economy/all.h index 8e1c2ed307..17207c22db 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/all.h +++ b/src/solver/variable/include/antares/solver/variable/economy/all.h @@ -49,12 +49,16 @@ #include "inflow.h" #include "localMatchingRuleViolations.h" #include "lold.h" +#include "loldCsr.h" #include "lolp.h" +#include "lolpCsr.h" +#include "max-mrg-csr.h" #include "max-mrg.h" #include "nbOfDispatchedUnits.h" #include "nonProportionalCost.h" #include "operatingCost.h" #include "overallCost.h" +#include "overallCostCsr.h" #include "overflow.h" #include "pumping.h" #include "renewableGeneration.h" @@ -91,59 +95,62 @@ namespace Antares::Solver::Variable::Economy /*! ** \brief All variables for a single area (economy) */ -typedef // Prices - OverallCost // Overall Cost (Op. Cost + Unsupplied Eng.) - >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> +typedef // Prices + OverallCost // Overall Cost (Op. Cost + Unsupplied Eng.) + >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> VariablesPerArea; /*! diff --git a/src/solver/variable/include/antares/solver/variable/economy/loldCsr.h b/src/solver/variable/include/antares/solver/variable/economy/loldCsr.h new file mode 100644 index 0000000000..299e83b94f --- /dev/null +++ b/src/solver/variable/include/antares/solver/variable/economy/loldCsr.h @@ -0,0 +1,242 @@ +/* +** Copyright 2007-2023 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditions of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** 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 +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ +#pragma once + +#include "../variable.h" + +namespace Antares::Solver::Variable::Economy +{ + +struct VCardLOLD_CSR +{ + //! Caption + static std::string Caption() + { + return "LOLD CSR"; + } + + //! Unit + static std::string Unit() + { + return "Hours"; + } + + //! The short description of the variable + static std::string Description() + { + return "LOLD for CSR"; + } + + //! The expecte results + typedef Results>>>> + ResultsType; + + static constexpr uint8_t categoryDataLevel = Category::DataLevel::area; + //! File level (provided by the type of the results) + static constexpr uint8_t categoryFileLevel = ResultsType::categoryFile + & (Category::FileLevel::id + | Category::FileLevel::va); + //! Precision (views) + static constexpr uint8_t precision = Category::all; + //! Indentation (GUI) + static constexpr uint8_t nodeDepthForGUI = +0; + //! Decimal precision + static constexpr uint8_t decimal = 2; + //! Number of columns used by the variable (One ResultsType per column) + static constexpr int columnCount = 1; + //! The Spatial aggregation + static constexpr uint8_t spatialAggregate = Category::spatialAggregateSum; + static constexpr uint8_t spatialAggregateMode = Category::spatialAggregateEachYear; + static constexpr uint8_t spatialAggregatePostProcessing = 0; + //! Intermediate values + static constexpr uint8_t hasIntermediateValues = 1; + //! Can this variable be non applicable (0 : no, 1 : yes) + static constexpr uint8_t isPossiblyNonApplicable = 0; + + typedef IntermediateValues IntermediateValuesBaseType; + typedef IntermediateValues* IntermediateValuesType; + + typedef IntermediateValuesBaseType* IntermediateValuesTypeForSpatialAg; + +}; // class VCard + +/*! +** \brief +*/ +template +class LOLD_CSR: public Variable::IVariable, NextT, VCardLOLD_CSR> +{ +public: + //! Type of the next static variable + typedef NextT NextType; + //! VCard + typedef VCardLOLD_CSR VCardType; + //! Ancestor + typedef Variable::IVariable, NextT, VCardType> AncestorType; + + //! List of expected results + typedef typename VCardType::ResultsType ResultsType; + + typedef VariableAccessor VariableAccessorType; + + enum + { + //! How many items have we got + count = 1 + NextT::count, + }; + + template + struct Statistics + { + enum + { + count = ((VCardType::categoryDataLevel & CDataLevel + && VCardType::categoryFileLevel & CFile) + ? (NextType::template Statistics::count + + VCardType::columnCount * ResultsType::count) + : NextType::template Statistics::count), + }; + }; + +public: + ~LOLD_CSR() + { + delete[] pValuesForTheCurrentYear; + } + + void initializeFromStudy(Data::Study& study) + { + pNbYearsParallel = study.maxNbYearsInParallel; + + // Intermediate values + InitializeResultsFromStudy(AncestorType::pResults, study); + + pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { + pValuesForTheCurrentYear[numSpace].initializeFromStudy(study); + } + // Next + NextType::initializeFromStudy(study); + } + + template + static void InitializeResultsFromStudy(R& results, Data::Study& study) + { + VariableAccessorType::InitializeAndReset(results, study); + } + + void simulationBegin() + { + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { + pValuesForTheCurrentYear[numSpace].reset(); + } + // Next + NextType::simulationBegin(); + } + + void yearBegin(unsigned int year, unsigned int numSpace) + { + // Reset the values for the current year + pValuesForTheCurrentYear[numSpace].reset(); + + // Next variable + NextType::yearBegin(year, numSpace); + } + + void yearEnd(unsigned int year, unsigned int numSpace) + { + // Compute all statistics for the current year (daily,weekly,monthly) + pValuesForTheCurrentYear[numSpace].computeStatisticsForTheCurrentYear(); + + // Next variable + NextType::yearEnd(year, numSpace); + } + + void computeSummary(std::map& numSpaceToYear, + unsigned int nbYearsForCurrentSummary) + { + for (unsigned int numSpace = 0; numSpace < nbYearsForCurrentSummary; ++numSpace) + { + // Merge all those values with the global results + AncestorType::pResults.merge(numSpaceToYear[numSpace] /*year*/, + pValuesForTheCurrentYear[numSpace]); + } + + // Next variable + NextType::computeSummary(numSpaceToYear, nbYearsForCurrentSummary); + } + + void hourForEachArea(State& state, unsigned int numSpace) + { + if (state.hourlyResults->ValeursHorairesDeDefaillancePositiveCSR[state.hourInTheWeek] > 0.5) + { + pValuesForTheCurrentYear[numSpace][state.hourInTheYear] = 1.; + } + + // Next variable + NextType::hourForEachArea(state, numSpace); + } + + Antares::Memory::Stored::ConstReturnType retrieveRawHourlyValuesForCurrentYear( + unsigned int, + unsigned int numSpace) const + { + return pValuesForTheCurrentYear[numSpace].hour; + } + + void localBuildAnnualSurveyReport(SurveyResults& results, + int fileLevel, + int precision, + unsigned int numSpace) const + { + // Initializing external pointer on current variable non applicable status + results.isCurrentVarNA = AncestorType::isNonApplicable; + + if (AncestorType::isPrinted[0]) + { + // Write the data for the current year + results.variableCaption = VCardType::Caption(); + results.variableUnit = VCardType::Unit(); + pValuesForTheCurrentYear[numSpace] + .template buildAnnualSurveyReport(results, fileLevel, precision); + } + } + +private: + //! Intermediate values for each year + typename VCardType::IntermediateValuesType pValuesForTheCurrentYear; + unsigned int pNbYearsParallel; + +}; // class LOLD_CSR + +} // namespace Antares::Solver::Variable::Economy diff --git a/src/solver/variable/include/antares/solver/variable/economy/lolpCsr.h b/src/solver/variable/include/antares/solver/variable/economy/lolpCsr.h new file mode 100644 index 0000000000..45d9ed61ac --- /dev/null +++ b/src/solver/variable/include/antares/solver/variable/economy/lolpCsr.h @@ -0,0 +1,242 @@ +/* +** Copyright 2007-2023 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditions of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** 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 +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ +#pragma once + +#include "../variable.h" + +namespace Antares::Solver::Variable::Economy +{ +struct VCardLOLP_CSR +{ + //! Caption + static std::string Caption() + { + return "LOLP CSR"; + } + + //! Unit + static std::string Unit() + { + return "%"; + } + + //! The short description of the variable + static std::string Description() + { + return "LOLP for CSR"; + } + + //! The expecte results + typedef Results> + ResultsType; + + //! The VCard to look for for calculating spatial aggregates + typedef VCardLOLP_CSR VCardForSpatialAggregate; + + static constexpr uint8_t categoryDataLevel = Category::DataLevel::area; + //! File level (provided by the type of the results) + static constexpr uint8_t categoryFileLevel = ResultsType::categoryFile + & (Category::FileLevel::id + | Category::FileLevel::va); + //! Precision (views) + static constexpr uint8_t precision = Category::all; + //! Indentation (GUI) + static constexpr uint8_t nodeDepthForGUI = +0; + //! Decimal precision + static constexpr uint8_t decimal = 2; + //! Number of columns used by the variable (One ResultsType per column) + static constexpr int columnCount = 1; + //! The Spatial aggregation + static constexpr uint8_t spatialAggregate = Category::spatialAggregateSum; + static constexpr uint8_t spatialAggregateMode = Category::spatialAggregateEachYear; + static constexpr uint8_t spatialAggregatePostProcessing = 0; + //! Intermediate values + static constexpr uint8_t hasIntermediateValues = 1; + //! Can this variable be non applicable (0 : no, 1 : yes) + static constexpr uint8_t isPossiblyNonApplicable = 0; + + typedef IntermediateValues IntermediateValuesBaseType; + typedef IntermediateValues* IntermediateValuesType; + + typedef IntermediateValuesBaseType* IntermediateValuesTypeForSpatialAg; + +}; // class VCard + +/*! +** \brief +*/ +template +class LOLP_CSR: public Variable::IVariable, NextT, VCardLOLP_CSR> +{ +public: + //! Type of the next static variable + typedef NextT NextType; + //! VCard + typedef VCardLOLP_CSR VCardType; + //! Ancestor + typedef Variable::IVariable, NextT, VCardType> AncestorType; + + //! List of expected results + typedef typename VCardType::ResultsType ResultsType; + + typedef VariableAccessor VariableAccessorType; + + enum + { + //! How many items have we got + count = 1 + NextT::count, + }; + + template + struct Statistics + { + enum + { + count = ((VCardType::categoryDataLevel & CDataLevel + && VCardType::categoryFileLevel & CFile) + ? (NextType::template Statistics::count + + VCardType::columnCount * ResultsType::count) + : NextType::template Statistics::count), + }; + }; + +public: + ~LOLP_CSR() + { + delete[] pValuesForTheCurrentYear; + } + + void initializeFromStudy(Data::Study& study) + { + pNbYearsParallel = study.maxNbYearsInParallel; + + // Intermediate values + InitializeResultsFromStudy(AncestorType::pResults, study); + + pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { + pValuesForTheCurrentYear[numSpace].initializeFromStudy(study); + } + + // Next + NextType::initializeFromStudy(study); + } + + template + static void InitializeResultsFromStudy(R& results, Data::Study& study) + { + VariableAccessorType::InitializeAndReset(results, study); + } + + void simulationBegin() + { + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { + pValuesForTheCurrentYear[numSpace].reset(); + } + // Next + NextType::simulationBegin(); + } + + void yearBegin(unsigned int year, unsigned int numSpace) + { + // Reset the values for the current year + pValuesForTheCurrentYear[numSpace].reset(); + + // Next variable + NextType::yearBegin(year, numSpace); + } + + void yearEnd(unsigned int year, unsigned int numSpace) + { + // Compute all statistics for the current year (daily,weekly,monthly) + pValuesForTheCurrentYear[numSpace].computeStatisticsOrForTheCurrentYear(); + + // Next variable + NextType::yearEnd(year, numSpace); + } + + void computeSummary(std::map& numSpaceToYear, + unsigned int nbYearsForCurrentSummary) + { + for (unsigned int numSpace = 0; numSpace < nbYearsForCurrentSummary; ++numSpace) + { + // Merge all those values with the global results + AncestorType::pResults.merge(numSpaceToYear[numSpace] /*year*/, + pValuesForTheCurrentYear[numSpace]); + } + + // Next variable + NextType::computeSummary(numSpaceToYear, nbYearsForCurrentSummary); + } + + void hourForEachArea(State& state, unsigned int numSpace) + { + if (state.hourlyResults->ValeursHorairesDeDefaillancePositiveCSR[state.hourInTheWeek] > 0.5) + { + pValuesForTheCurrentYear[numSpace][state.hourInTheYear] = 100; + } + + // Next variable + NextType::hourForEachArea(state, numSpace); + } + + Antares::Memory::Stored::ConstReturnType retrieveRawHourlyValuesForCurrentYear( + unsigned int, + unsigned int numSpace) const + { + return pValuesForTheCurrentYear[numSpace].hour; + } + + void localBuildAnnualSurveyReport(SurveyResults& results, + int fileLevel, + int precision, + unsigned int numSpace) const + { + // Initializing external pointer on current variable non applicable status + results.isCurrentVarNA = AncestorType::isNonApplicable; + + if (AncestorType::isPrinted[0]) + { + // Write the data for the current year + results.variableCaption = VCardType::Caption(); + results.variableUnit = VCardType::Unit(); + pValuesForTheCurrentYear[numSpace] + .template buildAnnualSurveyReport(results, fileLevel, precision); + } + } + +private: + //! Intermediate values for each year + typename VCardType::IntermediateValuesType pValuesForTheCurrentYear; + unsigned int pNbYearsParallel; + +}; // class LOLP_CSR + +} // namespace Antares::Solver::Variable::Economy diff --git a/src/solver/variable/include/antares/solver/variable/economy/max-mrg-csr.h b/src/solver/variable/include/antares/solver/variable/economy/max-mrg-csr.h new file mode 100644 index 0000000000..2ff8edc89d --- /dev/null +++ b/src/solver/variable/include/antares/solver/variable/economy/max-mrg-csr.h @@ -0,0 +1,243 @@ +/* +** Copyright 2007-2023 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditions of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** 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 +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ +#pragma once + +#include "../variable.h" +#include "max-mrg-utils.h" + +namespace Antares::Solver::Variable::Economy +{ +struct VCardMAX_MRG_CSR +{ + //! Caption + static std::string Caption() + { + return "MAX MRG CSR"; + } + + //! Unit + static std::string Unit() + { + return "MWh"; + } + + //! The short description of the variable + static std::string Description() + { + return "Max margin for CSR"; + } + + //! The expecte results + typedef Results>>>> + ResultsType; + + //! The VCard to look for for calculating spatial aggregates + typedef VCardMAX_MRG_CSR VCardForSpatialAggregate; + + static constexpr uint8_t categoryDataLevel = Category::DataLevel::area; + //! File level (provided by the type of the results) + static constexpr uint8_t categoryFileLevel = ResultsType::categoryFile + & (Category::FileLevel::id + | Category::FileLevel::va); + //! Precision (views) + static constexpr uint8_t precision = Category::all; + //! Indentation (GUI) + static constexpr uint8_t nodeDepthForGUI = +0; + //! Decimal precision + static constexpr uint8_t decimal = 0; + //! Number of columns used by the variable (One ResultsType per column) + static constexpr int columnCount = 1; + //! The Spatial aggregation + static constexpr uint8_t spatialAggregate = Category::spatialAggregateSum; + static constexpr uint8_t spatialAggregateMode = Category::spatialAggregateEachYear; + static constexpr uint8_t spatialAggregatePostProcessing = 0; + //! Intermediate values + static constexpr uint8_t hasIntermediateValues = 1; + //! Can this variable be non applicable (0 : no, 1 : yes) + static constexpr uint8_t isPossiblyNonApplicable = 0; + + typedef IntermediateValues IntermediateValuesBaseType; + typedef IntermediateValues* IntermediateValuesType; + + typedef IntermediateValuesBaseType* IntermediateValuesTypeForSpatialAg; + +}; // class VCard + +/*! +** \brief Prepare MAX.MRG results for a given week +*/ +template +void PrepareMaxMRGFor(const State& state, double* opmrg, uint numSpace); + +/*! +** \brief Max MRG +*/ +template +class MaxMrgCsr: public Variable::IVariable, NextT, VCardMAX_MRG_CSR> +{ +public: + //! Type of the next static variable + typedef NextT NextType; + //! VCard + typedef VCardMAX_MRG_CSR VCardType; + //! Ancestor + typedef Variable::IVariable, NextT, VCardType> AncestorType; + + //! List of expected results + typedef typename VCardType::ResultsType ResultsType; + + typedef VariableAccessor VariableAccessorType; + + enum + { + //! How many items have we got + count = 1 + NextT::count, + }; + + template + struct Statistics + { + enum + { + count = ((VCardType::categoryDataLevel & CDataLevel + && VCardType::categoryFileLevel & CFile) + ? (NextType::template Statistics::count + + VCardType::columnCount * ResultsType::count) + : NextType::template Statistics::count), + }; + }; + +public: + ~MaxMrgCsr() + { + delete[] pValuesForTheCurrentYear; + } + + void initializeFromStudy(Data::Study& study) + { + pNbYearsParallel = study.maxNbYearsInParallel; + + // Intermediate values + InitializeResultsFromStudy(AncestorType::pResults, study); + + pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { + pValuesForTheCurrentYear[numSpace].initializeFromStudy(study); + } + + // Next + NextType::initializeFromStudy(study); + } + + template + static void InitializeResultsFromStudy(R& results, Data::Study& study) + { + VariableAccessorType::InitializeAndReset(results, study); + } + + void yearBegin(unsigned int year, unsigned int numSpace) + { + // Reset the values for the current year + pValuesForTheCurrentYear[numSpace].reset(); + // Next variable + NextType::yearBegin(year, numSpace); + } + + void yearEnd(unsigned int year, unsigned int numSpace) + { + // Compute all statistics for the current year (daily,weekly,monthly) + pValuesForTheCurrentYear[numSpace].computeStatisticsForTheCurrentYear(); + + // Next variable + NextType::yearEnd(year, numSpace); + } + + void computeSummary(std::map& numSpaceToYear, + unsigned int nbYearsForCurrentSummary) + { + for (unsigned int numSpace = 0; numSpace < nbYearsForCurrentSummary; ++numSpace) + { + // Merge all those values with the global results + AncestorType::pResults.merge(numSpaceToYear[numSpace] /*year*/, + pValuesForTheCurrentYear[numSpace]); + } + + // Next variable + NextType::computeSummary(numSpaceToYear, nbYearsForCurrentSummary); + } + + void weekForEachArea(State& state, unsigned int numSpace) + { + double* rawhourly = Memory::RawPointer(pValuesForTheCurrentYear[numSpace].hour); + + // Getting data required to compute max margin + MaxMrgCSRdataFactory maxMRGcsrDataFactory(state, numSpace); + MaxMRGinput maxMRGinput = maxMRGcsrDataFactory.data(); + computeMaxMRG(rawhourly + state.hourInTheYear, maxMRGinput); + + // next + NextType::weekForEachArea(state, numSpace); + } + + Antares::Memory::Stored::ConstReturnType retrieveRawHourlyValuesForCurrentYear( + unsigned int, + unsigned int numSpace) const + { + return pValuesForTheCurrentYear[numSpace].hour; + } + + void localBuildAnnualSurveyReport(SurveyResults& results, + int fileLevel, + int precision, + unsigned int numSpace) const + { + // Initializing external pointer on current variable non applicable status + results.isCurrentVarNA = AncestorType::isNonApplicable; + + if (AncestorType::isPrinted[0]) + { + // Write the data for the current year + results.variableCaption = VCardType::Caption(); + results.variableUnit = VCardType::Unit(); + pValuesForTheCurrentYear[numSpace] + .template buildAnnualSurveyReport(results, fileLevel, precision); + } + } + +private: + //! Intermediate values for each year + typename VCardType::IntermediateValuesType pValuesForTheCurrentYear; + unsigned int pNbYearsParallel; + +}; // class MaxMrgCsr + +} // namespace Antares::Solver::Variable::Economy diff --git a/src/solver/variable/include/antares/solver/variable/economy/max-mrg-utils.h b/src/solver/variable/include/antares/solver/variable/economy/max-mrg-utils.h new file mode 100644 index 0000000000..2a5de71b74 --- /dev/null +++ b/src/solver/variable/include/antares/solver/variable/economy/max-mrg-utils.h @@ -0,0 +1,56 @@ +#pragma once + +#include + +#include "../state.h" + +namespace Antares::Solver::Variable::Economy +{ + +struct MaxMRGinput +{ + double* spillage = nullptr; + double* dens = nullptr; + double* hydroGeneration = nullptr; + Antares::Data::TimeSeries* maxHourlyGenPower = nullptr; + double* dtgMargin = nullptr; + unsigned int hourInYear = 0; + unsigned int year = 0; + Date::Calendar* calendar = nullptr; + std::string areaName; +}; + +void computeMaxMRG(double* maxMrgOut, const MaxMRGinput& in); + +class MaxMrgDataFactory +{ +public: + MaxMrgDataFactory(const State& state, unsigned int numSpace); + virtual MaxMRGinput data() = 0; + +protected: + // in data + const State& state_; + const unsigned int numSpace_ = 0; + RESULTATS_HORAIRES& weeklyResults_; + // data to be built + MaxMRGinput maxMRGinput_; +}; + +class MaxMrgUsualDataFactory: public MaxMrgDataFactory +{ + using MaxMrgDataFactory::MaxMrgDataFactory; + +public: + virtual MaxMRGinput data() override; +}; + +class MaxMrgCSRdataFactory: public MaxMrgDataFactory +{ + using MaxMrgDataFactory::MaxMrgDataFactory; + +public: + virtual MaxMRGinput data() override; +}; + +} // namespace Antares::Solver::Variable::Economy diff --git a/src/solver/variable/include/antares/solver/variable/economy/max-mrg.h b/src/solver/variable/include/antares/solver/variable/economy/max-mrg.h index 959d6f16e7..a53b893947 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/max-mrg.h +++ b/src/solver/variable/include/antares/solver/variable/economy/max-mrg.h @@ -23,6 +23,8 @@ #include "antares/solver/variable/variable.h" +#include "max-mrg-utils.h" + namespace Antares { namespace Solver @@ -92,11 +94,6 @@ struct VCardMARGE }; // class VCard -/*! -** \brief Prepare MAX.MRG results for a given week -*/ -void PrepareMaxMRG(const State& state, double* opmrg, uint numSpace); - /*! ** \brief Max MRG */ @@ -206,8 +203,6 @@ class Marge: public Variable::IVariable, NextT, VCardMARGE> { // Compute all statistics for the current year (daily,weekly,monthly) pValuesForTheCurrentYear[numSpace].computeStatisticsForTheCurrentYear(); - // Merge all those values with the global results - // AncestorType::pResults.merge(year, pValuesForTheCurrentYear); // Next variable NextType::yearEnd(year, numSpace); @@ -242,7 +237,11 @@ class Marge: public Variable::IVariable, NextT, VCardMARGE> void weekForEachArea(State& state, unsigned int numSpace) { double* rawhourly = Memory::RawPointer(pValuesForTheCurrentYear[numSpace].hour); - PrepareMaxMRG(state, rawhourly + state.hourInTheYear, numSpace); + + // Getting data required to compute max margin + MaxMrgUsualDataFactory maxMRGdataFactory(state, numSpace); + MaxMRGinput maxMRGinput = maxMRGdataFactory.data(); + computeMaxMRG(rawhourly + state.hourInTheYear, maxMRGinput); // next NextType::weekForEachArea(state, numSpace); diff --git a/src/solver/variable/include/antares/solver/variable/economy/overallCostCsr.h b/src/solver/variable/include/antares/solver/variable/economy/overallCostCsr.h new file mode 100644 index 0000000000..63739b686b --- /dev/null +++ b/src/solver/variable/include/antares/solver/variable/economy/overallCostCsr.h @@ -0,0 +1,253 @@ +/* +** Copyright 2007-2023 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditions of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** 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 +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ +#pragma once + +#include "../variable.h" + +namespace Antares::Solver::Variable::Economy +{ +struct VCardOverallCostCsr +{ + //! Caption + static std::string Caption() + { + return "OV. COST CSR"; + } + + //! Unit + static std::string Unit() + { + return "Euro"; + } + + //! The short description of the variable + static std::string Description() + { + return "Overall Cost throughout all MC years"; + } + + //! The expecte results + typedef Results, + R::AllYears::Average // Use these values for spatial cluster + > + ResultsType; + + //! The VCard to look for for calculating spatial aggregates + typedef VCardOverallCostCsr VCardForSpatialAggregate; + + static constexpr uint8_t categoryDataLevel = Category::DataLevel::area; + //! File level (provided by the type of the results) + static constexpr uint8_t categoryFileLevel = ResultsType::categoryFile + & (Category::FileLevel::id + | Category::FileLevel::va); + //! Precision (views) + static constexpr uint8_t precision = Category::all; + //! Indentation (GUI) + static constexpr uint8_t nodeDepthForGUI = +0; + //! Decimal precision + static constexpr uint8_t decimal = 0; + //! Number of columns used by the variable (One ResultsType per column) + static constexpr int columnCount = 1; + //! The Spatial aggregation + static constexpr uint8_t spatialAggregate = Category::spatialAggregateSum; + static constexpr uint8_t spatialAggregateMode = Category::spatialAggregateEachYear; + static constexpr uint8_t spatialAggregatePostProcessing = 0; + //! Intermediate values + static constexpr uint8_t hasIntermediateValues = 1; + //! Can this variable be non applicable (0 : no, 1 : yes) + static constexpr uint8_t isPossiblyNonApplicable = 0; + + typedef IntermediateValues IntermediateValuesBaseType; + typedef IntermediateValues* IntermediateValuesType; + + typedef IntermediateValuesBaseType* IntermediateValuesTypeForSpatialAg; + +}; // class VCard + +/*! +** \brief C02 Average value of the overall OverallCostCsr emissions expected from all +** the thermal dispatchable clusters +*/ +template +class OverallCostCsr: public Variable::IVariable, NextT, VCardOverallCostCsr> +{ +public: + //! Type of the next static variable + typedef NextT NextType; + //! VCard + typedef VCardOverallCostCsr VCardType; + //! Ancestor + typedef Variable::IVariable, NextT, VCardType> AncestorType; + + //! List of expected results + typedef typename VCardType::ResultsType ResultsType; + + typedef VariableAccessor VariableAccessorType; + + enum + { + //! How many items have we got + count = 1 + NextT::count, + }; + + template + struct Statistics + { + enum + { + count = ((VCardType::categoryDataLevel & CDataLevel + && VCardType::categoryFileLevel & CFile) + ? (NextType::template Statistics::count + + VCardType::columnCount * ResultsType::count) + : NextType::template Statistics::count), + }; + }; + +public: + ~OverallCostCsr() + { + delete[] pValuesForTheCurrentYear; + } + + void initializeFromStudy(Data::Study& study) + { + pNbYearsParallel = study.maxNbYearsInParallel; + + // Intermediate values + InitializeResultsFromStudy(AncestorType::pResults, study); + + // Intermediate values + pValuesForTheCurrentYear = new VCardType::IntermediateValuesBaseType[pNbYearsParallel]; + for (unsigned int numSpace = 0; numSpace < pNbYearsParallel; numSpace++) + { + pValuesForTheCurrentYear[numSpace].initializeFromStudy(study); + } + + NextType::initializeFromStudy(study); + } + + template + static void InitializeResultsFromStudy(R& results, Data::Study& study) + { + VariableAccessorType::InitializeAndReset(results, study); + } + + void yearBegin(unsigned int year, unsigned int numSpace) + { + // Reset the values for the current year + pValuesForTheCurrentYear[numSpace].reset(); + + NextType::yearBegin(year, numSpace); + } + + void yearEndBuildForEachThermalCluster(State& state, uint year, unsigned int numSpace) + { + for (unsigned int i = state.study.runtime.rangeLimits.hour[Data::rangeBegin]; + i <= state.study.runtime.rangeLimits.hour[Data::rangeEnd]; + ++i) + { + pValuesForTheCurrentYear[numSpace][i] += state.thermalClusterOperatingCostForYear[i]; + } + + NextType::yearEndBuildForEachThermalCluster(state, year, numSpace); + } + + void yearEnd(unsigned int year, unsigned int numSpace) + { + // Compute all statistics for the current year (daily, weekly, monthly) + pValuesForTheCurrentYear[numSpace].computeStatisticsForTheCurrentYear(); + + NextType::yearEnd(year, numSpace); + } + + void computeSummary(std::map& numSpaceToYear, + unsigned int nbYearsForCurrentSummary) + { + for (unsigned int numSpace = 0; numSpace < nbYearsForCurrentSummary; ++numSpace) + { + // Merge all those values with the global results + AncestorType::pResults.merge(numSpaceToYear[numSpace] /*year*/, + pValuesForTheCurrentYear[numSpace]); + } + + NextType::computeSummary(numSpaceToYear, nbYearsForCurrentSummary); + } + + void hourForEachArea(State& state, unsigned int numSpace) + { + const double costForSpilledOrUnsuppliedEnergyCSR = + // Total UnsupliedEnergy emissions + (state.hourlyResults->ValeursHorairesDeDefaillancePositiveCSR[state.hourInTheWeek] + * state.area->thermal.unsuppliedEnergyCost) + + (state.hourlyResults->ValeursHorairesDeDefaillanceNegative[state.hourInTheWeek] + * state.area->thermal.spilledEnergyCost) + // Current hydro storage and pumping generation costs + + (state.hourlyResults->valeurH2oHoraire[state.hourInTheWeek] + * (state.hourlyResults->TurbinageHoraire[state.hourInTheWeek] + - state.area->hydro.pumpingEfficiency + * state.hourlyResults->PompageHoraire[state.hourInTheWeek])); + + pValuesForTheCurrentYear[numSpace][state.hourInTheYear] + += costForSpilledOrUnsuppliedEnergyCSR; + + NextType::hourForEachArea(state, numSpace); + } + + Antares::Memory::Stored::ConstReturnType retrieveRawHourlyValuesForCurrentYear( + unsigned int, + unsigned int numSpace) const + { + return pValuesForTheCurrentYear[numSpace].hour; + } + + void localBuildAnnualSurveyReport(SurveyResults& results, + int fileLevel, + int precision, + unsigned int numSpace) const + { + // Initializing external pointer on current variable non applicable status + results.isCurrentVarNA = AncestorType::isNonApplicable; + + if (AncestorType::isPrinted[0]) + { + // Write the data for the current year + results.variableCaption = VCardType::Caption(); + results.variableUnit = VCardType::Unit(); + pValuesForTheCurrentYear[numSpace] + .template buildAnnualSurveyReport(results, fileLevel, precision); + } + } + +private: + //! Intermediate values for each year + typename VCardType::IntermediateValuesType pValuesForTheCurrentYear; + unsigned int pNbYearsParallel; + +}; // class OverallCostCsr + +} // namespace Antares::Solver::Variable::Economy diff --git a/src/solver/variable/include/antares/solver/variable/economy/unsupliedEnergyCsr.h b/src/solver/variable/include/antares/solver/variable/economy/unsupliedEnergyCsr.h index e4a989de2c..a83ccb2e03 100644 --- a/src/solver/variable/include/antares/solver/variable/economy/unsupliedEnergyCsr.h +++ b/src/solver/variable/include/antares/solver/variable/economy/unsupliedEnergyCsr.h @@ -60,8 +60,6 @@ struct VCardUnsupliedEnergyCSR //! The VCard to look for for calculating spatial aggregates typedef VCardUnsupliedEnergyCSR VCardForSpatialAggregate; - - //! Data Level static constexpr uint8_t categoryDataLevel = Category::DataLevel::area; //! File level (provided by the type of the results) static constexpr uint8_t categoryFileLevel = ResultsType::categoryFile diff --git a/src/solver/variable/max-mrg-utils.cpp b/src/solver/variable/max-mrg-utils.cpp new file mode 100644 index 0000000000..bfa93c1567 --- /dev/null +++ b/src/solver/variable/max-mrg-utils.cpp @@ -0,0 +1,171 @@ +/* +** Copyright 2007-2023 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditions of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** 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 +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ + +#include + +#include +#include +#include + +using namespace Yuni; + +const unsigned int nbHoursInWeek = 168; + +namespace Antares::Solver::Variable::Economy +{ + +MaxMrgDataFactory::MaxMrgDataFactory(const State& state, unsigned int numSpace): + state_(state), + numSpace_(numSpace), + weeklyResults_(state.problemeHebdo->ResultatsHoraires[state.area->index]) +{ + maxMRGinput_.hydroGeneration = weeklyResults_.TurbinageHoraire.data(); + maxMRGinput_.maxHourlyGenPower = &state_.area->hydro.series->maxHourlyGenPower; + maxMRGinput_.dtgMargin = state_.area->scratchpad[numSpace].dispatchableGenerationMargin; + maxMRGinput_.hourInYear = state.hourInTheYear; + maxMRGinput_.year = state.problemeHebdo->year; + maxMRGinput_.calendar = &state.study.calendar; + maxMRGinput_.areaName = state_.area->name.c_str(); +} + +MaxMRGinput MaxMrgUsualDataFactory::data() +{ + if (state_.simplexRunNeeded) + { + maxMRGinput_.spillage = weeklyResults_.ValeursHorairesDeDefaillanceNegative.data(); + } + else + { + maxMRGinput_.spillage = state_.resSpilled[state_.area->index]; + } + + maxMRGinput_.dens = weeklyResults_.ValeursHorairesDeDefaillancePositive.data(); + return maxMRGinput_; +} + +MaxMRGinput MaxMrgCSRdataFactory::data() +{ + maxMRGinput_.spillage = weeklyResults_.ValeursHorairesDeDefaillanceNegative.data(); + maxMRGinput_.dens = weeklyResults_.ValeursHorairesDeDefaillancePositiveCSR.data(); + return maxMRGinput_; +} + +void computeMaxMRG(double* maxMrgOut, const MaxMRGinput& in) +{ + assert(maxMrgOut && "Invalid OP.MRG target"); + + // Following block could be replaced with : + // double weekHydroGen = std::accumulate(in.hydroGeneration, in.hydroGeneration + nbHoursInWeek, + // 0.); + double weekHydroGen = 0.; + for (uint h = 0; h != nbHoursInWeek; ++h) + { + weekHydroGen += in.hydroGeneration[h]; + } + + if (Yuni::Math::Zero(weekHydroGen)) + { + for (uint h = 0; h != nbHoursInWeek; ++h) + { + maxMrgOut[h] = in.spillage[h] + in.dtgMargin[h] - in.dens[h]; + } + return; + } + + // Initialisation + std::vector OI(nbHoursInWeek); + for (uint h = 0; h != nbHoursInWeek; ++h) + { + OI[h] = in.spillage[h] + in.dtgMargin[h] - in.dens[h]; + } + + // Following block could be replaced with : + // double bottom = *std::min_element(OI.begin(), OI.end()); + // double top = *std::max_element(OI.begin(), OI.end()); + double bottom = +std::numeric_limits::max(); + double top = 0; + for (uint i = 0; i != nbHoursInWeek; ++i) + { + double oii = OI[i]; + if (oii > top) + { + top = oii; + } + if (oii < bottom) + { + bottom = oii; + } + } + + double ecart = 1.; + uint loop = 100; // arbitrary - maximum number of iterations + + do + { + double niveau = (top + bottom) * 0.5; + double SP = 0; // S+ + double SM = 0; // S- + + for (uint h = 0; h != nbHoursInWeek; ++h) + { + assert(h < HOURS_PER_YEAR && "calendar overflow"); + if (niveau > OI[h]) + { + maxMrgOut[h] = Math::Min(niveau, + OI[h] + + in.maxHourlyGenPower->getCoefficient(in.year, + h + in.hourInYear) + - in.hydroGeneration[h]); + SM += maxMrgOut[h] - OI[h]; + } + else + { + maxMrgOut[h] = Math::Max(niveau, OI[h] - in.hydroGeneration[h]); + SP += OI[h] - maxMrgOut[h]; + } + } + + ecart = SP - SM; + if (ecart > 0) + { + bottom = niveau; + } + else + { + top = niveau; + } + + if (!--loop) + { + logs.error() << "OP.MRG: " << in.areaName + << ": infinite loop detected. please check input data"; + return; + } + } while (ecart * ecart > 0.25); +} + +} // namespace Antares::Solver::Variable::Economy diff --git a/src/tests/src/libs/antares/writer/test_zip_writer.cpp b/src/tests/src/libs/antares/writer/test_zip_writer.cpp new file mode 100644 index 0000000000..ffa0d89fed --- /dev/null +++ b/src/tests/src/libs/antares/writer/test_zip_writer.cpp @@ -0,0 +1,127 @@ +/* +** Copyright 2007-2023 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditions of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** 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 +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ +#define BOOST_TEST_MODULE test - writer tests + +#include +#include + +#include "yuni/job/queue/service.h" + +#include "antares/benchmarking/DurationCollector.h" +#include "antares/writer/i_writer.h" +#include "antares/writer/writer_factory.h" + +#include "utils.h" + +extern "C" +{ +#include +#include +#include +#include +} + +using namespace Yuni::Job; +using Antares::Solver::IResultWriter; +using Benchmarking::IDurationCollector; +using Benchmarking::NullDurationCollector; + +// Handles lifetime of necessary objects +struct TestContext +{ + std::shared_ptr threadPool; + std::unique_ptr durationCollector; + std::shared_ptr writer; +}; + +std::shared_ptr createThreadPool(int size) +{ + auto threadPool = std::make_shared(); + threadPool->maximumThreadCount(size); + threadPool->start(); + return threadPool; +} + +std::string removeExtension(const std::string& name, const std::string& ext) +{ + int length = name.size(); + if (name.size() > ext.size() && name.substr(length - ext.size()) == ext) + { + return name.substr(0, length - ext.size()); + } + return name; +} + +TestContext createContext(const std::filesystem::path zipPath, int threadCount) +{ + auto threadPool = createThreadPool(threadCount); + std::unique_ptr + durationCollector = std::make_unique(); + std::string archiveName = zipPath.string(); + auto writer = Antares::Solver::resultWriterFactory(Antares::Data::zipArchive, + removeExtension(zipPath.string(), ".zip"), + threadPool, + *durationCollector); + return {threadPool, std::move(durationCollector), writer}; +} + +using ZipReaderHandle = void*; + +void checkZipContent(ZipReaderHandle handle, + const std::string& path, + const std::string& expectedContent) +{ + BOOST_CHECK(mz_zip_reader_locate_entry(handle, path.c_str(), 0) == MZ_OK); + BOOST_CHECK(mz_zip_reader_entry_open(handle) == MZ_OK); + char buffer[4096]; + int bytesRead = mz_zip_reader_entry_read(handle, buffer, sizeof(buffer)); + std::string stringRead(buffer, bytesRead); + BOOST_CHECK(stringRead == expectedContent); + mz_zip_reader_entry_close(handle); +} + +BOOST_AUTO_TEST_CASE(test_zip) +{ + // Writer some content to test.zip, possibly from 2 threads + auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + auto zipPath = working_tmp_dir / "test.zip"; + auto context = createContext(zipPath, 2); + std::string content1 = "test-content1"; + std::string content2 = "test-content2"; + context.writer->addEntryFromBuffer("test-path", content1); + context.writer->addEntryFromBuffer("test-second-path", content2); + context.writer->flush(); + context.writer->finalize(true); + + // Check content is correct + ZipReaderHandle readerHandle = mz_zip_reader_create(); + std::string zipPathStr = zipPath.string(); + BOOST_CHECK(mz_zip_reader_open_file(readerHandle, zipPathStr.c_str()) == MZ_OK); + checkZipContent(readerHandle, "test-path", "test-content1"); + checkZipContent(readerHandle, "test-second-path", "test-content2"); + mz_zip_reader_close(readerHandle); +} diff --git a/src/tests/src/solver/optimisation/adequacy_patch.cpp b/src/tests/src/solver/optimisation/adequacy_patch.cpp new file mode 100644 index 0000000000..f6c5fddeb0 --- /dev/null +++ b/src/tests/src/solver/optimisation/adequacy_patch.cpp @@ -0,0 +1,386 @@ +#define BOOST_TEST_MODULE test adequacy patch functions + +#define WIN32_LEAN_AND_MEAN + +#include +#include +#include +#include + +#include + +#include +#include "antares/study/parameters/adq-patch-params.h" + +#include "adequacy_patch_csr/adq_patch_curtailment_sharing.h" +#include "adequacy_patch_local_matching/adq_patch_local_matching.h" + +static double origineExtremite = -1; +static double extremiteOrigine = 5; + +using namespace Antares::Data::AdequacyPatch; +namespace tt = boost::test_tools; + +static const double flowArea0toArea1_positive = 10; +static const double flowArea0toArea1_negative = -10; +static const double flowArea2toArea0_positive = 30; +static const double flowArea2toArea0_negative = -30; +static const double positiveEnsInit = 50.0; + +std::pair calculateAreaFlowBalanceForOneTimeStep( + double ensInit, + bool includeFlowsOutsideAdqPatchToDensNew, + AdequacyPatchMode Area1Mode, + AdequacyPatchMode Area2Mode, + double flowToArea1, + double flowFromArea2) +{ + PROBLEME_HEBDO problem; + int Area = 0; + uint hour = 0; + + // allocate memory + problem.adequacyPatchRuntimeData = std::make_shared(); + problem.adequacyPatchRuntimeData->originAreaMode.resize(3); + problem.adequacyPatchRuntimeData->extremityAreaMode.resize(3); + + AdqPatchParams adqPatchParams; + + problem.ResultatsHoraires.resize(1); + problem.ResultatsHoraires[0].ValeursHorairesDeDefaillancePositive = std::vector(1); + problem.ValeursDeNTC = std::vector(1); + problem.ValeursDeNTC[0].ValeurDuFlux = std::vector(3); + problem.IndexSuivantIntercoOrigine = std::vector(3); + problem.IndexSuivantIntercoExtremite = std::vector(3); + problem.IndexDebutIntercoOrigine = std::vector(1); + problem.IndexDebutIntercoExtremite = std::vector(1); + + // input values + adqPatchParams.localMatching.setToZeroOutsideInsideLinks + = !includeFlowsOutsideAdqPatchToDensNew; + problem.ResultatsHoraires[Area].ValeursHorairesDeDefaillancePositive[hour] = ensInit; + int Interco = 1; + problem.IndexDebutIntercoOrigine[Area] = Interco; + problem.adequacyPatchRuntimeData->extremityAreaMode[Interco] = Area1Mode; + problem.ValeursDeNTC[hour].ValeurDuFlux[Interco] = flowToArea1; + problem.IndexSuivantIntercoOrigine[Interco] = -1; + + Interco = 2; + problem.IndexDebutIntercoExtremite[Area] = Interco; + problem.adequacyPatchRuntimeData->originAreaMode[Interco] = Area2Mode; + problem.ValeursDeNTC[hour].ValeurDuFlux[Interco] = flowFromArea2; + problem.IndexSuivantIntercoExtremite[Interco] = -1; + + // get results + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew, std::ignore) = calculateAreaFlowBalance( + &problem, + adqPatchParams.localMatching.setToZeroOutsideInsideLinks, + Area, + hour); + + return std::make_pair(netPositionInit, densNew); +} + +AdqPatchParams createParams() +{ + AdqPatchParams p; + p.enabled = true; + p.curtailmentSharing.includeHurdleCost = true; + p.curtailmentSharing.priceTakingOrder = AdqPatchPTO::isDens; + + return p; +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 virtual-area, and Area2-virtual area +// flow from Area0 -> Area1 is positive +// flow from Area2 -> Area0 is positive +// DensNew parameter should NOT include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE( + calculateAreaFlowBalanceForOneTimeStep_virtual_virtual_NotIncludeOut_positiveFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + false, + virtualArea, + virtualArea, + flowArea0toArea1_positive, + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(netPositionInit, 0.0); + BOOST_CHECK_EQUAL(densNew, 0.0); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area inside adq-patch, and Area2-virtual area +// flow from Area0 -> Area1 is positive +// flow from Area2 -> Area0 is positive +// DensNew parameter should NOT include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE( + calculateAreaFlowBalanceForOneTimeStep_inside_virtual_NotIncludeOut_positiveFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + false, + physicalAreaInsideAdqPatch, + virtualArea, + flowArea0toArea1_positive, + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(netPositionInit, -flowArea0toArea1_positive); + BOOST_CHECK_EQUAL(densNew, 0.0); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area inside adq-patch, and Area2-virtual area +// flow from Area0 -> Area1 is positive +// flow from Area2 -> Area0 is positive +// DensNew parameter should NOT include flows from areas outside adq patch +// ensInit = 50.0 +BOOST_AUTO_TEST_CASE( + calculateAreaFlowBalanceForOneTimeStep_inside_virtual_NotIncludeOut_positiveFlow_ensInitGraterThanZero) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + positiveEnsInit, + false, + physicalAreaInsideAdqPatch, + virtualArea, + flowArea0toArea1_positive, + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(netPositionInit, -flowArea0toArea1_positive); + BOOST_CHECK_EQUAL(densNew, positiveEnsInit - flowArea0toArea1_positive); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area inside adq-patch, and Area2 physical area outside adq-patch +// flow from Area0 -> Area1 is positive +// flow from Area2 -> Area0 is positive +// DensNew parameter should NOT include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE( + calculateAreaFlowBalanceForOneTimeStep_inside_outside_NotIncludeOut_positiveFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + false, + physicalAreaInsideAdqPatch, + physicalAreaOutsideAdqPatch, + flowArea0toArea1_positive, + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(netPositionInit, -flowArea0toArea1_positive); + BOOST_CHECK_EQUAL(densNew, 0.0); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area inside adq-patch, and Area2 physical area inside adq-patch +// flow from Area0 -> Area1 is positive +// flow from Area2 -> Area0 is positive +// DensNew parameter should NOT include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE( + calculateAreaFlowBalanceForOneTimeStep_inside_inside_NotIncludeOut_positiveFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + false, + physicalAreaInsideAdqPatch, + physicalAreaInsideAdqPatch, + flowArea0toArea1_positive, + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(netPositionInit, -flowArea0toArea1_positive + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(densNew, -flowArea0toArea1_positive + flowArea2toArea0_positive); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area inside adq-patch, and Area2 physical area outside adq-patch +// flow from Area0 -> Area1 is positive +// flow from Area2 -> Area0 is positive +// DensNew parameter SHOULD include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE(calculateAreaFlowBalanceForOneTimeStep_inside_outside_IncludeOut_positiveFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + true, + physicalAreaInsideAdqPatch, + physicalAreaOutsideAdqPatch, + flowArea0toArea1_positive, + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(netPositionInit, -flowArea0toArea1_positive); + BOOST_CHECK_EQUAL(densNew, -flowArea0toArea1_positive + flowArea2toArea0_positive); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area outside adq-patch, and Area2 physical area outside adq-patch +// flow from Area0 -> Area1 is positive +// flow from Area2 -> Area0 is positive +// DensNew parameter SHOULD include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE(calculateAreaFlowBalanceForOneTimeStep_outside_outside_IncludeOut_positiveFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + true, + physicalAreaOutsideAdqPatch, + physicalAreaOutsideAdqPatch, + flowArea0toArea1_positive, + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(netPositionInit, 0.0); + BOOST_CHECK_EQUAL(densNew, flowArea2toArea0_positive); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area outside adq-patch, and Area2 physical area inside adq-patch +// flow from Area0 -> Area1 is positive +// flow from Area2 -> Area0 is positive +// DensNew parameter SHOULD include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE(calculateAreaFlowBalanceForOneTimeStep_outside_inside_IncludeOut_positiveFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + true, + physicalAreaOutsideAdqPatch, + physicalAreaInsideAdqPatch, + flowArea0toArea1_positive, + flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(netPositionInit, +flowArea2toArea0_positive); + BOOST_CHECK_EQUAL(densNew, +flowArea2toArea0_positive); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area inside adq-patch, and Area2 physical area outside adq-patch +// flow from Area0 -> Area1 is negative +// flow from Area2 -> Area0 is negative +// DensNew parameter SHOULD include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE(calculateAreaFlowBalanceForOneTimeStep_inside_outside_IncludeOut_negativeFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + true, + physicalAreaInsideAdqPatch, + physicalAreaOutsideAdqPatch, + flowArea0toArea1_negative, + flowArea2toArea0_negative); + BOOST_CHECK_EQUAL(netPositionInit, -flowArea0toArea1_negative); + BOOST_CHECK_EQUAL(densNew, -flowArea0toArea1_negative); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area outside adq-patch, and Area2 physical area outside adq-patch +// flow from Area0 -> Area1 is negative +// flow from Area2 -> Area0 is negative +// DensNew parameter SHOULD include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE(calculateAreaFlowBalanceForOneTimeStep_outside_outside_IncludeOut_negativeFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + true, + physicalAreaOutsideAdqPatch, + physicalAreaOutsideAdqPatch, + flowArea0toArea1_negative, + flowArea2toArea0_negative); + BOOST_CHECK_EQUAL(netPositionInit, 0.0); + BOOST_CHECK_EQUAL(densNew, -flowArea0toArea1_negative); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area outside adq-patch, and Area2 physical area inside adq-patch +// flow from Area0 -> Area1 is negative +// flow from Area2 -> Area0 is negative +// DensNew parameter SHOULD include flows from areas outside adq patch +BOOST_AUTO_TEST_CASE(calculateAreaFlowBalanceForOneTimeStep_outside_inside_IncludeOut_negativeFlow) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 0.0, + true, + physicalAreaOutsideAdqPatch, + physicalAreaInsideAdqPatch, + flowArea0toArea1_negative, + flowArea2toArea0_negative); + BOOST_CHECK_EQUAL(netPositionInit, flowArea2toArea0_negative); + BOOST_CHECK_EQUAL(densNew, 0.0); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area inside adq-patch, and Area2 physical area inside adq-patch +// flow from Area0 -> Area1 is positiive +// flow from Area2 -> Area0 is negative +// DensNew parameter SHOULD include flows from areas outside adq patch +// ensInit = 50.0 +BOOST_AUTO_TEST_CASE( + calculateAreaFlowBalanceForOneTimeStep_outside_inside_IncludeOut_negativeFlow_initEnsEqualTo50) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + positiveEnsInit, + true, + physicalAreaInsideAdqPatch, + physicalAreaInsideAdqPatch, + flowArea0toArea1_positive, + flowArea2toArea0_negative); + BOOST_CHECK_EQUAL(netPositionInit, -flowArea0toArea1_positive + flowArea2toArea0_negative); + BOOST_CHECK_EQUAL(densNew, positiveEnsInit + netPositionInit); +} + +// Area 0 is physical area inside adq-patch connected to two areas: +// Area1 physical area inside adq-patch, and Area2 physical area inside adq-patch +// flow from Area0 -> Area1 is positiive +// flow from Area2 -> Area0 is negative +// DensNew parameter SHOULD include flows from areas outside adq patch +// ensInit = 2.0 +BOOST_AUTO_TEST_CASE( + calculateAreaFlowBalanceForOneTimeStep_outside_inside_IncludeOut_negativeFlow_initEnsEqualTo0) +{ + double netPositionInit; + double densNew; + std::tie(netPositionInit, densNew) = calculateAreaFlowBalanceForOneTimeStep( + 2.0, + true, + physicalAreaInsideAdqPatch, + physicalAreaInsideAdqPatch, + flowArea0toArea1_positive, + flowArea2toArea0_negative); + 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.checkAdqPatchSimulationModeEconomyOnly(Antares::Data::SimulationMode::Economy)); + BOOST_CHECK_NO_THROW(p.checkAdqPatchIncludeHurdleCost(true)); +} + +BOOST_AUTO_TEST_CASE(check_adq_param_wrong_mode) +{ + auto p = createParams(); + BOOST_CHECK_THROW(p.checkAdqPatchSimulationModeEconomyOnly( + Antares::Data::SimulationMode::Adequacy), + Error::IncompatibleSimulationModeForAdqPatch); +} + +BOOST_AUTO_TEST_CASE(check_adq_param_wrong_hurdle_cost) +{ + auto p = createParams(); + BOOST_CHECK_THROW(p.checkAdqPatchIncludeHurdleCost(false), Error::IncompatibleHurdleCostCSR); +} diff --git a/src/tests/src/solver/optimisation/adequacy_patch/adequacy_patch.cpp b/src/tests/src/solver/optimisation/adequacy_patch/adequacy_patch.cpp index ea9762838b..9f716ecb77 100644 --- a/src/tests/src/solver/optimisation/adequacy_patch/adequacy_patch.cpp +++ b/src/tests/src/solver/optimisation/adequacy_patch/adequacy_patch.cpp @@ -31,7 +31,6 @@ #include #include #include "antares/solver/optimisation/adequacy_patch_csr/adq_patch_curtailment_sharing.h" -#include "antares/solver/optimisation/adequacy_patch_csr/post_processing.h" #include "antares/study/parameters/adq-patch-params.h" static double origineExtremite = -1; @@ -402,75 +401,3 @@ BOOST_AUTO_TEST_CASE(check_adq_param_wrong_hurdle_cost) auto p = createParams(); BOOST_CHECK_THROW(p.checkAdqPatchIncludeHurdleCost(false), Error::IncompatibleHurdleCostCSR); } - -BOOST_AUTO_TEST_SUITE(adq_patch_post_processing) - -BOOST_AUTO_TEST_CASE(dtg_mrg_triggered_low_ens) -{ - const bool triggered = true; - const double dtgMrg = 32.; - const double ens = 21.; - - BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) == 11., tt::tolerance(1.e-6)); - - BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) + recomputeENS_MRG(triggered, dtgMrg, ens) - == std::abs(dtgMrg - ens), - tt::tolerance(1.e-6)); -} - -BOOST_AUTO_TEST_CASE(dtg_mrg_triggered_high_ens) -{ - const bool triggered = true; - const double dtgMrg = 32.; - const double ens = 42.; - - BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) == 0., tt::tolerance(1.e-6)); - - BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) + recomputeENS_MRG(triggered, dtgMrg, ens) - == std::abs(dtgMrg - ens), - tt::tolerance(1.e-6)); -} - -BOOST_AUTO_TEST_CASE(dtg_mrg_not_triggered_low_ens) -{ - const bool triggered = false; - const double dtgMrg = 32.; - const double ens = 21.; - - BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) == dtgMrg, tt::tolerance(1.e-6)); - BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) + recomputeENS_MRG(triggered, dtgMrg, ens) - == dtgMrg + ens, - tt::tolerance(1.e-6)); -} - -BOOST_AUTO_TEST_CASE(dtg_mrg_not_triggered_high_ens) -{ - const bool triggered = false; - const double dtgMrg = 32.; - const double ens = 42.; - - BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) == dtgMrg, tt::tolerance(1.e-6)); - BOOST_TEST(recomputeDTG_MRG(triggered, dtgMrg, ens) + recomputeENS_MRG(triggered, dtgMrg, ens) - == dtgMrg + ens, - tt::tolerance(1.e-6)); -} - -BOOST_AUTO_TEST_CASE(mrgprice_high_enscsr) -{ - const double ensCsr = 21.; - const double originalCost = 3.; - const double unsuppliedEnergyCost = 1000.; - BOOST_TEST(recomputeMRGPrice(ensCsr, originalCost, unsuppliedEnergyCost) - == -unsuppliedEnergyCost, - tt::tolerance(1.e-6)); -} - -BOOST_AUTO_TEST_CASE(mrgprice_low_enscsr) -{ - const double ensCsr = 0.; - const double originalCost = 3.; - const double unsuppliedEnergyCost = 1000.; - BOOST_TEST(recomputeMRGPrice(ensCsr, originalCost, unsuppliedEnergyCost) == originalCost, - tt::tolerance(1.e-6)); -} -BOOST_AUTO_TEST_SUITE_END() diff --git a/src/ui/simulator/application/main/create.cpp b/src/ui/simulator/application/main/create.cpp index 03d3f57a71..bb2182d148 100644 --- a/src/ui/simulator/application/main/create.cpp +++ b/src/ui/simulator/application/main/create.cpp @@ -293,7 +293,13 @@ void ApplWnd::internalInitialize() statusbar->SetStatusStyles(2, styles); statusbar->SetMinHeight(14); - statusbar->SetStatusText(wxT(""), 1); + statusbar->Connect(statusbar->GetId(), + wxEVT_CONTEXT_MENU, + wxContextMenuEventHandler(ApplWnd::evtOnContextMenuStatusBar), + nullptr, + this); + + statusbar->SetStatusText(wxT("| "), 1); wxFont f = statusbar->GetFont(); f.SetPointSize(f.GetPointSize() - 1); diff --git a/src/ui/simulator/application/main/internal-ids.h b/src/ui/simulator/application/main/internal-ids.h index 33d8f6f764..57893d5187 100644 --- a/src/ui/simulator/application/main/internal-ids.h +++ b/src/ui/simulator/application/main/internal-ids.h @@ -172,6 +172,16 @@ enum MenusID mnIDLaunchAnalyzer, mnIDLaunchConstraintsBuilder, + //! \name Popup Menu Operator for selected cells on any grid + //@{ + mnIDPopupOpNone, + mnIDPopupOpAverage, + mnIDPopupOpCellCount, + mnIDPopupOpMinimum, + mnIDPopupOpMaximum, + mnIDPopupOpSum, + //@} + //! \name Popup Menu Operator for selected nodes on any layer //@{ mnIDPopupSelectionHide, diff --git a/src/ui/simulator/application/main/main.cpp b/src/ui/simulator/application/main/main.cpp index 137b009c2b..38131d6552 100644 --- a/src/ui/simulator/application/main/main.cpp +++ b/src/ui/simulator/application/main/main.cpp @@ -179,6 +179,14 @@ EVT_MENU(mnInternalLogMessage, ApplWnd::onLogMessage) EVT_MENU(mnIDLaunchAnalyzer, ApplWnd::evtLaunchAnalyzer) EVT_MENU(mnIDLaunchConstraintsBuilder, ApplWnd::evtLaunchConstraintsBuilder) +// Context menu : Operator for selected cells (grid) +EVT_MENU(mnIDPopupOpNone, ApplWnd::evtOnContextMenuChangeOperator) +EVT_MENU(mnIDPopupOpAverage, ApplWnd::evtOnContextMenuChangeOperator) +EVT_MENU(mnIDPopupOpCellCount, ApplWnd::evtOnContextMenuChangeOperator) +EVT_MENU(mnIDPopupOpMinimum, ApplWnd::evtOnContextMenuChangeOperator) +EVT_MENU(mnIDPopupOpMaximum, ApplWnd::evtOnContextMenuChangeOperator) +EVT_MENU(mnIDPopupOpSum, ApplWnd::evtOnContextMenuChangeOperator) + EVT_MENU_OPEN(ApplWnd::evtOnMenuOpen) EVT_MENU_CLOSE(ApplWnd::evtOnMenuClose) @@ -245,6 +253,8 @@ ApplWnd::ApplWnd() : pageRenewableCommon(nullptr), pageNodalOptim(nullptr), pWndBindingConstraints(nullptr), + pGridSelectionOperator(new Component::Datagrid::Selection::CellCount()), + pGridSelectionAttachedGrid(nullptr), pMapContextMenu(nullptr), pUserNotes(nullptr), pMainNotebookAlreadyHasItsComponents(false), @@ -308,6 +318,13 @@ ApplWnd::~ApplWnd() OnStudyAreasChanged.clear(); OnStudyAreaDelete.clear(); + // Delete the grid operator + if (pGridSelectionOperator) + { + delete pGridSelectionOperator; + pGridSelectionOperator = nullptr; // May be needed in some cases + } + // Disconnect all events destroyBoundEvents(); // Unregister the global pointer to the instance @@ -346,6 +363,34 @@ void ApplWnd::selectSystem() pNotebook->select(wxT("sys"), true); } +void ApplWnd::evtOnContextMenuChangeOperator(wxCommandEvent& evt) +{ + switch (evt.GetId()) + { + case mnIDPopupOpNone: + gridOperatorSelectedCells(nullptr); + break; + case mnIDPopupOpAverage: + gridOperatorSelectedCells(new Component::Datagrid::Selection::Average()); + break; + case mnIDPopupOpCellCount: + gridOperatorSelectedCells(new Component::Datagrid::Selection::CellCount()); + break; + case mnIDPopupOpMinimum: + gridOperatorSelectedCells(new Component::Datagrid::Selection::Minimum()); + break; + case mnIDPopupOpMaximum: + gridOperatorSelectedCells(new Component::Datagrid::Selection::Maximum()); + break; + case mnIDPopupOpSum: + gridOperatorSelectedCells(new Component::Datagrid::Selection::Sum()); + break; + default: + break; + } + evt.Skip(); +} + static inline void EnableItem(wxMenuBar* menu, int id, bool opened) { auto* item = menu->FindItem(id); @@ -494,6 +539,7 @@ void ApplWnd::evtOnUpdateGUIAfterStudyIO(bool opened) // Reset the status bar resetDefaultStatusBarText(); + gridOperatorSelectedCellsUpdateResult(pGridSelectionAttachedGrid); // reload the user notes and districts if (not aboutToQuit and study) @@ -519,6 +565,7 @@ void ApplWnd::evtOnUpdateGUIAfterStudyIO(bool opened) { GetSizer()->Clear(true); pUserNotes = nullptr; + pGridSelectionAttachedGrid = nullptr; pBigDaddy = nullptr; pMainSizer = nullptr; pData->wipPanel = nullptr; @@ -778,6 +825,24 @@ void ApplWnd::onRenewableGenerationModellingChanged(bool init) refreshInputMenuOnRenewableModellingChanged(aggregated); } +void ApplWnd::gridOperatorSelectedCells(Component::Datagrid::Selection::IOperator* v) +{ + delete pGridSelectionOperator; + pGridSelectionOperator = v; + gridOperatorSelectedCellsUpdateResult(pGridSelectionAttachedGrid); +} + +Component::Datagrid::Selection::IOperator* ApplWnd::gridOperatorSelectedCells() const +{ + return pGridSelectionOperator; +} + +void ApplWnd::disableGridOperatorIfGrid(wxGrid* grid) +{ + if (pGridSelectionAttachedGrid == grid) + gridOperatorSelectedCellsUpdateResult(nullptr); +} + void ApplWnd::title() { assert(wxIsMainThread() == true and "Must be ran from the main thread"); diff --git a/src/ui/simulator/application/main/main.h b/src/ui/simulator/application/main/main.h index 0b1f9dd8bb..7b7683805e 100644 --- a/src/ui/simulator/application/main/main.h +++ b/src/ui/simulator/application/main/main.h @@ -26,6 +26,7 @@ #include #include "../../toolbox/components/notebook/notebook.h" +#include "../../toolbox/components/datagrid/selectionoperation.h" #include "../../toolbox/components/map/settings.h" #include #include "fwd.h" @@ -105,6 +106,41 @@ class ApplWnd final : public Component::Frame::WxLocalFrame, public Yuni::IEvent */ Map::Component* map() const; + /*! + ** \name Grid operator (for selected cells) + ** + ** A grid operator computes an operation (Sum, average...) on all selected + ** cells of the grid that currently has the focus. The result of this + ** computation is displayed in the status bar. + ** + ** \see Antares::Component::Datagrid::Component::onGridEnter() + ** \see Antares::Component::Datagrid::Component::onGridLeave() + */ + //@{ + /*! + ** \brief Get the current grid operator for selected cells + */ + Component::Datagrid::Selection::IOperator* gridOperatorSelectedCells() const; + + /*! + ** \brief Set the grid operator for selected cells + */ + void gridOperatorSelectedCells(Component::Datagrid::Selection::IOperator* v); + + /*! + ** \brief Update the GUI to display the result of the grid operator + ** + ** This method should be called each time the cells selection changes. + ** \param grid The `wxGrid` that has currently the focus (may be NULL) + */ + void gridOperatorSelectedCellsUpdateResult(wxGrid* grid); + + /*! + ** \brief Disable the grid operator + */ + void disableGridOperatorIfGrid(wxGrid* grid); + //@} + //! \name Title of the Window //@{ void title(); @@ -327,6 +363,8 @@ class ApplWnd final : public Component::Frame::WxLocalFrame, public Yuni::IEvent //! Create a complete menu for the window wxMenuBar* createMenu(); + //! Create a popup menu for all available operators on selected cells (grid) + wxMenu* createPopupMenuOperatorsOnGrid(); //! Create menu: File wxMenu* createMenuFiles(); @@ -398,6 +436,9 @@ class ApplWnd final : public Component::Frame::WxLocalFrame, public Yuni::IEvent //! \name Event: Context menu //@{ + //! Show the context menu associated to the status bar + void evtOnContextMenuStatusBar(wxContextMenuEvent& evt); + void evtOnContextMenuChangeOperator(wxCommandEvent& evt); void evtOnContextMenuMap(int x, int y); //@} @@ -696,6 +737,10 @@ class ApplWnd final : public Component::Frame::WxLocalFrame, public Yuni::IEvent Component::Notebook::Page* pageScBuilderHydroInitialLevels; Component::Notebook::Page* pageScBuilderHydroFinalLevels; + //! The current grid operator to use on selected cells + Component::Datagrid::Selection::IOperator* pGridSelectionOperator; + wxGrid* pGridSelectionAttachedGrid; + //! A context menu for the map wxMenu* pMapContextMenu; diff --git a/src/ui/simulator/application/main/menu.cpp b/src/ui/simulator/application/main/menu.cpp index 11121bce3c..619269b283 100644 --- a/src/ui/simulator/application/main/menu.cpp +++ b/src/ui/simulator/application/main/menu.cpp @@ -64,6 +64,21 @@ wxMenuBar* ApplWnd::createMenu() return ret; } +wxMenu* ApplWnd::createPopupMenuOperatorsOnGrid() +{ + auto* menu = new wxMenu(); + + // Wizard + Menu::CreateItem(menu, mnIDPopupOpNone, wxT("None"), "images/16x16/empty.png"); + menu->AppendSeparator(); + Menu::CreateItem(menu, mnIDPopupOpAverage, wxT("Average ")); + Menu::CreateItem(menu, mnIDPopupOpCellCount, wxT("Cell count ")); + Menu::CreateItem(menu, mnIDPopupOpMinimum, wxT("Minimum ")); + Menu::CreateItem(menu, mnIDPopupOpMaximum, wxT("Maximum ")); + Menu::CreateItem(menu, mnIDPopupOpSum, wxT("Sum ")); + return menu; +} + wxMenu* ApplWnd::createMenuFiles() { delete pMenuFile; diff --git a/src/ui/simulator/application/main/statusbar.cpp b/src/ui/simulator/application/main/statusbar.cpp index a12dd4a290..ed33372524 100644 --- a/src/ui/simulator/application/main/statusbar.cpp +++ b/src/ui/simulator/application/main/statusbar.cpp @@ -22,17 +22,16 @@ #include #include "main.h" #include "../../windows/version.h" -#include "antares/study/study.h" -// Datagrid -#include "../../toolbox/components/datagrid/component.h" +#include "../study.h" #include "../../toolbox/components/datagrid/gridhelper.h" #include #include -namespace Antares -{ -namespace Forms +using namespace Component::Datagrid; + +namespace Antares::Forms { + void ApplWnd::resetDefaultStatusBarText() { assert(wxIsMainThread() == true && "Must be ran from the main thread"); @@ -41,5 +40,216 @@ void ApplWnd::resetDefaultStatusBarText() #endif } -} // namespace Forms -} // namespace Antares + +bool oneCellSelected(wxGrid& grid) +{ + const wxGridCellCoordsArray& cells(grid.GetSelectedCells()); + return cells.size() > 0; +} + +size_t updateStatisticsOpForOneCell(wxGrid& grid, + VGridHelper* gridHelper, + Selection::IOperator* op) +{ + size_t totalCell = 0; + const wxGridCellCoordsArray& cells(grid.GetSelectedCells()); + for (uint i = 0; i < (uint)cells.size(); ++i) + { + auto& cell = cells[i]; + op->appendValue(gridHelper->GetNumericValue(cell.GetRow(), cell.GetCol())); + ++totalCell; + } + return totalCell; +} + +bool rowsSelected(wxGrid& grid) +{ + const wxArrayInt& rows(grid.GetSelectedRows()); + return rows.size() > 0; +} + +size_t updateStatisticsOpForRows(wxGrid& grid, + VGridHelper* gridHelper, + Selection::IOperator* op) +{ + size_t totalCell = 0; + int colCount = grid.GetNumberCols(); + const wxArrayInt& rows(grid.GetSelectedRows()); + for (uint i = 0; i < (uint)rows.size(); ++i) + { + for (int col = 0; col < colCount; ++col) + { + op->appendValue(gridHelper->GetNumericValue(rows[i], col)); + ++totalCell; + } + } + return totalCell; +} + +bool columnsSelected(wxGrid& grid) +{ + const wxArrayInt& cols(grid.GetSelectedCols()); + return cols.size() > 0; +} + +size_t updateStatisticsOpForColumns(wxGrid& grid, + VGridHelper* gridHelper, + Selection::IOperator* op) +{ + size_t totalCell = 0; + int rowCount = grid.GetNumberRows(); + const wxArrayInt& cols(grid.GetSelectedCols()); + for (uint i = 0; i < (uint)cols.size(); ++i) + { + for (int row = 0; row < rowCount; ++row) + { + op->appendValue(gridHelper->GetNumericValue(row, cols[i])); + ++totalCell; + } + } + return totalCell; +} + +bool blockSelected(wxGrid& grid) +{ + // Blocks. We always expect blocks top left and bottom right to have the same size, since their + // entries are supposed to correspond. + const wxGridCellCoordsArray& blockTopLeft(grid.GetSelectionBlockTopLeft()); + const wxGridCellCoordsArray& blockBottomRight(grid.GetSelectionBlockBottomRight()); + return (blockTopLeft.size() == blockBottomRight.size()) && (blockTopLeft.size() > 0); +} + +size_t updateStatisticsOpForBlock(wxGrid& grid, + VGridHelper* gridHelper, + Selection::IOperator* op) +{ + size_t totalCell = 0; + const wxGridCellCoordsArray& blockTopLeft(grid.GetSelectionBlockTopLeft()); + const wxGridCellCoordsArray& blockBottomRight(grid.GetSelectionBlockBottomRight()); + size_t blockSize = blockTopLeft.size(); + + for (uint i = 0; i < blockSize; ++i) + { + const wxGridCellCoords& topLeft = blockTopLeft[i]; + const wxGridCellCoords& bottomRight = blockBottomRight[i]; + for (int row = topLeft.GetRow(); row <= bottomRight.GetRow(); ++row) + { + for (int col = topLeft.GetCol(); col <= bottomRight.GetCol(); ++col) + { + op->appendValue(gridHelper->GetNumericValue(row, col)); + ++totalCell; + } + } + } + return totalCell; +} + +/* +** Applies a functor to all selected cells. Returns the number of selected +** cells. +*/ +static size_t applyOperatorOnSelectedCells(wxGrid& grid, + VGridHelper* gridHelper, + Selection::IOperator* op) +{ + assert(wxIsMainThread() == true and "Must be ran from the main thread"); + + if (oneCellSelected(grid)) + { + return updateStatisticsOpForOneCell(grid, gridHelper, op); + } + + if (rowsSelected(grid)) + { + return updateStatisticsOpForRows(grid, gridHelper, op); + } + + if (columnsSelected(grid)) + { + return updateStatisticsOpForColumns(grid, gridHelper, op); + } + + if (blockSelected(grid)) + { + return updateStatisticsOpForBlock(grid, gridHelper, op); + } + + return 0; +} + +void ApplWnd::gridOperatorSelectedCellsUpdateResult(wxGrid* grid) +{ + assert(wxIsMainThread() == true and "Must be ran from the main thread"); + enum + { + fieldIndex = 1, + }; + // The status bar + auto* statusBar = GetStatusBar(); + pGridSelectionAttachedGrid = grid; + if (statusBar) + { + if (not CurrentStudyIsValid()) + { + statusBar->SetStatusText(wxEmptyString, fieldIndex); + return; + } + if (not pGridSelectionOperator) + { + statusBar->SetStatusText(wxT("| (none)"), fieldIndex); + return; + } + + if (grid and grid->GetTable()) + { + auto* gridHelper = dynamic_cast(grid->GetTable()); + if (gridHelper) + { + // Reset of the operator + pGridSelectionOperator->reset(); + // Browse all selected cells + if (applyOperatorOnSelectedCells(*grid, gridHelper, pGridSelectionOperator)) + { + // Update the GUI + statusBar->SetStatusText(wxString() + << wxT("| ") << pGridSelectionOperator->caption() + << wxT(" = ") << pGridSelectionOperator->result(), + fieldIndex); + return; + } + } + } + // Empty + statusBar->SetStatusText( + wxString(wxT("| (")) << pGridSelectionOperator->caption() << wxT(')'), fieldIndex); + } +} + +void ApplWnd::evtOnContextMenuStatusBar(wxContextMenuEvent& evt) +{ + if (GUIIsLock()) + return; + + wxStatusBar* statusBar = GetStatusBar(); + if (statusBar) + { + wxRect rect; + if (statusBar->GetFieldRect(1, rect)) + { + const wxPoint pos = statusBar->ScreenToClient(evt.GetPosition()); + if (rect.Contains(pos)) + { + if (!pPopupMenuOperatorsGrid) + { + // Popup menu: Operators for selected cells on any grid + pPopupMenuOperatorsGrid = createPopupMenuOperatorsOnGrid(); + } + + statusBar->PopupMenu(pPopupMenuOperatorsGrid); + } + } + } + evt.Skip(); +} + +} // namespace Antares::Forms \ No newline at end of file diff --git a/src/ui/simulator/cmake/components.cmake b/src/ui/simulator/cmake/components.cmake index 0586928a48..df72d40b83 100644 --- a/src/ui/simulator/cmake/components.cmake +++ b/src/ui/simulator/cmake/components.cmake @@ -48,6 +48,7 @@ SET(SRC_TOOLBOX_COM_DBGRID_RENDERERS toolbox/components/datagrid/renderer.h toolbox/components/datagrid/renderer.hxx toolbox/components/datagrid/renderer.cpp + toolbox/components/datagrid/selectionoperation.h toolbox/components/datagrid/renderer/adequacy-patch-area-grid.h toolbox/components/datagrid/renderer/adequacy-patch-area-grid.cpp toolbox/components/datagrid/renderer/area.h diff --git a/src/ui/simulator/toolbox/components/datagrid/dbgrid.cpp b/src/ui/simulator/toolbox/components/datagrid/dbgrid.cpp index dc8624172e..84fe490800 100644 --- a/src/ui/simulator/toolbox/components/datagrid/dbgrid.cpp +++ b/src/ui/simulator/toolbox/components/datagrid/dbgrid.cpp @@ -120,6 +120,11 @@ DBGrid::DBGrid(Component* parent) : DBGrid::~DBGrid() { + // Remove any remaining reference + auto* mainFrm = Forms::ApplWnd::Instance(); + if (mainFrm) + mainFrm->disableGridOperatorIfGrid(this); + pParentComponent = nullptr; otherGrid_ = nullptr; } @@ -128,6 +133,10 @@ void DBGrid::onGridSelectCell(wxGridEvent& evt) { assert(GetParent() && "invalid parent"); + auto* mainFrm = Forms::ApplWnd::Instance(); + if (mainFrm) + mainFrm->gridOperatorSelectedCellsUpdateResult(this); + pCurrentPosition.x = evt.GetCol(); pCurrentPosition.y = evt.GetRow(); auto* r = ((Component*)GetParent())->renderer(); @@ -141,6 +150,9 @@ void DBGrid::onGridRangeSelect(wxGridRangeSelectEvent& evt) { assert(GetGridWindow() && "invalid grid window"); + Forms::ApplWnd* mainFrm = Forms::ApplWnd::Instance(); + if (mainFrm) + mainFrm->gridOperatorSelectedCellsUpdateResult(this); if (GetGridWindow()) GetGridWindow()->SetFocus(); evt.Skip(); @@ -148,6 +160,9 @@ void DBGrid::onGridRangeSelect(wxGridRangeSelectEvent& evt) void DBGrid::onGridLeave(wxFocusEvent& evt) { + auto* mainFrm = Forms::ApplWnd::Instance(); + if (mainFrm) + mainFrm->gridOperatorSelectedCellsUpdateResult(nullptr); evt.Skip(); } @@ -202,6 +217,10 @@ void DBGrid::ensureDataAreLoaded() r->invalidate = false; // Post an event to update the gui after the data are loaded + Forms::ApplWnd* mainFrm = Forms::ApplWnd::Instance(); + if (mainFrm) + mainFrm->disableGridOperatorIfGrid(this); + assert(pAllowRefresh == true); parent->forceRefresh(); if (GetTable()) diff --git a/src/ui/simulator/toolbox/components/datagrid/selectionoperation.h b/src/ui/simulator/toolbox/components/datagrid/selectionoperation.h new file mode 100644 index 0000000000..a7deebcf32 --- /dev/null +++ b/src/ui/simulator/toolbox/components/datagrid/selectionoperation.h @@ -0,0 +1,247 @@ +/* +** Copyright 2007-2018 RTE +** Authors: Antares_Simulator Team +** +** This file is part of Antares_Simulator. +** +** Antares_Simulator is free software: you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation, either version 3 of the License, or +** (at your option) any later version. +** +** There are special exceptions to the terms and conditions of the +** license as they are applied to this software. View the full text of +** the exceptions in file COPYING.txt in the directory of this software +** distribution +** +** 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 +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with Antares_Simulator. If not, see . +** +** SPDX-License-Identifier: licenceRef-GPL3_WITH_RTE-Exceptions +*/ +#ifndef __ANTARES_TOOLBOX_COMPONENT_DATAGRID_SELECTION_OPERATION_H__ +#define __ANTARES_TOOLBOX_COMPONENT_DATAGRID_SELECTION_OPERATION_H__ + +#include "wx-wrapper.h" +#include +#include + +namespace Antares +{ +namespace Component +{ +namespace Datagrid +{ +namespace Selection +{ +class IOperator +{ +public: + IOperator() + { + } + virtual ~IOperator() + { + } + + /*! + ** \brief Caption of the operator + */ + virtual const wxChar* caption() const = 0; + + /*! + ** \brief Reset all internal values + */ + virtual void reset() = 0; + + /*! + ** \brief Manage a new value + */ + virtual void appendValue(const double v) = 0; + + /*! + ** \brief Get the result + */ + virtual double result() const = 0; + +}; // class IOperator + +class Average final : public IOperator +{ +public: + Average() : pValue(0.), pCount(0) + { + } + + virtual ~Average() + { + } + + virtual const wxChar* caption() const + { + return wxT("Average"); + } + + virtual void reset() + { + pValue = 0.; + pCount = 0; + } + + virtual void appendValue(const double v) + { + pValue += v; + ++pCount; + } + + virtual double result() const + { + return pValue / (double)pCount; + } + +private: + double pValue; + uint pCount; + +}; // class Average + +class Sum final : public IOperator +{ +public: + Sum() : pValue(0.) + { + } + + virtual const wxChar* caption() const + { + return wxT("Sum"); + } + + virtual void reset() + { + pValue = 0.; + } + + virtual void appendValue(const double v) + { + pValue += v; + } + + virtual double result() const + { + return pValue; + } + +private: + double pValue; + +}; // class Sum + +class CellCount final : public IOperator +{ +public: + CellCount() : pCount(0) + { + } + + virtual const wxChar* caption() const + { + return wxT("Cell Count"); + } + + virtual void reset() + { + pCount = 0; + } + + virtual void appendValue(const double) + { + ++pCount; + } + + virtual double result() const + { + return (double)pCount; + } + +private: + uint pCount; + +}; // class Average + +class Minimum final : public IOperator +{ +public: + Minimum() : pValue(std::numeric_limits::infinity()) + { + } + + virtual const wxChar* caption() const + { + return wxT("Minimum"); + } + + virtual void reset() + { + pValue = std::numeric_limits::infinity(); + } + + virtual void appendValue(const double v) + { + if (v < pValue) + pValue = v; + } + + virtual double result() const + { + return pValue; + } + +private: + double pValue; + +}; // class Sum + +class Maximum final : public IOperator +{ +public: + Maximum() : pValue(-std::numeric_limits::infinity()) + { + } + + virtual const wxChar* caption() const + { + return wxT("Maximum"); + } + virtual void reset() + { + pValue = -std::numeric_limits::infinity(); + } + + virtual void appendValue(const double v) + { + if (v > pValue) + pValue = v; + } + + virtual double result() const + { + return pValue; + } + +private: + double pValue; + +}; // class Sum + +} // namespace Selection +} // namespace Datagrid +} // namespace Component +} // namespace Antares + +#endif // __ANTARES_TOOLBOX_COMPONENT_DATAGRID_SELECTION_OPERATION_H__ From 5d4c1689631521f39fae5eb59606a5ccd2498032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Thu, 19 Dec 2024 15:29:31 +0100 Subject: [PATCH 06/14] Modeler 2.5a: Add parameters and YAML parser (#2539) Co-authored-by: payetvin <113102157+payetvin@users.noreply.github.com> Co-authored-by: Vincent Payet --- src/CMakeLists.txt | 1 + src/libs/antares/io/CMakeLists.txt | 3 +- src/libs/antares/io/include/antares/io/file.h | 3 +- src/solver/modelParser/CMakeLists.txt | 4 +- src/solver/modeler/CMakeLists.txt | 1 + src/solver/modeler/parameters/CMakeLists.txt | 14 ++++ src/solver/modeler/parameters/encoder.hxx | 23 ++++++ .../modeler/parameters/modelerParameters.h | 18 +++++ .../parameters/parseModelerParameters.h | 11 +++ .../parameters/parseModelerParameters.cpp | 16 ++++ src/solver/systemParser/CMakeLists.txt | 2 - .../libs/antares/yaml-parser/CMakeLists.txt | 7 +- src/tests/src/solver/modeler/CMakeLists.txt | 1 + .../solver/modeler/parameters/CMakeLists.txt | 14 ++++ .../parameters/testParametersParsing.cpp | 74 +++++++++++++++++++ 15 files changed, 179 insertions(+), 13 deletions(-) create mode 100644 src/solver/modeler/parameters/CMakeLists.txt create mode 100644 src/solver/modeler/parameters/encoder.hxx create mode 100644 src/solver/modeler/parameters/include/antares/solver/modeler/parameters/modelerParameters.h create mode 100644 src/solver/modeler/parameters/include/antares/solver/modeler/parameters/parseModelerParameters.h create mode 100644 src/solver/modeler/parameters/parseModelerParameters.cpp create mode 100644 src/tests/src/solver/modeler/parameters/CMakeLists.txt create mode 100644 src/tests/src/solver/modeler/parameters/testParametersParsing.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 13c67fe7a0..32beee7a3a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -191,6 +191,7 @@ endif() find_package(Boost REQUIRED) find_package(antlr4-runtime REQUIRED) +find_package(yaml-cpp REQUIRED) #Sirius solver if(POLICY CMP0074) diff --git a/src/libs/antares/io/CMakeLists.txt b/src/libs/antares/io/CMakeLists.txt index 9e3211e14b..dc62a95aea 100644 --- a/src/libs/antares/io/CMakeLists.txt +++ b/src/libs/antares/io/CMakeLists.txt @@ -12,6 +12,7 @@ source_group("io" FILES ${SRC_IO}) add_library(io ${SRC_IO} ) +add_library(Antares::io ALIAS io) target_link_libraries(io PRIVATE @@ -26,4 +27,4 @@ target_include_directories(io install(DIRECTORY include/antares DESTINATION "include" -) \ No newline at end of file +) diff --git a/src/libs/antares/io/include/antares/io/file.h b/src/libs/antares/io/include/antares/io/file.h index b401b1cece..a9aed8c850 100644 --- a/src/libs/antares/io/include/antares/io/file.h +++ b/src/libs/antares/io/include/antares/io/file.h @@ -22,8 +22,7 @@ #define __LIBS_ANTARES_IO_FILE_H__ #include - -#include +#include namespace Antares::IO { diff --git a/src/solver/modelParser/CMakeLists.txt b/src/solver/modelParser/CMakeLists.txt index 1881ba78fa..8e5ac13726 100644 --- a/src/solver/modelParser/CMakeLists.txt +++ b/src/solver/modelParser/CMakeLists.txt @@ -1,5 +1,3 @@ -find_package(yaml-cpp REQUIRED) - set(SOURCES parser.cpp encoders.hxx @@ -24,4 +22,4 @@ target_link_libraries(modelParser install(DIRECTORY include/antares DESTINATION "include" -) \ No newline at end of file +) diff --git a/src/solver/modeler/CMakeLists.txt b/src/solver/modeler/CMakeLists.txt index 3c631240ac..74378f6f7f 100644 --- a/src/solver/modeler/CMakeLists.txt +++ b/src/solver/modeler/CMakeLists.txt @@ -1,2 +1,3 @@ add_subdirectory(api) add_subdirectory(ortoolsImpl) +add_subdirectory(parameters) diff --git a/src/solver/modeler/parameters/CMakeLists.txt b/src/solver/modeler/parameters/CMakeLists.txt new file mode 100644 index 0000000000..33cfda091e --- /dev/null +++ b/src/solver/modeler/parameters/CMakeLists.txt @@ -0,0 +1,14 @@ +add_library(modeler-parameters + include/antares/solver/modeler/parameters/modelerParameters.h + include/antares/solver/modeler/parameters/parseModelerParameters.h + parseModelerParameters.cpp + encoder.hxx) + +target_link_libraries(modeler-parameters + PRIVATE + yaml-cpp + Antares::io) + +target_include_directories(modeler-parameters + PUBLIC + $) diff --git a/src/solver/modeler/parameters/encoder.hxx b/src/solver/modeler/parameters/encoder.hxx new file mode 100644 index 0000000000..32de3e0d83 --- /dev/null +++ b/src/solver/modeler/parameters/encoder.hxx @@ -0,0 +1,23 @@ +#include + +#include "yaml-cpp/yaml.h" + +namespace YAML +{ +template<> +struct convert +{ + static bool decode(const Node& node, Antares::Solver::ModelerParameters& rhs) + { + if (!node.IsMap()) + { + return false; + } + rhs.solver = node["solver"].as(); + rhs.solverLogs = node["solver-logs"].as(false); + rhs.solverParameters = node["solver-parameters"].as(); + rhs.noOutput = node["no-output"].as(false); + return true; + } +}; +} // namespace YAML diff --git a/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/modelerParameters.h b/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/modelerParameters.h new file mode 100644 index 0000000000..c6977a748b --- /dev/null +++ b/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/modelerParameters.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace Antares::Solver +{ +struct ModelerParameters +{ + // OR-Tools solver to be used for the simulation + std::string solver; + // Display solver logs ON/OFF + bool solverLogs = false; + // Specific solver parameters + std::string solverParameters; + // Write output results + bool noOutput = false; +}; +} // namespace Antares::Solver diff --git a/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/parseModelerParameters.h b/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/parseModelerParameters.h new file mode 100644 index 0000000000..2409fcddf1 --- /dev/null +++ b/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/parseModelerParameters.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include + +namespace Antares::Solver +{ + +ModelerParameters parseModelerParameters(const std::filesystem::path& path); +} // namespace Antares::Solver diff --git a/src/solver/modeler/parameters/parseModelerParameters.cpp b/src/solver/modeler/parameters/parseModelerParameters.cpp new file mode 100644 index 0000000000..39935db38c --- /dev/null +++ b/src/solver/modeler/parameters/parseModelerParameters.cpp @@ -0,0 +1,16 @@ +#include +#include + +#include + +#include "encoder.hxx" + +namespace Antares::Solver +{ +ModelerParameters parseModelerParameters(const std::filesystem::path& path) +{ + const auto contents = Antares::IO::readFile(path); + YAML::Node root = YAML::Load(contents); + return root.as(); +} +} // namespace Antares::Solver diff --git a/src/solver/systemParser/CMakeLists.txt b/src/solver/systemParser/CMakeLists.txt index 79e1262644..37e09a616a 100644 --- a/src/solver/systemParser/CMakeLists.txt +++ b/src/solver/systemParser/CMakeLists.txt @@ -1,5 +1,3 @@ -find_package(yaml-cpp REQUIRED) - set(SOURCES parser.cpp converter.cpp diff --git a/src/tests/src/libs/antares/yaml-parser/CMakeLists.txt b/src/tests/src/libs/antares/yaml-parser/CMakeLists.txt index 1633966826..dd9ef54891 100644 --- a/src/tests/src/libs/antares/yaml-parser/CMakeLists.txt +++ b/src/tests/src/libs/antares/yaml-parser/CMakeLists.txt @@ -1,6 +1,4 @@ - -find_package(yaml-cpp CONFIG REQUIRED) -Set(SRCS test_yaml_parser.cpp +set(SRCS test_yaml_parser.cpp ) set(execname "yaml-parser-test") @@ -8,8 +6,7 @@ add_executable(${execname} ${SRCS}) target_link_libraries(${execname} PRIVATE yaml-cpp - Boost::unit_test_framework - ) + Boost::unit_test_framework) add_test(NAME yaml-parser COMMAND ${execname}) diff --git a/src/tests/src/solver/modeler/CMakeLists.txt b/src/tests/src/solver/modeler/CMakeLists.txt index 53d257b04e..9a39b3b19b 100644 --- a/src/tests/src/solver/modeler/CMakeLists.txt +++ b/src/tests/src/solver/modeler/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(api) +add_subdirectory(parameters) diff --git a/src/tests/src/solver/modeler/parameters/CMakeLists.txt b/src/tests/src/solver/modeler/parameters/CMakeLists.txt new file mode 100644 index 0000000000..3e989c2b03 --- /dev/null +++ b/src/tests/src/solver/modeler/parameters/CMakeLists.txt @@ -0,0 +1,14 @@ +# Zip writer +add_executable(parse-parameters testParametersParsing.cpp) + +target_link_libraries(parse-parameters + PRIVATE + Boost::unit_test_framework + modeler-parameters + test_utils_unit +) + +set_target_properties(parse-parameters PROPERTIES FOLDER Unit-tests/test-writer) + +add_test(NAME parse-parameters COMMAND parse-parameters) +set_tests_properties(parse-parameters PROPERTIES LABELS unit) diff --git a/src/tests/src/solver/modeler/parameters/testParametersParsing.cpp b/src/tests/src/solver/modeler/parameters/testParametersParsing.cpp new file mode 100644 index 0000000000..aa2b14732b --- /dev/null +++ b/src/tests/src/solver/modeler/parameters/testParametersParsing.cpp @@ -0,0 +1,74 @@ +/* + * 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 . + */ +#define WIN32_LEAN_AND_MEAN + +#include +#define BOOST_TEST_MODULE parse modeler parameters + +#include + +#include + +#include "files-system.h" + +BOOST_AUTO_TEST_SUITE(read_modeler_parameters) + +BOOST_AUTO_TEST_CASE(all_properties_set) +{ + const auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + const auto fileP = working_tmp_dir / "parameters.yaml"; + { + std::ofstream param(fileP); + param << R"( +solver: sirius +solver-logs: false +solver-parameters: PRESOLVE 1 +no-output: true)"; + } + + auto params = Antares::Solver::parseModelerParameters(fileP); + BOOST_CHECK_EQUAL(params.solver, "sirius"); + BOOST_CHECK_EQUAL(params.solverLogs, false); + BOOST_CHECK_EQUAL(params.solverParameters, "PRESOLVE 1"); + BOOST_CHECK_EQUAL(params.noOutput, true); +} + +BOOST_AUTO_TEST_CASE(all_properties_set_out_of_order) +{ + const auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + const auto fileP = working_tmp_dir / "parameters.yaml"; + { + std::ofstream param(fileP); + param << R"( +solver-logs: false +solver: sirius +solver-parameters: PRESOLVE 1 +no-output: true)"; + } + + auto params = Antares::Solver::parseModelerParameters(fileP); + BOOST_CHECK_EQUAL(params.solver, "sirius"); + BOOST_CHECK_EQUAL(params.solverLogs, false); + BOOST_CHECK_EQUAL(params.solverParameters, "PRESOLVE 1"); + BOOST_CHECK_EQUAL(params.noOutput, true); +} + +BOOST_AUTO_TEST_SUITE_END() From 03508dec0fe5dec66ff432f1c98d390b7d3d4262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Thu, 19 Dec 2024 15:52:13 +0100 Subject: [PATCH 07/14] Fix segfault caused by invalid index [ANT-2582] (#2543) --- .../constraints/NbDispUnitsMinBoundSinceMinUpTime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/solver/optimisation/constraints/NbDispUnitsMinBoundSinceMinUpTime.cpp b/src/solver/optimisation/constraints/NbDispUnitsMinBoundSinceMinUpTime.cpp index a1a73ef2fa..bb298a3f8d 100644 --- a/src/solver/optimisation/constraints/NbDispUnitsMinBoundSinceMinUpTime.cpp +++ b/src/solver/optimisation/constraints/NbDispUnitsMinBoundSinceMinUpTime.cpp @@ -54,7 +54,7 @@ void NbDispUnitsMinBoundSinceMinUpTime::add(int pays, int index, int pdt) builder.greaterThan(); if (builder.NumberOfVariables() > 1) { - data.CorrespondanceCntNativesCntOptim[pays] + data.CorrespondanceCntNativesCntOptim[pdt] .NumeroDeContrainteDesContraintesDeDureeMinDeMarche[cluster] = builder.data.nombreDeContraintes; From 212167b14aee8639b9bd99b89b57866f5a37e669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Fri, 20 Dec 2024 14:08:45 +0100 Subject: [PATCH 08/14] Add and use add_boost_test CMake helper function (#2545) Allow adding unit test in a single line, avoiding repetition of CMake targets. TODO - [x] Add optional argument for `target_include_directories` - [ ] Allow more labels / directories (IDE specific) ? - [x] Use `add_boost_test` in place of `add_executable` where needed This pull request includes significant changes to the CMake build system for various tests, primarily focusing on simplifying and standardizing the test definitions by introducing a new macro. The main changes involve replacing existing test setup code with a new `add_boost_test` function, which consolidates the test setup into a single line. --- .../binding_constraints/CMakeLists.txt | 40 ++--- .../end-to-end/simple_study/CMakeLists.txt | 46 ++---- src/tests/macros.cmake | 38 +++++ src/tests/src/api_internal/CMakeLists.txt | 39 ++--- src/tests/src/api_lib/CMakeLists.txt | 23 +-- src/tests/src/libs/antares/CMakeLists.txt | 143 ++++++------------ .../antares/antlr4-interface/CMakeLists.txt | 25 +-- .../libs/antares/benchmarking/CMakeLists.txt | 18 +-- .../libs/antares/concurrency/CMakeLists.txt | 17 +-- .../src/libs/antares/inifile/CMakeLists.txt | 18 +-- .../src/libs/antares/study/CMakeLists.txt | 16 +- .../libs/antares/study/area/CMakeLists.txt | 60 ++------ .../antares/study/constraint/CMakeLists.txt | 58 ++----- .../study/output-folder/CMakeLists.txt | 34 +---- .../antares/study/parameters/CMakeLists.txt | 22 +-- .../antares/study/parts/hydro/CMakeLists.txt | 53 ++----- .../study/scenario-builder/CMakeLists.txt | 68 ++------- .../libs/antares/study/series/CMakeLists.txt | 27 +--- .../short-term-storage-input/CMakeLists.txt | 37 +---- .../thermal-price-definition/CMakeLists.txt | 47 ++---- .../src/libs/antares/writer/CMakeLists.txt | 21 +-- .../libs/antares/yaml-parser/CMakeLists.txt | 17 +-- .../src/solver/expressions/CMakeLists.txt | 48 +++--- .../CMakeLists.txt | 23 +-- src/tests/src/solver/lps/CMakeLists.txt | 23 +-- .../src/solver/modelParser/CMakeLists.txt | 50 +++--- .../src/solver/modeler/api/CMakeLists.txt | 34 ++--- .../solver/modeler/parameters/CMakeLists.txt | 19 +-- .../solver/optim-model-filler/CMakeLists.txt | 43 ++---- .../adequacy_patch/CMakeLists.txt | 29 +--- .../name-translator/CMakeLists.txt | 23 +-- .../optimisation/translator/CMakeLists.txt | 23 +-- .../src/solver/simulation/CMakeLists.txt | 132 +++++----------- src/tests/src/solver/utils/CMakeLists.txt | 30 ++-- .../src/study/system-model/CMakeLists.txt | 30 ++-- 35 files changed, 398 insertions(+), 976 deletions(-) create mode 100644 src/tests/macros.cmake diff --git a/src/tests/end-to-end/binding_constraints/CMakeLists.txt b/src/tests/end-to-end/binding_constraints/CMakeLists.txt index 72e2e46f62..788899db61 100644 --- a/src/tests/end-to-end/binding_constraints/CMakeLists.txt +++ b/src/tests/end-to-end/binding_constraints/CMakeLists.txt @@ -1,30 +1,10 @@ -find_package(Boost COMPONENTS unit_test_framework REQUIRED) -enable_testing() - -#bigobj support needed for windows compilation -if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") -endif(MSVC) - -add_executable(tests-binding_constraints - test_binding_constraints.cpp - ) - -target_link_libraries(tests-binding_constraints - PRIVATE - Boost::unit_test_framework - model_antares - antares-solver-simulation - antares-solver-hydro - antares-solver-ts-generator - Antares::tests::in-memory-study - ) - -target_include_directories(tests-binding_constraints - PRIVATE - ${CMAKE_SOURCE_DIR}/solver - ) - -add_test(NAME end-to-end-binding_constraints COMMAND tests-binding_constraints) -set_property(TEST end-to-end-binding_constraints PROPERTY LABELS end-to-end) -set_target_properties(tests-binding_constraints PROPERTIES FOLDER Unit-tests/end_to_end) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + +add_boost_test(tests-binding_constraints + SRC test_binding_constraints.cpp + LIBS + model_antares + antares-solver-simulation + antares-solver-hydro + antares-solver-ts-generator + Antares::tests::in-memory-study) diff --git a/src/tests/end-to-end/simple_study/CMakeLists.txt b/src/tests/end-to-end/simple_study/CMakeLists.txt index cc5c93b410..e7dd6e2fa9 100644 --- a/src/tests/end-to-end/simple_study/CMakeLists.txt +++ b/src/tests/end-to-end/simple_study/CMakeLists.txt @@ -1,35 +1,11 @@ -find_package(Boost COMPONENTS unit_test_framework REQUIRED) -enable_testing() - -#bigobj support needed for windows compilation -if(MSVC) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") -endif(MSVC) - -add_executable(tests-simple-study - simple-study.cpp -) - -target_link_libraries(tests-simple-study - PRIVATE - antares-solver-hydro - antares-solver-variable - antares-solver-simulation - antares-solver-ts-generator - model_antares - ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} - Antares::tests::in-memory-study -) - -target_include_directories(tests-simple-study - PRIVATE - ${CMAKE_SOURCE_DIR}/solver -) - -add_test(NAME end-to-end-simple-study COMMAND tests-simple-study) -set_property(TEST end-to-end-simple-study PROPERTY LABELS end-to-end) -set_target_properties(tests-simple-study PROPERTIES FOLDER Unit-tests/end_to_end) - -# Storing tests-simple-study under the folder Unit-tests in the IDE - -#---------------------------------------------------------- +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + +add_boost_test(tests-simple-study + SRC simple-study.cpp + LIBS + antares-solver-hydro + antares-solver-variable + antares-solver-simulation + antares-solver-ts-generator + model_antares + Antares::tests::in-memory-study) diff --git a/src/tests/macros.cmake b/src/tests/macros.cmake new file mode 100644 index 0000000000..8d57ddf55b --- /dev/null +++ b/src/tests/macros.cmake @@ -0,0 +1,38 @@ +# The following function allows to add a test in a single line +# Arguments +# SRC path to the sources +# (optional) LIBS path to the libs to link +# (optional) INCLUDE include paths +# NOTE it's not necessary to add Boost::unit_test_framework + +function(add_boost_test) + set(options "") + set(oneValueArgs) + set(multiValueArgs SRC LIBS INCLUDE) + cmake_parse_arguments(PARSE_ARGV 0 arg + "${options}" "${oneValueArgs}" "${multiValueArgs}") + # Bypass cmake_parse_arguments for the 1st argument + set(TEST_NAME ${ARGV0}) + add_executable(${TEST_NAME} ${arg_SRC}) + # All tests use boost + target_link_libraries(${TEST_NAME} PRIVATE ${arg_LIBS} Boost::unit_test_framework) + + # Optional: add private include directories + if (NOT "${arg_INCLUDE}" STREQUAL "") + target_include_directories(${TEST_NAME} PRIVATE ${arg_INCLUDE}) + endif() + + add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME}) + + # Adding labels allows ctest filter what tests to run + set_property(TEST ${TEST_NAME} PROPERTY LABELS unit) + + # Give the IDE some directions to display tests in a "Unit-tests" folder + set_target_properties(${TEST_NAME} PROPERTIES FOLDER Unit-tests) + + # Linux only. TODO remove ? + if(UNIX AND NOT APPLE) + target_link_libraries(${TEST_NAME} PRIVATE stdc++fs) + endif() + +endfunction() diff --git a/src/tests/src/api_internal/CMakeLists.txt b/src/tests/src/api_internal/CMakeLists.txt index 1c972cd4c6..e3bb61472e 100644 --- a/src/tests/src/api_internal/CMakeLists.txt +++ b/src/tests/src/api_internal/CMakeLists.txt @@ -1,28 +1,11 @@ -set(EXECUTABLE_NAME test-api) -add_executable(${EXECUTABLE_NAME}) - -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_api.cpp -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - Antares::solver_api - Antares::tests::in-memory-study - test_utils_unit -) - -target_include_directories(${EXECUTABLE_NAME} - PRIVATE - #Allow to use the private headers - $ -) - -# Storing tests-ts-numbers under the folder Unit-tests in the IDE -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) - -add_test(NAME test-api COMMAND ${EXECUTABLE_NAME}) - -set_property(TEST test-api PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + +add_boost_test(test-api + SRC test_api.cpp + LIBS + Antares::solver_api + Antares::tests::in-memory-study + test_utils_unit + #Allow to use the private headers + INCLUDE + $) diff --git a/src/tests/src/api_lib/CMakeLists.txt b/src/tests/src/api_lib/CMakeLists.txt index b5ce633955..f45e9d65e4 100644 --- a/src/tests/src/api_lib/CMakeLists.txt +++ b/src/tests/src/api_lib/CMakeLists.txt @@ -1,20 +1,5 @@ -set(EXECUTABLE_NAME test-client-api) -add_executable(${EXECUTABLE_NAME}) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_api.cpp -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - Antares::solver_api -) - -# Storing tests-ts-numbers under the folder Unit-tests in the IDE -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) - -add_test(NAME test-client-api COMMAND ${EXECUTABLE_NAME}) - -set_property(TEST test-client-api PROPERTY LABELS unit) +add_boost_test(test-client-api + SRC test_api.cpp + LIBS Antares::solver_api) diff --git a/src/tests/src/libs/antares/CMakeLists.txt b/src/tests/src/libs/antares/CMakeLists.txt index 97ef92fd0e..90def4d900 100644 --- a/src/tests/src/libs/antares/CMakeLists.txt +++ b/src/tests/src/libs/antares/CMakeLists.txt @@ -18,108 +18,63 @@ set(SRC_MATRIX_LIB # Necessary cpp files ${src_libs_antares}/jit/jit.cpp - logs/logs.cpp - ) + logs/logs.cpp) add_library(matrix ${SRC_MATRIX_LIB}) target_link_libraries(matrix PUBLIC - yuni-static-core -) + yuni-static-core) target_include_directories(matrix - PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}/logs" - "${src_libs_antares}/jit/include" - ) - -# Storing lib-matrix under the folder Unit-tests in the IDE -set_target_properties(matrix PROPERTIES FOLDER Unit-tests) + PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/logs" + "${src_libs_antares}/jit/include") # Building tests on Matrix save operations -set(SRC_TEST_MATRIX_SAVE - logs/antares/logs/logs.h - array/fill-matrix.h - array/matrix-bypass-load.h - array/tests-matrix-save.h - array/tests-matrix-save.cpp - ) - -add_executable(tests-matrix-save ${SRC_TEST_MATRIX_SAVE}) - -target_include_directories(tests-matrix-save - PRIVATE - "${src_libs_antares}/array/include" - "${src_libs_antares}/io/include" - "${src_libs_antares}/jit/include" - "${src_libs_antares}/memory/include" - "${CMAKE_CURRENT_SOURCE_DIR}/logs" - "${CMAKE_CURRENT_SOURCE_DIR}/jit" - "${CMAKE_SOURCE_DIR}/tests/src/libs" - - ) - -target_link_libraries(tests-matrix-save - PRIVATE - matrix - yuni-static-core - Boost::unit_test_framework - antares-core -) - -# Storing tests-matrix-save under the folder Unit-tests in the IDE -set_target_properties(tests-matrix-save PROPERTIES FOLDER Unit-tests) - -add_test(NAME save-matrix COMMAND tests-matrix-save) - -set_property(TEST save-matrix PROPERTY LABELS unit) +add_boost_test(tests-matrix-save + SRC + logs/antares/logs/logs.h + array/fill-matrix.h + array/matrix-bypass-load.h + array/tests-matrix-save.h + array/tests-matrix-save.cpp + INCLUDE + "${src_libs_antares}/array/include" + "${src_libs_antares}/io/include" + "${src_libs_antares}/jit/include" + "${src_libs_antares}/memory/include" + "${CMAKE_CURRENT_SOURCE_DIR}/logs" + "${CMAKE_CURRENT_SOURCE_DIR}/jit" + "${CMAKE_SOURCE_DIR}/tests/src/libs" + LIBS + matrix + yuni-static-core + antares-core) # Building tests on Matrix load operations -set(SRC_TEST_MATRIX_LOAD - array/fill-matrix.h - array/matrix-bypass-load.h - array/tests-matrix-load.h - array/tests-matrix-load.cpp - ) - -add_executable(tests-matrix-load ${SRC_TEST_MATRIX_LOAD}) -target_include_directories(tests-matrix-load - PRIVATE - "${src_libs_antares}/array/include" - "${src_libs_antares}/io/include" - "${src_libs_antares}/jit/include" - "${src_libs_antares}/memory/include" - "${CMAKE_CURRENT_SOURCE_DIR}/logs" - "${CMAKE_CURRENT_SOURCE_DIR}/jit" - "${CMAKE_SOURCE_DIR}/tests/src/libs" -) - - -target_link_libraries(tests-matrix-load - PRIVATE - matrix - yuni-static-core - Boost::unit_test_framework - antares-core -) - -# Storing tests-matrix-load under the folder Unit-tests in the IDE -set_target_properties(tests-matrix-load PROPERTIES FOLDER Unit-tests) - -add_test(NAME load-matrix COMMAND tests-matrix-load) - -set_property(TEST load-matrix PROPERTY LABELS unit) - - -add_executable(test-utils test_utils.cpp) -target_link_libraries(test-utils - PRIVATE - Boost::unit_test_framework - Antares::utils - yuni-static-core -) -set_target_properties(test-utils PROPERTIES FOLDER Unit-tests/test-utils) - -add_test(NAME test-utils COMMAND test-utils) -set_property(TEST test-utils PROPERTY LABELS unit) +add_boost_test(tests-matrix-load + SRC + array/fill-matrix.h + array/matrix-bypass-load.h + array/tests-matrix-load.h + array/tests-matrix-load.cpp + INCLUDE + "${src_libs_antares}/array/include" + "${src_libs_antares}/io/include" + "${src_libs_antares}/jit/include" + "${src_libs_antares}/memory/include" + "${CMAKE_CURRENT_SOURCE_DIR}/logs" + "${CMAKE_CURRENT_SOURCE_DIR}/jit" + "${CMAKE_SOURCE_DIR}/tests/src/libs" + LIBS + matrix + yuni-static-core + antares-core) + +# Test utilities +add_boost_test(test-utils + SRC test_utils.cpp + LIBS + Antares::utils + yuni-static-core) diff --git a/src/tests/src/libs/antares/antlr4-interface/CMakeLists.txt b/src/tests/src/libs/antares/antlr4-interface/CMakeLists.txt index f74e12981c..508489e76a 100644 --- a/src/tests/src/libs/antares/antlr4-interface/CMakeLists.txt +++ b/src/tests/src/libs/antares/antlr4-interface/CMakeLists.txt @@ -1,20 +1,9 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) find_package(antlr4-runtime CONFIG REQUIRED) -Set(SRCS test_antlr_interface.cpp -) - -set(execname "antlr-interface-test") -add_executable(${execname} ${SRCS}) -target_link_libraries(${execname} - PRIVATE - antlr-interface - Boost::unit_test_framework - ) - - -target_include_directories(${execname} - PRIVATE - ${ANTLR4_INCLUDE_DIR}) -add_test(NAME antlr-interface COMMAND ${execname}) - -set_tests_properties(antlr-interface PROPERTIES LABELS unit) +add_boost_test(antlr-interface-test + SRC test_antlr_interface.cpp + LIBS + antlr-interface + INCLUDE + ${ANTLR4_INCLUDE_DIR}) diff --git a/src/tests/src/libs/antares/benchmarking/CMakeLists.txt b/src/tests/src/libs/antares/benchmarking/CMakeLists.txt index 911f6e12e4..4ad4a1b712 100644 --- a/src/tests/src/libs/antares/benchmarking/CMakeLists.txt +++ b/src/tests/src/libs/antares/benchmarking/CMakeLists.txt @@ -1,15 +1,5 @@ -set(PROJ test-duration-collector) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -add_executable(${PROJ}) -target_sources(${PROJ} PRIVATE test_duration_collector.cpp) -target_link_libraries(${PROJ} - PRIVATE - Antares::benchmarking - Boost::unit_test_framework -) - -set_target_properties(${PROJ} PROPERTIES FOLDER Unit-tests/${PROJ}) - -add_test(NAME ${PROJ} COMMAND ${PROJ}) - -set_property(TEST ${PROJ} PROPERTY LABELS unit) +add_boost_test(test-duration-collector + SRC test_duration_collector.cpp + LIBS Antares::benchmarking) diff --git a/src/tests/src/libs/antares/concurrency/CMakeLists.txt b/src/tests/src/libs/antares/concurrency/CMakeLists.txt index 563d89524f..07004c0290 100644 --- a/src/tests/src/libs/antares/concurrency/CMakeLists.txt +++ b/src/tests/src/libs/antares/concurrency/CMakeLists.txt @@ -1,14 +1,5 @@ -add_executable(test-concurrency) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -target_sources(test-concurrency PRIVATE test_concurrency.cpp) - -target_link_libraries(test-concurrency - PRIVATE - Boost::unit_test_framework - Antares::concurrency -) - -set_target_properties(test-concurrency PROPERTIES FOLDER Unit-tests/test-concurrency) - -add_test(NAME concurrency COMMAND test-concurrency) -set_property(TEST concurrency PROPERTY LABELS unit) +add_boost_test(test-concurrency + SRC test_concurrency.cpp + LIBS Antares::concurrency) diff --git a/src/tests/src/libs/antares/inifile/CMakeLists.txt b/src/tests/src/libs/antares/inifile/CMakeLists.txt index 1670c13084..e99ae8500d 100644 --- a/src/tests/src/libs/antares/inifile/CMakeLists.txt +++ b/src/tests/src/libs/antares/inifile/CMakeLists.txt @@ -1,15 +1,5 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -add_executable(test_inifile_io test_inifile_io.cpp) - -target_link_libraries(test_inifile_io - PRIVATE - inifile - Boost::unit_test_framework -) - -# Storing executable under the folder Unit-tests in the IDE -set_target_properties(test_inifile_io PROPERTIES FOLDER Unit-tests/test_inifile_io) - -add_test(NAME test_inifile_io COMMAND test_inifile_io) - -set_property(TEST test_inifile_io PROPERTY LABELS unit) +add_boost_test(test_inifile_io + SRC test_inifile_io.cpp + LIBS inifile) diff --git a/src/tests/src/libs/antares/study/CMakeLists.txt b/src/tests/src/libs/antares/study/CMakeLists.txt index c4edfc9dfa..b78478c050 100644 --- a/src/tests/src/libs/antares/study/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/CMakeLists.txt @@ -1,3 +1,5 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + set(src_tests_src_libs_antares_study "${CMAKE_CURRENT_SOURCE_DIR}") add_subdirectory(area) @@ -10,14 +12,6 @@ add_subdirectory(parts) add_subdirectory(series) add_subdirectory(parameters) -add_executable(test-study) -target_sources(test-study PRIVATE test_study.cpp) -target_link_libraries(test-study - PRIVATE - Antares::study - Boost::unit_test_framework -) - -add_test(NAME test-study COMMAND test-study) - -set_property(TEST test-study PROPERTY LABELS unit) +add_boost_test(test-study + SRC test_study.cpp + LIBS Antares::study) diff --git a/src/tests/src/libs/antares/study/area/CMakeLists.txt b/src/tests/src/libs/antares/study/area/CMakeLists.txt index fc726aa02c..947fbeed46 100644 --- a/src/tests/src/libs/antares/study/area/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/area/CMakeLists.txt @@ -1,3 +1,5 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + # Useful variables definitions set(src_libs_antares_study "${CMAKE_SOURCE_DIR}/libs/antares/study") @@ -9,29 +11,10 @@ set(SRC_LINK_PROPERTIES files-helper.cpp test-save-link-properties.cpp ) -add_executable(test-save-link-properties ${SRC_LINK_PROPERTIES}) - -target_include_directories(test-save-link-properties - PRIVATE - "${src_libs_antares_study}/include" -) -target_link_libraries(test-save-link-properties - PRIVATE - Boost::unit_test_framework - model_antares -) -# Linux -if(UNIX AND NOT APPLE) -target_link_libraries(test-save-link-properties PRIVATE stdc++fs) -endif() - - -# Storing test-save-link-properties under the folder Unit-tests in the IDE -set_target_properties(test-save-link-properties PROPERTIES FOLDER Unit-tests) - -add_test(NAME save-link-properties COMMAND test-save-link-properties) - -set_property(TEST save-link-properties PROPERTY LABELS unit) +add_boost_test(test-save-link-properties + SRC ${SRC_LINK_PROPERTIES} + INCLUDE "${src_libs_antares_study}/include" + LIBS model_antares) # =================================== # Tests on area's optimization.ini @@ -39,30 +22,9 @@ set_property(TEST save-link-properties PROPERTY LABELS unit) set(SRC_AREA_OPTIMIZATION files-helper.h files-helper.cpp - test-save-area-optimization-ini.cpp -) -add_executable(test-save-area-optimization-ini ${SRC_AREA_OPTIMIZATION}) - -target_include_directories(test-save-area-optimization-ini - PRIVATE - "${src_libs_antares_study}/include" -) -target_link_libraries(test-save-area-optimization-ini - PRIVATE - Boost::unit_test_framework - model_antares -) - -# Linux -if(UNIX AND NOT APPLE) -target_link_libraries(test-save-area-optimization-ini PRIVATE stdc++fs) -endif() - - -# Storing test-save-area-optimization-ini under the folder Unit-tests in the IDE -set_target_properties(test-save-area-optimization-ini PROPERTIES FOLDER Unit-tests) - -add_test(NAME save-area-optimization COMMAND test-save-area-optimization-ini) - -set_property(TEST save-area-optimization PROPERTY LABELS unit) + test-save-area-optimization-ini.cpp) +add_boost_test(test-save-area-optimization-ini + SRC ${SRC_AREA_OPTIMIZATION} + INCLUDE "${src_libs_antares_study}/include" + LIBS model_antares) diff --git a/src/tests/src/libs/antares/study/constraint/CMakeLists.txt b/src/tests/src/libs/antares/study/constraint/CMakeLists.txt index f9940d2247..c5295f5455 100644 --- a/src/tests/src/libs/antares/study/constraint/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/constraint/CMakeLists.txt @@ -1,45 +1,13 @@ -add_executable(test_constraint - test_constraint.cpp - ) - -target_link_libraries(test_constraint - PRIVATE - test_utils_unit - Boost::unit_test_framework - Antares::study - ) - -# Storing test_constraint under the folder Unit-tests in the IDE -set_target_properties(test_constraint PROPERTIES FOLDER Unit-tests) - -if(UNIX AND NOT APPLE) - target_link_libraries(test_constraint PRIVATE stdc++fs) -endif() - -add_test(NAME test_constraint COMMAND test_constraint) - -set_property(TEST test_constraint PROPERTY LABELS unit) - -################ - -add_executable(test_groups - test_group.cpp - ) - -target_link_libraries(test_groups - PRIVATE - test_utils_unit - Boost::unit_test_framework - Antares::study - ) - -# Storing test_constraint under the folder Unit-tests in the IDE -set_target_properties(test_groups PROPERTIES FOLDER Unit-tests) - -if(UNIX AND NOT APPLE) - target_link_libraries(test_groups PRIVATE stdc++fs) -endif() - -add_test(NAME test_groups COMMAND test_groups) - -set_property(TEST test_groups PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + +add_boost_test(test_constraint + SRC test_constraint.cpp + LIBS + test_utils_unit + Antares::study) + +add_boost_test(test_groups + SRC test_group.cpp + LIBS + test_utils_unit + Antares::study) diff --git a/src/tests/src/libs/antares/study/output-folder/CMakeLists.txt b/src/tests/src/libs/antares/study/output-folder/CMakeLists.txt index feca6f3bb8..06988e3e85 100644 --- a/src/tests/src/libs/antares/study/output-folder/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/output-folder/CMakeLists.txt @@ -1,31 +1,9 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + # Useful variables definitions set(src_libs_antares_study "${CMAKE_SOURCE_DIR}/libs/antares/study") -add_executable(test-folder-output study.cpp) - -target_include_directories(test-folder-output - PRIVATE - "${src_libs_antares_study}" -) - -target_link_libraries(test-folder-output - PRIVATE - Boost::unit_test_framework - Antares::study -) - -# Linux -if(UNIX AND NOT APPLE) -target_link_libraries(test-folder-output PRIVATE stdc++fs) -endif() - - -# Storing test-save-link-properties under the folder Unit-tests in the IDE -set_target_properties(test-folder-output PROPERTIES FOLDER Unit-tests) - -import_std_libs(test-folder-output) - -add_test(NAME folder-output COMMAND test-folder-output) -set_property(TEST folder-output PROPERTY LABELS unit) - - +add_boost_test(test-folder-output + SRC study.cpp + INCLUDE "${src_libs_antares_study}" + LIBS Antares::study) diff --git a/src/tests/src/libs/antares/study/parameters/CMakeLists.txt b/src/tests/src/libs/antares/study/parameters/CMakeLists.txt index 7e22aad5d1..39341e10ae 100644 --- a/src/tests/src/libs/antares/study/parameters/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/parameters/CMakeLists.txt @@ -1,20 +1,8 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + # ==================================== # Tests on Parameters class # ==================================== -set(SRC_PARAMETERS_TESTS - parameters-tests.cpp -) -add_executable(parameters-tests ${SRC_PARAMETERS_TESTS}) - -target_link_libraries(parameters-tests - PRIVATE - Boost::unit_test_framework - Antares::study -) - -# Storing parameters-tests under the folder Unit-tests in the IDE -set_target_properties(parameters-tests PROPERTIES FOLDER Unit-tests/parameters-tests) - -add_test(NAME parameters-tests COMMAND parameters-tests) - -set_property(TEST parameters-tests PROPERTY LABELS unit) +add_boost_test(parameters-tests + SRC parameters-tests.cpp + LIBS Antares::study) diff --git a/src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt b/src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt index 52937063c8..8b5dee7bc3 100644 --- a/src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/parts/hydro/CMakeLists.txt @@ -1,44 +1,15 @@ -# Hydro data reader -set(SRC_HYDRO_READER - test-hydroreader-class.cpp) - -add_executable(test-hydro-reader ${SRC_HYDRO_READER}) - -target_link_libraries(test-hydro-reader - PRIVATE - Boost::unit_test_framework - Antares::study - test_utils_unit -) - -# Linux -if(UNIX AND NOT APPLE) - target_link_libraries(test-hydro-reader PRIVATE stdc++fs) -endif() - -set_target_properties(test-hydro-reader PROPERTIES FOLDER Unit-tests/hydro) -add_test(NAME hydro-reader COMMAND test-hydro-reader) -set_property(TEST hydro-reader PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) +# Hydro data reader +add_boost_test(test-hydro-reader + SRC test-hydroreader-class.cpp + LIBS + Antares::study + test_utils_unit) # Hydro series -set(SRC_HYDRO_SERIES - test-hydro-series.cpp) - -add_executable(test-hydro-series ${SRC_HYDRO_SERIES}) - -target_link_libraries(test-hydro-series - PRIVATE - Boost::unit_test_framework - Antares::study - test_utils_unit -) - -# Linux -if(UNIX AND NOT APPLE) - target_link_libraries(test-hydro-series PRIVATE stdc++fs) -endif() - -set_target_properties(test-hydro-series PROPERTIES FOLDER Unit-tests/hydro) -add_test(NAME hydro-series COMMAND test-hydro-series) -set_property(TEST hydro-series PROPERTY LABELS unit) \ No newline at end of file +add_boost_test(test-hydro-series + SRC test-hydro-series.cpp + LIBS + Antares::study + test_utils_unit) diff --git a/src/tests/src/libs/antares/study/scenario-builder/CMakeLists.txt b/src/tests/src/libs/antares/study/scenario-builder/CMakeLists.txt index 2f65c75b70..2444753e9c 100644 --- a/src/tests/src/libs/antares/study/scenario-builder/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/scenario-builder/CMakeLists.txt @@ -1,62 +1,26 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + # Useful variables definitions set(src_libs_antares_study "${CMAKE_SOURCE_DIR}/libs/antares/study") # ==================================== # Tests on reading scenario-builder # ==================================== -set(SRC_SC_BUILDER_READ - test-sc-builder-file-read-line.cpp -) -add_executable(test-sc-builder-file-read-line ${SRC_SC_BUILDER_READ}) - -target_include_directories(test-sc-builder-file-read-line - PRIVATE - "${src_libs_antares_study}/include" -) - -target_link_libraries(test-sc-builder-file-read-line - PRIVATE - Boost::unit_test_framework - model_antares -) -# Linux -if(UNIX AND NOT APPLE) -target_link_libraries(test-sc-builder-file-read-line PRIVATE stdc++fs) -endif() - - -# Storing test-sc-builder-file-read-line under the folder Unit-tests in the IDE -add_test(NAME sc-builder-file-read-line COMMAND test-sc-builder-file-read-line) -set_property(TEST sc-builder-file-read-line PROPERTY LABELS unit) -set_target_properties(test-sc-builder-file-read-line PROPERTIES FOLDER Unit-tests/sc-builder) - - +add_boost_test(test-sc-builder-file-read-line + SRC test-sc-builder-file-read-line.cpp + INCLUDE "${src_libs_antares_study}/include" + LIBS model_antares) # ==================================== # Tests on saving scenario-builder # ==================================== -set(SRC_SC_BUILDER_SAVE - test-sc-builder-file-save.cpp - "${src_tests_src_libs_antares_study}/area/files-helper.cpp" -) -add_executable(test-sc-builder-file-save ${SRC_SC_BUILDER_SAVE}) - -target_include_directories(test-sc-builder-file-save - PRIVATE - "${src_libs_antares_study}" - "${src_libs_antares_study}/scenario-builder" - "${src_tests_src_libs_antares_study}" -) - -target_link_libraries(test-sc-builder-file-save - PRIVATE - Boost::unit_test_framework - model_antares -) - -# Storing test-sc-builder-file-savee under the folder Unit-tests in the IDE -set_target_properties(test-sc-builder-file-save PROPERTIES FOLDER Unit-tests/sc-builder) - -add_test(NAME sc-builder-file-save COMMAND test-sc-builder-file-save) - -set_property(TEST sc-builder-file-save PROPERTY LABELS unit) +add_boost_test(test-sc-builder-file-save + SRC + test-sc-builder-file-save.cpp + "${src_tests_src_libs_antares_study}/area/files-helper.cpp" + INCLUDE + "${src_libs_antares_study}" + "${src_libs_antares_study}/scenario-builder" + "${src_tests_src_libs_antares_study}" + LIBS + model_antares) diff --git a/src/tests/src/libs/antares/study/series/CMakeLists.txt b/src/tests/src/libs/antares/study/series/CMakeLists.txt index 27c31d1728..7777264127 100644 --- a/src/tests/src/libs/antares/study/series/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/series/CMakeLists.txt @@ -1,22 +1,11 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + # ==================================== # Tests on TimeSeries class # ==================================== -set(SRC_TIMESERIES_TESTS - timeseries-tests.cpp -) -add_executable(timeseries-tests ${SRC_TIMESERIES_TESTS}) - -target_link_libraries(timeseries-tests - PRIVATE - Antares::array - Boost::unit_test_framework - Antares::series - antares-solver-simulation -) - -# Storing timeseries-tests under the folder Unit-tests in the IDE -set_target_properties(timeseries-tests PROPERTIES FOLDER Unit-tests/timeseries-tests) - -add_test(NAME timeseries-tests COMMAND timeseries-tests) - -set_property(TEST timeseries-tests PROPERTY LABELS unit) +add_boost_test(timeseries-tests + SRC timeseries-tests.cpp + LIBS + Antares::array + Antares::series + antares-solver-simulation) diff --git a/src/tests/src/libs/antares/study/short-term-storage-input/CMakeLists.txt b/src/tests/src/libs/antares/study/short-term-storage-input/CMakeLists.txt index 045e8ed944..afa269be4e 100644 --- a/src/tests/src/libs/antares/study/short-term-storage-input/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/short-term-storage-input/CMakeLists.txt @@ -1,33 +1,6 @@ -# Useful variables definitions -set(src_libs_antares_study "${CMAKE_SOURCE_DIR}/libs/antares/study") +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -# ==================================== -# Tests on reading scenario-builder -# ==================================== -set(SRC_SC_BUILDER_READ - short-term-storage-input-output.cpp -) -add_executable(short-term-storage-input ${SRC_SC_BUILDER_READ}) - -target_include_directories(short-term-storage-input - PRIVATE - "${src_libs_antares_study}/parts/short-term-storage" -) - -target_link_libraries(short-term-storage-input - PRIVATE - Boost::unit_test_framework - model_antares -) -# Linux -if(UNIX AND NOT APPLE) -target_link_libraries(short-term-storage-input PRIVATE stdc++fs) -endif() - - -# Storing short-term-storage-input under the folder Unit-tests in the IDE -set_target_properties(short-term-storage-input PROPERTIES FOLDER Unit-tests/short-term-storage-input) - -add_test(NAME short-term-storage-input COMMAND short-term-storage-input) - -set_property(TEST short-term-storage-input PROPERTY LABELS unit) +add_boost_test(short-term-storage-input + SRC short-term-storage-input-output.cpp + LIBS model_antares + INCLUDE "${src_libs_antares_study}/parts/short-term-storage") diff --git a/src/tests/src/libs/antares/study/thermal-price-definition/CMakeLists.txt b/src/tests/src/libs/antares/study/thermal-price-definition/CMakeLists.txt index 43c7aca74e..1b37de47a3 100644 --- a/src/tests/src/libs/antares/study/thermal-price-definition/CMakeLists.txt +++ b/src/tests/src/libs/antares/study/thermal-price-definition/CMakeLists.txt @@ -1,3 +1,5 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + # Useful variables definitions set(src_libs_antares_study "${CMAKE_SOURCE_DIR}/libs/antares/study") set(src_libs_antares_checks "${CMAKE_SOURCE_DIR}/libs/antares/checks") @@ -5,36 +7,15 @@ set(src_libs_antares_checks "${CMAKE_SOURCE_DIR}/libs/antares/checks") # ==================================== # Tests on thermal price definition # ==================================== -set(SRC_THERM_PRICE_DEF - thermal-price-definition.cpp -) -add_executable(thermal-price-definition ${SRC_THERM_PRICE_DEF}) - -target_include_directories(thermal-price-definition - PRIVATE - "${src_libs_antares_study}/parts/thermal" - "${src_libs_antares_study}/area" - "${src_libs_antares_study}" - "${src_libs_antares_checks}" -) - -target_link_libraries(thermal-price-definition - PRIVATE - Boost::unit_test_framework - checks - Antares::study - Antares::exception - Antares::checks -) -# Linux -if(UNIX AND NOT APPLE) -target_link_libraries(thermal-price-definition PRIVATE stdc++fs) -endif() - - -# Storing thermal-price-definition under the folder Unit-tests in the IDE -set_target_properties(thermal-price-definition PROPERTIES FOLDER Unit-tests/thermal-price-definition) - -add_test(NAME thermal-price-definition COMMAND thermal-price-definition) - -set_property(TEST thermal-price-definition PROPERTY LABELS unit) +add_boost_test(thermal-price-definition + SRC thermal-price-definition.cpp + LIBS + checks + Antares::study + Antares::exception + Antares::checks + INCLUDE + "${src_libs_antares_study}/parts/thermal" + "${src_libs_antares_study}/area" + "${src_libs_antares_study}" + "${src_libs_antares_checks}") diff --git a/src/tests/src/libs/antares/writer/CMakeLists.txt b/src/tests/src/libs/antares/writer/CMakeLists.txt index b85bcce05c..36f5a678a0 100644 --- a/src/tests/src/libs/antares/writer/CMakeLists.txt +++ b/src/tests/src/libs/antares/writer/CMakeLists.txt @@ -1,15 +1,10 @@ -# Zip writer -add_executable(test-writer test_writer.cpp) - -target_link_libraries(test-writer - PRIVATE - Boost::unit_test_framework - Antares::result_writer - test_utils_unit - MINIZIP::minizip -) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -set_target_properties(test-writer PROPERTIES FOLDER Unit-tests/test-writer) +# Zip writer +add_boost_test(test-writer + SRC test_writer.cpp + LIBS + Antares::result_writer + test_utils_unit + MINIZIP::minizip) -add_test(NAME writer COMMAND test-writer) -set_tests_properties(writer PROPERTIES LABELS unit) diff --git a/src/tests/src/libs/antares/yaml-parser/CMakeLists.txt b/src/tests/src/libs/antares/yaml-parser/CMakeLists.txt index dd9ef54891..dbb1a0535a 100644 --- a/src/tests/src/libs/antares/yaml-parser/CMakeLists.txt +++ b/src/tests/src/libs/antares/yaml-parser/CMakeLists.txt @@ -1,14 +1,5 @@ -set(SRCS test_yaml_parser.cpp -) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -set(execname "yaml-parser-test") -add_executable(${execname} ${SRCS}) -target_link_libraries(${execname} - PRIVATE - yaml-cpp - Boost::unit_test_framework) - - -add_test(NAME yaml-parser COMMAND ${execname}) - -set_tests_properties(yaml-parser PROPERTIES LABELS unit) +add_boost_test(yaml-parser-test + SRC test_yaml_parser.cpp + LIBS yaml-cpp) diff --git a/src/tests/src/solver/expressions/CMakeLists.txt b/src/tests/src/solver/expressions/CMakeLists.txt index 4eeca6d0fe..c41dde6d3b 100644 --- a/src/tests/src/solver/expressions/CMakeLists.txt +++ b/src/tests/src/solver/expressions/CMakeLists.txt @@ -1,31 +1,17 @@ -set(EXECUTABLE_NAME test-expressions) -add_executable(${EXECUTABLE_NAME}) - -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_main.cpp - test_nodes.cpp - test_PrintAndEvalNodes.cpp - test_TimeIndexVisitor.cpp - test_SubstitutionVisitor.cpp - test_LinearVisitor.cpp - test_CompareVisitor.cpp - test_CloneVisitor.cpp - test_DeepWideTrees.cpp - test_Iterators.cpp - test_AstDOTStyleVisitor.cpp -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - solver-expressions - solver-expressions-iterators -) - -# Storing tests-ts-numbers under the folder Unit-tests in the IDE -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) - -add_test(NAME test-expressions COMMAND ${EXECUTABLE_NAME}) - -set_property(TEST test-expressions PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) +add_boost_test(test-expressions + SRC + test_main.cpp + test_nodes.cpp + test_PrintAndEvalNodes.cpp + test_TimeIndexVisitor.cpp + test_SubstitutionVisitor.cpp + test_LinearVisitor.cpp + test_CompareVisitor.cpp + test_CloneVisitor.cpp + test_DeepWideTrees.cpp + test_Iterators.cpp + test_AstDOTStyleVisitor.cpp + LIBS + solver-expressions + solver-expressions-iterators) diff --git a/src/tests/src/solver/infeasible-problem-analysis/CMakeLists.txt b/src/tests/src/solver/infeasible-problem-analysis/CMakeLists.txt index 8a8a0e9544..845f1cd124 100644 --- a/src/tests/src/solver/infeasible-problem-analysis/CMakeLists.txt +++ b/src/tests/src/solver/infeasible-problem-analysis/CMakeLists.txt @@ -1,16 +1,7 @@ -add_executable(test-unfeasible-problem-analyzer) -target_sources(test-unfeasible-problem-analyzer - PRIVATE - test-unfeasible-problem-analyzer.cpp) -target_link_libraries(test-unfeasible-problem-analyzer - PRIVATE - Boost::unit_test_framework - infeasible_problem_analysis - ortools::ortools -) - -add_test(NAME test-unfeasible-problem-analyzer COMMAND test-unfeasible-problem-analyzer) - -# Storing the executable under the folder Unit-tests in Visual Studio -set_target_properties(test-unfeasible-problem-analyzer PROPERTIES FOLDER Unit-tests) -set_property(TEST test-unfeasible-problem-analyzer PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) +add_boost_test(test-unfeasible-problem-analyzer + SRC + test-unfeasible-problem-analyzer.cpp + LIBS + infeasible_problem_analysis + ortools::ortools) diff --git a/src/tests/src/solver/lps/CMakeLists.txt b/src/tests/src/solver/lps/CMakeLists.txt index 89121152ba..596dd71ff6 100644 --- a/src/tests/src/solver/lps/CMakeLists.txt +++ b/src/tests/src/solver/lps/CMakeLists.txt @@ -1,20 +1,5 @@ -set(EXECUTABLE_NAME test-lps) -add_executable(${EXECUTABLE_NAME}) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_lps.cpp -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - antares-solver-simulation -) - -# Storing tests-ts-numbers under the folder Unit-tests in the IDE -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) - -add_test(NAME test-lps COMMAND ${EXECUTABLE_NAME}) - -set_property(TEST test-lps PROPERTY LABELS unit) +add_boost_test(test-lps + SRC test_lps.cpp + LIBS antares-solver-simulation) diff --git a/src/tests/src/solver/modelParser/CMakeLists.txt b/src/tests/src/solver/modelParser/CMakeLists.txt index 9c5fad1f82..5969d66c16 100644 --- a/src/tests/src/solver/modelParser/CMakeLists.txt +++ b/src/tests/src/solver/modelParser/CMakeLists.txt @@ -1,34 +1,18 @@ -# Add source files -set(SOURCE_FILES - testModelParser.cpp - testModelTranslator.cpp - testConvertorVisitor.cpp - test_full.cpp - enum_operators.h - testSystemParser.cpp - testSystemConverter.cpp -) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -# Add executable -add_executable(TestModelParser ${SOURCE_FILES}) - -# Link libraries -target_link_libraries(TestModelParser - PRIVATE - Boost::unit_test_framework - Antares::solver-expressions - Antares::modelConverter - Antares::modelParser - Antares::systemParser - Antares::antares-study-system-model - Antares::antlr-interface -) - -# Storing test-toybox under the folder Unit-tests in the IDE -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) - -# Add the test -add_test(NAME TestModelParser COMMAND TestModelParser) - -# Set test properties -set_property(TEST TestModelParser PROPERTY LABELS unit) +add_boost_test(TestModelParser + SRC + testModelParser.cpp + testModelTranslator.cpp + testConvertorVisitor.cpp + test_full.cpp + enum_operators.h + testSystemParser.cpp + testSystemConverter.cpp + LIBS + Antares::solver-expressions + Antares::modelConverter + Antares::modelParser + Antares::systemParser + Antares::antares-study-system-model + Antares::antlr-interface) diff --git a/src/tests/src/solver/modeler/api/CMakeLists.txt b/src/tests/src/solver/modeler/api/CMakeLists.txt index ae048140aa..76915ff504 100644 --- a/src/tests/src/solver/modeler/api/CMakeLists.txt +++ b/src/tests/src/solver/modeler/api/CMakeLists.txt @@ -1,24 +1,12 @@ -set(EXECUTABLE_NAME unit-tests-for-modeler-api) -add_executable(${EXECUTABLE_NAME}) - -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_main.cpp - testModelerLinearProblemWithOrtools.cpp - testModelerLPbuilder.cpp -) -target_include_directories(${EXECUTABLE_NAME} - PRIVATE - "${src_solver_optimisation}" -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - Antares::modeler-ortools-impl -) - -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) -add_test(NAME ${EXECUTABLE_NAME} COMMAND ${EXECUTABLE_NAME}) -set_property(TEST ${EXECUTABLE_NAME} PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + +add_boost_test(unit-tests-for-modeler-api + SRC + test_main.cpp + testModelerLinearProblemWithOrtools.cpp + testModelerLPbuilder.cpp + INCLUDE + "${src_solver_optimisation}" + LIBS + Antares::modeler-ortools-impl) diff --git a/src/tests/src/solver/modeler/parameters/CMakeLists.txt b/src/tests/src/solver/modeler/parameters/CMakeLists.txt index 3e989c2b03..85c27e2969 100644 --- a/src/tests/src/solver/modeler/parameters/CMakeLists.txt +++ b/src/tests/src/solver/modeler/parameters/CMakeLists.txt @@ -1,14 +1,7 @@ -# Zip writer -add_executable(parse-parameters testParametersParsing.cpp) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -target_link_libraries(parse-parameters - PRIVATE - Boost::unit_test_framework - modeler-parameters - test_utils_unit -) - -set_target_properties(parse-parameters PROPERTIES FOLDER Unit-tests/test-writer) - -add_test(NAME parse-parameters COMMAND parse-parameters) -set_tests_properties(parse-parameters PROPERTIES LABELS unit) +add_boost_test(parse-parameters + SRC testParametersParsing.cpp + LIBS + modeler-parameters + test_utils_unit) diff --git a/src/tests/src/solver/optim-model-filler/CMakeLists.txt b/src/tests/src/solver/optim-model-filler/CMakeLists.txt index fa81c819b7..e6853bf8fc 100644 --- a/src/tests/src/solver/optim-model-filler/CMakeLists.txt +++ b/src/tests/src/solver/optim-model-filler/CMakeLists.txt @@ -1,29 +1,16 @@ -set(EXECUTABLE_NAME unit-tests-for-component-filler) -add_executable(${EXECUTABLE_NAME}) - -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_main.cpp - test_componentFiller.cpp - test_linearExpression.cpp - test_readLinearExpressionVisitor.cpp - test_readLinearConstraintVisitor.cpp -) -target_include_directories(${EXECUTABLE_NAME} - PRIVATE - "${src_solver_optimisation}" -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - antares-study-system-model - Antares::modeler-ortools-impl - Antares::optim-model-filler - test_utils_unit -) - -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) -add_test(NAME ${EXECUTABLE_NAME} COMMAND ${EXECUTABLE_NAME}) -set_property(TEST ${EXECUTABLE_NAME} PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) +add_boost_test(unit-tests-for-component-filler + SRC + test_main.cpp + test_componentFiller.cpp + test_linearExpression.cpp + test_readLinearExpressionVisitor.cpp + test_readLinearConstraintVisitor.cpp + INCLUDE + "${src_solver_optimisation}" + LIBS + antares-study-system-model + Antares::modeler-ortools-impl + Antares::optim-model-filler + test_utils_unit) diff --git a/src/tests/src/solver/optimisation/adequacy_patch/CMakeLists.txt b/src/tests/src/solver/optimisation/adequacy_patch/CMakeLists.txt index bb28a99864..94aa87d377 100644 --- a/src/tests/src/solver/optimisation/adequacy_patch/CMakeLists.txt +++ b/src/tests/src/solver/optimisation/adequacy_patch/CMakeLists.txt @@ -1,24 +1,11 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + # Useful variables definitions set(src_solver_optimisation "${CMAKE_SOURCE_DIR}/solver/optimisation") -set(EXECUTABLE_NAME tests-adq-patch) -add_executable(${EXECUTABLE_NAME} adequacy_patch.cpp) - -target_include_directories(${EXECUTABLE_NAME} - PRIVATE - "${src_solver_optimisation}" -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - model_antares - array -) - -# Storing tests-ts-numbers under the folder Unit-tests in the IDE -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) - -add_test(NAME test-adq-patch COMMAND ${EXECUTABLE_NAME}) - -set_property(TEST test-adq-patch PROPERTY LABELS unit) +add_boost_test(tests-adq-patch + SRC adequacy_patch.cpp + INCLUDE "${src_solver_optimisation}" + LIBS + model_antares + array) diff --git a/src/tests/src/solver/optimisation/name-translator/CMakeLists.txt b/src/tests/src/solver/optimisation/name-translator/CMakeLists.txt index f5e1f0619d..81275e4af1 100644 --- a/src/tests/src/solver/optimisation/name-translator/CMakeLists.txt +++ b/src/tests/src/solver/optimisation/name-translator/CMakeLists.txt @@ -1,20 +1,5 @@ -set(EXECUTABLE_NAME test-name-translator) -add_executable(${EXECUTABLE_NAME}) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_name_translator.cpp -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - model_antares -) - -# Storing tests-ts-numbers under the folder Unit-tests in the IDE -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) - -add_test(NAME test-name-translator COMMAND ${EXECUTABLE_NAME}) - -set_property(TEST test-name-translator PROPERTY LABELS unit) +add_boost_test(test-name-translator + SRC test_name_translator.cpp + LIBS model_antares) diff --git a/src/tests/src/solver/optimisation/translator/CMakeLists.txt b/src/tests/src/solver/optimisation/translator/CMakeLists.txt index 87f3d5a0cb..c211b7d32e 100644 --- a/src/tests/src/solver/optimisation/translator/CMakeLists.txt +++ b/src/tests/src/solver/optimisation/translator/CMakeLists.txt @@ -1,20 +1,5 @@ -set(EXECUTABLE_NAME test-translator) -add_executable(${EXECUTABLE_NAME}) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_translator.cpp -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - model_antares -) - -# Storing tests-ts-numbers under the folder Unit-tests in the IDE -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) - -add_test(NAME test-translator COMMAND ${EXECUTABLE_NAME}) - -set_property(TEST test-translator PROPERTY LABELS unit) +add_boost_test(test-translator + SRC test_translator.cpp + LIBS model_antares) diff --git a/src/tests/src/solver/simulation/CMakeLists.txt b/src/tests/src/solver/simulation/CMakeLists.txt index 294005454b..76d67765f7 100644 --- a/src/tests/src/solver/simulation/CMakeLists.txt +++ b/src/tests/src/solver/simulation/CMakeLists.txt @@ -1,3 +1,5 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + # Useful variables definitions set(src_solver_simulation "${CMAKE_SOURCE_DIR}/solver/simulation") set(src_solver_hydro "${CMAKE_SOURCE_DIR}/solver/hydro") @@ -11,112 +13,50 @@ set(SRC_TS_NUMBERS ${src_solver_simulation}/timeseries-numbers.cpp ${src_solver_simulation}/include/antares/solver/simulation/ITimeSeriesNumbersWriter.h) -add_executable(tests-ts-numbers tests-ts-numbers.cpp ${SRC_TS_NUMBERS}) - -target_include_directories(tests-ts-numbers - PRIVATE - "${src_solver_simulation}" - "${src_libs_antares_study}" -) -target_link_libraries(tests-ts-numbers - PRIVATE - Antares::utils - Boost::unit_test_framework - model_antares - antares-solver-simulation - antares-solver-ts-generator -) - -# Storing tests-ts-numbers under the folder Unit-tests in the IDE -set_target_properties(tests-ts-numbers PROPERTIES FOLDER Unit-tests) +add_boost_test(tests-ts-numbers + SRC tests-ts-numbers.cpp ${SRC_TS_NUMBERS} + INCLUDE + "${src_solver_simulation}" + "${src_libs_antares_study}" + LIBS + Antares::utils + model_antares + antares-solver-simulation + antares-solver-ts-generator) -add_test(NAME ts-numbers COMMAND tests-ts-numbers) - -set_property(TEST ts-numbers PROPERTY LABELS unit) # =================================== # Tests on area's store-timeseries-number # =================================== -set(SRC_STORE_TS - test-store-timeseries-number.cpp - ) -add_executable(test-store-timeseries-number ${SRC_STORE_TS}) - -target_link_libraries(test-store-timeseries-number - PRIVATE - Boost::unit_test_framework - test_utils_unit - antares-solver-simulation - Antares::study - Antares::result_writer - ) - -# Linux -if(UNIX AND NOT APPLE) - target_link_libraries(test-store-timeseries-number PRIVATE stdc++fs) -endif() - -set_target_properties(test-store-timeseries-number PROPERTIES FOLDER Unit-tests) - -add_test(NAME store-timeseries-number COMMAND test-store-timeseries-number) - -set_property(TEST store-timeseries-number PROPERTY LABELS unit) +add_boost_test(test-store-timeseries-number + SRC test-store-timeseries-number.cpp + LIBS + test_utils_unit + antares-solver-simulation + Antares::study + Antares::result_writer) # =================================== # Tests on time series # =================================== -set(SRC_STORE_TS - test-time_series.cpp - ) -add_executable(test-time_series ${SRC_STORE_TS}) - -target_link_libraries(test-time_series - PRIVATE - Boost::unit_test_framework - test_utils_unit - antares-solver-simulation - Antares::study - ) - -# Linux -if(UNIX AND NOT APPLE) - target_link_libraries(test-time_series PRIVATE stdc++fs) -endif() - - -set_target_properties(test-time_series PROPERTIES FOLDER Unit-tests) - -add_test(NAME time_series COMMAND test-time_series) - -set_property(TEST time_series PROPERTY LABELS unit) +add_boost_test(test-time_series + SRC test-time_series.cpp + LIBS + test_utils_unit + antares-solver-simulation + Antares::study) # =================================== # Tests on hydro final reservoir level functions # =================================== - -add_executable(test-hydro_final test-hydro-final-reservoir-level-functions.cpp) - -target_include_directories(test-hydro_final - PRIVATE - "${src_solver_simulation}" - "${src_libs_antares_study}" - "${src_solver_hydro}" -) -target_link_libraries(test-hydro_final - PRIVATE - Boost::unit_test_framework - Antares::study - antares-solver-simulation - Antares::array -) - -# Linux -if(UNIX AND NOT APPLE) - target_link_libraries(test-hydro_final PRIVATE stdc++fs) -endif() - -set_target_properties(test-hydro_final PROPERTIES FOLDER Unit-tests) - -add_test(NAME hydro_final COMMAND test-hydro_final) - -set_property(TEST hydro_final PROPERTY LABELS unit) \ No newline at end of file +add_boost_test(test-hydro_final + SRC + test-hydro-final-reservoir-level-functions.cpp + INCLUDE + "${src_solver_simulation}" + "${src_libs_antares_study}" + "${src_solver_hydro}" + LIBS + Antares::study + antares-solver-simulation + Antares::array) diff --git a/src/tests/src/solver/utils/CMakeLists.txt b/src/tests/src/solver/utils/CMakeLists.txt index b3331c6249..e93e01b496 100644 --- a/src/tests/src/solver/utils/CMakeLists.txt +++ b/src/tests/src/solver/utils/CMakeLists.txt @@ -1,20 +1,10 @@ -set(src_utils "${CMAKE_SOURCE_DIR}/solver/utils") - -set(EXECUTABLE_NAME tests-basis-status) -add_executable(${EXECUTABLE_NAME} basis_status.cpp) - - -target_include_directories(${EXECUTABLE_NAME} - PRIVATE - "${src_utils}" # basis_status_impl.h is private -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - ortools::ortools - Antares::solverUtils -) - -add_test(NAME test-basis-status COMMAND ${EXECUTABLE_NAME}) -set_property(TEST test-basis-status PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + +add_boost_test(tests-basis-status + SRC + basis_status.cpp + INCLUDE + "${CMAKE_SOURCE_DIR}/solver/utils" + LIBS + ortools::ortools + Antares::solverUtils) diff --git a/src/tests/src/study/system-model/CMakeLists.txt b/src/tests/src/study/system-model/CMakeLists.txt index 727635be3e..624da708a7 100644 --- a/src/tests/src/study/system-model/CMakeLists.txt +++ b/src/tests/src/study/system-model/CMakeLists.txt @@ -1,20 +1,10 @@ -set(EXECUTABLE_NAME test-system-model) -add_executable(${EXECUTABLE_NAME}) - -target_sources(${EXECUTABLE_NAME} - PRIVATE - test_main.cpp - test_component.cpp - test_system.cpp -) - -target_link_libraries(${EXECUTABLE_NAME} - PRIVATE - Boost::unit_test_framework - antares-study-system-model - test_utils_unit -) - -set_target_properties(${EXECUTABLE_NAME} PROPERTIES FOLDER Unit-tests) -add_test(NAME test-system-model COMMAND ${EXECUTABLE_NAME}) -set_property(TEST test-system-model PROPERTY LABELS unit) +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) +add_boost_test(test-system-model + SRC + test_main.cpp + test_component.cpp + test_system.cpp + LIBS + Boost::unit_test_framework + antares-study-system-model + test_utils_unit) From f5f634c71cbcc0e91ca09c4febe4caab17e4356e Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Tue, 24 Dec 2024 11:24:22 +0100 Subject: [PATCH 09/14] rc 8 (#2547) --- .github/workflows/ubuntu.yml | 14 +++++++------- .github/workflows/windows-vcpkg.yml | 8 -------- simtest.json | 2 +- src/CMakeLists.txt | 2 +- 4 files changed, 9 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index daceabc0ff..226e8a01b0 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -170,7 +170,7 @@ jobs: run: | cd _build ctest -C Release --output-on-failure -L "unit|end-to-end" - + - name: Upload logs for failed tests if: ${{ failure() }} @@ -178,7 +178,7 @@ jobs: with: name: test-log path: ${{ github.workspace }}/_build/Testing/Temporary/LastTest.log - + - name: Run tests about infinity on BCs RHS if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests @@ -186,7 +186,7 @@ jobs: simtest-tag: ${{ env.SIMTEST }} batch-name: valid-v830 os: ${{ env.os }} - + - name: Run MILP with CBC if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests @@ -197,18 +197,18 @@ jobs: os: ${{ env.os }} - name: Run tests on adequacy patch (CSR) - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} + simtest-tag: ${{ env.SIMTEST }} batch-name: adequacy-patch-CSR os: ${{ env.os }} - + - name: Run parallel tests if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} uses: ./.github/workflows/run-tests with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} + simtest-tag: ${{ env.SIMTEST }} batch-name: valid-parallel os: ${{ env.os }} variant: "parallel" diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 37d47eaadf..5fb4b19603 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -188,14 +188,6 @@ jobs: batch-name: adequacy-patch-CSR os: ${{ env.os }} - - name: Run tests about infinity on BCs RHS - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: valid-v830 - os: ${{ env.test-platform }} - - name: Run tests about infinity on BCs RHS if: ${{ env.RUN_SIMPLE_TESTS == 'true' && !cancelled() }} uses: ./.github/workflows/run-tests diff --git a/simtest.json b/simtest.json index 11b8cee038..4f6f12a31e 100644 --- a/simtest.json +++ b/simtest.json @@ -1,3 +1,3 @@ { - "version": "v9.2.0g" + "version": "v9.2.0h" } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 32beee7a3a..1f0a6712b2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -7,7 +7,7 @@ set(ANTARES_VERSION_REVISION 0) # Beta release set(ANTARES_BETA 0) -set(ANTARES_RC 7) +set(ANTARES_RC 8) set(ANTARES_VERSION_YEAR 2024) From 832e89b42a77d337f8c5b7de742fa2761d8536c1 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Tue, 31 Dec 2024 17:16:50 +0100 Subject: [PATCH 10/14] Modeler 2.5a: Read models and system yaml files [ANT-2306] (#2540) Add the main modeler as a new binary Directory loadFiles added, used to call previous work to read yaml files by handling I/O and errors related to yaml parsing --- src/solver/modeler/CMakeLists.txt | 39 ++++ src/solver/modeler/loadFiles/CMakeLists.txt | 34 +++ src/solver/modeler/loadFiles/handleErrors.cpp | 38 +++ .../solver/modeler/loadFiles/loadFiles.h | 54 +++++ .../modeler/loadFiles/readLibraries.cpp | 92 ++++++++ .../modeler/loadFiles/readParameters.cpp | 59 +++++ src/solver/modeler/loadFiles/readSystem.cpp | 73 ++++++ src/solver/modeler/main.cpp | 68 ++++++ src/solver/modeler/parameters/CMakeLists.txt | 18 +- src/solver/modeler/parameters/encoder.hxx | 21 ++ .../modeler/parameters/modelerParameters.h | 21 ++ .../parameters/parseModelerParameters.h | 28 ++- .../parameters/parseModelerParameters.cpp | 34 ++- src/tests/src/solver/modeler/CMakeLists.txt | 2 +- .../solver/modeler/loadFiles/CMakeLists.txt | 10 + .../loadFiles/testLoadModelerFiles.cpp | 220 ++++++++++++++++++ .../testParameters.cpp} | 70 +++--- .../solver/modeler/parameters/CMakeLists.txt | 7 - src/tests/src/utils/files-system.cpp | 4 +- src/tests/src/utils/files-system.h | 2 +- 20 files changed, 838 insertions(+), 56 deletions(-) create mode 100644 src/solver/modeler/loadFiles/CMakeLists.txt create mode 100644 src/solver/modeler/loadFiles/handleErrors.cpp create mode 100644 src/solver/modeler/loadFiles/include/antares/solver/modeler/loadFiles/loadFiles.h create mode 100644 src/solver/modeler/loadFiles/readLibraries.cpp create mode 100644 src/solver/modeler/loadFiles/readParameters.cpp create mode 100644 src/solver/modeler/loadFiles/readSystem.cpp create mode 100644 src/solver/modeler/main.cpp create mode 100644 src/tests/src/solver/modeler/loadFiles/CMakeLists.txt create mode 100644 src/tests/src/solver/modeler/loadFiles/testLoadModelerFiles.cpp rename src/tests/src/solver/modeler/{parameters/testParametersParsing.cpp => loadFiles/testParameters.cpp} (50%) delete mode 100644 src/tests/src/solver/modeler/parameters/CMakeLists.txt diff --git a/src/solver/modeler/CMakeLists.txt b/src/solver/modeler/CMakeLists.txt index 74378f6f7f..cb31b11fd4 100644 --- a/src/solver/modeler/CMakeLists.txt +++ b/src/solver/modeler/CMakeLists.txt @@ -1,3 +1,42 @@ add_subdirectory(api) add_subdirectory(ortoolsImpl) +add_subdirectory(loadFiles) add_subdirectory(parameters) + +OMESSAGE(" :: modeler") + +set(exec_name "antares-modeler") + +add_library(modeler-lib INTERFACE + ${SRCS} +) + +add_executable(antares-modeler + main.cpp + ${SRCS} +) + +set_target_properties(antares-modeler PROPERTIES OUTPUT_NAME ${exec_name}) + +target_link_libraries(modeler-lib + INTERFACE + Antares::loadModelerFiles + Antares::modelerParameters +) + +target_link_libraries(antares-modeler + PRIVATE + modeler-lib +) + +import_std_libs(antares-modeler) +executable_strip(antares-modeler) + +copy_dependency(sirius_solver antares-modeler) + +install(TARGETS antares-modeler EXPORT antares-modeler DESTINATION bin) + +INSTALL(EXPORT antares-modeler + FILE antares-modelerConfig.cmake + DESTINATION cmake +) diff --git a/src/solver/modeler/loadFiles/CMakeLists.txt b/src/solver/modeler/loadFiles/CMakeLists.txt new file mode 100644 index 0000000000..678aa9386c --- /dev/null +++ b/src/solver/modeler/loadFiles/CMakeLists.txt @@ -0,0 +1,34 @@ +set(SOURCES + readSystem.cpp + readLibraries.cpp + readParameters.cpp + handleErrors.cpp + + include/antares/solver/modeler/loadFiles/loadFiles.h +) + +# Create the library +add_library(loadModelerFiles STATIC ${SOURCES}) +add_library(Antares::loadModelerFiles ALIAS loadModelerFiles) + +# Specify include directories +target_include_directories(loadModelerFiles + PUBLIC + $ +) + +# Link dependencies (if any) +target_link_libraries(loadModelerFiles + PUBLIC + Antares::antares-study-system-model + PRIVATE + Antares::io + Antares::systemParser + Antares::modelParser + Antares::modelConverter + Antares::modelerParameters +) + +install(DIRECTORY include/antares + DESTINATION "include" +) diff --git a/src/solver/modeler/loadFiles/handleErrors.cpp b/src/solver/modeler/loadFiles/handleErrors.cpp new file mode 100644 index 0000000000..4ee2352970 --- /dev/null +++ b/src/solver/modeler/loadFiles/handleErrors.cpp @@ -0,0 +1,38 @@ +/* + * 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 . + */ + +#include +#include "antares/solver/modeler/loadFiles/loadFiles.h" + +namespace Antares::Solver::LoadFiles +{ + +void handleYamlError(const YAML::Exception& e, const std::string& context) +{ + logs.error() << "Error while parsing the yaml file: " << context; + if (!e.mark.is_null()) + { + logs.error() << "Line " << e.mark.line << " column " << e.mark.column; + } + logs.error() << e.what(); +} + +} // namespace Antares::Solver::LoadFiles diff --git a/src/solver/modeler/loadFiles/include/antares/solver/modeler/loadFiles/loadFiles.h b/src/solver/modeler/loadFiles/include/antares/solver/modeler/loadFiles/loadFiles.h new file mode 100644 index 0000000000..ff3882e554 --- /dev/null +++ b/src/solver/modeler/loadFiles/include/antares/solver/modeler/loadFiles/loadFiles.h @@ -0,0 +1,54 @@ +/* + * 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 . + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include + +namespace Antares::Solver::LoadFiles +{ + +ModelerParameters loadParameters(const std::filesystem::path& studyPath); + +std::vector loadLibraries(const std::filesystem::path& studyPath); + +Study::SystemModel::System loadSystem(const std::filesystem::path& studyPath, + const std::vector& libraries); + +void handleYamlError(const YAML::Exception& e, const std::string& context); + +/// Generic error class for all loading errors to catch in the main +class ErrorLoadingYaml: public std::runtime_error +{ +public: + explicit ErrorLoadingYaml(const std::string& s): + runtime_error(s) + { + } +}; + +} // namespace Antares::Solver::LoadFiles diff --git a/src/solver/modeler/loadFiles/readLibraries.cpp b/src/solver/modeler/loadFiles/readLibraries.cpp new file mode 100644 index 0000000000..be6b8e15d8 --- /dev/null +++ b/src/solver/modeler/loadFiles/readLibraries.cpp @@ -0,0 +1,92 @@ +/* + * 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 . + */ + +#include + +#include +#include +#include +#include +#include "antares/solver/modeler/loadFiles/loadFiles.h" + +namespace fs = std::filesystem; + +namespace Antares::Solver::LoadFiles +{ + +static Study::SystemModel::Library loadSingleLibrary(const fs::path& filePath) +{ + std::string libraryStr; + try + { + libraryStr = IO::readFile(filePath); + } + catch (const std::runtime_error& e) + { + logs.error() << "Error while trying to read this library file: " << filePath; + throw ErrorLoadingYaml(e.what()); + } + + ModelParser::Parser parser; + ModelParser::Library libraryObj; + + try + { + libraryObj = parser.parse(libraryStr); + } + catch (const YAML::Exception& e) + { + handleYamlError(e, filePath.string()); + throw ErrorLoadingYaml(e.what()); + } + + try + { + return ModelConverter::convert(libraryObj); + } + catch (const std::runtime_error& e) + { + logs.error() << "Error while converting this library yaml: " << filePath; + throw ErrorLoadingYaml(e.what()); + } +} + +std::vector loadLibraries(const fs::path& studyPath) +{ + std::vector libraries; + + const fs::path directoryPath = studyPath / "input" / "model-libraries"; + for (const auto& entry: fs::directory_iterator(directoryPath)) + { + if (entry.path().extension() != ".yml") + { + logs.info() << entry.path() + << " ignored, only files having the `.yml` extension are loaded"; + continue; + } + + libraries.push_back(loadSingleLibrary(entry.path())); + logs.info() << "Library loaded: " << libraries.back().Id(); + } + + return libraries; +} +} // namespace Antares::Solver::LoadFiles diff --git a/src/solver/modeler/loadFiles/readParameters.cpp b/src/solver/modeler/loadFiles/readParameters.cpp new file mode 100644 index 0000000000..bab889cb7e --- /dev/null +++ b/src/solver/modeler/loadFiles/readParameters.cpp @@ -0,0 +1,59 @@ +/* + * 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 . + */ + +#include + +#include +#include +#include "antares/solver/modeler/loadFiles/loadFiles.h" +#include "antares/solver/modeler/parameters/parseModelerParameters.h" + +namespace fs = std::filesystem; + +namespace Antares::Solver::LoadFiles +{ + +ModelerParameters loadParameters(const fs::path& studyPath) +{ + std::string filename = "parameters.yml"; + std::string paramStr; + try + { + paramStr = IO::readFile(studyPath / filename); + } + catch (const std::runtime_error& e) + { + logs.error() << "Error while trying to read file parameters.yml"; + throw ErrorLoadingYaml(e.what()); + } + + try + { + return parseModelerParameters(paramStr); + } + catch (const YAML::Exception& e) + { + handleYamlError(e, filename); + throw ErrorLoadingYaml(e.what()); + } +} + +} // namespace Antares::Solver::LoadFiles diff --git a/src/solver/modeler/loadFiles/readSystem.cpp b/src/solver/modeler/loadFiles/readSystem.cpp new file mode 100644 index 0000000000..dac47889cc --- /dev/null +++ b/src/solver/modeler/loadFiles/readSystem.cpp @@ -0,0 +1,73 @@ +/* + * 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 . + */ + +#include + +#include +#include +#include +#include +#include "antares/solver/modeler/loadFiles/loadFiles.h" + +namespace fs = std::filesystem; + +namespace Antares::Solver::LoadFiles +{ + +Study::SystemModel::System loadSystem(const fs::path& studyPath, + const std::vector& libraries) +{ + std::string filename = "system.yml"; + std::string systemStr; + try + { + systemStr = IO::readFile(studyPath / "input" / filename); + } + catch (const std::runtime_error& e) + { + logs.error() << "Error while trying to read file system.yml"; + throw ErrorLoadingYaml(e.what()); + } + + SystemParser::Parser parser; + SystemParser::System systemObj; + try + { + systemObj = parser.parse(systemStr); + } + catch (const YAML::Exception& e) + { + handleYamlError(e, filename); + throw ErrorLoadingYaml(e.what()); + } + + try + { + return SystemConverter::convert(systemObj, libraries); + } + catch (const std::runtime_error& e) + { + logs.error() << "Error while converting the system yaml to components"; + throw ErrorLoadingYaml(e.what()); + } +} + +} // namespace Antares::Solver::LoadFiles diff --git a/src/solver/modeler/main.cpp b/src/solver/modeler/main.cpp new file mode 100644 index 0000000000..a4d071660b --- /dev/null +++ b/src/solver/modeler/main.cpp @@ -0,0 +1,68 @@ +/* + * 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 . + */ + +#include +#include +#include + +using namespace Antares; +using namespace Antares::Solver; + +int main(int argc, const char** argv) +{ + if (argc < 1) + { + logs.error() << "No study path provided, exiting."; + return EXIT_FAILURE; + } + + std::filesystem::path studyPath(argv[1]); + logs.info() << "Study path: " << studyPath; + + if (!std::filesystem::is_directory(studyPath)) + { + logs.error() << "The path provided isn't a valid directory, exiting"; + return EXIT_FAILURE; + } + + try + { + const auto parameters = LoadFiles::loadParameters(studyPath); + logs.info() << "Parameters loaded"; + const auto libraries = LoadFiles::loadLibraries(studyPath); + logs.info() << "Libraries loaded"; + const auto system = LoadFiles::loadSystem(studyPath, libraries); + logs.info() << "System loaded"; + } + catch (const LoadFiles::ErrorLoadingYaml&) + { + logs.error() << "Error while loading files, exiting"; + return EXIT_FAILURE; + } + catch (const std::exception& e) + { + logs.error() << e.what(); + logs.error() << "Error during the execution, exiting"; + return EXIT_FAILURE; + } + + return 0; +} diff --git a/src/solver/modeler/parameters/CMakeLists.txt b/src/solver/modeler/parameters/CMakeLists.txt index 33cfda091e..7ab35d5002 100644 --- a/src/solver/modeler/parameters/CMakeLists.txt +++ b/src/solver/modeler/parameters/CMakeLists.txt @@ -1,14 +1,16 @@ -add_library(modeler-parameters - include/antares/solver/modeler/parameters/modelerParameters.h - include/antares/solver/modeler/parameters/parseModelerParameters.h - parseModelerParameters.cpp - encoder.hxx) +add_library(modelerParameters + include/antares/solver/modeler/parameters/modelerParameters.h + include/antares/solver/modeler/parameters/parseModelerParameters.h + parseModelerParameters.cpp + encoder.hxx) -target_link_libraries(modeler-parameters +add_library(Antares::modelerParameters ALIAS modelerParameters) + +target_link_libraries(modelerParameters PRIVATE yaml-cpp - Antares::io) + Antares::io) -target_include_directories(modeler-parameters +target_include_directories(modelerParameters PUBLIC $) diff --git a/src/solver/modeler/parameters/encoder.hxx b/src/solver/modeler/parameters/encoder.hxx index 32de3e0d83..c43d195ccc 100644 --- a/src/solver/modeler/parameters/encoder.hxx +++ b/src/solver/modeler/parameters/encoder.hxx @@ -1,3 +1,24 @@ +/* + * 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 . + */ + #include #include "yaml-cpp/yaml.h" diff --git a/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/modelerParameters.h b/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/modelerParameters.h index c6977a748b..6ea6e1072d 100644 --- a/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/modelerParameters.h +++ b/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/modelerParameters.h @@ -1,3 +1,24 @@ +/* + * 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 . + */ + #pragma once #include diff --git a/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/parseModelerParameters.h b/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/parseModelerParameters.h index 2409fcddf1..f0c9bd7238 100644 --- a/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/parseModelerParameters.h +++ b/src/solver/modeler/parameters/include/antares/solver/modeler/parameters/parseModelerParameters.h @@ -1,11 +1,33 @@ +/* + * 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 . + */ + #pragma once #include #include -namespace Antares::Solver +namespace Antares::Solver::LoadFiles { -ModelerParameters parseModelerParameters(const std::filesystem::path& path); -} // namespace Antares::Solver +ModelerParameters parseModelerParameters(const std::string& content); + +} // namespace Antares::Solver::LoadFiles diff --git a/src/solver/modeler/parameters/parseModelerParameters.cpp b/src/solver/modeler/parameters/parseModelerParameters.cpp index 39935db38c..470b7a66e4 100644 --- a/src/solver/modeler/parameters/parseModelerParameters.cpp +++ b/src/solver/modeler/parameters/parseModelerParameters.cpp @@ -1,16 +1,38 @@ +/* + * 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 . + */ + #include -#include #include +#include #include "encoder.hxx" -namespace Antares::Solver +namespace Antares::Solver::LoadFiles { -ModelerParameters parseModelerParameters(const std::filesystem::path& path) + +ModelerParameters parseModelerParameters(const std::string& content) { - const auto contents = Antares::IO::readFile(path); - YAML::Node root = YAML::Load(contents); + YAML::Node root = YAML::Load(content); return root.as(); } -} // namespace Antares::Solver + +} // namespace Antares::Solver::LoadFiles diff --git a/src/tests/src/solver/modeler/CMakeLists.txt b/src/tests/src/solver/modeler/CMakeLists.txt index 9a39b3b19b..d532a0a77d 100644 --- a/src/tests/src/solver/modeler/CMakeLists.txt +++ b/src/tests/src/solver/modeler/CMakeLists.txt @@ -1,2 +1,2 @@ add_subdirectory(api) -add_subdirectory(parameters) +add_subdirectory(loadFiles) diff --git a/src/tests/src/solver/modeler/loadFiles/CMakeLists.txt b/src/tests/src/solver/modeler/loadFiles/CMakeLists.txt new file mode 100644 index 0000000000..896c759e06 --- /dev/null +++ b/src/tests/src/solver/modeler/loadFiles/CMakeLists.txt @@ -0,0 +1,10 @@ +include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) + +add_boost_test(loadFiles + SRC + testLoadModelerFiles.cpp + testParameters.cpp + LIBS + Antares::modelerParameters + Antares::loadModelerFiles + test_utils_unit) diff --git a/src/tests/src/solver/modeler/loadFiles/testLoadModelerFiles.cpp b/src/tests/src/solver/modeler/loadFiles/testLoadModelerFiles.cpp new file mode 100644 index 0000000000..61fe4decf1 --- /dev/null +++ b/src/tests/src/solver/modeler/loadFiles/testLoadModelerFiles.cpp @@ -0,0 +1,220 @@ +/* + * 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 . + */ +#define WIN32_LEAN_AND_MEAN + +#include +#define BOOST_TEST_MODULE load modeler files + +#include + +#include + +#include "files-system.h" + +BOOST_AUTO_TEST_SUITE(test_modeler_files_loading) + +namespace fs = std::filesystem; + +struct FixtureLoadFile +{ + fs::path studyPath; + fs::path inputPath; + fs::path libraryDirPath; + + FixtureLoadFile() + { + studyPath = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + inputPath = createFolder(studyPath.string(), "input"); + libraryDirPath = createFolder(inputPath.string(), "model-libraries"); + } + + ~FixtureLoadFile() + { + fs::remove_all(studyPath); + } +}; + +BOOST_AUTO_TEST_CASE(files_not_existing) +{ + fs::path studyPath = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + std::vector libraries; + + BOOST_CHECK_THROW(Antares::Solver::LoadFiles::loadLibraries(studyPath), std::runtime_error); + BOOST_CHECK_THROW(Antares::Solver::LoadFiles::loadSystem(studyPath, libraries), + std::runtime_error); +} + +BOOST_FIXTURE_TEST_CASE(read_one_lib_treile, FixtureLoadFile) +{ + std::ofstream libStream(libraryDirPath / "simple.yml"); + libStream << R"( + library: + id: lib_id + description: lib_description + port-types: [] + models: [] + )"; + libStream.close(); + + auto libraries = Antares::Solver::LoadFiles::loadLibraries(studyPath); + BOOST_CHECK_EQUAL(libraries[0].Id(), "lib_id"); +} + +BOOST_FIXTURE_TEST_CASE(dont_read_bad_extension, FixtureLoadFile) +{ + createFile(libraryDirPath.string(), "abc.txt"); + auto libraries = Antares::Solver::LoadFiles::loadLibraries(studyPath); + BOOST_CHECK(libraries.empty()); +} + +BOOST_FIXTURE_TEST_CASE(incorrect_library, FixtureLoadFile) +{ + std::ofstream libStream(libraryDirPath / "simple.yml"); + libStream << R"( + library: + port-types: [] + models: [] + )"; + libStream.close(); + + BOOST_CHECK_THROW(Antares::Solver::LoadFiles::loadLibraries(studyPath), std::runtime_error); +} + +BOOST_FIXTURE_TEST_CASE(incorrect_library2, FixtureLoadFile) +{ + std::ofstream libStream(libraryDirPath / "simple.yml"); + libStream << R"( + library: + id: std + port-types: [] + - id: generator + description: A basic generator model + + )"; + libStream.close(); + BOOST_CHECK_THROW(Antares::Solver::LoadFiles::loadLibraries(studyPath), std::runtime_error); +} + +BOOST_FIXTURE_TEST_CASE(read_several_lib_file, FixtureLoadFile) +{ + std::ofstream libStream(libraryDirPath / "simple.yml"); + libStream << R"( + library: + id: lib_id + description: lib_description + port-types: [] + models: [] + )"; + libStream.close(); + + std::ofstream libStream2(libraryDirPath / "2.yml"); + libStream2 << R"( + library: + id: lib_id2 + description: lib_description + port-types: [] + models: [] + )"; + libStream2.close(); + + std::ofstream libStream3(libraryDirPath / "3.yml"); + libStream3 << R"( + library: + id: lib_id3 + description: lib_description + port-types: [] + models: [] + )"; + libStream3.close(); + + auto libraries = Antares::Solver::LoadFiles::loadLibraries(studyPath); + + auto checkLibIdInVector = [&libraries](const std::string& libId) + { + return std::ranges::find_if(libraries, [&libId](const auto& l) { return l.Id() == libId; }) + != libraries.end(); + }; + + BOOST_CHECK(checkLibIdInVector("lib_id")); + BOOST_CHECK(checkLibIdInVector("lib_id2")); + BOOST_CHECK(checkLibIdInVector("lib_id3")); + + BOOST_CHECK(!checkLibIdInVector("id not in vector")); +} + +BOOST_FIXTURE_TEST_CASE(read_system_file, FixtureLoadFile) +{ + std::ofstream libStream(libraryDirPath / "simple.yml"); + libStream << R"( + library: + id: std + description: lib_description + port-types: [] + models: + - id: generator + description: A basic generator model + + )"; + libStream.close(); + + std::ofstream systemStream(inputPath / "system.yml"); + systemStream << R"( + system: + id: base_system + description: two components + components: + - id: N + model: std.generator + scenario-group: group-234 + )"; + systemStream.close(); + + auto libraries = Antares::Solver::LoadFiles::loadLibraries(studyPath); + auto system = Antares::Solver::LoadFiles::loadSystem(studyPath, libraries); +} + +BOOST_FIXTURE_TEST_CASE(read_invalid_system_file, FixtureLoadFile) +{ + std::ofstream libStream(libraryDirPath / "simple.yml"); + libStream << R"( + library: + id: std + description: lib_description + port-types: [] + models: + - id: generator + description: A basic generator model + + )"; + libStream.close(); + + std::ofstream systemStream(inputPath / "system.yml"); + systemStream << R"( + system: + )"; + systemStream.close(); + + auto libraries = Antares::Solver::LoadFiles::loadLibraries(studyPath); + BOOST_CHECK_THROW(Antares::Solver::LoadFiles::loadSystem(studyPath, libraries), + std::runtime_error); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/tests/src/solver/modeler/parameters/testParametersParsing.cpp b/src/tests/src/solver/modeler/loadFiles/testParameters.cpp similarity index 50% rename from src/tests/src/solver/modeler/parameters/testParametersParsing.cpp rename to src/tests/src/solver/modeler/loadFiles/testParameters.cpp index aa2b14732b..fb529f3111 100644 --- a/src/tests/src/solver/modeler/parameters/testParametersParsing.cpp +++ b/src/tests/src/solver/modeler/loadFiles/testParameters.cpp @@ -21,54 +21,66 @@ #define WIN32_LEAN_AND_MEAN #include -#define BOOST_TEST_MODULE parse modeler parameters #include -#include +#include #include "files-system.h" -BOOST_AUTO_TEST_SUITE(read_modeler_parameters) - -BOOST_AUTO_TEST_CASE(all_properties_set) +BOOST_AUTO_TEST_CASE(read_parameters) { - const auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); - const auto fileP = working_tmp_dir / "parameters.yaml"; - { - std::ofstream param(fileP); - param << R"( -solver: sirius -solver-logs: false -solver-parameters: PRESOLVE 1 -no-output: true)"; - } + auto studyPath = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + std::ofstream paramStream(studyPath / "parameters.yml"); + paramStream << R"( + solver: sirius + solver-logs: false + solver-parameters: PRESOLVE 1 + no-output: true + )"; + paramStream.close(); - auto params = Antares::Solver::parseModelerParameters(fileP); + auto params = Antares::Solver::LoadFiles::loadParameters(studyPath); BOOST_CHECK_EQUAL(params.solver, "sirius"); BOOST_CHECK_EQUAL(params.solverLogs, false); BOOST_CHECK_EQUAL(params.solverParameters, "PRESOLVE 1"); BOOST_CHECK_EQUAL(params.noOutput, true); } -BOOST_AUTO_TEST_CASE(all_properties_set_out_of_order) +BOOST_AUTO_TEST_CASE(read_parameters_out_of_order) { - const auto working_tmp_dir = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); - const auto fileP = working_tmp_dir / "parameters.yaml"; - { - std::ofstream param(fileP); - param << R"( -solver-logs: false -solver: sirius -solver-parameters: PRESOLVE 1 -no-output: true)"; - } + auto studyPath = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + std::ofstream paramStream(studyPath / "parameters.yml"); + paramStream << R"( + solver-logs: false + solver: sirius + solver-parameters: PRESOLVE 1 + no-output: true + )"; + paramStream.close(); - auto params = Antares::Solver::parseModelerParameters(fileP); + auto params = Antares::Solver::LoadFiles::loadParameters(studyPath); BOOST_CHECK_EQUAL(params.solver, "sirius"); BOOST_CHECK_EQUAL(params.solverLogs, false); BOOST_CHECK_EQUAL(params.solverParameters, "PRESOLVE 1"); BOOST_CHECK_EQUAL(params.noOutput, true); } -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_CASE(parameters_missing) +{ + auto studyPath = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + std::ofstream paramStream(studyPath / "parameters.yml"); + paramStream << R"( + solver-logs: false + no-output: true + )"; + paramStream.close(); + + BOOST_CHECK_THROW(Antares::Solver::LoadFiles::loadParameters(studyPath), std::runtime_error); +} + +BOOST_AUTO_TEST_CASE(file_missing) +{ + auto studyPath = CREATE_TMP_DIR_BASED_ON_TEST_NAME(); + BOOST_CHECK_THROW(Antares::Solver::LoadFiles::loadParameters(studyPath), std::runtime_error); +} diff --git a/src/tests/src/solver/modeler/parameters/CMakeLists.txt b/src/tests/src/solver/modeler/parameters/CMakeLists.txt deleted file mode 100644 index 85c27e2969..0000000000 --- a/src/tests/src/solver/modeler/parameters/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -include(${CMAKE_SOURCE_DIR}/tests/macros.cmake) - -add_boost_test(parse-parameters - SRC testParametersParsing.cpp - LIBS - modeler-parameters - test_utils_unit) diff --git a/src/tests/src/utils/files-system.cpp b/src/tests/src/utils/files-system.cpp index f6097ee82b..e8d6163ea7 100644 --- a/src/tests/src/utils/files-system.cpp +++ b/src/tests/src/utils/files-system.cpp @@ -10,7 +10,7 @@ fs::path generateAndCreateDirName(const std::string& dirName) return working_dir; } -void createFolder(const std::string& path, const std::string& folder_name) +fs::path createFolder(const std::string& path, const std::string& folder_name) { fs::path folder_path = fs::path(path.c_str()) / folder_name.c_str(); @@ -22,6 +22,8 @@ void createFolder(const std::string& path, const std::string& folder_name) { std::cerr << "Exception creating folder '" + folder_name + "': " + e.what() + "\n"; } + + return folder_path; } void createFile(const std::string& folder_path, const std::string& file_name) diff --git a/src/tests/src/utils/files-system.h b/src/tests/src/utils/files-system.h index 092b498350..9ad4503e54 100644 --- a/src/tests/src/utils/files-system.h +++ b/src/tests/src/utils/files-system.h @@ -31,6 +31,6 @@ std::filesystem::path generateAndCreateDirName(const std::string&); -void createFolder(const std::string& path, const std::string& folder_name); +std::filesystem::path createFolder(const std::string& path, const std::string& folder_name); void createFile(const std::string& folder_path, const std::string& file_name); void removeFolder(std::string& path, std::string& folder_name); From 9a9715ebdba370b59bf8aa637071b68abf2f2733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Fri, 3 Jan 2025 09:43:05 +0100 Subject: [PATCH 11/14] High-level API: provide output path instead of returning it [ANT-2561] (#2548) TODO - [x] Fix build for api_client_test (missing argument) - [x] Fix extra output directory created by Simulator, for example 20241204-1554eco and 20241204-1554eco-2 --- src/api/API.cpp | 21 +++++++++++++------ .../include/antares/api/SimulationResults.h | 10 ++++----- src/api/include/antares/api/solver.h | 1 + src/api/private/API.h | 2 ++ src/api/solver.cpp | 5 +++-- src/api_client_example/src/API_client.cpp | 5 +++-- src/api_client_example/src/API_client.h | 5 +++-- src/api_client_example/tests/test.cpp | 8 ++++--- src/format-code.sh | 2 +- src/solver/application/application.cpp | 6 +++--- src/tests/src/api_internal/test_api.cpp | 21 +++++-------------- src/tests/src/api_lib/test_api.cpp | 2 +- 12 files changed, 46 insertions(+), 42 deletions(-) diff --git a/src/api/API.cpp b/src/api/API.cpp index 7bcda34502..63b4a9fda8 100644 --- a/src/api/API.cpp +++ b/src/api/API.cpp @@ -34,6 +34,7 @@ namespace Antares::API { SimulationResults APIInternal::run( const IStudyLoader& study_loader, + const std::filesystem::path& output, const Antares::Solver::Optimization::OptimizationOptions& optOptions) { try @@ -43,9 +44,9 @@ SimulationResults APIInternal::run( catch (const ::Antares::Error::StudyFolderDoesNotExist& e) { Antares::API::Error err{.reason = e.what()}; - return {.simulationPath = "", .antares_problems = {}, .error = err}; + return {.antares_problems = {}, .error = err}; } - return execute(optOptions); + return execute(output, optOptions); } /** @@ -56,6 +57,7 @@ SimulationResults APIInternal::run( * dupllication */ SimulationResults APIInternal::execute( + const std::filesystem::path& output, const Antares::Solver::Optimization::OptimizationOptions& optOptions) const { // study_ == nullptr e.g when the -h flag is given @@ -63,7 +65,7 @@ SimulationResults APIInternal::execute( { using namespace std::string_literals; Antares::API::Error err{.reason = "Couldn't create study"s}; - return {.simulationPath{}, .antares_problems{}, .error = err}; + return {.antares_problems{}, .error = err}; } Settings settings; @@ -75,10 +77,19 @@ SimulationResults APIInternal::execute( auto ioQueueService = std::make_shared(); ioQueueService->maximumThreadCount(1); ioQueueService->start(); + + study_->folderOutput = output; auto resultWriter = Solver::resultWriterFactory(parameters.resultFormat, study_->folderOutput, ioQueueService, durationCollector); + + // In some cases (e.g tests) we don't want to write anything + if (!output.empty()) + { + study_->saveAboutTheStudy(*resultWriter); + } + SimulationObserver simulationObserver; optimizationInfo = simulationRun(*study_, @@ -90,8 +101,6 @@ SimulationResults APIInternal::execute( // Importing Time-Series if asked study_->importTimeseriesIntoInput(); - return {.simulationPath = study_->folderOutput, - .antares_problems = simulationObserver.acquireLps(), - .error{}}; + return {.antares_problems = simulationObserver.acquireLps(), .error{}}; } } // namespace Antares::API diff --git a/src/api/include/antares/api/SimulationResults.h b/src/api/include/antares/api/SimulationResults.h index 5a5e93982a..31f0e9aec0 100644 --- a/src/api/include/antares/api/SimulationResults.h +++ b/src/api/include/antares/api/SimulationResults.h @@ -23,6 +23,7 @@ #include #include #include + #include "antares/solver/lps/LpsFromAntares.h" namespace Antares::API @@ -31,7 +32,8 @@ namespace Antares::API * @struct Error * @brief The Error structure is used to represent an error that occurred during the simulation. */ -struct Error { +struct Error +{ /** * @brief The reason for the error. */ @@ -45,10 +47,6 @@ struct Error { */ struct [[nodiscard("Contains results and potential error")]] SimulationResults { - /** - * @brief The path to the simulation (output). - */ - std::filesystem::path simulationPath; /** * @brief weekly problems */ @@ -59,4 +57,4 @@ struct [[nodiscard("Contains results and potential error")]] SimulationResults std::optional error; }; -} \ No newline at end of file +} // namespace Antares::API diff --git a/src/api/include/antares/api/solver.h b/src/api/include/antares/api/solver.h index a8279c00c8..64fa13ac55 100644 --- a/src/api/include/antares/api/solver.h +++ b/src/api/include/antares/api/solver.h @@ -36,5 +36,6 @@ namespace Antares::API */ SimulationResults PerformSimulation( const std::filesystem::path& study_path, + const std::filesystem::path& output, const Antares::Solver::Optimization::OptimizationOptions& optOptions) noexcept; } // namespace Antares::API diff --git a/src/api/private/API.h b/src/api/private/API.h index 3561f6d21b..c52c3304bf 100644 --- a/src/api/private/API.h +++ b/src/api/private/API.h @@ -48,11 +48,13 @@ class APIInternal * @return SimulationResults object which contains the results of the simulation. */ SimulationResults run(const IStudyLoader& study_loader, + const std::filesystem::path& output, const Antares::Solver::Optimization::OptimizationOptions& optOptions); private: std::shared_ptr study_; SimulationResults execute( + const std::filesystem::path& output, const Antares::Solver::Optimization::OptimizationOptions& optOptions) const; }; diff --git a/src/api/solver.cpp b/src/api/solver.cpp index 4e65696f8a..ac6810e7f1 100644 --- a/src/api/solver.cpp +++ b/src/api/solver.cpp @@ -30,18 +30,19 @@ namespace Antares::API SimulationResults PerformSimulation( const std::filesystem::path& study_path, + const std::filesystem::path& output, const Antares::Solver::Optimization::OptimizationOptions& optOptions) noexcept { try { APIInternal api; FileTreeStudyLoader study_loader(study_path); - return api.run(study_loader, optOptions); + return api.run(study_loader, output, optOptions); } catch (const std::exception& e) { Antares::API::Error err{.reason = e.what()}; - return SimulationResults{.simulationPath = study_path, .antares_problems{}, .error = err}; + return SimulationResults{.antares_problems{}, .error = err}; } } diff --git a/src/api_client_example/src/API_client.cpp b/src/api_client_example/src/API_client.cpp index 9cb19d8e59..8ebba07042 100644 --- a/src/api_client_example/src/API_client.cpp +++ b/src/api_client_example/src/API_client.cpp @@ -23,7 +23,8 @@ #include -Antares::API::SimulationResults solve(std::filesystem::path study_path) +Antares::API::SimulationResults solve(std::filesystem::path study_path, + std::filesystem::path output) { - return Antares::API::PerformSimulation(std::move(study_path), {}); + return Antares::API::PerformSimulation(std::move(study_path), std::move(output), {}); } diff --git a/src/api_client_example/src/API_client.h b/src/api_client_example/src/API_client.h index 5d8500649e..7f77a26e7f 100644 --- a/src/api_client_example/src/API_client.h +++ b/src/api_client_example/src/API_client.h @@ -22,7 +22,8 @@ #pragma once -#include #include +#include -Antares::API::SimulationResults solve(std::filesystem::path study_path); +Antares::API::SimulationResults solve(std::filesystem::path study_path, + std::filesystem::path output); diff --git a/src/api_client_example/tests/test.cpp b/src/api_client_example/tests/test.cpp index 4adee7bfd6..bd5b3d86a8 100644 --- a/src/api_client_example/tests/test.cpp +++ b/src/api_client_example/tests/test.cpp @@ -22,10 +22,12 @@ #define BOOST_TEST_MODULE test_client_api #include + #include "API_client.h" -BOOST_AUTO_TEST_CASE(test_run) { - auto results = solve("dummy_study_test_client_api"); +BOOST_AUTO_TEST_CASE(test_run) +{ + auto results = solve("dummy_study_test_client_api", {}); BOOST_CHECK(results.error); BOOST_CHECK(!results.error->reason.empty()); auto c = results.error->reason; @@ -34,4 +36,4 @@ BOOST_AUTO_TEST_CASE(test_run) { BOOST_CHECK(results.error->reason.find("folder") != std::string::npos); BOOST_CHECK(results.error->reason.find("not") != std::string::npos); BOOST_CHECK(results.error->reason.find("exist") != std::string::npos); -} \ No newline at end of file +} diff --git a/src/format-code.sh b/src/format-code.sh index abac85a423..752080ca58 100755 --- a/src/format-code.sh +++ b/src/format-code.sh @@ -3,7 +3,7 @@ if [ $# -eq 0 ] then # No arguments: format all - SOURCE_DIRS="analyzer/ libs/ solver/ tools/ config/ tests/ packaging/" + SOURCE_DIRS="analyzer/ libs/ solver/ tools/ config/ tests/ packaging/ api/" SOURCE_FILES=$(find $SOURCE_DIRS -regextype egrep -regex ".*/*\.(c|cxx|cpp|cc|h|hxx|hpp)$" ! -path '*/antlr-interface/*') else # Format files provided as arguments diff --git a/src/solver/application/application.cpp b/src/solver/application/application.cpp index 2d1695bcf0..43dfa3368d 100644 --- a/src/solver/application/application.cpp +++ b/src/solver/application/application.cpp @@ -161,9 +161,6 @@ void Application::readDataForTheStudy(Data::StudyLoadOptions& options) Antares::Solver::initializeSignalHandlers(resultWriter); - // Save about-the-study files (comments, notes, etc.) - study.saveAboutTheStudy(*resultWriter); - // Name of the simulation (again, if the value has been overwritten) if (!pSettings.simulationName.empty()) { @@ -375,6 +372,9 @@ void Application::execute() return; } + // Save about-the-study files (comments, notes, etc.) + pStudy->saveAboutTheStudy(*resultWriter); + SystemMemoryLogger memoryReport; memoryReport.interval(1000 * 60 * 5); // 5 minutes memoryReport.start(); diff --git a/src/tests/src/api_internal/test_api.cpp b/src/tests/src/api_internal/test_api.cpp index 5214aa8c10..47034cb19d 100644 --- a/src/tests/src/api_internal/test_api.cpp +++ b/src/tests/src/api_internal/test_api.cpp @@ -52,28 +52,17 @@ class InMemoryStudyLoader: public Antares::IStudyLoader builder.study->initializeRuntimeInfos(); builder.setNumberMCyears(1); builder.study->parameters.resultFormat = ResultFormat::inMemory; - builder.study->prepareOutput(); return std::move(builder.study); } bool success_ = true; }; -BOOST_AUTO_TEST_CASE(simulation_path_points_to_results) -{ - Antares::API::APIInternal api; - auto study_loader = std::make_unique(); - auto results = api.run(*study_loader.get(), {}); - BOOST_CHECK_EQUAL(results.simulationPath, std::filesystem::path{"no_output"}); - // Testing for "no_output" is a bit weird, but it's the only way to test this without actually - // running the simulation -} - BOOST_AUTO_TEST_CASE(api_run_contains_antares_problem) { Antares::API::APIInternal api; auto study_loader = std::make_unique(); - auto results = api.run(*study_loader.get(), {}); + auto results = api.run(*study_loader, {}, {}); BOOST_CHECK(!results.antares_problems.empty()); BOOST_CHECK(!results.error); @@ -83,7 +72,7 @@ BOOST_AUTO_TEST_CASE(result_failure_when_study_is_null) { Antares::API::APIInternal api; auto study_loader = std::make_unique(false); - auto results = api.run(*study_loader.get(), {}); + auto results = api.run(*study_loader, {}, {}); BOOST_CHECK(results.error); } @@ -93,7 +82,7 @@ BOOST_AUTO_TEST_CASE(result_contains_problems) { Antares::API::APIInternal api; auto study_loader = std::make_unique(); - auto results = api.run(*study_loader.get(), {}); + auto results = api.run(*study_loader, {}, {}); BOOST_CHECK(!results.antares_problems.empty()); BOOST_CHECK(!results.error); @@ -109,7 +98,7 @@ BOOST_AUTO_TEST_CASE(result_with_ortools_coin) .solverLogs = false, .solverParameters = ""}; - auto results = api.run(*study_loader.get(), opt); + auto results = api.run(*study_loader, {}, opt); BOOST_CHECK(!results.antares_problems.empty()); BOOST_CHECK(!results.error); @@ -126,7 +115,7 @@ BOOST_AUTO_TEST_CASE(invalid_ortools_solver) .solverLogs = true, .solverParameters = ""}; - auto shouldThrow = [&api, &study_loader, &opt] { return api.run(*study_loader.get(), opt); }; + auto shouldThrow = [&api, &study_loader, &opt] { return api.run(*study_loader, {}, opt); }; BOOST_CHECK_EXCEPTION(shouldThrow(), std::invalid_argument, checkMessage("Solver this-solver-does-not-exist not found")); diff --git a/src/tests/src/api_lib/test_api.cpp b/src/tests/src/api_lib/test_api.cpp index c1111b5c6a..8460c4533a 100644 --- a/src/tests/src/api_lib/test_api.cpp +++ b/src/tests/src/api_lib/test_api.cpp @@ -29,7 +29,7 @@ BOOST_AUTO_TEST_CASE(result_failure_when_study_path_invalid) { using namespace std::string_literals; - auto results = Antares::API::PerformSimulation("dummy"s, {}); + auto results = Antares::API::PerformSimulation("dummy"s, {}, {}); BOOST_CHECK(results.error); BOOST_CHECK(!results.error->reason.empty()); } From a71f438e28e832c8b8fa8767627d92a7e37b9e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Mon, 6 Jan 2025 10:31:39 +0100 Subject: [PATCH 12/14] Improve `add_boost_test` CMake function (#2552) - Start parsing argument from the 2nd one, ignore the 1st argument `${ARGV0}` since it's reserved to the test name - Remove the obsolete linking to `stdc++fs` (no longer necessary with modern compilers/linkers) --- src/tests/macros.cmake | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/tests/macros.cmake b/src/tests/macros.cmake index 8d57ddf55b..d68c7b4f2e 100644 --- a/src/tests/macros.cmake +++ b/src/tests/macros.cmake @@ -9,7 +9,7 @@ function(add_boost_test) set(options "") set(oneValueArgs) set(multiValueArgs SRC LIBS INCLUDE) - cmake_parse_arguments(PARSE_ARGV 0 arg + cmake_parse_arguments(PARSE_ARGV 1 arg "${options}" "${oneValueArgs}" "${multiValueArgs}") # Bypass cmake_parse_arguments for the 1st argument set(TEST_NAME ${ARGV0}) @@ -29,10 +29,4 @@ function(add_boost_test) # Give the IDE some directions to display tests in a "Unit-tests" folder set_target_properties(${TEST_NAME} PROPERTIES FOLDER Unit-tests) - - # Linux only. TODO remove ? - if(UNIX AND NOT APPLE) - target_link_libraries(${TEST_NAME} PRIVATE stdc++fs) - endif() - endfunction() From 361abdaefd58f0bd04a2b41c566a334640a29d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Mon, 6 Jan 2025 11:37:44 +0100 Subject: [PATCH 13/14] Update vcpkg@2023.07.21 -> vcpkg@2024.12.16, Boost@1.81.0 -> Boost@1.86.0 (#2553) The old tag seems to reference invalid URLs on Windows, e.g ``` Downloading https://mirror.msys2.org/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst Downloading https://repo.msys2.org/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst Downloading https://mirror.yandex.ru/mirrors/msys2/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst Downloading https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst Downloading https://mirrors.ustc.edu.cn/msys2/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst Downloading https://mirror.selfnet.de/msys2/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst error: Failed to download from mirror set error: https://mirror.msys2.org/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst: failed: status code 404 error: https://repo.msys2.org/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst: failed: status code 404 error: https://mirror.yandex.ru/mirrors/msys2/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst: failed: status code 404 error: https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst: failed: status code 404 error: https://mirrors.ustc.edu.cn/msys2/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst: failed: status code 404 error: https://mirror.selfnet.de/msys2/msys/x86_64/msys2-runtime-3.4.6-1-x86_64.pkg.tar.zst: failed: status code 404 ``` [source](https://github.com/AntaresSimulatorTeam/Antares_Simulator/actions/runs/12580772537/job/35063320582?pr=2552) --- src/vcpkg.json | 6 +++--- vcpkg | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/vcpkg.json b/src/vcpkg.json index 68a34fa53c..0a8e10c378 100644 --- a/src/vcpkg.json +++ b/src/vcpkg.json @@ -1,7 +1,7 @@ { "name": "antares-simulator", "version-string": "9.2.0", - "builtin-baseline": "9484a57dd560b89f0a583be08af6753611c57fd5", + "builtin-baseline": "b322364f06308bdd24823f9d8f03fe0cc86fd46f", "vcpkg-configuration": { "overlay-ports": [ "./ports" @@ -21,11 +21,11 @@ }, { "name": "boost-test", - "version>=": "1.81.0" + "version>=": "1.86.0" }, { "name": "boost-core", - "version>=": "1.81.0" + "version>=": "1.86.0" }, { "name": "minizip-ng", diff --git a/vcpkg b/vcpkg index 9d47b24eac..b322364f06 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 9d47b24eacbd1cd94f139457ef6cd35e5d92cc84 +Subproject commit b322364f06308bdd24823f9d8f03fe0cc86fd46f From 4a30c443cb821b482311095111bda33ffaf9cbba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Mon, 6 Jan 2025 14:54:50 +0100 Subject: [PATCH 14/14] Fix NonMovable class (#2555) --- src/ext/yuni/src/yuni/core/nonmovable.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ext/yuni/src/yuni/core/nonmovable.h b/src/ext/yuni/src/yuni/core/nonmovable.h index e9214e709f..c866e916ec 100644 --- a/src/ext/yuni/src/yuni/core/nonmovable.h +++ b/src/ext/yuni/src/yuni/core/nonmovable.h @@ -49,11 +49,12 @@ class YUNI_DECL NonMovable { protected: //! Default constructor - NonCopyable() + NonMovable() { } + //! Protected non-virtual destructor - ~NonCopyable() + ~NonMovable() { } };