diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index 7a29b6c5b3..c0df6c327c 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -17,6 +17,7 @@ env: GITHUB_TOKEN: ${{ github.token }} IS_RELEASE: ${{ github.event_name == 'release' && github.event.action == 'created' }} IS_PUSH: ${{ github.event_name == 'push' }} + ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true jobs: diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 17cb3478a9..a200843746 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.14) # FetchContent_MakeAvailable # Version set(ANTARES_VERSION_HI 8) set(ANTARES_VERSION_LO 6) -set(ANTARES_VERSION_REVISION 8) +set(ANTARES_VERSION_REVISION 9) set(ANTARES_VERSION_YEAR 2024) project(antares 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 0b997a2e77..be7c5a0bde 100644 --- a/src/libs/antares/study/parts/short-term-storage/properties.cpp +++ b/src/libs/antares/study/parts/short-term-storage/properties.cpp @@ -26,6 +26,8 @@ */ #include +#include + #include #include "properties.h" @@ -35,15 +37,15 @@ namespace Antares::Data::ShortTermStorage { const std::map Properties::ST_STORAGE_PROPERTY_GROUP_ENUM - = {{"PSP_open", Group::PSP_open}, - {"PSP_closed", Group::PSP_closed}, - {"Pondage", Group::Pondage}, - {"Battery", Group::Battery}, - {"Other1", Group::Other1}, - {"Other2", Group::Other2}, - {"Other3", Group::Other3}, - {"Other4", Group::Other4}, - {"Other5", Group::Other5}}; + = {{"PSP_OPEN", Group::PSP_open}, + {"PSP_CLOSED", Group::PSP_closed}, + {"PONDAGE", Group::Pondage}, + {"BATTERY", Group::Battery}, + {"OTHER1", Group::Other1}, + {"OTHER2", Group::Other2}, + {"OTHER3", Group::Other3}, + {"OTHER4", Group::Other4}, + {"OTHER5", Group::Other5}}; unsigned int groupIndex(Group group) { @@ -106,7 +108,9 @@ bool Properties::loadKey(const IniFile::Property* p) if (p->key == "group") { - if (auto it = Properties::ST_STORAGE_PROPERTY_GROUP_ENUM.find(p->value.c_str()); + std::string groupUpper = p->value.c_str(); + boost::to_upper(groupUpper); + if (auto it = Properties::ST_STORAGE_PROPERTY_GROUP_ENUM.find(groupUpper); it != Properties::ST_STORAGE_PROPERTY_GROUP_ENUM.end()) { this->group = it->second; diff --git a/src/solver/misc/options.cpp b/src/solver/misc/options.cpp index e4d482a999..e1fb15d666 100644 --- a/src/solver/misc/options.cpp +++ b/src/solver/misc/options.cpp @@ -54,20 +54,6 @@ using namespace Yuni; using namespace Antares; using namespace Antares::Data; -static std::string availableOrToolsSolversString() -{ - const std::list availableSolverList = getAvailableOrtoolsSolverName(); - std::string availableSolverListStr; - for (auto it = availableSolverList.begin(); it != availableSolverList.end(); it++) - { - availableSolverListStr += *it + ";"; - } - // Remove last semicolumn - if (!availableSolverListStr.empty()) - availableSolverListStr.pop_back(); - return availableSolverListStr; -} - std::unique_ptr CreateParser(Settings& settings, Antares::Data::StudyLoadOptions& options) { diff --git a/src/solver/optimisation/post_process_commands.cpp b/src/solver/optimisation/post_process_commands.cpp index 16f36bc7bc..72334a7255 100644 --- a/src/solver/optimisation/post_process_commands.cpp +++ b/src/solver/optimisation/post_process_commands.cpp @@ -263,9 +263,9 @@ double CurtailmentSharingPostProcessCmd::calculateDensNewAndTotalLmrViolation() const auto& scratchpad = area_list_[Area]->scratchpad[thread_number_]; double dtgMrg = scratchpad.dispatchableGenerationMargin[hour]; // write down densNew values for all the hours - problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesDENS[hour] - = std::max(0.0, densNew - dtgMrg); - ; + problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesDENS[hour] = std::max( + 0.0, + densNew); // copy spilled Energy values into spilled Energy values after CSR problemeHebdo_->ResultatsHoraires[Area].ValeursHorairesSpilledEnergyAfterCSR[hour] = problemeHebdo_->ResultatsHoraires[Area] diff --git a/src/solver/utils/ortools_utils.cpp b/src/solver/utils/ortools_utils.cpp index 7503fe3d5c..ff6b04caae 100644 --- a/src/solver/utils/ortools_utils.cpp +++ b/src/solver/utils/ortools_utils.cpp @@ -401,6 +401,19 @@ std::list getAvailableOrtoolsSolverName() return result; } +std::string availableOrToolsSolversString() +{ + const std::list availableSolverList = getAvailableOrtoolsSolverName(); + std::ostringstream solvers; + for (const std::string& avail: availableSolverList) + { + bool last = &avail == &availableSolverList.back(); + std::string sep = last ? "." : ", "; + solvers << avail << sep; + } + return solvers.str(); +} + MPSolver* MPSolverFactory(const Antares::Optimization::PROBLEME_SIMPLEXE_NOMME* probleme, const std::string& solverName) { diff --git a/src/solver/utils/ortools_utils.h b/src/solver/utils/ortools_utils.h index e5d63fe765..e08a52f0ca 100644 --- a/src/solver/utils/ortools_utils.h +++ b/src/solver/utils/ortools_utils.h @@ -21,6 +21,13 @@ void ORTOOLS_EcrireJeuDeDonneesLineaireAuFormatMPS(MPSolver* solver, */ std::list getAvailableOrtoolsSolverName(); +/*! + * \brief Return a single string containing all solvers available, separated by a ", " and ending + * with a ".". + * + */ +std::string availableOrToolsSolversString(); + /*! * \brief Create a MPSolver with correct linear or mixed variant * diff --git a/src/tools/batchrun/CMakeLists.txt b/src/tools/batchrun/CMakeLists.txt index a4ba01d80b..2457da817f 100644 --- a/src/tools/batchrun/CMakeLists.txt +++ b/src/tools/batchrun/CMakeLists.txt @@ -39,6 +39,7 @@ set(BATCHRUN_LIBS libantares-core libantares-core-calendar yuni-static-core + utils ${CMAKE_THREADS_LIBS_INIT} ) diff --git a/src/tools/batchrun/main.cpp b/src/tools/batchrun/main.cpp index 34635bfe07..f8f34f2abd 100644 --- a/src/tools/batchrun/main.cpp +++ b/src/tools/batchrun/main.cpp @@ -32,12 +32,15 @@ #include #include #include +#include #include #include #include #include "../../ui/common/winmain.hxx" #include #include +#include "../solver/utils/ortools_utils.h" + #ifdef YUNI_OS_WINDOWS #include #endif @@ -84,7 +87,8 @@ int main(int argc, char* argv[]) Antares::Resources::Initialize(argc, argv, true); // options - String optInput; + std::string optInput; + std::string ortoolsSolver; bool optNoTSImport = false; bool optIgnoreAllConstraints = false; bool optForceExpansion = false; @@ -95,6 +99,7 @@ int main(int argc, char* argv[]) bool optNoOutput = false; bool optParallel = false; bool optVerbose = false; + bool ortoolsUsed = false; Nullable optYears; Nullable optSolver; Nullable optName; @@ -143,6 +148,19 @@ int main(int argc, char* argv[]) ' ', "force-parallel", "Override the max number of years computed simultaneously"); + + // add option for ortools use + // --use-ortools + options.addFlag(ortoolsUsed, ' ', "use-ortools", "Use ortools library to launch solver"); + + //--ortools-solver + options.add(ortoolsSolver, + ' ', + "ortools-solver", + "Ortools solver used for simulation (only available with use-ortools " + "option)\nAvailable solver list : " + + availableOrToolsSolversString()); + options.remainingArguments(optInput); // Version options.addParagraph("\nMisc."); @@ -176,163 +194,179 @@ int main(int argc, char* argv[]) logs.error() << "contradictory options: --economy and --adequacy"; return EXIT_FAILURE; } - } - - // Source Folder - logs.debug() << "Folder : `" << optInput << '`'; - String solver; - if (optSolver.empty()) - { - Solver::FindLocation(solver); - if (solver.empty()) + if (ortoolsUsed) { - logs.fatal() << "The solver has not been found"; - return EXIT_FAILURE; - } - } - else - { - String tmp; - IO::MakeAbsolute(tmp, *optSolver); - IO::Normalize(solver, tmp); - if (not IO::File::Exists(solver)) - { - logs.fatal() << "The solver has not been found. specify --solver=" << solver; - return EXIT_FAILURE; + const auto availableSolvers = getAvailableOrtoolsSolverName(); + if (auto it + = std::find(availableSolvers.begin(), availableSolvers.end(), ortoolsSolver); + it == availableSolvers.end()) + { + logs.error() << "Please specify a solver using --ortools-solver. Available solvers " + << availableOrToolsSolversString() << ""; + return EXIT_FAILURE; + } } - } - logs.info() << " Solver: '" << solver << "'"; - logs.info(); - logs.info(); - logs.info() << "Searching for studies..."; - logs.info(); - MyStudyFinder finder; - finder.lookup(optInput); - finder.wait(); + // Source Folder + logs.debug() << "Folder : `" << optInput << '`'; - if (not finder.list.empty()) - { - if (finder.list.size() > 1) - logs.info() << "Found " << finder.list.size() << " studyies"; + String solver; + if (optSolver.empty()) + { + Solver::FindLocation(solver); + if (solver.empty()) + { + logs.fatal() << "The solver has not been found"; + return EXIT_FAILURE; + } + } else - logs.info() << "Found 1 study"; - logs.info() << "Starting..."; - - if (!(!optName)) { - String name; - name = *optName; - name.replace("\"", "\\\""); - *optName = name; + String tmp; + IO::MakeAbsolute(tmp, *optSolver); + IO::Normalize(solver, tmp); + if (not IO::File::Exists(solver)) + { + logs.fatal() << "The solver has not been found. specify --solver=" << solver; + return EXIT_FAILURE; + } } - // The folder that contains the solver - String dirname; - IO::ExtractFilePath(dirname, solver); + logs.info() << " Solver: '" << solver << "'"; + logs.info(); + logs.info(); + logs.info() << "Searching for studies..."; + logs.info(); + MyStudyFinder finder; + finder.lookup(optInput); + finder.wait(); - String cmd; - - uint studyIndx = 0; - foreach (auto& studypath, finder.list) + if (not finder.list.empty()) { - ++studyIndx; - - logs.info(); - if (optVerbose) - logs.info(); - - logs.checkpoint() << "Running simulation: `" << studypath << "` (" << studyIndx << '/' - << (uint)finder.list.size() << ')'; - if (optVerbose) - logs.debug(); - - cmd.clear(); - if (not System::windows) - cmd << "nice "; + if (finder.list.size() > 1) + logs.info() << "Found " << finder.list.size() << " studyies"; else - cmd << "call "; // why is it required for working ??? - cmd << "\"" << solver << "\""; - if (optForce) - cmd << " --force"; - if (optForceExpansion) - cmd << " --economy"; - if (optForceEconomy) - cmd << " --economy"; - if (optForceAdequacy) - cmd << " --adequacy"; + logs.info() << "Found 1 study"; + logs.info() << "Starting..."; + if (!(!optName)) - cmd << " --name=\"" << *optName << "\""; - if (!(!optYears)) - cmd << " --year=" << *optYears; - if (optNoOutput) - cmd << " --no-output"; - if (optYearByYear) - cmd << " --year-by-year"; - if (optNoTSImport) - cmd << " --no-ts-import"; - if (optIgnoreAllConstraints) - cmd << " --no-constraints"; - if (optParallel) - cmd << " --parallel"; - if (!(!optForceParallel)) - cmd << " --force-parallel=" << *optForceParallel; - cmd << " \"" << studypath << "\""; - if (!optVerbose) - cmd << sendToNull(); - - // Changing the current working directory - IO::Directory::Current::Set(dirname); - // Executing the converter - if (optVerbose) - logs.info() << "Executing " << cmd; + { + String name; + name = *optName; + name.replace("\"", "\\\""); + *optName = name; + } - // Execute the command - int cmd_return_code = system(cmd.c_str()); + // The folder that contains the solver + String dirname; + IO::ExtractFilePath(dirname, solver); - if (cmd_return_code != 0) - logs.error() << "An error occured."; - else - logs.info() << "Success."; + String cmd; - if (cmd_return_code == -1) + uint studyIndx = 0; + foreach (auto& studypath, finder.list) { -#ifdef YUNI_OS_WINDOWS - switch (errno) + ++studyIndx; + + logs.info(); + if (optVerbose) + logs.info(); + + logs.checkpoint() << "Running simulation: `" << studypath << "` (" << studyIndx + << '/' << (uint)finder.list.size() << ')'; + if (optVerbose) + logs.debug(); + + cmd.clear(); + if (not System::windows) + cmd << "nice "; + else + cmd << "call "; // why is it required for working ??? + cmd << "\"" << solver << "\""; + if (optForce) + cmd << " --force"; + if (optForceExpansion) + cmd << " --economy"; + if (optForceEconomy) + cmd << " --economy"; + if (optForceAdequacy) + cmd << " --adequacy"; + if (!(!optName)) + cmd << " --name=\"" << *optName << "\""; + if (!(!optYears)) + cmd << " --year=" << *optYears; + if (optNoOutput) + cmd << " --no-output"; + if (optYearByYear) + cmd << " --year-by-year"; + if (optNoTSImport) + cmd << " --no-ts-import"; + if (optIgnoreAllConstraints) + cmd << " --no-constraints"; + if (optParallel) + cmd << " --parallel"; + if (optForceParallel) + cmd << " --force-parallel=" << *optForceParallel; + if (ortoolsUsed) + cmd << " --use-ortools --ortools-solver=" << ortoolsSolver; + + cmd << " \"" << studypath << "\""; + if (!optVerbose) + cmd << sendToNull(); + + // Changing the current working directory + IO::Directory::Current::Set(dirname); + // Executing the converter + if (optVerbose) + logs.info() << "Executing " << cmd; + + // Execute the command + int cmd_return_code = system(cmd.c_str()); + + if (cmd_return_code != 0) + logs.error() << "An error occured."; + else + logs.info() << "Success."; + + if (cmd_return_code == -1) { - case E2BIG: - logs.error() << "Argument list (which is system dependent) is too big"; - break; - case ENOENT: - logs.error() << "Command interpreter cannot be found"; - break; - case ENOEXEC: - logs.error() - << "Command-interpreter file has invalid format and is not executable"; - break; - case ENOMEM: - logs.error() << "Not enough memory is available to execute command"; - break; - } +#ifdef YUNI_OS_WINDOWS + switch (errno) + { + case E2BIG: + logs.error() << "Argument list (which is system dependent) is too big"; + break; + case ENOENT: + logs.error() << "Command interpreter cannot be found"; + break; + case ENOEXEC: + logs.error() + << "Command-interpreter file has invalid format and is not executable"; + break; + case ENOMEM: + logs.error() << "Not enough memory is available to execute command"; + break; + } #endif + } } - } - logs.info() << "Done."; + logs.info() << "Done."; - // Time interval - if (optVerbose) + // Time interval + if (optVerbose) + { + logs.debug(); + logs.debug(); + } + } + else { - logs.debug(); - logs.debug(); + logs.fatal() << "No study has been found."; + return 4; } - } - else - { - logs.fatal() << "No study has been found."; - return 4; - } - return 0; + return 0; + } }