From 5e6a57fd368b305d119a654e84e78a45114597cd Mon Sep 17 00:00:00 2001 From: Sylvain Leclerc Date: Wed, 5 Jun 2024 15:13:52 +0200 Subject: [PATCH 01/13] Install sirius solver with VCPKG, remove antares-deps (#2090) **Description** Continues the work of #2078 (which should be merged before in feature branch feature/vcpkg-dependencies), to push further the use of VCPKG, and in particular remove the need for the home-made antares-deps repository. Hence, this includes: - Addition of sirius-solver "overlay" port to install sirius with VCPKG - Removal of antares-deps and associated code --------- Signed-off-by: Sylvain Leclerc --- .github/workflows/centos7.yml | 14 +- .../action.yml | 9 -- .../action.yml | 13 +- .github/workflows/oracle8.yml | 2 +- .github/workflows/sonarcloud.yml | 11 -- .github/workflows/ubuntu.yml | 20 --- .github/workflows/windows-vcpkg.yml | 11 -- .gitmodules | 4 - antares-deps-version.json | 3 - .../1-Development-requirements.md | 12 +- .../developer-guide/2-Dependencies-install.md | 111 ++++++---------- docs/developer-guide/3-Build.md | 122 +++++++++++------- src/CMakeLists.txt | 57 +------- src/antares-deps | 1 - src/ports/sirius-solver/portfile.cmake | 21 +++ src/ports/sirius-solver/vcpkg.json | 16 +++ src/ui/CMakeLists.txt | 5 - src/vcpkg.json | 6 + 18 files changed, 170 insertions(+), 268 deletions(-) delete mode 100644 antares-deps-version.json delete mode 160000 src/antares-deps create mode 100644 src/ports/sirius-solver/portfile.cmake create mode 100644 src/ports/sirius-solver/vcpkg.json diff --git a/.github/workflows/centos7.yml b/.github/workflows/centos7.yml index 5f5a34d4b6..3308dab812 100644 --- a/.github/workflows/centos7.yml +++ b/.github/workflows/centos7.yml @@ -7,7 +7,6 @@ on: branches: - develop - dependabot/* - schedule: - cron: '21 2 * * *' workflow_call: @@ -71,15 +70,7 @@ jobs: - name: Init submodule run: | - git submodule update --init --remote src/antares-deps src/tests/resources/Antares_Simulator_Tests - - - name: Download & extract precompiled deps at root - run: | - ANTARES_DEPS_VERSION=$(cut -d'"' -f4 antares-deps-version.json | grep -Ev '\{|\}') - cd / - wget https://github.com/AntaresSimulatorTeam/antares-deps/releases/download/v${ANTARES_DEPS_VERSION}/rte-antares-deps-centos7-Release.tar.gz - tar -xvf rte-antares-deps-centos7-Release.tar.gz - rm -rf rte-antares-deps-centos7-Release.tar.gz + git submodule update --init --remote src/tests/resources/Antares_Simulator_Tests - name: Config OR-Tools URL run: | @@ -110,14 +101,13 @@ jobs: -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ -DCMAKE_TOOLCHAIN_FILE=$GITHUB_WORKSPACE/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DVCPKG_TARGET_TRIPLET=x64-linux-release \ - -DDEPS_INSTALL_DIR=/rte-antares-deps-Release \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=ON \ - -DBUILD_not_system=OFF \ -DBUILD_TOOLS=ON \ -DBUILD_UI=OFF \ -DCMAKE_PREFIX_PATH=${{ env.ORTOOLSDIR }}/install \ + - name: Build run: | source /opt/rh/devtoolset-10/enable diff --git a/.github/workflows/download-extract-precompiled-libraries-tgz/action.yml b/.github/workflows/download-extract-precompiled-libraries-tgz/action.yml index 00852138af..d6b87bcaa5 100644 --- a/.github/workflows/download-extract-precompiled-libraries-tgz/action.yml +++ b/.github/workflows/download-extract-precompiled-libraries-tgz/action.yml @@ -1,9 +1,6 @@ name: "Download extract .tgz precompiled libraries" description: "Download and extract .tgz precompiled libraries from antares-deps and antares-simulator repository" inputs: - antares-deps-version: - description: 'antares-deps version' - required: true os: description: 'operational system used for github action' required: true @@ -21,12 +18,6 @@ inputs: runs: using: "composite" steps: - - name: Download & extract antares-deps - shell: bash - run: | - wget https://github.com/AntaresSimulatorTeam/antares-deps/releases/download/v${{inputs.antares-deps-version}}/rte-antares-deps-${{inputs.os}}-${{inputs.buildtype}}.tar.gz - tar -xvf rte-antares-deps-${{inputs.os}}-${{inputs.buildtype}}.tar.gz - rm -rf rte-antares-deps-${{inputs.os}}-${{inputs.buildtype}}.tar.gz - name: Download & extract OR-Tools shell: bash diff --git a/.github/workflows/download-extract-precompiled-libraries-zip/action.yml b/.github/workflows/download-extract-precompiled-libraries-zip/action.yml index 745b76236c..52eec0beea 100644 --- a/.github/workflows/download-extract-precompiled-libraries-zip/action.yml +++ b/.github/workflows/download-extract-precompiled-libraries-zip/action.yml @@ -1,9 +1,6 @@ name: "Download extract .zip precompiled libraries" description: "Download and extract .zip precompiled libraries from antares-deps and antares-simulator repository" inputs: - antares-deps-version: - description: 'antares-deps version' - required: true os: description: 'operational system used for github action' required: true @@ -20,15 +17,7 @@ inputs: runs: using: "composite" - steps: - - name: Download & extract antares-deps - shell: bash - run: | - wget https://github.com/AntaresSimulatorTeam/antares-deps/releases/download/v${{inputs.antares-deps-version}}/rte-antares-deps-${{inputs.os}}-${{inputs.buildtype}}.zip - unzip rte-antares-deps-${{inputs.os}}-${{inputs.buildtype}}.zip - rm -rf rte-antares-deps-${{inputs.os}}-${{inputs.buildtype}}.zip - echo "${GITHUB_WORKSPACE}/rte-antares-deps-Release/bin" >> $GITHUB_PATH - + steps: - name: Download & extract OR-Tools shell: bash run: | diff --git a/.github/workflows/oracle8.yml b/.github/workflows/oracle8.yml index 23c5d49d57..92b65a9a72 100644 --- a/.github/workflows/oracle8.yml +++ b/.github/workflows/oracle8.yml @@ -85,7 +85,7 @@ jobs: rm ortools.zip - name: Init submodule - run: git submodule update --init --remote src/antares-deps src/tests/resources/Antares_Simulator_Tests + run: git submodule update --init --remote src/tests/resources/Antares_Simulator_Tests - name: Install dependencies run: | diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml index cf326c2d72..cfe5324d3c 100644 --- a/.github/workflows/sonarcloud.yml +++ b/.github/workflows/sonarcloud.yml @@ -54,17 +54,9 @@ jobs: sudo apt-get install libboost-test-dev sudo apt-get install g++-10 gcc-10 - - name: Read antares-deps version - id: antares-deps-version - uses: notiz-dev/github-action-json-property@release - with: - path: 'antares-deps-version.json' - prop_path: 'antares_deps_version' - - name: Download pre-compiled librairies uses: ./.github/workflows/download-extract-precompiled-libraries-tgz with: - antares-deps-version: ${{steps.antares-deps-version.outputs.prop}} os: ${{matrix.os}} buildtype: Debug ortools-url: ${{env.ORTOOLS_URL}} @@ -85,7 +77,6 @@ jobs: - name: Init submodule run: | - git submodule update --init src/antares-deps git submodule update --init --remote src/tests/resources/Antares_Simulator_Tests - name: Configure @@ -97,13 +88,11 @@ jobs: -DCMAKE_CXX_COMPILER=/usr/bin/g++-10 \ -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DVCPKG_TARGET_TRIPLET=x64-linux-release \ - -DDEPS_INSTALL_DIR=./rte-antares-deps-Debug \ -DCODE_COVERAGE=ON \ -DCMAKE_BUILD_TYPE=Debug \ -DCMAKE_PREFIX_PATH="../install;${{ env.ORTOOLS_DIR }}/install" \ -DBUILD_TESTING=ON \ -DMZ_CODE_COVERAGE=ON \ - -DBUILD_not_system=OFF \ -DPython3_EXECUTABLE='${{ steps.setup-python.outputs.python-path }}' - name: Build diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index cbb66c6df8..2bcf2954a0 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -68,7 +68,6 @@ jobs: with: key: ${{ env.os }} - - name : Init VCPKG submodule run: | git submodule update --init vcpkg @@ -96,19 +95,6 @@ jobs: sudo apt-get install uuid-dev libwxgtk3.0-gtk3-dev sudo apt-get install g++-10 gcc-10 - - name: export wxWidgets script - shell: bash - run: | - export WX_CONFIG=${{env.WX_CONFIG}} - - - name: Read antares-deps version - id: antares-deps-version - uses: notiz-dev/github-action-json-property@release - with: - path: 'antares-deps-version.json' - prop_path: 'antares_deps_version' - - - name: Config OR-Tools URL run: | echo "ORTOOLS_URL=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_ubuntu-20.04_static_sirius.zip" >> $GITHUB_ENV @@ -116,7 +102,6 @@ jobs: - name: Download pre-compiled librairies uses: ./.github/workflows/download-extract-precompiled-libraries-tgz with: - antares-deps-version: ${{steps.antares-deps-version.outputs.prop}} os: ${{env.os}} ortools-url: ${{env.ORTOOLS_URL}} ortools-dir: ${{env.ORTOOLS_DIR}} @@ -134,11 +119,8 @@ jobs: - name: Init submodule run: | - git submodule update --init src/antares-deps git submodule update --init --remote --recursive src/tests/resources/Antares_Simulator_Tests - - - name: Configure run: | cmake -B _build -S src \ @@ -148,10 +130,8 @@ jobs: -DCMAKE_CXX_COMPILER=/usr/bin/g++-10 \ -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake \ -DVCPKG_TARGET_TRIPLET=x64-linux-release \ - -DDEPS_INSTALL_DIR=${{github.workspace}}/rte-antares-deps-Release \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=ON \ - -DBUILD_not_system=OFF \ -DBUILD_TOOLS=ON \ -DCMAKE_PREFIX_PATH=${{ env.ORTOOLS_DIR }}/install \ -DPython3_EXECUTABLE="${{ env.Python3_ROOT_DIR }}/bin/python" diff --git a/.github/workflows/windows-vcpkg.yml b/.github/workflows/windows-vcpkg.yml index 4eb484b8d0..ccc8794dcb 100644 --- a/.github/workflows/windows-vcpkg.yml +++ b/.github/workflows/windows-vcpkg.yml @@ -94,17 +94,9 @@ jobs: # Allows to restore a cache when deps have only partially changed (like adding a dependency) restore-keys: vcpkg-cache-windows- - - name: Read antares-deps version - id: antares-deps-version - uses: notiz-dev/github-action-json-property@release - with: - path: 'antares-deps-version.json' - prop_path: 'antares_deps_version' - - name: Download pre-compiled librairies uses: ./.github/workflows/download-extract-precompiled-libraries-zip with: - antares-deps-version: ${{steps.antares-deps-version.outputs.prop}} os: ${{env.os}} ortools-url: ${{env.ORTOOLS_URL}} ortools-dir: ${{env.ORTOOLS_DIR}} @@ -121,7 +113,6 @@ jobs: - name: Init submodule run: | - git submodule update --init src/antares-deps git submodule update --init --remote src/tests/resources/Antares_Simulator_Tests - name: Enable git longpaths @@ -131,7 +122,6 @@ jobs: shell: bash run: | cmake -B _build -S src \ - -DDEPS_INSTALL_DIR=rte-antares-deps-Release \ -DCMAKE_PREFIX_PATH="${{ env.ORTOOLS_DIR }}/install" \ -DVCPKG_ROOT="${{env.VCPKG_ROOT}}" \ -DVCPKG_TARGET_TRIPLET=${{ env.triplet }} \ @@ -139,7 +129,6 @@ jobs: -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=ON \ -DBUILD_TOOLS=ON \ - -DBUILD_not_system=OFF \ -DPython3_EXECUTABLE="${{ env.Python3_ROOT_DIR }}/python.exe" \ -DCMAKE_VS_GLOBALS="CLToolExe=cl.exe;CLToolPath=${GITHUB_WORKSPACE}/ccache;TrackFileAccess=false;UseMultiToolTask=true;DebugInformationFormat=OldStyle" diff --git a/.gitmodules b/.gitmodules index 9bee42d242..77fb4921c7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,7 +1,3 @@ -[submodule "src/antares-deps"] - path = src/antares-deps - url = https://github.com/AntaresSimulatorTeam/antares-deps.git - branch = v2.0.2b [submodule "src/tests/resources/Antares_Simulator_Tests"] path = src/tests/resources/Antares_Simulator_Tests url = https://github.com/AntaresSimulatorTeam/Antares_Simulator_Tests.git diff --git a/antares-deps-version.json b/antares-deps-version.json deleted file mode 100644 index ced7f5add0..0000000000 --- a/antares-deps-version.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "antares_deps_version": "2.0.2b" -} diff --git a/docs/developer-guide/1-Development-requirements.md b/docs/developer-guide/1-Development-requirements.md index 7378d198cc..02c0896f33 100644 --- a/docs/developer-guide/1-Development-requirements.md +++ b/docs/developer-guide/1-Development-requirements.md @@ -11,13 +11,17 @@ The compilation of *Antares Simulator* requires C++17 support. === "Centos" By default, GCC version on Centos is old. - Some external repositories must be enabled depedning on your version of the OS: + Some external repositories must be enabled depending on your version of the OS: #### Centos 7 You must enable the EPEL repository: ``` sudo yum install epel-release - sudo yum install centos-release-scl + sudo yum install git redhat-lsb-core make wget centos-release-scl scl-utils rpm-build + sudo yum install devtoolset-10-gcc* + + scl enable devtoolset-10 bash + source /opt/rh/rh-git227/enable ``` #### Centos 8 @@ -25,8 +29,8 @@ The compilation of *Antares Simulator* requires C++17 support. ``` sudo yum install dnf-plugins-core sudo yum config-manager --set-enabled PowerTools - sudo yum install devtoolset-9 - scl enable devtoolset-9 bash + sudo yum install devtoolset-10 + scl enable devtoolset-10 bash ``` === "Ubuntu/Debian" diff --git a/docs/developer-guide/2-Dependencies-install.md b/docs/developer-guide/2-Dependencies-install.md index 45a96e08f0..1177228e6a 100644 --- a/docs/developer-guide/2-Dependencies-install.md +++ b/docs/developer-guide/2-Dependencies-install.md @@ -10,94 +10,61 @@ toc_depth: 2 - [OR-Tools](https://github.com/rte-france.com/or-tools) (fork from [Google](https://github.com/google/or-tools)) - [wxWidgets](https://github.com/wxWidgets/wxWidgets) (Only for the complete Antares Simulator solution with GUI) -- [Boost](https://www.boost.org/) libraries: test (Only for unit tests) +- [minizip](https://github.com/zlib-ng/minizip-ng) library, with its dependency zlib +- [Boost](https://www.boost.org/) libraries: header libraries and boost-test library +- [libuuid](https://linux.die.net/man/3/libuuid) on Linux systems -These third-party libraries can be installed: -- by building them from sources (see [here](3-Build.md) for more information) -- or using a package manager. +We favor using [vcpkg](https://github.com/microsoft/vcpkg) for building and installing most of those dependencies, +see [build instructions](3-Build.md) which explain how it integrates with CMake build. +However, we still have a few exceptions that must be installed in a different way, see next sections. -## Install with package manager +Although not encouraged, it's still possible to install those dependencies yourself and add +their installation path to your `CMAKE_PREFIX_PATH`. -=== "Windows" +## OR-Tools - For Windows we will use [vcpkg](https://github.com/microsoft/vcpkg) to download and compile the libraries. vcpkg is available as a submodule in *ANTARES*. - - You must install the corresponding [vcpkg-triplet](https://vcpkg.readthedocs.io/en/latest/users/integration/#triplet-selection) depending on Antares version and libraries load: - - - ``x64-windows`` : 64 bits version with dynamic libraries load - - ``x86-windows`` : 32 bits version with dynamic libraries load - - ``x64-windows-static``: 64 bits version with static libraries load - - ``x86-windows-static``: 32 bits version with static libraries load - - The vcpkg-triplet used will be named [vcpg-triplet] later in this document. - - - Init submodule and install vcpkg - - ``` - git submodule update --init vcpkg - cd vcpkg - .\bootstrap-vcpkg.bat - ``` - - Note: - > all vcpkg command further described must be run from vcpkg folder. This folder will be named [vcpkg_root] later in this document. +OR-Tools may be installed in one of 2 ways: + +1. **As a pre-compiled dependency** + + You can [download](https://github.com/rte-france/or-tools/releases) a precompiled OR-Tools archive that contains headers & static libraries. + Please note that dynamic linking with OR-Tools is only supported in Linux. - - Install dependencies - ``` - cd vcpkg - vcpkg install wxwidgets boost-test --triplet [vcpg-triplet] - ``` + Decompress the archive, and provide its path as a `CMAKE_PREFIX_PATH`. + +2. **As part of the build** + + You may enable the `BUILD_ORTOOLS` configuration option to build it from source during Antares build, + as documented in [build instructions](3-Build.md). + + The drawback of this second approach is that OR-Tools may need to be built again when you + run again a cmake configure step, therefore it's not advised for developers. + + +## Linux: libuuid and wxWidgets + +On Linux systems, libuuid development packages need to be installed with your +OS package manager. +You will also need to install wxWidgets if you want to build the GUI. + === "Centos" ``` - sudo yum install git redhat-lsb-core gcc gcc-c++ make wget centos-release-scl scl-utils rpm-build - sudo yum install cmake3 devtoolset-9 - sudo yum install libuuid-devel unzip wxGTK3-devel boost-test boost-devel + sudo yum install libuuid-devel + sudo yum install wxGTK3-devel ``` + === "Ubuntu 20.04 or 22.04 / Debian 11" ``` - sudo apt install uuid-dev libwxgtk3.0-gtk3-dev - sudo apt install libboost-test-dev + sudo apt install uuid-dev + sudo apt install libwxgtk3.0-gtk3-dev ``` === "Ubuntu 23.04 / Debian 12" ``` - sudo apt install uuid-dev libwxgtk3.2-dev libboost-test-dev + sudo apt install uuid-dev + sudo apt install libwxgtk3.2-dev ``` - -## Automatic libraries compilation from sources -[The Antares dependencies compilation repository](https://github.com/AntaresSimulatorTeam/antares-deps) is a submodule that can be used for automatic libraries compilation from sources. - -Apart from OR-Tools, all dependencies can be built at configure time using the option `-DBUILD_ALL=ON` (`OFF` by default). -For a list of available options, see [the Antares dependencies compilation repository](https://github.com/AntaresSimulatorTeam/antares-deps). - -You can set `-DBUILD_ORTOOLS=ON` to download & build OR-Tools. It is also possible to use a precompiled archive, see below. - -For compiling the package yourself from git, additional build dependencies are needed (see [here](1-Development-requirements.md)). - -### Pre-compiled OR-Tools: release+static only -You can [download](https://github.com/rte-france/or-tools/releases) a precompiled OR-Tools archive that contains headers & static libraries. - -Please note that dynamic linking with OR-Tools is only supported in Linux. - -Decompress the archive, and provide its path as a `CMAKE_PREFIX_PATH`. If you use XPRESS, you may need also to specify `XPRESS_ROOT`. - -### Defining dependency install directory -When using multiple directories for Antares development with multiple branches, it can be useful to have a common dependency install directory. - -Dependency install directory can be specified with `DEPS_INSTALL_DIR`. By default, install directory is `/../rte-antares-deps-` - -Note: -> `DEPS_INSTALL_DIR` is added to `CMAKE_PREFIX_PATH` - -### Pre-compiled libraries download: release version only -You can download a pre-compiled antares-deps archive from [Antares dependencies compilation repository][antares-deps-url]. Only release versions are available. - -Note: -> For Windows, you must you use a MSVC version compatible with the MSVC version used in the GitHub Action that made the release. - -[antares-deps-url]: https://github.com/AntaresSimulatorTeam/antares-deps/releases - diff --git a/docs/developer-guide/3-Build.md b/docs/developer-guide/3-Build.md index 14f7ccdbe3..860c9f47cb 100644 --- a/docs/developer-guide/3-Build.md +++ b/docs/developer-guide/3-Build.md @@ -1,69 +1,77 @@ # Build -Before build, make sure that dependencies are [installed](2-Dependencies-install.md). -## Environment settings -On CentOS, enable `devtoolset-9` and `rh-git227`: -``` -scl enable devtoolset-9 bash -source /opt/rh/rh-git227/enable -``` -## Update git submodule -``` -git submodule update --init src/antares-deps -``` -> 💡 **Ignore submodules to make git operations faster** -> Antares_Simulator is quite a large project, with a few large submodules. In file .git/config, you can add this line to all [submodule] sections -> ``` -> ignore = all -> ``` -> This way git won't waste time computing diff on these when checking out, diffing commits, etc. git operations should be a lot faster. -> Keep in mind that your submodules won't be updated. +Before building, make sure that dependencies are [installed](2-Dependencies-install.md). + +## Install VCPKG + +Although you may install third party dependencies yourself, the preferred way is +to rely on [vcpkg](https://github.com/microsoft/vcpkg) and its CMake integration +to build and install most of them. + +The first step will be to install VCPKG using its bootstrap script: -## Configure build with CMake === "Windows" ``` - cmake -B _build -S [antares_src] -DVCPKG_ROOT=[vcpkg_root] -DVCPKG_TARGET_TRIPLET=[vcpkg-triplet] -DCMAKE_BUILD_TYPE=release + git submodule update --init vcpkg + cd vcpkg + .\bootstrap-vcpkg.bat ``` - > **Note:** cpack NSIS installer creation needs an 'out-of-source build'. The build directory must be outside `[antares_src]` directory -=== "CentOS" +=== "Linux" ``` - cmake3 -B _build -S [antares_src] -DCMAKE_BUILD_TYPE=release + git submodule update --init vcpkg + cd vcpkg + ./bootstrap-vcpkg.sh ``` -=== "Ubuntu/Debian" + +## Configure build with CMake + +The preferred way of building the project is to use a pre-compiled version of OR-Tools and to install +other dependencies using vcpkg. To achieve this, you will need to define VCPKG-related variables, +and add your OR-tools install path to `CMAKE_PREFIX_PATH`: + + +=== "Windows" ``` - cmake -B _build -S [antares_src] -DCMAKE_BUILD_TYPE=release + cmake -B _build -S src -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_TARGET_TRIPLET=x64-windows-antares \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH= + ``` + + > **Note:** cpack NSIS installer creation needs an 'out-of-source build'. The build directory must be outside `src` directory + + +=== "Linux" + + ``` + cmake -B _build -S src -DCMAKE_TOOLCHAIN_FILE=../vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_TARGET_TRIPLET=x64-linux-antares \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH= ``` Here is a list of mandatory or optional CMake configuration options: -| Option | Mandatory | Description | Expected value | Default value | -|:----------------------|-----------|----------------------------------------------------------------------------------|----------------------------------------|-----------------------------------------------------------| -| `CMAKE_C_COMPILER` | **yes** | Select C compiler | `gcc_-10` | | -| `CMAKE_CXX_COMPILER` | **yes** | Select C++ compiler | `g++-10` | | -| `CMAKE_BUILD_TYPE` | **yes** | Define build type | `Release` / `Debug` / `RelWithDebInfo` | | -| `BUILD_UI` | no | Enable or disable Antares Simulator UI[^1] compilation | `ON` / `OFF` | `ON` | -| `BUILD_ALL` | no | Enable build of ALL external libraries | `ON` / `OFF` | `OFF` | -| `DEPS_INSTALL_DIR` | no | Define dependencies libraries install directory | absolute path to an existing directory | `/../rte-antares-deps-` | -| `USE_PRECOMPILED_EXT` | no | This option must be set if you use wxWidget as precompiled external library | `ON` / `OFF` | `OFF` | -| `BUILD_TESTING` | no | Enable build for unit tests | `ON` / `OFF` | `OFF` | -| `BUILD_ORTOOLS` | no | Enable build for OR-Tools and its dependencies (requires an Internet connection) | `ON` / `OFF` | `OFF` | +| Option | Mandatory | Description | Expected value | Default value | +|:-----------------------|--------------|----------------------------------------------------------------------------------|---------------------------------------------|-----------------------------------------------------------| +| `CMAKE_C_COMPILER` | OS-dependent | Select C compiler | `gcc-10` | | +| `CMAKE_CXX_COMPILER` | OS-dependent | Select C++ compiler | `g++-10` | | +| `CMAKE_BUILD_TYPE` | **yes** | Define build type | `Release` / `Debug` / `RelWithDebInfo` | | +| `BUILD_UI` | no | Enable or disable Antares Simulator UI[^1] compilation | `ON` / `OFF` | `ON` | +| `BUILD_TESTING` | no | Enable build for unit tests | `ON` / `OFF` | `OFF` | +| `BUILD_ORTOOLS` | no | Enable build for OR-Tools and its dependencies (requires an Internet connection) | `ON` / `OFF` | `OFF` | +| `CMAKE_TOOLCHAIN_FILE` | no | Path to VCPKG toolchain file, allows to integrate VCPKG with cmake build | `../vcpkg/scripts/buildsystems/vcpkg.cmake` | | +| `VCPKG_TARGET_TRIPLET` | no | Define VCPKG triplet (build type for dependencies etc.) | `x64-windows-antares` / `x64-linux-antares` | | > 💡 **Disable the UI build to make builds faster** > The UI takes up a good chunk of compilation time. It is enabled by default, but you can disable it by turning off `BUILD_UI` -Additional options for Windows: - -| Option | Description | -|:-----------------------|------------------------| -| `VCPKG_ROOT` | Define vcpkg directory | -| `VCPKG_TARGET_TRIPLET` | Define [vcpkg-triplet] | - > 💡 **Use Ninja to speed up target generation by CMake** -> At configure time, you may specify Ninja for generation instead of traditional Make. This will speed up the update +> At configure time, you may specify Ninja for generation instead of traditional Make. This will speed up the update > step after you make small changes to the code. > ``` > cmake -S src [...] -G Ninja @@ -74,17 +82,17 @@ Additional options for Windows: === "Windows" ``` - cmake --build _build --config release -j8 + cmake --build _build --config Release -j8 ``` === "CentOS" ``` - cmake3 --build _build --config release -j8 + cmake3 --build _build -j8 ``` === "Ubuntu/Debian" ``` - cmake --build _build --config release -j8 + cmake --build _build -j8 ``` > 💡 Compilation can be done on several processors with `-j` option. @@ -92,4 +100,24 @@ Additional options for Windows: The final GUI file can be executed at `_build/ui/simulator/antares-X.Y-ui-simulator` +## Developer tips + +### Use a compiler cache +In order to avoid unnecessary rebuilds, for example when you switch branches, you may use a compiler cache +such as ccache. Using it under Linux systems is pretty easy with CMake, you only need to specify it +as the compiler launcher at configure time: +``` +cmake ... -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache ... +``` + +### Ignore submodules to make git operations faster +Antares_Simulator is quite a large project, with a few large submodules. In file .git/config, you can add this line to all [submodule] sections +``` +ignore = all +``` +This way git won't waste time computing diff on these when checking out, diffing commits, etc. git operations should be a lot faster. +Keep in mind that your submodules won't be updated. + + + [^1]: GUI support has been dropped in favor of [Antares Web](https://antares-web.readthedocs.io) \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 763c40cb96..51fdc67271 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -196,69 +196,15 @@ if (${BUILD_MERSENNE_TWISTER_PYBIND11}) find_package(pybind11 REQUIRED) endif() -#Define install directory -if (NOT DEPS_INSTALL_DIR) - SET(DEPS_INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../rte-antares-deps-${CMAKE_BUILD_TYPE}) - -else() - if(NOT IS_ABSOLUTE ${DEPS_INSTALL_DIR}) - SET(DEPS_INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../${DEPS_INSTALL_DIR}) - endif() -endif() - - -# Add DEPS_INSTALL_DIR with antares-xpansion CMAKE_BUILD_TYPE -if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") - - string(REPLACE ${CMAKE_BUILD_TYPE} Release - DEPS_INSTALL_DIR_XPANSION - ${DEPS_INSTALL_DIR}) - - list(APPEND CMAKE_PREFIX_PATH ${DEPS_INSTALL_DIR_XPANSION}) - -elseif("${CMAKE_BUILD_TYPE}" STREQUAL "debug") - - string(REPLACE ${CMAKE_BUILD_TYPE} Debug - DEPS_INSTALL_DIR_XPANSION - ${DEPS_INSTALL_DIR}) - - list(APPEND CMAKE_PREFIX_PATH ${DEPS_INSTALL_DIR_XPANSION}) - -endif() - -list(APPEND CMAKE_PREFIX_PATH ${DEPS_INSTALL_DIR}) -message(STATUS "CMAKE_PREFIX_PATH : ${CMAKE_PREFIX_PATH}") - -# Build Needed dependencies -add_subdirectory(antares-deps) - -#Add needed definition in case of external dependencies compilation -include (antares-deps/cmake/additionnal-definitions.cmake) - #Boost header libraries find_package(Boost REQUIRED) -#TODO : Add ZLIB if VCPKG used why is this needed -if (VCPKG_TOOLCHAIN) - #zlib - find_package(ZLIB REQUIRED) -endif() - #Sirius solver if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) endif() -if (VCPKG_TOOLCHAIN) - list(APPEND CMAKE_PREFIX_PATH "${sirius_solver_ROOT}") - list(APPEND CMAKE_PREFIX_PATH "${ortools_ROOT}") -endif() - -find_package(sirius_solver) - -if (NOT sirius_solver_FOUND) - message (FATAL_ERROR "Sirius solver not found. Sirius solver can be compiled with -DBUILD_sirius=ON or you can specify previous dependency install directory with -DCMAKE_PREFIX_PATH or -DDEPS_INSTALL_DIR") -endif() +find_package(sirius_solver REQUIRED) find_package(ortools) if(NOT ortools_FOUND OR BUILD_ORTOOLS) @@ -298,7 +244,6 @@ else () endif () endif () - #wxWidget not needed for all library find is done in ui CMakeLists.txt if (VCPKG_TOOLCHAIN AND NOT BUILD_wxWidgets) #Add cmake directory to CMAKE_MODULE_PATH to use specific FindwxWidgets package needed for vcpkg diff --git a/src/antares-deps b/src/antares-deps deleted file mode 160000 index 0d6bebfb90..0000000000 --- a/src/antares-deps +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 0d6bebfb901e47ec6ac1c73cb61a522803c81b98 diff --git a/src/ports/sirius-solver/portfile.cmake b/src/ports/sirius-solver/portfile.cmake new file mode 100644 index 0000000000..30cce62622 --- /dev/null +++ b/src/ports/sirius-solver/portfile.cmake @@ -0,0 +1,21 @@ +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO "rte-france/sirius-solver" + REF "antares-integration-v1.4" + SHA512 1eecb351b32490a82a2f93bf91e77ea4fd55cffc92c466b4136314e70d8a70328e4fda5257a46c08c431fd7013475050bc3908fcedee4fbdd746ed1ab6cb0efd + HEAD_REF main +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}/src" +) + +vcpkg_cmake_install() + +vcpkg_cmake_config_fixup(PACKAGE_NAME sirius_solver CONFIG_PATH cmake) + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/include") + +vcpkg_copy_pdbs() + +file(INSTALL "${SOURCE_PATH}/LICENSE.TXT" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) diff --git a/src/ports/sirius-solver/vcpkg.json b/src/ports/sirius-solver/vcpkg.json new file mode 100644 index 0000000000..8e4a0a36df --- /dev/null +++ b/src/ports/sirius-solver/vcpkg.json @@ -0,0 +1,16 @@ +{ + "name": "sirius-solver", + "version": "1.4", + "port-version": 0, + "description": "Sirius solver", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 0c8f846f96..8bb000564a 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -1,9 +1,4 @@ - -if (USE_PRECOMPILED_EXT AND UNIX) - set (wxWidgets_CONFIG_EXECUTABLE ${DEPS_INSTALL_DIR}/bin/wx-config) -endif() - #wxWidget required find_package(wxWidgets REQUIRED COMPONENTS net core base richtext propgrid aui adv html xml) include(${wxWidgets_USE_FILE}) diff --git a/src/vcpkg.json b/src/vcpkg.json index f15f208a42..011ede41ad 100644 --- a/src/vcpkg.json +++ b/src/vcpkg.json @@ -3,11 +3,17 @@ "version-string": "9.1.0", "builtin-baseline": "9484a57dd560b89f0a583be08af6753611c57fd5", "vcpkg-configuration": { + "overlay-ports": [ + "./ports" + ], "overlay-triplets": [ "./triplets" ] }, "dependencies": [ + { + "name": "sirius-solver" + }, { "name": "wxwidgets", "platform": "windows" From f485d5245a061b73e9d5cd26a03eac551b8d4365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jason=20Mar=C3=A9chal?= <45510813+JasonMarechal25@users.noreply.github.com> Date: Thu, 6 Jun 2024 13:27:19 +0200 Subject: [PATCH 02/13] Remove extra caching vcpkg (#2145) --- .github/workflows/ubuntu.yml | 530 +++++++++++++++++------------------ 1 file changed, 254 insertions(+), 276 deletions(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 2bcf2954a0..c774854d16 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -47,287 +47,265 @@ jobs: if: "!contains(github.event.head_commit.message, '[skip ci]')" steps: - - uses: actions/checkout@v4 - with: - ref: ${{ env.REF }} - - - name: Install VCPKG - run: git submodule update --init vcpkg && ./vcpkg/bootstrap-vcpkg.sh -disableMetrics - - - name: Restore vcpkg binary dir from cache - id: cache-vcpkg-binary - uses: actions/cache/restore@v4 - with: - path: ${{ github.workspace }}/vcpkg_cache - key: vcpkg-cache-ubuntu-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} - # Allows to restore a cache when deps have only partially changed (like adding a dependency) - restore-keys: vcpkg-cache-ubuntu- - - - name: ccache - uses: hendrikmuhs/ccache-action@v1.2 - with: + - uses: actions/checkout@v4 + with: + ref: ${{ env.REF }} + + - name: Install VCPKG + run: git submodule update --init vcpkg && ./vcpkg/bootstrap-vcpkg.sh -disableMetrics + + - name: Restore vcpkg binary dir from cache + id: cache-vcpkg-binary + uses: actions/cache/restore@v4 + with: + path: ${{ github.workspace }}/vcpkg_cache + key: vcpkg-cache-ubuntu-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} + # Allows to restore a cache when deps have only partially changed (like adding a dependency) + restore-keys: vcpkg-cache-ubuntu- + + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: key: ${{ env.os }} - - name : Init VCPKG submodule - run: | - git submodule update --init vcpkg - - # Restore both vcpkg and its artifacts from the GitHub cache service. - - name: Restore vcpkg and its artifacts. - uses: actions/cache@v4 - with: - # The first path is the location of vcpkg (it contains the vcpkg executable and data files). - # The other paths starting with '!' are exclusions: they contain termporary files generated during the build of the installed packages. - path: | - ${{ env.VCPKG_ROOT }} - !${{ env.VCPKG_ROOT }}/buildtrees - !${{ env.VCPKG_ROOT }}/packages - !${{ env.VCPKG_ROOT }}/downloads - # The key is composed in a way that it gets properly invalidated: this must happen whenever vcpkg's Git commit id changes, or the list of packages changes. In this case a cache miss must happen and a new entry with a new key with be pushed to GitHub the cache service. - # The key includes: hash of the vcpkg.json file, the hash of the vcpkg Git commit id, and the used vcpkg's triplet. The vcpkg's commit id would suffice, but computing an hash out it does not harm. - # Note: given a key, the cache content is immutable. If a cache entry has been created improperly, in order the recreate the right content the key must be changed as well, and it must be brand new (i.e. not existing already). - key: | - ${{ hashFiles( 'vcpkg_manifest/vcpkg.json' ) }}-${{ hashFiles( '.git/modules/vcpkg/HEAD' )}}-${{ env.triplet }} - - - name: Install libraries - run: | - sudo apt-get update - sudo apt-get install uuid-dev libwxgtk3.0-gtk3-dev - sudo apt-get install g++-10 gcc-10 - - - name: Config OR-Tools URL - run: | + - name: Install libraries + run: | + sudo apt-get update + sudo apt-get install uuid-dev libwxgtk3.0-gtk3-dev + sudo apt-get install g++-10 gcc-10 + + - name: Config OR-Tools URL + run: | echo "ORTOOLS_URL=https://github.com/rte-france/or-tools/releases/download/$(cat ortools_tag)/ortools_cxx_ubuntu-20.04_static_sirius.zip" >> $GITHUB_ENV - - name: Download pre-compiled librairies - uses: ./.github/workflows/download-extract-precompiled-libraries-tgz - with: - os: ${{env.os}} - ortools-url: ${{env.ORTOOLS_URL}} - ortools-dir: ${{env.ORTOOLS_DIR}} - - - name: Set up Python - id: setup-python - uses: actions/setup-python@v5 - with: - python-version: '3.12' - - - name: Install dependencies - run: | + - name: Download pre-compiled librairies + uses: ./.github/workflows/download-extract-precompiled-libraries-tgz + with: + os: ${{env.os}} + ortools-url: ${{env.ORTOOLS_URL}} + ortools-dir: ${{env.ORTOOLS_DIR}} + + - name: Set up Python + id: setup-python + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install dependencies + run: | python -m pip install --upgrade pip pip3 install -r src/tests/examples/requirements.txt - - name: Init submodule - run: | + - name: Configure + run: | + cmake -B _build -S src \ + -DCMAKE_C_COMPILER_LAUNCHER=ccache \ + -DCMAKE_C_COMPILER=/usr/bin/gcc-10 \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_CXX_COMPILER=/usr/bin/g++-10 \ + -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake \ + -DVCPKG_TARGET_TRIPLET=x64-linux-release \ + -DCMAKE_BUILD_TYPE=Release \ + -DBUILD_TESTING=ON \ + -DBUILD_TOOLS=ON \ + -DCMAKE_PREFIX_PATH=${{ env.ORTOOLS_DIR }}/install \ + -DPython3_EXECUTABLE="${{ env.Python3_ROOT_DIR }}/bin/python" + + - name: Build + run: | + cmake --build _build -j$(nproc) + + # simtest + - name: Read simtest version + id: simtest-version + uses: notiz-dev/github-action-json-property@release + with: + path: 'simtest.json' + prop_path: 'version' + + - name: Init submodule + run: | git submodule update --init --remote --recursive src/tests/resources/Antares_Simulator_Tests - - - name: Configure - run: | - cmake -B _build -S src \ - -DCMAKE_C_COMPILER_LAUNCHER=ccache \ - -DCMAKE_C_COMPILER=/usr/bin/gcc-10 \ - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ - -DCMAKE_CXX_COMPILER=/usr/bin/g++-10 \ - -DCMAKE_TOOLCHAIN_FILE=${{ github.workspace }}/vcpkg/scripts/buildsystems/vcpkg.cmake \ - -DVCPKG_TARGET_TRIPLET=x64-linux-release \ - -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTING=ON \ - -DBUILD_TOOLS=ON \ - -DCMAKE_PREFIX_PATH=${{ env.ORTOOLS_DIR }}/install \ - -DPython3_EXECUTABLE="${{ env.Python3_ROOT_DIR }}/bin/python" - - - name: Build - run: | - cmake --build _build -j$(nproc) - - # simtest - - name: Read simtest version - id: simtest-version - uses: notiz-dev/github-action-json-property@release - with: - path: 'simtest.json' - prop_path: 'version' - - - - name: Run named mps tests - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: valid-named-mps - os: ${{ env.os }} - variant: "named-mps" - - - name: Run unfeasibility-related tests - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - run: | - cd _build - ctest -C Release --output-on-failure -R "^unfeasible$" - - - name: Run unit and end-to-end tests - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - run: | - cd _build - ctest -C Release --output-on-failure -L "unit|end-to-end" - - - name: Upload logs for failed tests - if: ${{ failure() }} - uses: actions/upload-artifact@v4 - 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' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: valid-v830 - os: ${{ env.os }} - - - name: Run MILP with CBC - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: valid-milp - variant: "milp-cbc" - os: ${{ env.os }} - - - name: Run tests introduced in v860 - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: valid-v860 - os: ${{ env.os }} - - - name: Run tests introduced in v870 - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: valid-v870 - os: ${{ env.os }} - - - name: Run tests introduced in v910 - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: valid-v910 - os: ${{ env.os }} - - - name: Run short-tests - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: short-tests - os: ${{ env.os }} - - - name: Run mps tests - if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: valid-mps - os: ${{ env.os }} - - - name: Run tests for 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 medium-tests - if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: medium-tests - os: ${{ env.os }} - - - name: Run long-tests-1 - if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: long-tests-1 - os: ${{ env.os }} - - - name: Run long-tests-2 - if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: long-tests-2 - os: ${{ env.os }} - - - name: Run long-tests-3 - if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} - uses: ./.github/workflows/run-tests - with: - simtest-tag: ${{steps.simtest-version.outputs.prop}} - batch-name: long-tests-3 - os: ${{ env.os }} - - - name: Installer .deb creation - run: | - cd _build - cpack -G DEB - - - name: .tar.gz creation - run: | - cd _build - cpack -G TGZ - - - name: Solver archive creation - run: | - cd _build - cmake --install . --prefix install - pushd . - cd install/bin - tar czf ../../antares-solver_ubuntu20.04.tar.gz antares-solver libsirius_solver.so - popd - rm -rf install - - - name: Installer archive upload push - uses: actions/upload-artifact@v4 - with: - name: targz - path: _build/*.tar.gz - - - name: Installer deb upload push - uses: actions/upload-artifact@v4 - with: - name: deb - path: _build/*.deb - - - - name: Publish assets - if: ${{ env.IS_RELEASE == 'true' }} - env: - GITHUB_TOKEN: ${{ github.token }} - tag: ${{ github.event.inputs.release_tag }} - run: | - gh release upload "$tag" _build/*.tar.gz _build/*.deb - - - name: Cache vcpkg binary dir - if: always() - id: save-cache-vcpkg-binary - uses: actions/cache/save@v4 - with: - path: ${{ github.workspace }}/vcpkg_cache - key: vcpkg-cache-ubuntu-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} + + - name: Run named mps tests + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-named-mps + os: ${{ env.os }} + variant: "named-mps" + + - name: Run unfeasibility-related tests + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + run: | + cd _build + ctest -C Release --output-on-failure -R "^unfeasible$" + + - name: Run unit and end-to-end tests + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + run: | + cd _build + ctest -C Release --output-on-failure -L "unit|end-to-end" + + - name: Upload logs for failed tests + if: ${{ failure() }} + uses: actions/upload-artifact@v4 + 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' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-v830 + os: ${{ env.os }} + + - name: Run MILP with CBC + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-milp + variant: "milp-cbc" + os: ${{ env.os }} + + - name: Run tests introduced in v860 + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-v860 + os: ${{ env.os }} + + - name: Run tests introduced in v870 + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-v870 + os: ${{ env.os }} + + - name: Run tests introduced in v910 + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-v910 + os: ${{ env.os }} + + - name: Run short-tests + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: short-tests + os: ${{ env.os }} + + - name: Run mps tests + if: ${{ env.RUN_SIMPLE_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: valid-mps + os: ${{ env.os }} + + - name: Run tests for 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 medium-tests + if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: medium-tests + os: ${{ env.os }} + + - name: Run long-tests-1 + if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: long-tests-1 + os: ${{ env.os }} + + - name: Run long-tests-2 + if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: long-tests-2 + os: ${{ env.os }} + + - name: Run long-tests-3 + if: ${{ env.RUN_EXTENDED_TESTS == 'true' }} + uses: ./.github/workflows/run-tests + with: + simtest-tag: ${{steps.simtest-version.outputs.prop}} + batch-name: long-tests-3 + os: ${{ env.os }} + + - name: Installer .deb creation + run: | + cd _build + cpack -G DEB + + - name: .tar.gz creation + run: | + cd _build + cpack -G TGZ + + - name: Solver archive creation + run: | + cd _build + cmake --install . --prefix install + pushd . + cd install/bin + tar czf ../../antares-solver_ubuntu20.04.tar.gz antares-solver libsirius_solver.so + popd + rm -rf install + + - name: Installer archive upload push + uses: actions/upload-artifact@v4 + with: + name: targz + path: _build/*.tar.gz + + - name: Installer deb upload push + uses: actions/upload-artifact@v4 + with: + name: deb + path: _build/*.deb + + + - name: Publish assets + if: ${{ env.IS_RELEASE == 'true' }} + env: + GITHUB_TOKEN: ${{ github.token }} + tag: ${{ github.event.inputs.release_tag }} + run: | + gh release upload "$tag" _build/*.tar.gz _build/*.deb + + - name: Cache vcpkg binary dir + if: always() + id: save-cache-vcpkg-binary + uses: actions/cache/save@v4 + with: + path: ${{ github.workspace }}/vcpkg_cache + key: vcpkg-cache-ubuntu-${{ hashFiles('src/vcpkg.json', '.git/modules/vcpkg/HEAD') }} From a5398197a81a3290942644efba720a63cad4734b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Thu, 6 Jun 2024 14:25:43 +0200 Subject: [PATCH 03/13] Use constexpr instead of enum to eliminate warnings (#2144) --- .../include/antares/solver/variable/constants.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/solver/variable/include/antares/solver/variable/constants.h b/src/solver/variable/include/antares/solver/variable/constants.h index 89f9dcf70e..cea6298346 100644 --- a/src/solver/variable/include/antares/solver/variable/constants.h +++ b/src/solver/variable/include/antares/solver/variable/constants.h @@ -27,16 +27,13 @@ namespace Solver { namespace Variable { -enum Constant -{ - maxHoursInAYear = 8785, - maxDaysInAYear = 7 * 53 + 1, // 366, - maxWeeksInAYear = 53, - maxHoursInADay = 24, - maxMonths = 12, - maxDaysInAWeek = 7, - maxHoursInAWeek = 24 * 7, // 168, -}; +constexpr unsigned int maxHoursInAYear = 8785; +constexpr unsigned int maxDaysInAYear = 7 * 53 + 1; // 366, +constexpr unsigned int maxWeeksInAYear = 53; +constexpr unsigned int maxHoursInADay = 24; +constexpr unsigned int maxMonths = 12; +constexpr unsigned int maxDaysInAWeek = 7; +constexpr unsigned int maxHoursInAWeek = 24 * 7; // 168 template struct PrecisionToPrintfFormat From a89c067326ab7be40442c33174ab4b9d1d58a898 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Thu, 6 Jun 2024 17:12:36 +0200 Subject: [PATCH 04/13] Fix changelog for v9.1.0 (#2146) Most of the contents for v9.1.0 were under section 8.8.3 --------- Co-authored-by: abdoulbari zaher <32519851+a-zakir@users.noreply.github.com> --- docs/developer-guide/CHANGELOG.md | 84 +++++++++++++++---------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/docs/developer-guide/CHANGELOG.md b/docs/developer-guide/CHANGELOG.md index 67aa64da57..d6606547da 100644 --- a/docs/developer-guide/CHANGELOG.md +++ b/docs/developer-guide/CHANGELOG.md @@ -10,51 +10,8 @@ toc_depth: 2 * Scenarized & hourly values for hydro pumping and hydro generation. Previously this data was not scenarized and daily. * STS groups are now "dynamic" : group names are no longer fixed by code, user is free to define these groups. * Add optimization options from command line in OR-Tools / XPRESS (#1837) -#### TODO - -## Branch 9.0.x - -### 9.0.0 -#### License -* Use licence MPL 2.0 instead of GPL3_WITH_RTE-Exceptions (#1812) - -#### Improvements -* Include overflow variable in HydroPower constraint (#1903) -* Add total time logging at the end of the simulation (#1908) -* Add STS level constraint to suspect list for infeasible problem analysis (#1891) - -#### For developers -* Use precompiled OR-Tools for Oracle Linux 8 CI (#1893) -* Change version behavior to allow more flexibility (#1898) - -#### Code quality -* Use std::shared_ptr instead of indices for active binding constraints in results (#1887) -* Fix a few compilation warnings (#1880) -* Scratchpad numspace (#1749) - -#### Tests -* Fix invalid index causing segfault in `test-study` test (#1902) - -## Branch 8.8.x (end of support 12/2025) - -### 8.8.5 (05/2024) -#### Bugfix -- [UI] Fix opening a study from the file browser -- Fix crash occurring when duplicate thermal clusters are present in a study (same name) -- Fix formula for "PROFIT BY PLANT" - -### 8.8.4 (03/2024) -#### Bugfix -* Adequacy patch CSR - fix DTG MRG (#1982) -* Fix ts numbers for no gen clusters (#1969) -* Remove unitcount limit for time series generation (#1960) - -### 8.8.3 (02/2024) -#### Bugfix -* Fix an issue where depending on the platform the output archive could contain several entries of the same area and inrco files #### Improvements -* Remove sc-builder prefix "hgp", use "h" instead for max hydro pumping & generation timeseries. * Rationalize consistency checks on the number of columns (#2073) * Documentation reorganization and improvement (#2024) (#2023) (#2022) * Add doc for thermal heuristic (#2048) @@ -102,6 +59,47 @@ toc_depth: 2 * Remove deps-build Actions (#2043) * Remove unused logs.hxx (#2026) +## Branch 9.0.x + +### 9.0.0 +#### License +* Use licence MPL 2.0 instead of GPL3_WITH_RTE-Exceptions (#1812) + +#### Improvements +* Include overflow variable in HydroPower constraint (#1903) +* Add total time logging at the end of the simulation (#1908) +* Add STS level constraint to suspect list for infeasible problem analysis (#1891) + +#### For developers +* Use precompiled OR-Tools for Oracle Linux 8 CI (#1893) +* Change version behavior to allow more flexibility (#1898) + +#### Code quality +* Use std::shared_ptr instead of indices for active binding constraints in results (#1887) +* Fix a few compilation warnings (#1880) +* Scratchpad numspace (#1749) + +#### Tests +* Fix invalid index causing segfault in `test-study` test (#1902) + +## Branch 8.8.x (end of support 12/2025) + +### 8.8.5 (05/2024) +#### Bugfix +- [UI] Fix opening a study from the file browser +- Fix crash occurring when duplicate thermal clusters are present in a study (same name) +- Fix formula for "PROFIT BY PLANT" + +### 8.8.4 (03/2024) +#### Bugfix +* Adequacy patch CSR - fix DTG MRG (#1982) +* Fix ts numbers for no gen clusters (#1969) +* Remove unitcount limit for time series generation (#1960) + +### 8.8.3 (02/2024) +#### Bugfix +* Fix an issue where depending on the platform the output archive could contain several entries of the same area and interco files + ### 8.8.2 #### Bugfix * Fix segfault caused by uninitialized `cluster.series.timeseriesNumbers` (#1876). This bug was introduced in v8.8.1 by #1752 From 8d6cdc4156357f630babc524ffb49612704f6306 Mon Sep 17 00:00:00 2001 From: guilpier-code <62292552+guilpier-code@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:08:52 +0200 Subject: [PATCH 05/13] Remove state from hydro ventilation (#2143) **State** type is passed to the hydro ventilation. The object **state** is used by the hydro ventilation to reach the weekly optimization problem, in order to update the hydro initial level of a MC year. This important update is hidden in the depth of the code whereas it should be more highlighted (when a year starts). Furthermore, removing state alleviates a bit the hydro ventilation, already too complicated. Eventually, removing dependency of class **HydroManagement** to **State** allows to : - highlight the update of hydro initial level when beginning a year - loose a dependency to **State** --- .../solver/hydro/management/management.h | 7 ++----- src/solver/hydro/management/daily.cpp | 17 +++++------------ src/solver/hydro/management/management.cpp | 3 +-- src/solver/simulation/adequacy.cpp | 1 + src/solver/simulation/common-eco-adq.cpp | 17 +++++++++++++++++ src/solver/simulation/economy.cpp | 1 + .../antares/solver/simulation/common-eco-adq.h | 4 ++++ .../antares/solver/simulation/solver.hxx | 1 - 8 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/solver/hydro/include/antares/solver/hydro/management/management.h b/src/solver/hydro/include/antares/solver/hydro/management/management.h index 29f64fbd93..78f3d4e6ea 100644 --- a/src/solver/hydro/include/antares/solver/hydro/management/management.h +++ b/src/solver/hydro/include/antares/solver/hydro/management/management.h @@ -112,7 +112,6 @@ class HydroManagement final //! Perform the hydro ventilation void makeVentilation(double* randomReservoirLevel, - Solver::Variable::State& state, uint y, Antares::Data::Area::ScratchMap& scratchmap); @@ -152,12 +151,10 @@ class HydroManagement final // \return The total inflow for the whole year double prepareMonthlyTargetGenerations(Data::Area& area, TmpDataByArea& data); - void prepareDailyOptimalGenerations(Solver::Variable::State& state, - uint y, + void prepareDailyOptimalGenerations(uint y, Antares::Data::Area::ScratchMap& scratchmap); - void prepareDailyOptimalGenerations(Solver::Variable::State& state, - Data::Area& area, + void prepareDailyOptimalGenerations(Data::Area& area, uint y, Antares::Data::Area::ScratchMap& scratchmap); diff --git a/src/solver/hydro/management/daily.cpp b/src/solver/hydro/management/daily.cpp index 649de96f5d..8391b523d0 100644 --- a/src/solver/hydro/management/daily.cpp +++ b/src/solver/hydro/management/daily.cpp @@ -40,7 +40,6 @@ #include "antares/solver/hydro/daily2/h2o2_j_fonctions.h" #include "antares/solver/hydro/management/management.h" #include "antares/solver/simulation/sim_extern_variables_globales.h" -#include "antares/solver/variable/state.h" using namespace Yuni; @@ -220,10 +219,9 @@ struct DebugData }; inline void HydroManagement::prepareDailyOptimalGenerations( - Solver::Variable::State& state, - Data::Area& area, - uint y, - Antares::Data::Area::ScratchMap& scratchmap) + Data::Area& area, + uint y, + Antares::Data::Area::ScratchMap& scratchmap) { const auto srcinflows = area.hydro.series->storage.getColumn(y); @@ -546,10 +544,6 @@ inline void HydroManagement::prepareDailyOptimalGenerations( H2O2_J_Free(problem); } - uint firstDaySimu = parameters_.simulationDays.first; - state.problemeHebdo->previousSimulationFinalLevel[area.index] - = ventilationResults.NiveauxReservoirsDebutJours[firstDaySimu] * reservoirCapacity; - if (debugData) { debugData->writeDailyDebugData(calendar_, initReservoirLvlMonth, y, area.name); @@ -557,11 +551,10 @@ inline void HydroManagement::prepareDailyOptimalGenerations( } } -void HydroManagement::prepareDailyOptimalGenerations(Solver::Variable::State& state, - uint y, +void HydroManagement::prepareDailyOptimalGenerations(uint y, Antares::Data::Area::ScratchMap& scratchmap) { areas_.each([&](Data::Area& area) - { prepareDailyOptimalGenerations(state, area, y, scratchmap); }); + { prepareDailyOptimalGenerations(area, y, scratchmap); }); } } // namespace Antares diff --git a/src/solver/hydro/management/management.cpp b/src/solver/hydro/management/management.cpp index 5d8fb79d47..fe9311280d 100644 --- a/src/solver/hydro/management/management.cpp +++ b/src/solver/hydro/management/management.cpp @@ -519,7 +519,6 @@ bool HydroManagement::checksOnGenerationPowerBounds(uint year) const } void HydroManagement::makeVentilation(double* randomReservoirLevel, - Solver::Variable::State& state, uint y, Antares::Data::Area::ScratchMap& scratchmap) { @@ -534,7 +533,7 @@ void HydroManagement::makeVentilation(double* randomReservoirLevel, prepareEffectiveDemand(); prepareMonthlyOptimalGenerations(randomReservoirLevel, y); - prepareDailyOptimalGenerations(state, y, scratchmap); + prepareDailyOptimalGenerations(y, scratchmap); } } // namespace Antares diff --git a/src/solver/simulation/adequacy.cpp b/src/solver/simulation/adequacy.cpp index 5d3a54b261..f4e7f433d7 100644 --- a/src/solver/simulation/adequacy.cpp +++ b/src/solver/simulation/adequacy.cpp @@ -136,6 +136,7 @@ bool Adequacy::year(Progression::Task& progression, currentProblem.year = state.year; PrepareRandomNumbers(study, currentProblem, randomForYear); + SetInitialHydroLevel(study, currentProblem, hydroVentilationResults); state.startANewYear(); diff --git a/src/solver/simulation/common-eco-adq.cpp b/src/solver/simulation/common-eco-adq.cpp index 8abcb0cb98..b413b632d5 100644 --- a/src/solver/simulation/common-eco-adq.cpp +++ b/src/solver/simulation/common-eco-adq.cpp @@ -395,6 +395,23 @@ void PrepareRandomNumbers(Data::Study& study, }); } + +void SetInitialHydroLevel(Data::Study& study, + PROBLEME_HEBDO& problem, + const HYDRO_VENTILATION_RESULTS& hydroVentilationResults) +{ + uint firstDaySimu = study.parameters.simulationDays.first; + study.areas.each([&](Data::Area& area) + { + if (area.hydro.reservoirManagement) + { + double capacity = area.hydro.reservoirCapacity; + problem.previousSimulationFinalLevel[area.index] = + hydroVentilationResults[area.index].NiveauxReservoirsDebutJours[firstDaySimu] * capacity; + } + }); +} + void BuildThermalPartOfWeeklyProblem(Data::Study& study, PROBLEME_HEBDO& problem, const int PasDeTempsDebut, diff --git a/src/solver/simulation/economy.cpp b/src/solver/simulation/economy.cpp index 558c4f2095..0ffdf71d7b 100644 --- a/src/solver/simulation/economy.cpp +++ b/src/solver/simulation/economy.cpp @@ -126,6 +126,7 @@ bool Economy::year(Progression::Task& progression, currentProblem.year = state.year; PrepareRandomNumbers(study, currentProblem, randomForYear); + SetInitialHydroLevel(study, currentProblem, hydroVentilationResults); state.startANewYear(); diff --git a/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h b/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h index 2110c4cbe9..14d260af09 100644 --- a/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h +++ b/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h @@ -56,6 +56,10 @@ void PrepareRandomNumbers(Data::Study& study, PROBLEME_HEBDO& problem, yearRandomNumbers& randomForYear); +void SetInitialHydroLevel(Data::Study& study, + PROBLEME_HEBDO& problem, + const HYDRO_VENTILATION_RESULTS& hydroVentilationResults); + void BuildThermalPartOfWeeklyProblem(Data::Study& study, PROBLEME_HEBDO& problem, const int PasDeTempsDebut, diff --git a/src/solver/simulation/include/antares/solver/simulation/solver.hxx b/src/solver/simulation/include/antares/solver/simulation/solver.hxx index 70d88c47af..dc2a7d4e09 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver.hxx +++ b/src/solver/simulation/include/antares/solver/simulation/solver.hxx @@ -172,7 +172,6 @@ public: // 4 - Hydraulic ventilation pDurationCollector("hydro_ventilation") << [&] { hydroManagement.makeVentilation(randomReservoirLevel, - state[numSpace], y, scratchmap); }; From a121c7571a4b6e7fed2904b325aa8127dd25261e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Mon, 10 Jun 2024 10:59:09 +0200 Subject: [PATCH 06/13] Add `/D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR` to fix segfault (#2151) --- src/cmake/common-settings.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmake/common-settings.cmake b/src/cmake/common-settings.cmake index b659a5f46c..23326f6158 100644 --- a/src/cmake/common-settings.cmake +++ b/src/cmake/common-settings.cmake @@ -11,7 +11,7 @@ if (NOT WIN32) set(COMMON_GCC_FLAGS "${COMMON_GCC_FLAGS} -Werror=return-type") endif() set(COMMON_MSVC_FLAGS "/W3 /MP4") -set(COMMON_MSVC_FLAGS "${COMMON_MSVC_FLAGS} /we4715 /we4716") #adding no return or no return for all code paths as errors +set(COMMON_MSVC_FLAGS "${COMMON_MSVC_FLAGS} /we4715 /we4716 /D_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR") #adding no return or no return for all code paths as errors set(ADDITIONAL_C_FLAGS " -Wconversion -Wmissing-prototypes -Wstrict-prototypes") set(ADDITIONAL_C_FLAGS "${ADDITIONAL_C_FLAGS} -Wmissing-noreturn -Wpacked -Wredundant-decls -Wbad-function-cast -W -Wcast-align -Wcast-qual -Wsign-compare -fno-exceptions -Wdeclaration-after-statement") From f1cfbc0a1d3f75928d52a426d536df42aca3e141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Mon, 10 Jun 2024 17:07:22 +0200 Subject: [PATCH 07/13] Remove unused arrays & variables from `RESULTATS_HORAIRES` (#2147) Many `*Up`, `*Down`, `*Any` are unused. Remove them & allocations to simplify code and hopefully reduce memory footprint at runtime. --- .../opt_gestion_des_bornes_cas_lineaire.cpp | 3 -- .../sim_structure_probleme_economique.h | 17 ----------- .../simulation/sim_alloc_probleme_hebdo.cpp | 30 +------------------ 3 files changed, 1 insertion(+), 49 deletions(-) diff --git a/src/solver/optimisation/opt_gestion_des_bornes_cas_lineaire.cpp b/src/solver/optimisation/opt_gestion_des_bornes_cas_lineaire.cpp index dda3b10423..5bdbeef705 100644 --- a/src/solver/optimisation/opt_gestion_des_bornes_cas_lineaire.cpp +++ b/src/solver/optimisation/opt_gestion_des_bornes_cas_lineaire.cpp @@ -471,9 +471,6 @@ void OPT_InitialiserLesBornesDesVariablesDuProblemeLineaire(PROBLEME_HEBDO* prob .ValeursHorairesDeDefaillanceNegative[pdtHebdo]); AdresseOuPlacerLaValeurDesVariablesOptimisees[var] = adresseDuResultat; } - - problemeHebdo->ResultatsHoraires[pays].ValeursHorairesDeDefaillanceEnReserve[pdtHebdo] - = 0.0; } } 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 307be5b068..8f74ccb94a 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 @@ -250,9 +250,6 @@ struct PDISP_ET_COUTS_HORAIRES_PAR_PALIER std::vector CoutHoraireDeProductionDuPalierThermique; - std::vector CoutHoraireDuPalierThermiqueUp; - std::vector CoutHoraireDuPalierThermiqueDown; - std::vector NombreMaxDeGroupesEnMarcheDuPalierThermique; std::vector NombreMinDeGroupesEnMarcheDuPalierThermique; }; @@ -302,8 +299,6 @@ struct ENERGIES_ET_PUISSANCES_HYDRAULIQUES double PenalisationDeLaVariationDeProductionHydrauliqueSurVariationMax; double WeeklyWaterValueStateRegular; - double WeeklyWaterValueStateUp; - double WeeklyWaterValueStateDown; bool TurbinageEntreBornes; bool SansHeuristique; @@ -405,9 +400,6 @@ struct PRODUCTION_THERMIQUE_OPTIMALE { std::vector ProductionThermiqueDuPalier; - std::vector ProductionThermiqueDuPalierUp; - std::vector ProductionThermiqueDuPalierDown; - std::vector NombreDeGroupesEnMarcheDuPalier; std::vector NombreDeGroupesQuiDemarrentDuPalier; @@ -423,20 +415,11 @@ struct RESULTATS_HORAIRES std::vector ValeursHorairesLmrViolations; // adq patch lmr violations std::vector ValeursHorairesSpilledEnergyAfterCSR; // adq patch spillage after CSR std::vector ValeursHorairesDtgMrgCsr; // adq patch DTG MRG after CSR - std::vector ValeursHorairesDeDefaillancePositiveUp; - std::vector ValeursHorairesDeDefaillancePositiveDown; - std::vector ValeursHorairesDeDefaillancePositiveAny; std::vector ValeursHorairesDeDefaillanceNegative; - std::vector ValeursHorairesDeDefaillanceNegativeUp; - std::vector ValeursHorairesDeDefaillanceNegativeDown; - std::vector ValeursHorairesDeDefaillanceNegativeAny; - std::vector ValeursHorairesDeDefaillanceEnReserve; std::vector PompageHoraire; std::vector TurbinageHoraire; - std::vector TurbinageHoraireUp; - std::vector TurbinageHoraireDown; std::vector niveauxHoraires; std::vector valeurH2oHoraire; diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index aa1a5c90e3..860d2b8bfe 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -387,26 +387,11 @@ void SIM_AllocateAreas(PROBLEME_HEBDO& problem, 0.); // adq patch problem.ResultatsHoraires[k].ValeursHorairesDtgMrgCsr.assign(NombreDePasDeTemps, 0.); // adq patch - problem.ResultatsHoraires[k] - .ValeursHorairesDeDefaillancePositiveUp.assign(NombreDePasDeTemps, 0.); - problem.ResultatsHoraires[k] - .ValeursHorairesDeDefaillancePositiveDown.assign(NombreDePasDeTemps, 0.); - problem.ResultatsHoraires[k] - .ValeursHorairesDeDefaillancePositiveAny.assign(NombreDePasDeTemps, 0.); + problem.ResultatsHoraires[k].ValeursHorairesDeDefaillanceNegative.assign(NombreDePasDeTemps, 0.); - problem.ResultatsHoraires[k] - .ValeursHorairesDeDefaillanceNegativeUp.assign(NombreDePasDeTemps, 0.); - problem.ResultatsHoraires[k] - .ValeursHorairesDeDefaillanceNegativeDown.assign(NombreDePasDeTemps, 0.); - problem.ResultatsHoraires[k] - .ValeursHorairesDeDefaillanceNegativeAny.assign(NombreDePasDeTemps, 0.); - problem.ResultatsHoraires[k] - .ValeursHorairesDeDefaillanceEnReserve.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].TurbinageHoraire.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].PompageHoraire.assign(NombreDePasDeTemps, 0.); - problem.ResultatsHoraires[k].TurbinageHoraireUp.assign(NombreDePasDeTemps, 0.); - problem.ResultatsHoraires[k].TurbinageHoraireDown.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].CoutsMarginauxHoraires.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].niveauxHoraires.assign(NombreDePasDeTemps, 0.); problem.ResultatsHoraires[k].valeurH2oHoraire.assign(NombreDePasDeTemps, 0.); @@ -438,25 +423,12 @@ void SIM_AllocateAreas(PROBLEME_HEBDO& problem, problem.PaliersThermiquesDuPays[k] .PuissanceDisponibleEtCout[j] .NombreMinDeGroupesEnMarcheDuPalierThermique.assign(NombreDePasDeTemps, 0); - - problem.PaliersThermiquesDuPays[k] - .PuissanceDisponibleEtCout[j] - .CoutHoraireDuPalierThermiqueUp.assign(NombreDePasDeTemps, 0.); - problem.PaliersThermiquesDuPays[k] - .PuissanceDisponibleEtCout[j] - .CoutHoraireDuPalierThermiqueDown.assign(NombreDePasDeTemps, 0.); } for (unsigned j = 0; j < NombreDePasDeTemps; j++) { problem.ResultatsHoraires[k].ProductionThermique[j].ProductionThermiqueDuPalier.assign( nbPaliers, 0.); - problem.ResultatsHoraires[k] - .ProductionThermique[j] - .ProductionThermiqueDuPalierUp.assign(nbPaliers, 0.); - problem.ResultatsHoraires[k] - .ProductionThermique[j] - .ProductionThermiqueDuPalierDown.assign(nbPaliers, 0.); problem.ResultatsHoraires[k] .ProductionThermique[j] .NombreDeGroupesEnMarcheDuPalier.assign(nbPaliers, 0.); From 7b9a058ef400c9551e1a82fccb29a104ffdbbf57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Tue, 11 Jun 2024 15:10:37 +0200 Subject: [PATCH 08/13] Use sirius-solver@antares-integration-v1.5 (#2148) https://github.com/rte-france/sirius-solver/releases/tag/antares-integration-v1.5 --- src/ports/sirius-solver/portfile.cmake | 4 ++-- src/ports/sirius-solver/vcpkg.json | 2 +- src/vcpkg.json | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/ports/sirius-solver/portfile.cmake b/src/ports/sirius-solver/portfile.cmake index 30cce62622..287994c152 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.4" - SHA512 1eecb351b32490a82a2f93bf91e77ea4fd55cffc92c466b4136314e70d8a70328e4fda5257a46c08c431fd7013475050bc3908fcedee4fbdd746ed1ab6cb0efd + REF "antares-integration-v1.5" + SHA512 19c6c156861bdeb58c2f17f703124d52020c79f9b81734057bf1bc5dff3dbc464179f99aeab6c8c44a84de1f84ed8f4929f9a919d2bf8bd49ac737f656088e19 HEAD_REF main ) diff --git a/src/ports/sirius-solver/vcpkg.json b/src/ports/sirius-solver/vcpkg.json index 8e4a0a36df..ded804499d 100644 --- a/src/ports/sirius-solver/vcpkg.json +++ b/src/ports/sirius-solver/vcpkg.json @@ -1,6 +1,6 @@ { "name": "sirius-solver", - "version": "1.4", + "version": "1.5", "port-version": 0, "description": "Sirius solver", "dependencies": [ diff --git a/src/vcpkg.json b/src/vcpkg.json index 011ede41ad..fdd3963fd5 100644 --- a/src/vcpkg.json +++ b/src/vcpkg.json @@ -12,7 +12,8 @@ }, "dependencies": [ { - "name": "sirius-solver" + "name": "sirius-solver", + "version>=": "1.5" }, { "name": "wxwidgets", From 9cde7e57b64c07984b06894fb9fae31b47c162b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Tue, 11 Jun 2024 15:17:00 +0200 Subject: [PATCH 09/13] Add precision on `playlist_year +/-` properties (generaldata.ini) (#2156) --- docs/user-guide/solver/04-parameters.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/user-guide/solver/04-parameters.md b/docs/user-guide/solver/04-parameters.md index efe0e44ad4..bd46430336 100644 --- a/docs/user-guide/solver/04-parameters.md +++ b/docs/user-guide/solver/04-parameters.md @@ -792,13 +792,15 @@ They are **required** if [user-playlist](#user-playlist) is set to `true`. --- #### playlist_year - **Expected value:** `+ =` or `- =`, followed by a positive integer (example: `playlist_year + = 5`) -- **Required:** **yes**, if [user-playlist](#user-playlist) is set to `true`. +- **Required:** **yes**, if [user-playlist](#user-playlist) is set to `true`, ignored otherwise. - **Usage:** - for every Monte-Carlo year that you want the Antares Simulator to **study**, add the parameter entry `playlist_year + = i`, where `i` is the index of the year. - for every Monte-Carlo year that you want the Antares Simulator to **skip**, add the parameter entry `playlist_year - = i`, where `i` is the index of the year. +_Please note that by convention, the first year has index 0._ + --- #### playlist_year_weight [//]: # (TODO: document this parameter) From f758ed6aadf962367b336358d8d62e8c96a3caad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Omn=C3=A8s?= Date: Fri, 14 Jun 2024 15:06:44 +0200 Subject: [PATCH 10/13] Add I/O & doc for CurtailmentSharing::recomputeDTGMRG [ANT-1809] (#2141) --- docs/user-guide/04-migration-guides.md | 1 + src/libs/antares/study/parameters/adq-patch-params.cpp | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/docs/user-guide/04-migration-guides.md b/docs/user-guide/04-migration-guides.md index 354dfa692f..0e5f50726c 100644 --- a/docs/user-guide/04-migration-guides.md +++ b/docs/user-guide/04-migration-guides.md @@ -166,6 +166,7 @@ In file **settings/generaldata.ini**, in section `adequacy patch`, add propertie * `price-taking-order` [string] can take values `DENS` (default value) and `Load`. * `include-hurdle-cost-csr` [bool]. Default value = `false` * `check-csr-cost-function` [bool]. Default value = `false` +* `recompute-dtg-mrg` [bool]. Default value = `false` * `threshold-initiate-curtailment-sharing-rule` [double]. Default value = `0.0` * `threshold-display-local-matching-rule-violations` [double]. Default value = `0.0` * `threshold-csr-variable-bounds-relaxation` [int]. Default value = `3` diff --git a/src/libs/antares/study/parameters/adq-patch-params.cpp b/src/libs/antares/study/parameters/adq-patch-params.cpp index cbce2e51b0..99d0d0db33 100644 --- a/src/libs/antares/study/parameters/adq-patch-params.cpp +++ b/src/libs/antares/study/parameters/adq-patch-params.cpp @@ -71,6 +71,7 @@ void CurtailmentSharing::reset() priceTakingOrder = AdqPatchPTO::isDens; includeHurdleCost = false; checkCsrCostFunction = false; + recomputeDTGMRG = false; resetThresholds(); } @@ -121,6 +122,11 @@ bool CurtailmentSharing::updateFromKeyValue(const Yuni::String& key, const Yuni: { return value.to(checkCsrCostFunction); } + if (key == "recompute-dtg-mrg") + { + return value.to(recomputeDTGMRG); + } + // Thresholds if (key == "threshold-initiate-curtailment-sharing-rule") { @@ -156,6 +162,7 @@ void CurtailmentSharing::addProperties(IniFile::Section* section) const section->add("price-taking-order", PriceTakingOrderToString(priceTakingOrder)); section->add("include-hurdle-cost-csr", includeHurdleCost); section->add("check-csr-cost-function", checkCsrCostFunction); + section->add("recompute-dtg-mrg", recomputeDTGMRG); // Thresholds section->add("threshold-initiate-curtailment-sharing-rule", thresholdRun); From be3301cdb3b2b7ed232db72e68a874c353d51609 Mon Sep 17 00:00:00 2001 From: guilpier-code <62292552+guilpier-code@users.noreply.github.com> Date: Fri, 14 Jun 2024 16:03:41 +0200 Subject: [PATCH 11/13] Parallel years cleaning : few removal of "numspace" (#2128) See ticket [#1751](https://gopro-tickets.rte-france.com/browse/ANT-1751) For now, just a first analyze of how we could do to isolate **years** (from the simulation and what should not be inside a **year**). We take advantage of this to make some removals of **numSpace**. **Comments** : - **year job** and **simulation** are really intertwined, this is a first and important reason why a **year** are not isolated. For instance, when running a year of simulation, we call a function of the **simulation** object, not of the **year** object. - although what we first thought, **each year job creates a fresh new weekly optimization solver object**. This object solves every week problem, using the previous week's optimization solution as a base. Before creating a solver object, a year first **destroys the previous year's solver** (as well as the start base it holds). - I've heard that CI tests for parallel (currently passed at night run) don't generate the same output results as the same tests run in sequential. We assumed that it was because of the bases. Indeed, if the same simulation year is run starting from 2 different bases, it can lead to different simulation results. But given the previous point, that's not true : the simulation results should be identical whether we run a simulation sequentially or not. We may have broken something in the parallelism by not testing the it on CI. **Goals** : We want to isolate year jobs to make cleaner parallelism. Each year job should be designed so that it can be run in a thread independently from any other year job. In particular, a year job should hold its own memory spaces, and not shared memory as done currently. --------- Co-authored-by: Florian OMNES <26088210+flomnes@users.noreply.github.com> --- .../solver/hydro/management/management.h | 1 - src/solver/hydro/management/management.cpp | 2 - src/solver/simulation/adequacy.cpp | 10 +---- src/solver/simulation/economy.cpp | 8 +--- .../antares/solver/simulation/simulation.h | 2 +- .../antares/solver/simulation/solver.hxx | 40 +++++++++---------- .../simulation/sim_calcul_economique.cpp | 2 +- 7 files changed, 23 insertions(+), 42 deletions(-) diff --git a/src/solver/hydro/include/antares/solver/hydro/management/management.h b/src/solver/hydro/include/antares/solver/hydro/management/management.h index 78f3d4e6ea..3050515ca5 100644 --- a/src/solver/hydro/include/antares/solver/hydro/management/management.h +++ b/src/solver/hydro/include/antares/solver/hydro/management/management.h @@ -107,7 +107,6 @@ class HydroManagement final HydroManagement(const Data::AreaList& areas, const Data::Parameters& params, const Date::Calendar& calendar, - unsigned int maxNbYearsInParallel, Solver::IResultWriter& resultWriter); //! Perform the hydro ventilation diff --git a/src/solver/hydro/management/management.cpp b/src/solver/hydro/management/management.cpp index fe9311280d..b20be5e375 100644 --- a/src/solver/hydro/management/management.cpp +++ b/src/solver/hydro/management/management.cpp @@ -117,12 +117,10 @@ double BetaVariable(double a, double b, MersenneTwister& random) HydroManagement::HydroManagement(const Data::AreaList& areas, const Data::Parameters& params, const Date::Calendar& calendar, - unsigned int maxNbYearsInParallel, Solver::IResultWriter& resultWriter): areas_(areas), calendar_(calendar), parameters_(params), - maxNbYearsInParallel_(maxNbYearsInParallel), resultWriter_(resultWriter) { // Ventilation results memory allocation diff --git a/src/solver/simulation/adequacy.cpp b/src/solver/simulation/adequacy.cpp index f4e7f433d7..63d8462dfc 100644 --- a/src/solver/simulation/adequacy.cpp +++ b/src/solver/simulation/adequacy.cpp @@ -68,15 +68,7 @@ bool Adequacy::simulationBegin() pProblemesHebdo.resize(pNbMaxPerformedYearsInParallel); for (uint numSpace = 0; numSpace < pNbMaxPerformedYearsInParallel; numSpace++) { - SIM_InitialisationProblemeHebdo(study, pProblemesHebdo[numSpace], 168, numSpace); - - assert((uint)nbHoursInAWeek == (uint)pProblemesHebdo[numSpace].NombreDePasDeTemps - && "inconsistency"); - if ((uint)nbHoursInAWeek != (uint)pProblemesHebdo[numSpace].NombreDePasDeTemps) - { - logs.fatal() << "internal error"; - return false; - } + SIM_InitialisationProblemeHebdo(study, pProblemesHebdo[numSpace], nbHoursInAWeek, numSpace); } } diff --git a/src/solver/simulation/economy.cpp b/src/solver/simulation/economy.cpp index 0ffdf71d7b..02fac95314 100644 --- a/src/solver/simulation/economy.cpp +++ b/src/solver/simulation/economy.cpp @@ -73,13 +73,7 @@ bool Economy::simulationBegin() for (uint numSpace = 0; numSpace < pNbMaxPerformedYearsInParallel; numSpace++) { - SIM_InitialisationProblemeHebdo(study, pProblemesHebdo[numSpace], 168, numSpace); - - if ((uint)nbHoursInAWeek != (uint)pProblemesHebdo[numSpace].NombreDePasDeTemps) - { - logs.fatal() << "internal error"; - return false; - } + SIM_InitialisationProblemeHebdo(study, pProblemesHebdo[numSpace], nbHoursInAWeek, numSpace); auto options = createOptimizationOptions(study); weeklyOptProblems_[numSpace] = Antares::Solver::Optimization::WeeklyOptimization:: diff --git a/src/solver/simulation/include/antares/solver/simulation/simulation.h b/src/solver/simulation/include/antares/solver/simulation/simulation.h index 6d814157d1..bf214beff6 100644 --- a/src/solver/simulation/include/antares/solver/simulation/simulation.h +++ b/src/solver/simulation/include/antares/solver/simulation/simulation.h @@ -45,7 +45,7 @@ void SIM_AllocationProblemeHebdo(const Antares::Data::Study& study, */ void SIM_InitialisationProblemeHebdo(Antares::Data::Study& study, PROBLEME_HEBDO& problem, - int NombreDePasDeTemps, + unsigned int NombreDePasDeTemps, uint numspace); void SIM_RenseignementProblemeHebdo(const Antares::Data::Study& study, diff --git a/src/solver/simulation/include/antares/solver/simulation/solver.hxx b/src/solver/simulation/include/antares/solver/simulation/solver.hxx index dc2a7d4e09..87f38225cc 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver.hxx +++ b/src/solver/simulation/include/antares/solver/simulation/solver.hxx @@ -55,7 +55,7 @@ public: randomNumbers& pRandomForParallelYears, bool pPerformCalculations, Data::Study& pStudy, - std::vector& pState, + Variable::State& pState, bool pYearByYear, Benchmarking::DurationCollector& durationCollector, IResultWriter& resultWriter): @@ -75,7 +75,6 @@ public: hydroManagement(study.areas, study.parameters, study.calendar, - study.maxNbYearsInParallel, resultWriter) { hydroHotStart = (study.parameters.initialReservoirLevels.iniLevels == Data::irlHotStart); @@ -96,7 +95,7 @@ private: randomNumbers& randomForParallelYears; bool performCalculations; Data::Study& study; - std::vector& state; + Variable::State& state; bool yearByYear; bool hydroHotStart; Benchmarking::DurationCollector& pDurationCollector; @@ -155,8 +154,7 @@ public: // 1 - Applying random levels for current year if (hydroHotStart && firstSetParallelWithAPerformedYearWasRun) { - randomReservoirLevel = state[numSpace] - .problemeHebdo->previousYearFinalLevels.data(); + randomReservoirLevel = state.problemeHebdo->previousYearFinalLevels.data(); } else { @@ -177,7 +175,7 @@ public: }; // Updating the state - state[numSpace].year = y; + state.year = y; // 5 - Resetting all variables for the output simulation_->variables.yearBegin(y, numSpace); @@ -189,7 +187,7 @@ public: OptimizationStatisticsWriter optWriter(pResultWriter, y); yearFailed[y] = !simulation_->year(progression, - state[numSpace], + state, numSpace, randomForCurrentYear, failedWeekList, @@ -201,7 +199,7 @@ public: // Log failing weeks logFailedWeek(y, study, failedWeekList); - simulation_->variables.yearEndBuild(state[numSpace], y, numSpace); + simulation_->variables.yearEndBuild(state, y, numSpace); // 7 - End of the year, this is the last stade where the variables can retrieve // their data for this year. @@ -1059,19 +1057,19 @@ void ISimulation::loopThroughYears(uint firstYear, // continue; auto task = std::make_shared>( - this, - y, - set_it->yearFailed, - set_it->isFirstPerformedYearOfASet, - pFirstSetParallelWithAPerformedYearWasRun, - numSpace, - randomForParallelYears, - performCalculations, - study, - state, - pYearByYear, - pDurationCollector, - pResultWriter); + this, + y, + set_it->yearFailed, + set_it->isFirstPerformedYearOfASet, + pFirstSetParallelWithAPerformedYearWasRun, + numSpace, + randomForParallelYears, + performCalculations, + study, + state[numSpace], + pYearByYear, + pDurationCollector, + pResultWriter); results.add(Concurrency::AddTask(*pQueueService, task)); } // End loop over years of the current set of parallel years diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index 8b921dfec3..c51d8283dc 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -71,7 +71,7 @@ static void importShortTermStorages( void SIM_InitialisationProblemeHebdo(Data::Study& study, PROBLEME_HEBDO& problem, - int NombreDePasDeTemps, + unsigned int NombreDePasDeTemps, uint numspace) { int NombrePaliers; From 6edcad865005d73a8c5d79d6a96515a50bdaa3e0 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Mon, 17 Jun 2024 14:28:15 +0200 Subject: [PATCH 12/13] Remove hydro hotstart (#2131) https://github.com/AntaresSimulatorTeam/Antares_Simulator_Tests_NR/pull/24 Previously, the default value for property `initial-reservoir-levels` was `cold start`. --------- Co-authored-by: Guillaume PIERRE Co-authored-by: Florian OMNES --- docs/user-guide/solver/04-parameters.md | 3 +- docs/user-guide/solver/06-hydro-heuristics.md | 2 +- docs/user-guide/solver/09-appendix.md | 6 +- simtest.json | 2 +- src/libs/antares/study/fwd.cpp | 37 -------- .../antares/study/include/antares/study/fwd.h | 18 ---- .../study/include/antares/study/parameters.h | 11 --- .../antares/study/parts/hydro/container.h | 5 +- .../study/include/antares/study/study.h | 16 ---- src/libs/antares/study/load.cpp | 7 -- src/libs/antares/study/parameters.cpp | 28 ++---- .../antares/study/parts/hydro/container.cpp | 14 +-- src/libs/antares/study/study.cpp | 91 ------------------- src/solver/simulation/adequacy.cpp | 2 - src/solver/simulation/common-hydro-levels.cpp | 49 ++-------- src/solver/simulation/economy.cpp | 2 - .../solver/simulation/common-eco-adq.h | 8 -- .../sim_structure_probleme_economique.h | 2 - .../antares/solver/simulation/solver.h | 2 - .../antares/solver/simulation/solver.hxx | 45 ++------- .../simulation/sim_alloc_probleme_hebdo.cpp | 14 --- .../simulation/sim_calcul_economique.cpp | 18 +--- .../study/parameters/parameters-tests.cpp | 1 - .../windows/options/advanced/advanced.cpp | 63 +------------ .../windows/options/advanced/advanced.h | 7 +- 25 files changed, 46 insertions(+), 407 deletions(-) diff --git a/docs/user-guide/solver/04-parameters.md b/docs/user-guide/solver/04-parameters.md index bd46430336..fc8492a9e4 100644 --- a/docs/user-guide/solver/04-parameters.md +++ b/docs/user-guide/solver/04-parameters.md @@ -588,8 +588,7 @@ _**This section is under construction**_ These parameters are listed under the `[other preferences]` section in the `.ini` file. --- -#### initial-reservoir-levels -[//]: # (TODO: complete the usage paragraph) +#### initial-reservoir-levels (DEPRECATED since 9.2: cold start is default behavior) - **Expected value:** one of the following (case-insensitive): - `cold start` - `hot start` diff --git a/docs/user-guide/solver/06-hydro-heuristics.md b/docs/user-guide/solver/06-hydro-heuristics.md index 4d4de31f48..78ff065933 100644 --- a/docs/user-guide/solver/06-hydro-heuristics.md +++ b/docs/user-guide/solver/06-hydro-heuristics.md @@ -188,6 +188,6 @@ $$V_t^- + S_t \geq \underline{S_t}$$ $$Y - V_t^- \geq 0$$ -[^monthly_allocation]: In the first equation, $S_{t-1}$ is either the initial stock $S_0$ or the final stock of the previous year (hydro hot start) +[^monthly_allocation]: In the first equation, $S_{t-1}$ is equal to initial stock $S_0$ [^daily_allocation]: In the first equation, $S_{t-1}$ is either the initial stock used in M or the final stock of the previous month ($D(m-1)$) diff --git a/docs/user-guide/solver/09-appendix.md b/docs/user-guide/solver/09-appendix.md index 3ab1b49f6d..1f8e24673d 100644 --- a/docs/user-guide/solver/09-appendix.md +++ b/docs/user-guide/solver/09-appendix.md @@ -64,9 +64,9 @@ With `..._MPS` options, the full expression of the faulty problem(s) is printed thus allowing further analysis of the infeasibility issue. -## Details on the "initial-reservoir-levels" parameter -[//]: # (TODO: update this paragraph) -_**This section is under construction**_ +## Details on the "initial-reservoir-levels" parameter (DEPRECATED since 9.2) + +### version 9.2: The reservoir level is now always determined with cold start behavior. This parameter can take the two values "cold start" or "hot start". [default: cold start]. Simulations results may in some circumstances be heavily impacted by this setting, hence proper attention should be paid to its meaning before considering changing the default value. diff --git a/simtest.json b/simtest.json index 9029e0c9bb..422fd8e3bd 100644 --- a/simtest.json +++ b/simtest.json @@ -1,3 +1,3 @@ { - "version": "v9.1.0-rc5" + "version": "v9.2.0a" } diff --git a/src/libs/antares/study/fwd.cpp b/src/libs/antares/study/fwd.cpp index 68dae733e6..100a4b127e 100644 --- a/src/libs/antares/study/fwd.cpp +++ b/src/libs/antares/study/fwd.cpp @@ -91,43 +91,6 @@ const char* SeedToID(SeedIndex seed) return ""; } -// ... Initial reservoir levels ... -InitialReservoirLevels StringToInitialReservoirLevels(const AnyString& text) -{ - if (!text) - { - return irlUnknown; - } - - CString<24, false> s = text; - s.trim(); - s.toLower(); - if (s == "cold start") - { - return irlColdStart; - } - if (s == "hot start") - { - return irlHotStart; - } - - return irlUnknown; -} - -const char* InitialReservoirLevelsToCString(InitialReservoirLevels iniLevels) -{ - switch (iniLevels) - { - case irlColdStart: - return "cold start"; - case irlHotStart: - return "hot start"; - case irlUnknown: - return ""; - } - return ""; -} - // ... Hydro heuristic policy ... HydroHeuristicPolicy StringToHydroHeuristicPolicy(const AnyString& text) { diff --git a/src/libs/antares/study/include/antares/study/fwd.h b/src/libs/antares/study/include/antares/study/fwd.h index 56b6e3982b..6fa2819aca 100644 --- a/src/libs/antares/study/include/antares/study/fwd.h +++ b/src/libs/antares/study/include/antares/study/fwd.h @@ -382,24 +382,6 @@ const char* SeedToCString(SeedIndex seed); */ const char* SeedToID(SeedIndex seed); -// ... Initial reservoir levels ... -enum InitialReservoirLevels -{ - irlColdStart = 0, - irlHotStart, - irlUnknown, -}; - -/*! -** \brief Convert an Initial Reservoir Levels strategy into a text -*/ -const char* InitialReservoirLevelsToCString(InitialReservoirLevels iniLevels); - -/*! -** \brief Convert a text into an Initial Reservoir Levels strategy -*/ -InitialReservoirLevels StringToInitialReservoirLevels(const AnyString& text); - // ... Hydro heuristic policy ... enum HydroHeuristicPolicy { diff --git a/src/libs/antares/study/include/antares/study/parameters.h b/src/libs/antares/study/include/antares/study/parameters.h index fcbb8b0080..d9a1d467f0 100644 --- a/src/libs/antares/study/include/antares/study/parameters.h +++ b/src/libs/antares/study/include/antares/study/parameters.h @@ -463,12 +463,6 @@ class Parameters final RenewableGeneration renewableGeneration; - struct - { - //! Initial reservoir levels - InitialReservoirLevels iniLevels; - } initialReservoirLevels; - struct { //! Hydro heuristic policy @@ -481,11 +475,6 @@ class Parameters final HydroPricingMode hpMode; } hydroPricing; - // In case of hydro hot start and MC years simultaneous run - // ... Answers the question : do all sets of simultaneous years have the same size ? - // (obvious if the parallel mode is not required : answer is yes). - bool allSetsHaveSameSize; - //! Transmission capacities GlobalTransmissionCapacities transmissionCapacities; //! Simplex optimization range (day/week) diff --git a/src/libs/antares/study/include/antares/study/parts/hydro/container.h b/src/libs/antares/study/include/antares/study/parts/hydro/container.h index 5d79c65d30..e7467d9fb7 100644 --- a/src/libs/antares/study/include/antares/study/parts/hydro/container.h +++ b/src/libs/antares/study/include/antares/study/parts/hydro/container.h @@ -167,10 +167,9 @@ class PartHydro // As this function can be called a lot of times, we pass working variables and returned variables // as arguments, so that we don't have to create them locally (as in a classical function) each // time. -void getWaterValue(const double& level, +double getWaterValue(const double& level, const Matrix& waterValues, - const uint day, - double& waterValueToReturn); + const uint day); // Interpolates a rate from the credit modulation table according to a level double getWeeklyModulation(const double& level /* format : in % of reservoir capacity */, diff --git a/src/libs/antares/study/include/antares/study/study.h b/src/libs/antares/study/include/antares/study/study.h index cbe251805b..709bab62fe 100644 --- a/src/libs/antares/study/include/antares/study/study.h +++ b/src/libs/antares/study/include/antares/study/study.h @@ -421,22 +421,6 @@ class Study: public Yuni::NonCopyable, public LayerData */ void getNumberOfCores(const bool forceParallel, const uint nbYearsParallelForced); - /*! - ** \brief In case hydro hot start is enabled, checking all conditions are met. - ** - ** If hydro hot start is enabled, check that : - ** - For all areas for which reservoir management is enabled : - ** + Their starting level is initialized on the same day - ** + This day is the first day of the simulation calendar - ** - The simulation lasts exactly one year - ** - All batches (or sets) of simultaneous years have the same size (obvious if a parallel run - *is not required : answer is yes). - ** - ** If these conditions are not met, some error message is raised, when attempting to run the - *study. - */ - bool checkHydroHotStart(); - /*! ** \brief Remove timeseries if ts-generator is enabled */ diff --git a/src/libs/antares/study/load.cpp b/src/libs/antares/study/load.cpp index eefe3b2606..dca1b1eb15 100644 --- a/src/libs/antares/study/load.cpp +++ b/src/libs/antares/study/load.cpp @@ -166,13 +166,6 @@ void Study::parameterFiller(const StudyLoadOptions& options) parameters.firstMonthInYear, parameters.leapYear}); - // In case hydro hot start is enabled, check all conditions are met. - // (has to be called after areas load and calendar building) - if (usedByTheSolver && !checkHydroHotStart()) - { - logs.error() << "hydro hot start is enabled, conditions are not met. Aborting"; - } - // Reducing memory footprint reduceMemoryUsage(); } diff --git a/src/libs/antares/study/parameters.cpp b/src/libs/antares/study/parameters.cpp index 3ac64a284e..3517b09d21 100644 --- a/src/libs/antares/study/parameters.cpp +++ b/src/libs/antares/study/parameters.cpp @@ -311,15 +311,11 @@ void Parameters::reset() readonly = false; synthesis = true; - // Initial reservoir levels - initialReservoirLevels.iniLevels = irlColdStart; - // Hydro heuristic policy hydroHeuristicPolicy.hhPolicy = hhpAccommodateRuleCurves; // Hydro pricing hydroPricing.hpMode = hpHeuristic; - allSetsHaveSameSize = true; // Shedding strategies power.fluctuations = lssFreeModulations; @@ -810,19 +806,6 @@ static bool SGDIntLoadFamily_OtherPreferences(Parameters& d, d.hydroPricing.hpMode = hpHeuristic; return false; } - if (key == "initial-reservoir-levels") - { - auto iniLevels = StringToInitialReservoirLevels(value); - if (iniLevels != irlUnknown) - { - d.initialReservoirLevels.iniLevels = iniLevels; - return true; - } - logs.warning() << "parameters: invalid initital reservoir levels mode. Got '" << value - << "'. reset to cold start mode."; - d.initialReservoirLevels.iniLevels = irlColdStart; - return false; - } if (key == "number-of-cores-mode") { @@ -1155,6 +1138,15 @@ static bool SGDIntLoadFamily_Legacy(Parameters& d, return true; } + if (key == "initial-reservoir-levels") // ignored since 9.2 + { + if (version >= StudyVersion(9,2)) + logs.warning() << "Option initial-reservoir-levels is deprecated, please remove it from the study"; + else if (value == "hot start") + logs.warning() << "Hydro hot start not supported with this solver, please use a version < 9.2"; + return true; + } + return false; } @@ -1874,8 +1866,6 @@ void Parameters::saveToINI(IniFile& ini) const // Other preferences { auto* section = ini.addSection("other preferences"); - section->add("initial-reservoir-levels", - InitialReservoirLevelsToCString(initialReservoirLevels.iniLevels)); section->add("hydro-heuristic-policy", HydroHeuristicPolicyToCString(hydroHeuristicPolicy.hhPolicy)); section->add("hydro-pricing-mode", HydroPricingModeToCString(hydroPricing.hpMode)); diff --git a/src/libs/antares/study/parts/hydro/container.cpp b/src/libs/antares/study/parts/hydro/container.cpp index e86b32a568..103d7a83bb 100644 --- a/src/libs/antares/study/parts/hydro/container.cpp +++ b/src/libs/antares/study/parts/hydro/container.cpp @@ -938,10 +938,9 @@ bool PartHydro::CheckDailyMaxEnergy(const AnyString& areaName) return ret; } -void getWaterValue(const double& level /* format : in % of reservoir capacity */, +double getWaterValue(const double& level /* format : in % of reservoir capacity */, const Matrix& waterValues, - const uint day, - double& waterValueToReturn) + const uint day) { assert((level >= 0. && level <= 100.) && "getWaterValue function : invalid level"); double levelUp = ceil(level); @@ -949,13 +948,10 @@ void getWaterValue(const double& level /* format : in % of reservoir capacity */ if ((int)(levelUp) == (int)(levelDown)) { - waterValueToReturn = waterValues[(int)(levelUp)][day]; - } - else - { - waterValueToReturn = waterValues[(int)(levelUp)][day] * (level - levelDown) - + waterValues[(int)(levelDown)][day] * (levelUp - level); + return waterValues[(int)(levelUp)][day]; } + return waterValues[(int)(levelUp)][day] * (level - levelDown) + + waterValues[(int)(levelDown)][day] * (levelUp - level); } double getWeeklyModulation(const double& level /* format : in % of reservoir capacity */, diff --git a/src/libs/antares/study/study.cpp b/src/libs/antares/study/study.cpp index 8337795ca1..23f547783d 100644 --- a/src/libs/antares/study/study.cpp +++ b/src/libs/antares/study/study.cpp @@ -500,97 +500,6 @@ void Study::getNumberOfCores(const bool forceParallel, const uint nbYearsParalle // enabled. // Useful for RAM estimation. maxNbYearsInParallel_save = maxNbYearsInParallel; - - // Here we answer the question (useful only if hydro hot start is asked) : do all sets of - // parallel years have the same size ? - if (parameters.initialReservoirLevels.iniLevels == Antares::Data::irlHotStart - && setsOfParallelYears.size() && maxNbYearsInParallel > 1) - { - uint currentSetSize = (uint)setsOfParallelYears[0].size(); - if (setsOfParallelYears.size() > 1) - { - for (uint s = 1; s < setsOfParallelYears.size(); s++) - { - if (setsOfParallelYears[s].size() != currentSetSize) - { - parameters.allSetsHaveSameSize = false; - break; - } - } - } - } // End if hot start -} - -bool Study::checkHydroHotStart() -{ - bool hydroHotStart = (parameters.initialReservoirLevels.iniLevels == irlHotStart); - - // No need to check further if hydro hot start is not required - if (!hydroHotStart) - { - return true; - } - - // Here we answer the question (useful only if hydro hot start is asked) : In case of parallel - // run, do all sets of parallel years have the same size ? - if (maxNbYearsInParallel != 1 && !parameters.allSetsHaveSameSize) - { - logs.error() << "Hot Start Hydro option : conflict with parallelization parameters."; - logs.error() - << "Please update relevant simulation parameters or use Cold Start option. "; - return false; - } - - // Checking calendar conditions - // ... The simulation lasts one year exactly - uint nbDaysInSimulation = parameters.simulationDays.end - parameters.simulationDays.first + 1; - if (nbDaysInSimulation < 364) - { - logs.error() - << "Hot Start Hydro option : simulation calendar must cover one complete year. "; - logs.error() << "Please update data or use Cold Start option."; - return false; - } - - // ... For all areas for which reservoir management is enabled : - // - Their starting level is initialized on the same day - // - This day is the first day of the simulation calendar - const Area::Map::iterator end = areas.end(); - for (Area::Map::iterator i = areas.begin(); i != end; ++i) - { - // Reference to the area - Area* area = i->second; - - // No need to make a check on level initialization when reservoir management - // is not activated for the current area - if (!area->hydro.reservoirManagement) - { - continue; - } - - // Month the reservoir level is initialized according to. - // This month number is given in the civil calendar, from january to december (0 is - // january). - int initLevelOnMonth = area->hydro.initializeReservoirLevelDate; - - // Conversion of the previous month into simulation calendar - uint initLevelOnSimMonth = calendar.mapping.months[initLevelOnMonth]; - - // Previous month's first day in the year - uint initLevelOnSimDay = calendar.months[initLevelOnSimMonth].daysYear.first; - - // Check the day of level initialization is the first day of simulation - if (initLevelOnSimDay != parameters.simulationDays.first) - { - logs.error() - << "Hot Start Hydro option : area '" << area->name - << "' - hydro level must be initialized on the first simulation month. "; - logs.error() << "Please update data or use Cold Start option."; - return false; - } - } // End loop over areas - - return true; } bool Study::initializeRuntimeInfos() diff --git a/src/solver/simulation/adequacy.cpp b/src/solver/simulation/adequacy.cpp index 63d8462dfc..2b03f7bcdc 100644 --- a/src/solver/simulation/adequacy.cpp +++ b/src/solver/simulation/adequacy.cpp @@ -361,8 +361,6 @@ bool Adequacy::year(Progression::Task& progression, ++progression; } - updatingAnnualFinalHydroLevel(study.areas, currentProblem); - optWriter.finalize(); finalizeOptimizationStatistics(currentProblem, state); diff --git a/src/solver/simulation/common-hydro-levels.cpp b/src/solver/simulation/common-hydro-levels.cpp index 8564418f62..b322d62dec 100644 --- a/src/solver/simulation/common-hydro-levels.cpp +++ b/src/solver/simulation/common-hydro-levels.cpp @@ -105,12 +105,8 @@ void interpolateWaterValue(const Data::AreaList& areas, RESULTATS_HORAIRES& weeklyResults = problem.ResultatsHoraires[index]; - std::vector& waterVal = weeklyResults.valeurH2oHoraire; - - for (uint h = 0; h < nbHoursInAWeek; h++) - { - waterVal[h] = 0.; - } + auto& waterVal = weeklyResults.valeurH2oHoraire; + std::fill(waterVal.begin(), waterVal.end(), 0.); if (!area.hydro.reservoirManagement || !area.hydro.useWaterValue) { @@ -126,17 +122,16 @@ void interpolateWaterValue(const Data::AreaList& areas, std::vector& niv = weeklyResults.niveauxHoraires; - Antares::Data::getWaterValue(problem.previousSimulationFinalLevel[index] * 100 - / reservoirCapacity, - area.hydro.waterValues, - weekFirstDay, - waterVal[0]); + waterVal[0] = Data::getWaterValue(problem.previousSimulationFinalLevel[index] * 100 + / reservoirCapacity, + area.hydro.waterValues, + weekFirstDay); + for (uint h = 1; h < nbHoursInAWeek; h++) { - Antares::Data::getWaterValue(niv[h - 1], - area.hydro.waterValues, - daysOfWeek[h / 24], - waterVal[h]); + waterVal[h] = Data::getWaterValue(niv[h - 1], + area.hydro.waterValues, + daysOfWeek[h / 24]); } }); } @@ -164,28 +159,4 @@ void updatingWeeklyFinalHydroLevel(const Data::AreaList& areas, PROBLEME_HEBDO& }); } -void updatingAnnualFinalHydroLevel(const Data::AreaList& areas, PROBLEME_HEBDO& problem) -{ - if (!problem.hydroHotStart) - { - return; - } - - areas.each( - [&](const Data::Area& area) - { - if (!area.hydro.reservoirManagement) - { - return; - } - - uint index = area.index; - - double reservoirCapacity = area.hydro.reservoirCapacity; - - problem.previousYearFinalLevels[index] = problem.previousSimulationFinalLevel[index] - / reservoirCapacity; - }); -} - } // namespace Antares::Solver::Simulation diff --git a/src/solver/simulation/economy.cpp b/src/solver/simulation/economy.cpp index 02fac95314..934ebc4c2c 100644 --- a/src/solver/simulation/economy.cpp +++ b/src/solver/simulation/economy.cpp @@ -224,8 +224,6 @@ bool Economy::year(Progression::Task& progression, ++progression; } - updatingAnnualFinalHydroLevel(study.areas, currentProblem); - optWriter.finalize(); finalizeOptimizationStatistics(currentProblem, state); diff --git a/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h b/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h index 14d260af09..6ea4a9e003 100644 --- a/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h +++ b/src/solver/simulation/include/antares/solver/simulation/common-eco-adq.h @@ -141,14 +141,6 @@ void interpolateWaterValue(const Data::AreaList& areas, */ void updatingWeeklyFinalHydroLevel(const Data::AreaList& areas, PROBLEME_HEBDO& problem); -/* -** \brief Updating the year final reservoir level, to be used as a start for the year. -** -** \param areas : the areas of study -** \param problem The weekly problem, living over the whole simuation. -*/ -void updatingAnnualFinalHydroLevel(const Data::AreaList& areas, PROBLEME_HEBDO& problem); - /* ** \brief Compute the weighted average NTC for a link ** 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 8f74ccb94a..66400ed678 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 @@ -559,7 +559,6 @@ struct PROBLEME_HEBDO bool YaDeLaReserveJmoins1 = false; - std::vector previousYearFinalLevels; std::vector AllMustRunGeneration; OptimizationStatistics optimizationStatistics[2]; @@ -569,7 +568,6 @@ struct PROBLEME_HEBDO /* Hydro management */ std::vector CoefficientEcretementPMaxHydraulique; - bool hydroHotStart = false; std::vector previousSimulationFinalLevel; /* Results */ diff --git a/src/solver/simulation/include/antares/solver/simulation/solver.h b/src/solver/simulation/include/antares/solver/simulation/solver.h index 29c087759f..fe16b660b9 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver.h +++ b/src/solver/simulation/include/antares/solver/simulation/solver.h @@ -145,8 +145,6 @@ class ISimulation: public Impl uint pNbMaxPerformedYearsInParallel; //! Year by year output results bool pYearByYear; - //! Hydro hot start - bool pHydroHotStart; //! The first set of parallel year(s) with a performed year was already run ? bool pFirstSetParallelWithAPerformedYearWasRun; diff --git a/src/solver/simulation/include/antares/solver/simulation/solver.hxx b/src/solver/simulation/include/antares/solver/simulation/solver.hxx index 87f38225cc..adf8c23c4d 100644 --- a/src/solver/simulation/include/antares/solver/simulation/solver.hxx +++ b/src/solver/simulation/include/antares/solver/simulation/solver.hxx @@ -77,7 +77,6 @@ public: study.calendar, resultWriter) { - hydroHotStart = (study.parameters.initialReservoirLevels.iniLevels == Data::irlHotStart); scratchmap = study.areas.buildScratchMap(numSpace); } @@ -97,7 +96,6 @@ private: Data::Study& study; Variable::State& state; bool yearByYear; - bool hydroHotStart; Benchmarking::DurationCollector& pDurationCollector; IResultWriter& pResultWriter; HydroManagement hydroManagement; @@ -152,14 +150,7 @@ public: double* randomReservoirLevel = nullptr; // 1 - Applying random levels for current year - if (hydroHotStart && firstSetParallelWithAPerformedYearWasRun) - { - randomReservoirLevel = state.problemeHebdo->previousYearFinalLevels.data(); - } - else - { - randomReservoirLevel = randomForCurrentYear.pReservoirLevels; - } + randomReservoirLevel = randomForCurrentYear.pReservoirLevels; // 2 - Preparing the Time-series numbers // removed @@ -265,8 +256,6 @@ inline ISimulation::ISimulation( { pYearByYear = false; } - - pHydroHotStart = (study.parameters.initialReservoirLevels.iniLevels == Data::irlHotStart); } template @@ -765,34 +754,12 @@ void ISimulation::computeRandomNumbers( } } - if (pHydroHotStart) - { - if (!isPerformed || !area.hydro.reservoirManagement) - { - // This initial level should be unused, so -1, as impossible value, is - // suitable. - randomForYears.pYears[indexYear].pReservoirLevels[areaIndex] = -1.; - areaIndex++; - return; // Skipping the current area - } - - if (!pFirstSetParallelWithAPerformedYearWasRun) - { - randomForYears.pYears[indexYear].pReservoirLevels[areaIndex] = randomLevel; - } - // Else : means the start levels (multiple areas are affected) of a year are - // retrieved from a previous year and - // these levels are updated inside the year job (see year job). - } - else + // Current area's hydro starting (or initial) level computation + // (no matter if the year is performed or not, we always draw a random initial + // reservoir level to ensure the same results) + if (isPerformed) { - // Current area's hydro starting (or initial) level computation - // (no matter if the year is performed or not, we always draw a random initial - // reservoir level to ensure the same results) - if (isPerformed) - { - randomForYears.pYears[indexYear].pReservoirLevels[areaIndex] = randomLevel; - } + randomForYears.pYears[indexYear].pReservoirLevels[areaIndex] = randomLevel; } areaIndex++; diff --git a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp index 860d2b8bfe..03126fa752 100644 --- a/src/solver/simulation/sim_alloc_probleme_hebdo.cpp +++ b/src/solver/simulation/sim_alloc_probleme_hebdo.cpp @@ -119,20 +119,6 @@ void SIM_AllocationProblemeDonneesGenerales(PROBLEME_HEBDO& problem, problem.ShortTermStorage.resize(nbPays); - problem.previousYearFinalLevels.resize(0); - if (problem.hydroHotStart) - { - for (uint i = 0; i <= nbPays; i++) - { - auto& area = *(study.areas[i]); - if (area.hydro.reservoirManagement) - { - problem.previousYearFinalLevels.assign(nbPays, 0.); - break; - } - } - } - problem.ReserveJMoins1.resize(nbPays); problem.ResultatsHoraires.resize(nbPays); diff --git a/src/solver/simulation/sim_calcul_economique.cpp b/src/solver/simulation/sim_calcul_economique.cpp index c51d8283dc..155cb6b3bc 100644 --- a/src/solver/simulation/sim_calcul_economique.cpp +++ b/src/solver/simulation/sim_calcul_economique.cpp @@ -81,9 +81,6 @@ void SIM_InitialisationProblemeHebdo(Data::Study& study, problem.Expansion = (parameters.mode == Data::SimulationMode::Expansion); problem.firstWeekOfSimulation = false; - problem.hydroHotStart = (parameters.initialReservoirLevels.iniLevels - == Antares::Data::irlHotStart); - // gp adq : to be removed if (parameters.adqPatchParams.enabled) { @@ -210,11 +207,6 @@ void SIM_InitialisationProblemeHebdo(Data::Study& study, problem.previousSimulationFinalLevel[i] = -1.; - if (!problem.previousYearFinalLevels.empty()) - { - problem.previousYearFinalLevels[i] = -1.; - } - problem.CaracteristiquesHydrauliques[i].WeeklyWaterValueStateRegular = 0.; problem.CaracteristiquesHydrauliques[i].WeeklyGeneratingModulation = 1.; @@ -521,11 +513,11 @@ void SIM_RenseignementProblemeHebdo(const Study& study, if (area.hydro.useWaterValue) { - Antares::Data::getWaterValue( - problem.previousSimulationFinalLevel[k] * 100 / area.hydro.reservoirCapacity, - area.hydro.waterValues, - weekFirstDay, - problem.CaracteristiquesHydrauliques[k].WeeklyWaterValueStateRegular); + problem.CaracteristiquesHydrauliques[k].WeeklyWaterValueStateRegular = + getWaterValue( + problem.previousSimulationFinalLevel[k] * 100 / area.hydro.reservoirCapacity, + area.hydro.waterValues, + weekFirstDay); } if (problem.CaracteristiquesHydrauliques[k].PresenceDHydrauliqueModulable > 0) diff --git a/src/tests/src/libs/antares/study/parameters/parameters-tests.cpp b/src/tests/src/libs/antares/study/parameters/parameters-tests.cpp index f690649668..14ee6a4435 100644 --- a/src/tests/src/libs/antares/study/parameters/parameters-tests.cpp +++ b/src/tests/src/libs/antares/study/parameters/parameters-tests.cpp @@ -189,7 +189,6 @@ void Fixture::writeValidFile() threshold-csr-variable-bounds-relaxation = 3 [other preferences] - initial-reservoir-levels = cold start hydro-heuristic-policy = accommodate rule curves hydro-pricing-mode = fast power-fluctuations = free modulations diff --git a/src/ui/simulator/windows/options/advanced/advanced.cpp b/src/ui/simulator/windows/options/advanced/advanced.cpp index 97b0589bd4..a361fc227b 100644 --- a/src/ui/simulator/windows/options/advanced/advanced.cpp +++ b/src/ui/simulator/windows/options/advanced/advanced.cpp @@ -156,14 +156,12 @@ AdvancedParameters::AdvancedParameters(wxWindow* parent) : // Initial reservoir levels { label = Component::CreateLabel(this, wxT("Initial reservoir levels")); - button = new Component::Button(this, wxT("cold start"), "images/16x16/tag.png"); + button = new Component::Button(this, wxT(""), "images/16x16/tag.png"); button->SetBackgroundColour(bgColor); - button->menu(true); - onPopup.bind(this, &AdvancedParameters::onInitialReservoirLevels); button->onPopupMenu(onPopup); + button->caption("hydro hot start deprecated"); s->Add(label, 0, wxRIGHT | wxALIGN_RIGHT | wxALIGN_CENTER_VERTICAL); s->Add(button, 0, wxLEFT | wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL); - pBtnInitialReservoirLevels = button; } // Hydro heuristic policy { @@ -327,7 +325,6 @@ void AdvancedParameters::onResetToDefault(void*) parameters.timeSeriesAccuracyOnCorrelation &= ~Data::timeSeriesWind; parameters.timeSeriesAccuracyOnCorrelation &= ~Data::timeSeriesSolar; - parameters.initialReservoirLevels.iniLevels = Data::irlColdStart; parameters.hydroHeuristicPolicy.hhPolicy = Data::hhpAccommodateRuleCurves; parameters.hydroPricing.hpMode = Data::hpHeuristic; parameters.power.fluctuations = Data::lssFreeModulations; @@ -375,10 +372,6 @@ void AdvancedParameters::refresh() wxString text; - text = wxStringFromUTF8( - InitialReservoirLevelsToCString(study.parameters.initialReservoirLevels.iniLevels)); - pBtnInitialReservoirLevels->caption(text); - text = wxStringFromUTF8( HydroHeuristicPolicyToCString(study.parameters.hydroHeuristicPolicy.hhPolicy)); pBtnHydroHeuristicPolicy->caption(text); @@ -508,58 +501,6 @@ void AdvancedParameters::onSelectNumericQualityHigh(wxCommandEvent&) } } -void AdvancedParameters::onInitialReservoirLevels(Component::Button&, wxMenu& menu, void*) -{ - wxMenuItem* it; - wxString text; - - text = wxStringFromUTF8(InitialReservoirLevelsToCString(Data::irlColdStart)); - text << wxT(" [default]"); - it = Menu::CreateItem(&menu, wxID_ANY, text, "images/16x16/tag.png"); - menu.Connect(it->GetId(), - wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(AdvancedParameters::onSelectColdStart), - nullptr, - this); - - text.clear(); - text << wxStringFromUTF8(InitialReservoirLevelsToCString(Data::irlHotStart)); - it = Menu::CreateItem(&menu, wxID_ANY, text, "images/16x16/tag.png"); - menu.Connect(it->GetId(), - wxEVT_COMMAND_MENU_SELECTED, - wxCommandEventHandler(AdvancedParameters::onSelectHotStart), - nullptr, - this); -} - -void AdvancedParameters::onSelectColdStart(wxCommandEvent&) -{ - if (not CurrentStudyIsValid()) - return; - auto& study = *GetCurrentStudy(); - - if (study.parameters.initialReservoirLevels.iniLevels != Data::irlColdStart) - { - study.parameters.initialReservoirLevels.iniLevels = Data::irlColdStart; - MarkTheStudyAsModified(); - refresh(); - } -} - -void AdvancedParameters::onSelectHotStart(wxCommandEvent&) -{ - if (not CurrentStudyIsValid()) - return; - auto& study = *GetCurrentStudy(); - - if (study.parameters.initialReservoirLevels.iniLevels != Data::irlHotStart) - { - study.parameters.initialReservoirLevels.iniLevels = Data::irlHotStart; - MarkTheStudyAsModified(); - refresh(); - } -} - // ... Hydro heuristic policy void AdvancedParameters::onHydroHeuristicPolicy(Component::Button&, wxMenu& menu, void*) { diff --git a/src/ui/simulator/windows/options/advanced/advanced.h b/src/ui/simulator/windows/options/advanced/advanced.h index a42d87c9c8..1410d05595 100644 --- a/src/ui/simulator/windows/options/advanced/advanced.h +++ b/src/ui/simulator/windows/options/advanced/advanced.h @@ -69,11 +69,7 @@ class AdvancedParameters final : public wxDialog void onNumericQuality(Component::Button&, wxMenu&, void*, Data::TimeSeriesType ts); void onSelectNumericQualityStandard(wxCommandEvent& evt); void onSelectNumericQualityHigh(wxCommandEvent& evt); - - void onInitialReservoirLevels(Component::Button&, wxMenu&, void*); - void onSelectHotStart(wxCommandEvent& evt); - void onSelectColdStart(wxCommandEvent& evt); - + void onHydroHeuristicPolicy(Component::Button&, wxMenu& menu, void*); void onSelectAccomodateRuleCurves(wxCommandEvent& evt); void onSelectMaximizeGeneration(wxCommandEvent& evt); @@ -115,7 +111,6 @@ class AdvancedParameters final : public wxDialog Component::Button* pBtnNumericQualityWind; Component::Button* pBtnNumericQualitySolar; Component::Button* pBtnPowerFluctuations; - Component::Button* pBtnInitialReservoirLevels; Component::Button* pBtnHydroHeuristicPolicy; Component::Button* pBtnHydroPricing; Component::Button* pBtnSheddingPolicy; From 08003e3275588c4dff4edb7767951e0063f0ed85 Mon Sep 17 00:00:00 2001 From: payetvin <113102157+payetvin@users.noreply.github.com> Date: Mon, 17 Jun 2024 15:16:08 +0200 Subject: [PATCH 13/13] Move data validation to specialized functions [ANT-1213] (#2149) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The goal of this PR is to separate loading and validation of data. This separation will allow to have a modular loading. Slight change for admissible values of reservoir capacity (from ]1e-6, +oo[ to ]0, +oo[). --------- Co-authored-by: Florian Omnès Co-authored-by: Florian OMNES <26088210+flomnes@users.noreply.github.com> --- src/libs/antares/study/area/list.cpp | 2 + .../antares/study/parts/hydro/container.h | 14 +- .../antares/study/parts/hydro/prepro.h | 3 +- .../antares/study/parts/hydro/container.cpp | 600 ++++++------------ .../parts/hydro/hydromaxtimeseriesreader.cpp | 34 +- src/libs/antares/study/parts/hydro/prepro.cpp | 107 ++-- 6 files changed, 270 insertions(+), 490 deletions(-) diff --git a/src/libs/antares/study/area/list.cpp b/src/libs/antares/study/area/list.cpp index e7bd727287..417e60bae4 100644 --- a/src/libs/antares/study/area/list.cpp +++ b/src/libs/antares/study/area/list.cpp @@ -944,6 +944,7 @@ static bool AreaListLoadFromFolderSingleArea(Study& study, // if changes are required, please update reloadXCastData() buffer.clear() << study.folderInput << SEP << "hydro" << SEP << "prepro"; ret = area.hydro.prepro->loadFromFolder(study, area.id, buffer.c_str()) && ret; + ret = area.hydro.prepro->validate(area.id) && ret; } auto* hydroSeries = area.hydro.series; @@ -1160,6 +1161,7 @@ bool AreaList::loadFromFolder(const StudyLoadOptions& options) logs.info() << "Loading global hydro data..."; buffer.clear() << pStudy.folderInput << SEP << "hydro"; ret = PartHydro::LoadFromFolder(pStudy, buffer) && ret; + ret = PartHydro::validate(pStudy) && ret; } // Thermal data, specific to areas diff --git a/src/libs/antares/study/include/antares/study/parts/hydro/container.h b/src/libs/antares/study/include/antares/study/parts/hydro/container.h index e7467d9fb7..0297540a4d 100644 --- a/src/libs/antares/study/include/antares/study/parts/hydro/container.h +++ b/src/libs/antares/study/include/antares/study/parts/hydro/container.h @@ -52,7 +52,6 @@ class PartHydro pumpMod, }; -public: /*! ** \brief Load data for hydro container from a folder ** @@ -61,6 +60,13 @@ class PartHydro */ static bool LoadFromFolder(Study& study, const AnyString& folder); + /*! + ** \brief Check and validate the loaded datas + ** + ** \return A non-zero value if the operation succeeded, 0 otherwise + */ + static bool validate(Study& study); + /*! ** \brief Save data from several containers to a folder (except data for the prepro and *time-series) @@ -71,7 +77,6 @@ class PartHydro */ static bool SaveToFolder(const AreaList& areas, const AnyString& folder); -public: /*! ** \brief Default Constructor */ @@ -100,7 +105,6 @@ class PartHydro bool CheckDailyMaxEnergy(const AnyString& areaName); -public: //! Inter-daily breakdown (previously called Smoothing Factor or alpha) double interDailyBreakdown; //! Intra-daily modulation @@ -161,6 +165,10 @@ class PartHydro Matrix dailyNbHoursAtGenPmax; Matrix dailyNbHoursAtPumpPmax; +private: + static bool checkReservoirLevels(const Study& study); + static bool checkProperties(Study& study); + }; // class PartHydro // Interpolates a water value from a table according to a level and a day. diff --git a/src/libs/antares/study/include/antares/study/parts/hydro/prepro.h b/src/libs/antares/study/include/antares/study/parts/hydro/prepro.h index dbc015ecce..b35798f862 100644 --- a/src/libs/antares/study/include/antares/study/parts/hydro/prepro.h +++ b/src/libs/antares/study/include/antares/study/parts/hydro/prepro.h @@ -95,8 +95,9 @@ class PreproHydro ** \param folder The source folder (ex: `input/hydro/prepro`) ** \return A non-zero value if the operation succeeded, 0 otherwise */ - bool loadFromFolder(Study& s, const AreaName& areaID, const char folder[]); + bool loadFromFolder(Study& s, const AreaName& areaID, const std::string& folder); + bool validate(const std::string& areaID); /*! ** \brief Save hydro settings for the prepro into a folder ** diff --git a/src/libs/antares/study/parts/hydro/container.cpp b/src/libs/antares/study/parts/hydro/container.cpp index 103d7a83bb..0343c2878f 100644 --- a/src/libs/antares/study/parts/hydro/container.cpp +++ b/src/libs/antares/study/parts/hydro/container.cpp @@ -106,6 +106,37 @@ void PartHydro::reset() } } +template +static bool loadProperties(Study& study, + IniFile::Property* property, + const std::string& filename, + T PartHydro::*ptr) +{ + if (!property) + return false; + + bool ret = true; + + // Browse all properties + for (; property; property = property->next) + { + AreaName id = property->key; + id.toLower(); + + Area* area = study.areas.find(id); + if (area) + { + ret = property->value.to(area->hydro.*ptr) && ret; + } + else + { + logs.warning() << filename << ": `" << id << "`: Unknown area"; + return false; + } + } + return ret; +} + bool PartHydro::LoadFromFolder(Study& study, const AnyString& folder) { auto& buffer = study.bufferLoadingTS; @@ -200,46 +231,6 @@ bool PartHydro::LoadFromFolder(Study& study, const AnyString& folder) Matrix<>::optFixedSize, &study.dataBuffer) && ret; - - if (study.usedByTheSolver) - { - auto& col = area.hydro.inflowPattern[0]; - bool errorInflow = false; - for (unsigned int day = 0; day < DAYS_PER_YEAR; day++) - { - if (col[day] < 0 && !errorInflow) - { - logs.error() << area.name << ": invalid inflow value"; - errorInflow = true; - ret = false; - } - } - bool errorLevels = false; - auto& colMin = area.hydro.reservoirLevel[minimum]; - auto& colAvg = area.hydro.reservoirLevel[average]; - auto& colMax = area.hydro.reservoirLevel[maximum]; - for (unsigned int day = 0; day < DAYS_PER_YEAR; day++) - { - if (!errorLevels - && (colMin[day] < 0 || colAvg[day] < 0 || colMin[day] > colMax[day] - || colAvg[day] > 100 || colMax[day] > 100)) - { - logs.error() << area.name << ": invalid reservoir level value"; - errorLevels = true; - ret = false; - } - } - - for (int i = 0; i < 101; i++) - { - if ((area.hydro.creditModulation[i][0] < 0) - || (area.hydro.creditModulation[i][1] < 0)) - { - logs.error() << area.name << ": invalid credit modulation value"; - ret = false; - } - } - } }); IniFile ini; @@ -248,432 +239,217 @@ bool PartHydro::LoadFromFolder(Study& study, const AnyString& folder) return false; } - const char* const sectionName = "inter-daily-breakdown"; + if (IniFile::Section* section = ini.find("inter-daily-breakdown")) + { + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::interDailyBreakdown) && ret; + } - IniFile::Section* section; - IniFile::Property* property; + if (IniFile::Section* section = ini.find("intra-daily-modulation")) + { + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::intraDailyModulation) && ret; + } - if ((section = ini.find(sectionName))) + if (IniFile::Section* section = ini.find("reservoir")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - Area* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.interDailyBreakdown) && ret; - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::reservoirManagement) && ret; } - if ((section = ini.find("intra-daily-modulation"))) + if (IniFile::Section* section = ini.find("reservoir capacity")) { - if ((property = section->firstProperty)) - { - AreaName id; + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::reservoirCapacity) && ret; + } - // Browse all properties - for (; property; property = property->next) - { - id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.intraDailyModulation) && ret; - if (area->hydro.intraDailyModulation < 1.) - { - logs.error() - << area->id << ": Invalid intra-daily modulation. It must be >= 1.0, Got " - << area->hydro.intraDailyModulation << " (truncated to 1)"; - area->hydro.intraDailyModulation = 1.; - } - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + if (IniFile::Section* section = ini.find("follow load")) + { + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::followLoadModulations) && ret; } - if ((section = ini.find("reservoir"))) + if (IniFile::Section* section = ini.find("use water")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.reservoirManagement) && ret; - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::useWaterValue) && ret; } - if ((section = ini.find("reservoir capacity"))) + if (IniFile::Section* section = ini.find("hard bounds")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.reservoirCapacity) && ret; - if (area->hydro.reservoirCapacity < 1e-6) - { - logs.error() << area->id << ": Invalid reservoir capacity."; - area->hydro.reservoirCapacity = 0.; - } - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::hardBoundsOnRuleCurves) && ret; } - // Check on reservoir capacity (has to be done after reservoir management and capacity reading, - // not before). Some areas reservoir capacities may not be printed in hydro ini file when saving - // the study, because they are too small (< 1e-6). We cannot have reservoir management = yes and - // capacity = 0 because of further division by capacity. reservoir management = no and capacity - // = 0 is possible (no use of capacity further) - study.areas.each( - [&](Data::Area& area) - { - if (area.hydro.reservoirCapacity < 1e-3 && area.hydro.reservoirManagement) - { - logs.error() << area.name - << ": reservoir capacity not defined. Impossible to manage."; - ret = false && ret; - } - }); + if (IniFile::Section* section = ini.find("use heuristic")) + { + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::useHeuristicTarget) && ret; + } - if ((section = ini.find("inter-monthly-breakdown"))) + if (IniFile::Section* section = ini.find("power to level")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.intermonthlyBreakdown) && ret; - if (area->hydro.intermonthlyBreakdown < 0) - { - logs.error() << area->id << ": Invalid intermonthly breakdown"; - area->hydro.intermonthlyBreakdown = 0.; - } - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::powerToLevel) && ret; } - if ((section = ini.find("follow load"))) + + if (IniFile::Section* section = ini.find("initialize reservoir date")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.followLoadModulations) && ret; - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::initializeReservoirLevelDate) && ret; } - if ((section = ini.find("use water"))) + + if (IniFile::Section* section = ini.find("use leeway")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.useWaterValue) && ret; - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::useLeeway) && ret; } - if ((section = ini.find("hard bounds"))) + + if (IniFile::Section* section = ini.find("leeway low")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.hardBoundsOnRuleCurves) && ret; - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::leewayLowerBound) && ret; } - if ((section = ini.find("use heuristic"))) + + if (IniFile::Section* section = ini.find("leeway up")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.useHeuristicTarget) && ret; - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::leewayUpperBound) && ret; } - if ((section = ini.find("power to level"))) + + if (IniFile::Section* section = ini.find("pumping efficiency")) { - if ((property = section->firstProperty)) - { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.powerToLevel) && ret; - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } - } + ret = loadProperties(study, section->firstProperty, buffer, &PartHydro::pumpingEfficiency) && ret; } - if ((section = ini.find("initialize reservoir date"))) + + return ret; +} + +bool PartHydro::checkReservoirLevels(const Study& study) +{ + bool ret = true; + + for (const auto& [areaName, area] : study.areas) { - if ((property = section->firstProperty)) + if (!study.usedByTheSolver) + return true; + + auto& col = area->hydro.inflowPattern[0]; + bool errorInflow = false; + for (unsigned int day = 0; day < DAYS_PER_YEAR; day++) { - // Browse all properties - for (; property; property = property->next) + if (col[day] < 0 && !errorInflow) { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.initializeReservoirLevelDate) && ret; - if (area->hydro.initializeReservoirLevelDate < 0) - { - logs.error() << area->id << ": Invalid initialize reservoir date"; - area->hydro.initializeReservoirLevelDate = 0; - } - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } + logs.error() << areaName << ": invalid inflow value"; + errorInflow = true; + ret = false; } } - } - // Leeways : use leeway bounds (upper and lower) - if ((section = ini.find("use leeway"))) - { - if ((property = section->firstProperty)) + bool errorLevels = false; + auto& colMin = area->hydro.reservoirLevel[minimum]; + auto& colAvg = area->hydro.reservoirLevel[average]; + auto& colMax = area->hydro.reservoirLevel[maximum]; + for (unsigned int day = 0; day < DAYS_PER_YEAR; day++) { - // Browse all properties - for (; property; property = property->next) + if (!errorLevels + && (colMin[day] < 0 || colAvg[day] < 0 || colMin[day] > colMax[day] + || colAvg[day] > 100 || colMax[day] > 100)) { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.useLeeway) && ret; - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } + logs.error() << areaName << ": invalid reservoir level value"; + errorLevels = true; + ret = false; } } - } - if ((section = ini.find("leeway low"))) - { - if ((property = section->firstProperty)) + + for (int i = 0; i < 101; i++) { - // Browse all properties - for (; property; property = property->next) + if ((area->hydro.creditModulation[i][0] < 0) + || (area->hydro.creditModulation[i][1] < 0)) { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.leewayLowerBound) && ret; - if (area->hydro.leewayLowerBound < 0.) - { - logs.error() - << area->id << ": Invalid leeway lower bound. It must be >= 0.0, Got " - << area->hydro.leewayLowerBound; - area->hydro.leewayLowerBound = 0.; - } - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } + logs.error() << areaName << ": invalid credit modulation value"; + ret = false; } } } - if ((section = ini.find("leeway up"))) + + return ret; +} + +bool PartHydro::checkProperties(Study& study) +{ + bool ret = true; + + // Check on reservoir capacity (has to be done after reservoir management and capacity reading, + // not before). Some areas reservoir capacities may not be printed in hydro ini file when saving + // the study, because they are too small (< 1e-6). We cannot have reservoir management = yes and + // capacity = 0 because of further division by capacity. reservoir management = no and capacity + // = 0 is possible (no use of capacity further) + study.areas.each([&ret](Data::Area& area) { - if ((property = section->firstProperty)) + if (area.hydro.reservoirCapacity < 1e-3 && area.hydro.reservoirManagement) { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.leewayUpperBound) && ret; - if (area->hydro.leewayUpperBound < 0.) - { - logs.error() - << area->id << ": Invalid leeway upper bound. It must be >= 0.0, Got " - << area->hydro.leewayUpperBound; - area->hydro.leewayUpperBound = 0.; - } - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } + logs.error() << area.name + << ": reservoir capacity not defined. Impossible to manage."; + ret = false; } - } - // they are too small (< 1e-6). We cannot allow these areas to have reservoir management = - // true. - study.areas.each( - [&](Data::Area& area) - { - if (area.hydro.leewayLowerBound > area.hydro.leewayUpperBound) - { - logs.error() << area.id << ": Leeway lower bound greater than leeway upper bound."; - } - }); + if (!area.hydro.useHeuristicTarget && !area.hydro.useWaterValue) + { + logs.error() << area.name + << " : use water value = no conflicts with use heuristic target = no"; + ret = false; + } - if ((section = ini.find("pumping efficiency"))) - { - if ((property = section->firstProperty)) + if (area.hydro.intraDailyModulation < 1.) { - // Browse all properties - for (; property; property = property->next) - { - AreaName id = property->key; - id.toLower(); - - auto* area = study.areas.find(id); - if (area) - { - ret = property->value.to(area->hydro.pumpingEfficiency) && ret; - if (area->hydro.pumpingEfficiency < 0) - { - logs.error() << area->id << ": Invalid pumping efficiency"; - area->hydro.pumpingEfficiency = 0.; - } - } - else - { - logs.warning() << buffer << ": `" << id << "`: Unknown area"; - } - } + logs.error() + << area.id << ": Invalid intra-daily modulation. It must be >= 1.0, Got " + << area.hydro.intraDailyModulation << " (truncated to 1)"; + area.hydro.intraDailyModulation = 1.; } - } - study.areas.each( - [&](Data::Area& area) - { - if (not area.hydro.useHeuristicTarget && not area.hydro.useWaterValue) - { - logs.error() << area.name - << " : use water value = no conflicts with use heuristic target = no"; - ret = false && ret; - } - }); + if (area.hydro.reservoirCapacity < 0) + { + logs.error() << area.id << ": Invalid reservoir capacity."; + area.hydro.reservoirCapacity = 0.; + } + + if (area.hydro.intermonthlyBreakdown < 0) + { + logs.error() << area.id << ": Invalid intermonthly breakdown"; + area.hydro.intermonthlyBreakdown = 0.; + } + + if (area.hydro.initializeReservoirLevelDate < 0) + { + logs.error() << area.id << ": Invalid initialize reservoir date"; + area.hydro.initializeReservoirLevelDate = 0; + } + + if (area.hydro.leewayLowerBound < 0.) + { + logs.error() + << area.id << ": Invalid leeway lower bound. It must be >= 0.0, Got " + << area.hydro.leewayLowerBound; + area.hydro.leewayLowerBound = 0.; + } + + if (area.hydro.leewayUpperBound < 0.) + { + logs.error() + << area.id << ": Invalid leeway upper bound. It must be >= 0.0, Got " + << area.hydro.leewayUpperBound; + area.hydro.leewayUpperBound = 0.; + } + + if (area.hydro.leewayLowerBound > area.hydro.leewayUpperBound) + { + logs.error() << area.id << ": Leeway lower bound greater than leeway upper bound."; + } + + if (area.hydro.pumpingEfficiency < 0) + { + logs.error() << area.id << ": Invalid pumping efficiency"; + area.hydro.pumpingEfficiency = 0.; + } + }); return ret; } +bool PartHydro::validate(Study& study) +{ + bool ret = checkReservoirLevels(study); + return checkProperties(study) && ret; +} + bool PartHydro::SaveToFolder(const AreaList& areas, const AnyString& folder) { if (!folder) diff --git a/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.cpp b/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.cpp index b7864e5b31..fa2827fc88 100644 --- a/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.cpp +++ b/src/libs/antares/study/parts/hydro/hydromaxtimeseriesreader.cpp @@ -47,6 +47,24 @@ HydroMaxTimeSeriesReader::HydroMaxTimeSeriesReader(PartHydro& hydro, dailyMaxPumpAndGen.reset(4U, DAYS_PER_YEAR, true); } +static bool checkPower(const Matrix<>& dailyMaxPumpAndGen, const std::string& areaName) +{ + for (uint i = 0; i < 4U; ++i) + { + auto& col = dailyMaxPumpAndGen[i]; + for (uint day = 0; day < DAYS_PER_YEAR; ++day) + { + if (col[day] < 0. || (i % 2U /*column hours*/ && col[day] > 24.)) + { + logs.error() << areaName << ": invalid power or energy value"; + return false; + } + } + } + + return true; +} + bool HydroMaxTimeSeriesReader::loadDailyMaxPowersAndEnergies(const AnyString& folder, bool usedBySolver) { @@ -90,21 +108,6 @@ bool HydroMaxTimeSeriesReader::loadDailyMaxPowersAndEnergies(const AnyString& fo Matrix<>::optFixedSize, &fileContent) && ret; - - bool errorPowers = false; - for (uint i = 0; i < 4U; ++i) - { - auto& col = dailyMaxPumpAndGen[i]; - for (uint day = 0; day < DAYS_PER_YEAR; ++day) - { - if (!errorPowers && (col[day] < 0. || (i % 2U /*column hours*/ && col[day] > 24.))) - { - logs.error() << areaName_ << ": invalid power or energy value"; - errorPowers = true; - ret = false; - } - } - } } return ret; } @@ -138,6 +141,7 @@ void HydroMaxTimeSeriesReader::copyDailyMaxPumpingEnergy() const bool HydroMaxTimeSeriesReader::read(const AnyString& folder, bool usedBySolver) { bool ret = loadDailyMaxPowersAndEnergies(folder, usedBySolver); + ret = checkPower(dailyMaxPumpAndGen, areaName_) && ret; copyDailyMaxEnergy(); hydro_.series->buildHourlyMaxPowerFromDailyTS(dailyMaxPumpAndGen[genMaxP], dailyMaxPumpAndGen[pumpMaxP]); diff --git a/src/libs/antares/study/parts/hydro/prepro.cpp b/src/libs/antares/study/parts/hydro/prepro.cpp index d8ddb72352..9370c562fa 100644 --- a/src/libs/antares/study/parts/hydro/prepro.cpp +++ b/src/libs/antares/study/parts/hydro/prepro.cpp @@ -145,22 +145,30 @@ bool PreproHydro::saveToFolder(const AreaName& areaID, const char* folder) return false; } -bool PreproHydro::loadFromFolder(Study& s, const AreaName& areaID, const char* folder) +bool PreproHydro::loadFromFolder(Study& s, const AreaName& areaID, const std::string& folder) { - /* Asserts */ - assert(folder); - assert('\0' != *folder); - enum { mtrxOption = Matrix<>::optFixedSize | Matrix<>::optImmediate, }; + constexpr int maxNbOfLineToLoad = 12; data.resize(hydroPreproMax, 12, true); String& buffer = s.bufferLoadingTS; buffer.clear() << folder << SEP << areaID << SEP << "prepro.ini"; bool ret = PreproHydroLoadSettings(this, buffer); + + buffer.clear() << folder << SEP << areaID << SEP << "energy.txt"; + ret = data.loadFromCSVFile(buffer, hydroPreproMax, maxNbOfLineToLoad, mtrxOption, &s.dataBuffer) && ret; + + return ret; +} + +bool PreproHydro::validate(const std::string& areaID) +{ + bool ret = true; + if (intermonthlyCorrelation < 0. || intermonthlyCorrelation > 1.) { logs.error() << "Hydro: Prepro: `" << areaID @@ -175,77 +183,58 @@ bool PreproHydro::loadFromFolder(Study& s, const AreaName& areaID, const char* f } } - buffer.clear() << folder << SEP << areaID << SEP << "energy.txt"; - ret = data.loadFromCSVFile(buffer, hydroPreproMax, 12, mtrxOption, &s.dataBuffer) && ret; - - if (JIT::enabled) - { - return ret; - } - - // Checks + const auto& col = data[powerOverWater]; + for (unsigned i = 0; i != data.height; ++i) { - auto& col = data[powerOverWater]; - for (uint i = 0; i != data.height; ++i) + const double d = col[i]; + if (d < 0. || d > 1.) { - const double d = col[i]; - if (d < 0. || d > 1.) - { - logs.error() << "Hydro: Prepro: " << areaID - << ": invalid value for ROR (line: " << (i + 1) << ")"; - } + logs.error() << "Hydro: Prepro: " << areaID + << ": invalid value for ROR (line: " << (i + 1) << ")"; } } - { - auto& colMin = data[minimumEnergy]; - auto& colMax = data[maximumEnergy]; + const auto& colMin = data[minimumEnergy]; + const auto& colMax = data[maximumEnergy]; - for (uint i = 0; i != data.height; ++i) + for (unsigned i = 0; i != data.height; ++i) + { + if (colMin[i] < 0.) { - if (colMin[i] < 0.) - { - ret = false; - logs.error() << "Hydro: Prepro: `" << areaID - << "`: minimum energy: At least one value is negative (line: " - << (i + 1) << ')'; - continue; - } - if (colMin[i] > colMax[i]) - { - ret = false; - logs.error() << "Hydro: Prepro: `" << areaID - << "`: the minimum energy must be less than the maximum energy (line: " - << (i + 1) << ')'; - } + ret = false; + logs.error() << "Hydro: Prepro: `" << areaID + << "`: minimum energy: At least one value is negative (line: " + << (i + 1) << ')'; + continue; + } + if (colMin[i] > colMax[i]) + { + ret = false; + logs.error() << "Hydro: Prepro: `" << areaID + << "`: the minimum energy must be less than the maximum energy (line: " + << (i + 1) << ')'; } } + const auto& colExp = data[expectation]; + for (unsigned i = 0; i != data.height; i++) { - auto& colExp = data[expectation]; - - for (uint i = 0; i != data.height; i++) + if (colExp[i] < 0.) { - if (colExp[i] < 0.) - { - ret = false; - logs.error() << "Hydro: Prepro: `" << areaID - << "`: invalid value for expectation (line: " << (i + 1) << ")"; - } + ret = false; + logs.error() << "Hydro: Prepro: `" << areaID + << "`: invalid value for expectation (line: " << (i + 1) << ")"; } } + const auto& colStdDev = data[stdDeviation]; + for (unsigned i = 0; i != data.height; i++) { - auto& colStdDev = data[stdDeviation]; - - for (uint i = 0; i != data.height; i++) + if (colStdDev[i] < 0.) { - if (colStdDev[i] < 0.) - { - ret = false; - logs.error() << "Hydro: Prepro: `" << areaID - << "`: invalid value for standard deviation (line: " << (i + 1) << ")"; - } + ret = false; + logs.error() << "Hydro: Prepro: `" << areaID + << "`: invalid value for standard deviation (line: " << (i + 1) << ")"; } }