diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eabe800b6..a0c56016c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,6 +11,11 @@ jobs: name: Linux runs-on: ubuntu-latest steps: + - name: Install Boost + run: | + sudo apt-get update -y + sudo apt-get install -y libboost-all-dev + - name: Checkout sources uses: actions/checkout@v1 @@ -19,7 +24,6 @@ jobs: cmake -S $GITHUB_WORKSPACE -B $GITHUB_WORKSPACE/build-linux -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLES=ON - -DCMAKE_PREFIX_PATH=$BOOST_ROOT_1_72_0 - name: Build run: cmake --build $GITHUB_WORKSPACE/build-linux --parallel 3 @@ -33,7 +37,7 @@ jobs: name: MacOS runs-on: macos-latest steps: - - name: Pre-requisites + - name: Install Boost run: brew install boost - name: Checkout sources @@ -51,21 +55,32 @@ jobs: CTEST_OUTPUT_ON_FAILURE: 1 windows: + env: + BOOST_ROOT: C:\thirdparties\boost-1.72.0 + BOOST_URL: https://sourceforge.net/projects/boost/files/boost-binaries/1.72.0/boost_1_72_0-msvc-14.2-64.exe/download + LIBXML2_ROOT: C:\thirdparties\libxml2-2.9.10 + LIBXML2_URL: https://github.com/GNOME/libxml2/archive/v2.9.10.zip name: Windows runs-on: windows-latest steps: - - name: Pre-requisites + - name: Install LibXml2 shell: cmd run: | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat" choco install wget --no-progress - wget -nv https://github.com/GNOME/libxml2/archive/v2.9.10.zip + wget -nv %LIBXML2_URL% 7z x v2.9.10.zip cd libxml2-2.9.10/win32 - cscript configure.js compiler=msvc prefix=C:\thirdparties\libxml2-2.9.10 iconv=no + cscript configure.js compiler=msvc prefix=%LIBXML2_ROOT% iconv=no nmake -f Makefile.msvc nmake -f Makefile.msvc install + - name: Install Boost + shell: cmd + run: | + wget -nv -O boost-installer.exe %BOOST_URL% + boost-installer.exe /dir=%BOOST_ROOT% /sp- /verysilent /suppressmsgboxes /norestart + - name: Checkout sources uses: actions/checkout@v1 @@ -74,7 +89,6 @@ jobs: run: > cmake -S %GITHUB_WORKSPACE% -B %GITHUB_WORKSPACE%\build-windows -DBUILD_EXAMPLES=ON - -DCMAKE_PREFIX_PATH=%BOOST_ROOT_1_72_0%;C:\thirdparties\libxml2-2.9.10 - name: Build shell: cmd @@ -85,7 +99,7 @@ jobs: - name: Tests shell: cmd run: | - set PATH=%PATH%;C:\thirdparties\libxml2-2.9.10\bin;%BOOST_ROOT_1_72_0%\lib;%GITHUB_WORKSPACE%\build-windows\src\Release;%GITHUB_WORKSPACE%\build-windows\src\test\Release + set PATH=%PATH%;%LIBXML2_ROOT%\bin;%BOOST_ROOT%\lib64-msvc-14.2;%GITHUB_WORKSPACE%\build-windows\src\Release;%GITHUB_WORKSPACE%\build-windows\src\test\Release cmake --build %GITHUB_WORKSPACE%\build-windows --target RUN_TESTS --config Release --verbose env: CTEST_OUTPUT_ON_FAILURE: 1 @@ -118,6 +132,11 @@ jobs: env: SONAR_SCANNER_VERSION: 3.3.0.1492 + - name: Install Boost + run: | + sudo apt-get update -y + sudo apt-get install -y libboost-all-dev + - name: Checkout sources uses: actions/checkout@v1 @@ -127,7 +146,6 @@ jobs: -DCMAKE_BUILD_TYPE=Debug -DCODE_COVERAGE=TRUE -DBUILD_EXAMPLES=ON - -DCMAKE_PREFIX_PATH=$BOOST_ROOT_1_72_0 - name: Build run: > diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 567d098f8..85b56fe65 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -9,6 +9,11 @@ jobs: name: clang-tidy runs-on: ubuntu-latest steps: + - name: Install Boost + run: | + sudo apt-get update -y + sudo apt-get install -y libboost-all-dev + - name: Install clang-tidy run: | sudo apt-get install -y clang-tidy-9 @@ -22,6 +27,7 @@ jobs: cmake -S $GITHUB_WORKSPACE -B $GITHUB_WORKSPACE/build -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH=$BOOST_ROOT_1_72_0 + -DBUILD_EXAMPLES=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON - name: Clang Tidy diff --git a/CMakeLists.txt b/CMakeLists.txt index eb6bfa2e7..664cffb7c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,12 +4,19 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # -cmake_minimum_required(VERSION 3.12 FATAL_ERROR) +cmake_minimum_required(VERSION 3.15 FATAL_ERROR) + +if (${CMAKE_VERSION} VERSION_GREATER "3.15.0") + # Policy to activate a way to choose MSVC runtime. https://cmake.org/cmake/help/v3.15/policy/CMP0091.html + if (POLICY CMP0091) + cmake_policy(SET CMP0091 NEW) + endif () +endif () project(powsybl-iidm4cpp) set(IIDM_VERSION_MAJOR 1) -set(IIDM_VERSION_MINOR 3) +set(IIDM_VERSION_MINOR 4) set(IIDM_VERSION_PATCH 0) set(IIDM_VERSION ${IIDM_VERSION_MAJOR}.${IIDM_VERSION_MINOR}.${IIDM_VERSION_PATCH}) set(IIDM_SOVERSION ${IIDM_VERSION_MAJOR}) @@ -22,15 +29,27 @@ set(INSTALL_DOC_DIR share CACHE PATH "Installation directory for doxygen files") option(BUILD_DOXYGEN "Enable/Disable the generation of the Doxygen." OFF) option(BUILD_EXAMPLES "Enable/Disable the compilation of the examples." OFF) +option(BUILD_TESTS "Enable/Disable the compilation of unit tests." ON) +option(BUILD_TOOLS "Enable/Disable the compilation of tools." ON) +option(BUILD_SHARED_LIBS "Enable/disable build of shared libraries." ON) +option(BUILD_STATIC_LIBS "Enable/disable build of static libraries." ON) +option(BOOST_STATIC_LIBS "Use static version of boost libraries." OFF) +option(MSVC_STATIC_RUNTIME_LIBRARY "Enable/disable static runtime on Windows." OFF) + +# Handle options compatibility +if (BOOST_STATIC_LIBS AND BUILD_SHARED_LIBS) + message(FATAL_ERROR "BOOST_STATIC_LIBS and BUILD_SHARED_LIBS are ON and should not be used together. + BOOST_STATIC_LIBS should only be used with BUILD_STATIC_LIBS=ON and BUILD_SHARED_LIBS=OFF.") +endif () + +if (BUILD_STATIC_LIBS AND NOT BUILD_SHARED_LIBS) + set(TARGET_POSTFIX "-static") +endif () list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -if (${CMAKE_VERSION} VERSION_LESS "3.1.0") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11") -else () - set(CMAKE_CXX_STANDARD 11) - set(CMAKE_CXX_STANDARD_REQUIRED TRUE) -endif () +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED TRUE) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror -pedantic -Wswitch-enum") @@ -38,11 +57,26 @@ if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" STRE # set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -D_GLIBCXX_DEBUG") elseif (MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /wd4250 /wd4251 /wd4267 /wd4275") + if (NOT BUILD_SHARED_LIBS AND BUILD_STATIC_LIBS) + if (MSVC_STATIC_RUNTIME_LIBRARY) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + endif () + else() + if (MSVC_STATIC_RUNTIME_LIBRARY) + message(WARNING "MSVC_STATIC_RUNTIME_LIBRARY should be used with BUILD_SHARED_LIBS=OFF and BUILD_STATIC_LIBS=ON.") + endif () + endif () endif () -set(Boost_USE_STATIC_LIBS OFF) -find_package(Boost 1.65 REQUIRED COMPONENTS date_time filesystem program_options system unit_test_framework) +set(Boost_USE_STATIC_LIBS ${BOOST_STATIC_LIBS}) +set(Boost_USE_STATIC_RUNTIME ${MSVC_STATIC_RUNTIME_LIBRARY}) +if (BUILD_TESTS) + find_package(Boost 1.65 REQUIRED COMPONENTS date_time filesystem program_options system unit_test_framework) +else () + find_package(Boost 1.65 REQUIRED COMPONENTS date_time filesystem program_options system) +endif() find_package(LibXml2 REQUIRED) +find_package(Threads REQUIRED) if (WIN32) # On windows, also force prefix to avoid conflict between import file (for shared compilation) and static file @@ -55,6 +89,9 @@ enable_testing() set(CODE_COVERAGE FALSE CACHE BOOL "Enable code coverage") if (CODE_COVERAGE) + # if code-coverage is ON, force tests build + set(BUILD_TESTS ON) + include(CodeCoverage) code_coverage(NAME code-coverage OUTPUT_DIR coverage @@ -67,9 +104,16 @@ if (BUILD_DOXYGEN) endif () add_subdirectory(src) -add_subdirectory(test) add_subdirectory(extensions) -add_subdirectory(tools) + +if (BUILD_TOOLS) + add_subdirectory(tools) +endif () + +if (BUILD_TESTS) + add_subdirectory(test) +endif () + if (BUILD_EXAMPLES) add_subdirectory(examples) endif () diff --git a/README.md b/README.md index 094225ff7..3d81b7e0c 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ - [Build from sources](#build-from-sources) - [Build the examples](#build-the-examples) - [Generate the documentation](#generate-the-documentation) + - [Disable unit tests generation](#disable-tests-generation) - [Link with powsybl-iidm4cpp](#link-with-powsybl-iidm4cpp) - [Contributing](#contributing) @@ -33,7 +34,7 @@ To build powsybl-iidm4cpp, you need: ### Ubuntu 20.04 ``` $> apt install -y cmake g++ git libboost-all-dev libxml2-dev make -``` +``` ### Ubuntu 18.04 ``` @@ -145,11 +146,17 @@ $> cmake .. -DCMAKE_INSTALL_PREFIX= -DCMAKE_BUILD_TYPE= **Available options:** - BUILD_DOXYGEN: Generate the API documentation using doxygen (Default is **OFF**) - BUILD_EXAMPLES: Build the examples (Default is **OFF**) +- BUILD_TESTS: Generate unit tests (Default is **ON**) +- BUILD_TOOLS: Build the tools (Default is **ON**) +- BUILD_SHARED_LIBS: Build shared version of the library (Default is **ON**) +- BUILD_STATIC_LIBS: Build static version of library (Default is **ON**) +- BOOST_STATIC_LIBS: Use static version of Boost libraries (Default is **OFF**) +- MSVC_STATIC_RUNTIME_LIBRARY: Use MSVC static runtime (Default is **OFF**) **Note:** If you want to use custom version of **Boost** or **LibXML**, you would have to help `cmake` to find the required packages, using the `-DCMAKE_PREFIX_PATH` options: ``` $> cmake .. -DCMAKE_INSTALL_PREFIX= -DCMAKE_PREFIX_PATH=; -``` +``` 3. Build the sources ``` @@ -172,9 +179,9 @@ To build the examples, you have to pass the `-DBUILD_EXAMPLES=ON` flag to the co ``` $> cmake .. -DCMAKE_INSTALL_PREFIX= -DCMAKE_BUILD_TYPE= -DBUILD_EXAMPLES=ON $> cmake --build . -``` +``` -Click [here](examples/README.md) to see the list of available examples. +Click [here](examples/README.md) to see the list of available examples. ### Generate the documentation This project uses [doxygen](http://www.doxygen.nl/) to generate code documentation. To generate the API documentation using doxygen, add `-DBUILD_DOXYGEN=ON` flag to the configure command line. This will create a new `doxygen` target. @@ -184,20 +191,28 @@ $> cmake --build . --target doxygen ``` The HTML documentation is available in `/doc/html/index.html`. +### Disable unit tests generation +Unit tests generation may be disabled to increase compilation time. When disabled, `Boost::unit_test_framework` is not necessary to build successfully. +To disable tests generation, add `-DBUILD_TESTS=OFF` flag to the configure command line. +``` +$> cmake .. -DCMAKE_INSTALL_PREFIX= -DCMAKE_BUILD_TYPE= -DBUILD_TESTS=OFF +$> cmake --build . +``` + ## Link with powsybl-iidm4cpp We provide cmake script files that make it easy to use `powsybl-iidm4cpp` in a CMake project, that are installed in the `/LibIIDM/cmake` folder. To use the library in your project, add the `find_package` instruction to your `CMakeLists.txt` file: ``` find_package(LibIIDM REQUIRED) -``` +``` Then configure your project passing the `-DCMAKE_PREFIX_PATH=` option to the cmake command: ``` $> cmake ... -DCMAKE_PREFIX_PATH= ``` -A complete example is available [here](examples/example2). +A complete example is available [here](examples/example2). ## Contributing @@ -215,4 +230,4 @@ $> cmake --build . $> cmake --build . --target test $> cmake --build . --target code-coverage ``` -The HTML report is available in `/coverage/index.html`. +The HTML report is available in `/coverage/index.html`. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 91e2cbccc..d6b6edd88 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -6,3 +6,6 @@ # add_subdirectory(example1) +if (BUILD_STATIC_LIBS) + add_subdirectory(example3) +endif () diff --git a/examples/README.md b/examples/README.md index 6f65eeca7..96dd2b3c6 100644 --- a/examples/README.md +++ b/examples/README.md @@ -3,5 +3,6 @@ ## Basic examples - [Example 1](example1/README.md): Read and write an XIIDM file - [Example 2](example2/README.md): Use iidm4cpp in a CMake project +- [Example 3](example3/README.md): Use XIIDM extensions ## Advanced examples diff --git a/examples/example1/CMakeLists.txt b/examples/example1/CMakeLists.txt index 5cfb536dc..edb338f8e 100644 --- a/examples/example1/CMakeLists.txt +++ b/examples/example1/CMakeLists.txt @@ -6,4 +6,4 @@ # add_executable(example1 example1.cpp) -target_link_libraries(example1 PRIVATE iidm) +target_link_libraries(example1 PRIVATE iidm${TARGET_POSTFIX}) diff --git a/examples/example1/example1.cpp b/examples/example1/example1.cpp index 9e88efc65..8e2c33e29 100644 --- a/examples/example1/example1.cpp +++ b/examples/example1/example1.cpp @@ -27,11 +27,9 @@ int main(int argc, char** argv) { try { xmlInitParser(); - std::ifstream inputStream(argv[1]); - powsybl::iidm::Network network = powsybl::iidm::Network::readXml(inputStream); + powsybl::iidm::Network network = powsybl::iidm::Network::readXml(argv[1]); - std::ofstream outputStream(argv[2]); - powsybl::iidm::Network::writeXml(outputStream, network); + powsybl::iidm::Network::writeXml(argv[2], network); xmlCleanupParser(); diff --git a/examples/example2/CMakeLists.txt b/examples/example2/CMakeLists.txt index 23a606225..20c80b07d 100644 --- a/examples/example2/CMakeLists.txt +++ b/examples/example2/CMakeLists.txt @@ -11,7 +11,7 @@ cmake_minimum_required(VERSION 3.12 FATAL_ERROR) project(my-project) # Find the required dependencies: Boost, LibXML2 and IIDM and import the targets -find_package(Boost 1.56 REQUIRED COMPONENTS date_time filesystem program_options system unit_test_framework) +find_package(Boost 1.65 REQUIRED COMPONENTS date_time filesystem program_options system unit_test_framework) find_package(LibXml2 REQUIRED) find_package(LibIIDM REQUIRED) diff --git a/examples/example2/README.md b/examples/example2/README.md index 168626b75..0857a0aae 100644 --- a/examples/example2/README.md +++ b/examples/example2/README.md @@ -60,7 +60,7 @@ cmake_minimum_required(VERSION 3.12 FATAL_ERROR) project(my-project) # Find the required dependencies: Boost, LibXML2 and IIDM and import the targets -find_package(Boost 1.56 REQUIRED COMPONENTS date_time filesystem program_options system unit_test_framework) +find_package(Boost 1.65 REQUIRED COMPONENTS date_time filesystem program_options system unit_test_framework) find_package(LibXml2 REQUIRED) find_package(LibIIDM REQUIRED) diff --git a/examples/example3/CMakeLists.txt b/examples/example3/CMakeLists.txt new file mode 100644 index 000000000..b590b362e --- /dev/null +++ b/examples/example3/CMakeLists.txt @@ -0,0 +1,9 @@ +# +# Copyright (c) 2021, RTE (http://www.rte-france.com) +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +add_executable(example3 example3.cpp) +target_link_libraries(example3 PRIVATE iidm-static ext-iidm-static) diff --git a/examples/example3/README.md b/examples/example3/README.md new file mode 100644 index 000000000..fc1e5fce9 --- /dev/null +++ b/examples/example3/README.md @@ -0,0 +1,28 @@ +# Example 3 - Use XIIDM extensions + +This example shows how to create a cmake project that uses XIIDM extensions. In this example, we use the `EurostagNetworkFactory` to create a network. Then, we create an `ActivePowerRange` extension, attached to the generator `GEN`. Before exporting the network to an XIIDM file, we register its serializer. + +## Build +To build this example, you have to build the project passing the `-DBUILD_EXAMPLES=ON` flag to the configure command. Follow the [build instructions](../../README.md#build-from-sources) + +``` +$> cmake --build . +[ 49%] Built target iidm +[ 52%] Built target ext-iidm-static +[100%] Built target iidm-static +[100%] Building CXX object examples/example3/CMakeFiles/example3.dir/example3.cpp.o +[100%] Linking CXX executable example3 +[100%] Built target example3 +``` + +Note that in this example, we link with the static libraries but you can also link with the dynamic libraries. To do so, you have to change the `CMakeLists.txt` file: +``` +target_link_libraries(example3 PRIVATE iidm ext-iidm) +``` + +## Run the program +You can run the program we just compile, running the following command: +``` +$> ./example3 +Usage: ./example3 +``` diff --git a/examples/example3/example3.cpp b/examples/example3/example3.cpp new file mode 100644 index 000000000..79c038fa4 --- /dev/null +++ b/examples/example3/example3.cpp @@ -0,0 +1,61 @@ +/** + * @internal + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * @endinternal + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace xml = powsybl::iidm::converter::xml; +namespace ext = powsybl::iidm::extensions::iidm; + +/** + * @example example3.cpp + * This is an example of how to work with IIDM extensions. + */ +int main(int argc, char** argv) { + if (argc != 2) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return EXIT_FAILURE; + } + + try { + xmlInitParser(); + + powsybl::iidm::Network network = powsybl::network::EurostagFactory::createTutorial1Network(); + + network.getGenerator("GEN").newExtension() + .withDroop(4.0) + .withParticipate(true) + .add(); + + // Register the serializer for the ActivePowerControl extension + auto& extProvider = powsybl::iidm::ExtensionProviders::getInstance(); + extProvider.registerExtension(stdcxx::make_unique()); + + powsybl::iidm::Network::writeXml(argv[1], network); + + xmlCleanupParser(); + + } catch (const powsybl::PowsyblException& e) { + std::cout << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/extensions/entsoe/CMakeLists.txt b/extensions/entsoe/CMakeLists.txt index 615145a06..7973227b5 100644 --- a/extensions/entsoe/CMakeLists.txt +++ b/extensions/entsoe/CMakeLists.txt @@ -28,42 +28,58 @@ set(UNIT_TEST_SOURCES test/XnodeTest.cpp ) -# Shared library -add_library(${EXT_NAME} SHARED ${EXT_SOURCES}) -set_target_properties(${EXT_NAME} PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION} OUTPUT_NAME iidm-${EXT_NAME}) -target_include_directories(${EXT_NAME} - INTERFACE - $ - PUBLIC - $ -) -target_link_libraries(${EXT_NAME} PUBLIC iidm) +if (BUILD_SHARED_LIBS) + # Shared library + add_library(${EXT_NAME} SHARED ${EXT_SOURCES}) + set_target_properties(${EXT_NAME} PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION} OUTPUT_NAME iidm-${EXT_NAME}) + target_include_directories(${EXT_NAME} + INTERFACE + $ + PUBLIC + $ + ) + target_link_libraries(${EXT_NAME} PUBLIC iidm) -# Static library -add_library(${EXT_NAME}-static STATIC ${EXT_SOURCES}) -set_target_properties(${EXT_NAME}-static PROPERTIES OUTPUT_NAME iidm-${EXT_NAME}) -target_include_directories(${EXT_NAME}-static - INTERFACE - $ - PUBLIC - $ -) -target_link_libraries(${EXT_NAME}-static PUBLIC iidm) + # Installation + install(TARGETS ${EXT_NAME} + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () -# Unit tests -add_executable(unit-tests-${EXT_NAME} ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-${EXT_NAME} PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-${EXT_NAME} PRIVATE ${EXT_NAME} iidm-tests) +if (BUILD_STATIC_LIBS) + # Static library + add_library(${EXT_NAME}-static STATIC ${EXT_SOURCES}) + set_target_properties(${EXT_NAME}-static PROPERTIES OUTPUT_NAME iidm-${EXT_NAME}) + target_include_directories(${EXT_NAME}-static + INTERFACE + $ + PUBLIC + $ + ) + target_link_libraries(${EXT_NAME}-static PUBLIC iidm-static) -add_test(NAME ${EXT_NAME} COMMAND unit-tests-${EXT_NAME} -- --resources=${CMAKE_CURRENT_SOURCE_DIR}/resources) + # Installation + install(TARGETS ${EXT_NAME}-static + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () -# Installation -install(TARGETS ${EXT_NAME} ${EXT_NAME}-static - EXPORT iidm-targets - LIBRARY DESTINATION ${INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${INSTALL_LIB_DIR} - RUNTIME DESTINATION ${INSTALL_BIN_DIR} -) +if (BUILD_TESTS) + # Unit tests + add_executable(unit-tests-${EXT_NAME} ${UNIT_TEST_SOURCES}) + if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-${EXT_NAME} PRIVATE BOOST_TEST_DYN_LINK) + endif () + target_link_libraries(unit-tests-${EXT_NAME} PRIVATE ${EXT_NAME}${TARGET_POSTFIX} iidm-tests${TARGET_POSTFIX}) + + add_test(NAME ${EXT_NAME} COMMAND unit-tests-${EXT_NAME} -- --resources=${CMAKE_CURRENT_SOURCE_DIR}/resources) +endif() install(DIRECTORY include/powsybl DESTINATION ${INSTALL_INCLUDE_DIR} diff --git a/extensions/entsoe/include/powsybl/iidm/extensions/entsoe/XnodeAdder.hpp b/extensions/entsoe/include/powsybl/iidm/extensions/entsoe/XnodeAdder.hpp index 724520c79..7e73c3898 100644 --- a/extensions/entsoe/include/powsybl/iidm/extensions/entsoe/XnodeAdder.hpp +++ b/extensions/entsoe/include/powsybl/iidm/extensions/entsoe/XnodeAdder.hpp @@ -35,7 +35,7 @@ class XnodeAdder : public ExtensionAdder { /** * Copy constructor */ - XnodeAdder(const XnodeAdder& extendable) = default; + XnodeAdder(const XnodeAdder&) = default; /** * Move constructor diff --git a/extensions/entsoe/resources/entsoeArea.xml b/extensions/entsoe/resources/entsoeArea.xml index 719d4cddf..01db8bf64 100644 --- a/extensions/entsoe/resources/entsoeArea.xml +++ b/extensions/entsoe/resources/entsoeArea.xml @@ -1,5 +1,5 @@ - + FR diff --git a/extensions/entsoe/resources/mergedXnode.xml b/extensions/entsoe/resources/mergedXnode.xml index b6dc8fbe8..293f35664 100644 --- a/extensions/entsoe/resources/mergedXnode.xml +++ b/extensions/entsoe/resources/mergedXnode.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/entsoe/resources/xnode.xml b/extensions/entsoe/resources/xnode.xml index d072c5050..28b466dd4 100644 --- a/extensions/entsoe/resources/xnode.xml +++ b/extensions/entsoe/resources/xnode.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/entsoe/test/MergedXnodeTest.cpp b/extensions/entsoe/test/MergedXnodeTest.cpp index f99f36d45..1b16f621b 100644 --- a/extensions/entsoe/test/MergedXnodeTest.cpp +++ b/extensions/entsoe/test/MergedXnodeTest.cpp @@ -41,7 +41,7 @@ Network createNetwork() { .add(); VoltageLevel& vl1 = s1.newVoltageLevel() .setId("VL1") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl1.getBusBreakerView().newBus() @@ -53,7 +53,7 @@ Network createNetwork() { .add(); VoltageLevel& vl2 = s2.newVoltageLevel() .setId("VL2") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl2.getBusBreakerView().newBus() diff --git a/extensions/entsoe/test/XnodeTest.cpp b/extensions/entsoe/test/XnodeTest.cpp index 6ba871f57..137f743ef 100644 --- a/extensions/entsoe/test/XnodeTest.cpp +++ b/extensions/entsoe/test/XnodeTest.cpp @@ -40,7 +40,7 @@ Network createNetwork() { .add(); VoltageLevel& vl = s.newVoltageLevel() .setId("VL") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl.getBusBreakerView().newBus() diff --git a/extensions/entsoe/test/entsoe.cpp b/extensions/entsoe/test/entsoe.cpp index fa93da69d..d4a4e634b 100644 --- a/extensions/entsoe/test/entsoe.cpp +++ b/extensions/entsoe/test/entsoe.cpp @@ -8,14 +8,44 @@ #define BOOST_TEST_MODULE entsoe #include +#include +#include +#include +#include +#include #include #include +namespace xml = powsybl::iidm::converter::xml; +namespace ext = powsybl::iidm::extensions::entsoe; + namespace powsybl { namespace test { -BOOST_TEST_GLOBAL_FIXTURE(ExtensionFixture); +class ExtensionFixtureEnstsoe : public ResourceFixture { + public: + ExtensionFixtureEnstsoe(); + + ExtensionFixtureEnstsoe(const ExtensionFixtureEnstsoe&) = default; + + ExtensionFixtureEnstsoe(ExtensionFixtureEnstsoe&&) = default; + + ~ExtensionFixtureEnstsoe() = default; + + ExtensionFixtureEnstsoe& operator=(const ExtensionFixtureEnstsoe&) = default; + + ExtensionFixtureEnstsoe& operator=(ExtensionFixtureEnstsoe&&) = default; +}; + +ExtensionFixtureEnstsoe::ExtensionFixtureEnstsoe() { + auto& extProvider = powsybl::iidm::ExtensionProviders::getInstance(); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); +} + +BOOST_TEST_GLOBAL_FIXTURE(ExtensionFixtureEnstsoe); BOOST_TEST_GLOBAL_FIXTURE(XmlFixture); } // namespace test diff --git a/extensions/iidm/CMakeLists.txt b/extensions/iidm/CMakeLists.txt index 3692a27c5..859292b5c 100644 --- a/extensions/iidm/CMakeLists.txt +++ b/extensions/iidm/CMakeLists.txt @@ -35,42 +35,58 @@ set(UNIT_TEST_SOURCES test/VoltagePerReactivePowerControlTest.cpp ) -# Shared library -add_library(${EXT_NAME} SHARED ${EXT_SOURCES}) -set_target_properties(${EXT_NAME} PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION} OUTPUT_NAME iidm-${EXT_NAME}) -target_include_directories(${EXT_NAME} - INTERFACE - $ - PUBLIC - $ -) -target_link_libraries(${EXT_NAME} PUBLIC iidm) +if (BUILD_SHARED_LIBS) + # Shared library + add_library(${EXT_NAME} SHARED ${EXT_SOURCES}) + set_target_properties(${EXT_NAME} PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION} OUTPUT_NAME iidm-${EXT_NAME}) + target_include_directories(${EXT_NAME} + INTERFACE + $ + PUBLIC + $ + ) + target_link_libraries(${EXT_NAME} PUBLIC iidm) -# Static library -add_library(${EXT_NAME}-static STATIC ${EXT_SOURCES}) -set_target_properties(${EXT_NAME}-static PROPERTIES OUTPUT_NAME iidm-${EXT_NAME}) -target_include_directories(${EXT_NAME}-static - INTERFACE - $ - PUBLIC - $ -) -target_link_libraries(${EXT_NAME}-static PUBLIC iidm) + # Installation + install(TARGETS ${EXT_NAME} + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () -# Unit tests -add_executable(unit-tests-${EXT_NAME} ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-${EXT_NAME} PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-${EXT_NAME} PRIVATE ${EXT_NAME} iidm-tests) +if (BUILD_STATIC_LIBS) + # Static library + add_library(${EXT_NAME}-static STATIC ${EXT_SOURCES}) + set_target_properties(${EXT_NAME}-static PROPERTIES OUTPUT_NAME iidm-${EXT_NAME}) + target_include_directories(${EXT_NAME}-static + INTERFACE + $ + PUBLIC + $ + ) + target_link_libraries(${EXT_NAME}-static PUBLIC iidm-static) -add_test(NAME ${EXT_NAME} COMMAND unit-tests-${EXT_NAME} -- --resources=${CMAKE_CURRENT_SOURCE_DIR}/resources) + # Installation + install(TARGETS ${EXT_NAME}-static + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () -# Installation -install(TARGETS ${EXT_NAME} ${EXT_NAME}-static - EXPORT iidm-targets - LIBRARY DESTINATION ${INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${INSTALL_LIB_DIR} - RUNTIME DESTINATION ${INSTALL_BIN_DIR} -) +if (BUILD_TESTS) + # Unit tests + add_executable(unit-tests-${EXT_NAME} ${UNIT_TEST_SOURCES}) + if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-${EXT_NAME} PRIVATE BOOST_TEST_DYN_LINK) + endif () + target_link_libraries(unit-tests-${EXT_NAME} PRIVATE ${EXT_NAME}${TARGET_POSTFIX} iidm-tests${TARGET_POSTFIX}) + + add_test(NAME ${EXT_NAME} COMMAND unit-tests-${EXT_NAME} -- --resources=${CMAKE_CURRENT_SOURCE_DIR}/resources) +endif() install(DIRECTORY include/powsybl DESTINATION ${INSTALL_INCLUDE_DIR} diff --git a/extensions/iidm/resources/activePowerControl.xml b/extensions/iidm/resources/activePowerControl.xml index 67948ff56..e4c8047a2 100644 --- a/extensions/iidm/resources/activePowerControl.xml +++ b/extensions/iidm/resources/activePowerControl.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/iidm/resources/coordinatedReactiveControl.xml b/extensions/iidm/resources/coordinatedReactiveControl.xml index a59d1f4cc..15c34d50f 100644 --- a/extensions/iidm/resources/coordinatedReactiveControl.xml +++ b/extensions/iidm/resources/coordinatedReactiveControl.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/iidm/resources/threeWindingsTransformerPhaseAngleClock.xml b/extensions/iidm/resources/threeWindingsTransformerPhaseAngleClock.xml index 89c722045..db6fd3c49 100644 --- a/extensions/iidm/resources/threeWindingsTransformerPhaseAngleClock.xml +++ b/extensions/iidm/resources/threeWindingsTransformerPhaseAngleClock.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/iidm/resources/twoWindingsTransformerPhaseAngleClock.xml b/extensions/iidm/resources/twoWindingsTransformerPhaseAngleClock.xml index ef5c5c9ad..946ad557a 100644 --- a/extensions/iidm/resources/twoWindingsTransformerPhaseAngleClock.xml +++ b/extensions/iidm/resources/twoWindingsTransformerPhaseAngleClock.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/iidm/resources/voltagePerReactivePowerControl.xml b/extensions/iidm/resources/voltagePerReactivePowerControl.xml index cc17f4453..86548f690 100644 --- a/extensions/iidm/resources/voltagePerReactivePowerControl.xml +++ b/extensions/iidm/resources/voltagePerReactivePowerControl.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/iidm/src/ThreeWindingsTransformerPhaseAngleClock.cpp b/extensions/iidm/src/ThreeWindingsTransformerPhaseAngleClock.cpp index 4950c5acf..e1077e4b7 100644 --- a/extensions/iidm/src/ThreeWindingsTransformerPhaseAngleClock.cpp +++ b/extensions/iidm/src/ThreeWindingsTransformerPhaseAngleClock.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/extensions/iidm/src/TwoWindingsTransformerPhaseAngleClock.cpp b/extensions/iidm/src/TwoWindingsTransformerPhaseAngleClock.cpp index c0fbfc054..a9ecf77f3 100644 --- a/extensions/iidm/src/TwoWindingsTransformerPhaseAngleClock.cpp +++ b/extensions/iidm/src/TwoWindingsTransformerPhaseAngleClock.cpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/extensions/iidm/test/CoordinatedReactiveControlTest.cpp b/extensions/iidm/test/CoordinatedReactiveControlTest.cpp index 671f5dec8..df6d97c97 100644 --- a/extensions/iidm/test/CoordinatedReactiveControlTest.cpp +++ b/extensions/iidm/test/CoordinatedReactiveControlTest.cpp @@ -43,7 +43,7 @@ Network createNetwork() { .add(); VoltageLevel& vlgen = p1.newVoltageLevel() .setId("VLGEN") - .setNominalVoltage(24.0) + .setNominalV(24.0) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); Bus& ngen = vlgen.getBusBreakerView().newBus() diff --git a/extensions/iidm/test/VoltagePerReactivePowerControlTest.cpp b/extensions/iidm/test/VoltagePerReactivePowerControlTest.cpp index 65e2310fc..4f0cc350d 100644 --- a/extensions/iidm/test/VoltagePerReactivePowerControlTest.cpp +++ b/extensions/iidm/test/VoltagePerReactivePowerControlTest.cpp @@ -45,7 +45,7 @@ Network createStaticVarCompensatorTestNetwork() { .add(); VoltageLevel& vl1 = s1.newVoltageLevel() .setId("VL1") - .setNominalVoltage(380) + .setNominalV(380) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl1.getBusBreakerView().newBus() @@ -67,7 +67,7 @@ Network createStaticVarCompensatorTestNetwork() { .add(); VoltageLevel& vl2 = s2.newVoltageLevel() .setId("VL2") - .setNominalVoltage(380) + .setNominalV(380) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl2.getBusBreakerView().newBus() diff --git a/extensions/iidm/test/iidm.cpp b/extensions/iidm/test/iidm.cpp index 53295512b..edbac72b4 100644 --- a/extensions/iidm/test/iidm.cpp +++ b/extensions/iidm/test/iidm.cpp @@ -8,14 +8,48 @@ #define BOOST_TEST_MODULE iidm #include +#include +#include +#include +#include +#include +#include +#include #include #include +namespace xml = powsybl::iidm::converter::xml; +namespace ext = powsybl::iidm::extensions::iidm; + namespace powsybl { namespace test { -BOOST_TEST_GLOBAL_FIXTURE(ExtensionFixture); +class ExtensionFixtureIidm : public ResourceFixture { + public: + ExtensionFixtureIidm(); + + ExtensionFixtureIidm(const ExtensionFixtureIidm&) = default; + + ExtensionFixtureIidm(ExtensionFixtureIidm&&) = default; + + ~ExtensionFixtureIidm() = default; + + ExtensionFixtureIidm& operator=(const ExtensionFixtureIidm&) = default; + + ExtensionFixtureIidm& operator=(ExtensionFixtureIidm&&) = default; +}; + +ExtensionFixtureIidm::ExtensionFixtureIidm() { + auto& extProvider = powsybl::iidm::ExtensionProviders::getInstance(); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); +} + +BOOST_TEST_GLOBAL_FIXTURE(ExtensionFixtureIidm); BOOST_TEST_GLOBAL_FIXTURE(XmlFixture); } // namespace test diff --git a/extensions/sld/CMakeLists.txt b/extensions/sld/CMakeLists.txt index c43595328..171fddc36 100644 --- a/extensions/sld/CMakeLists.txt +++ b/extensions/sld/CMakeLists.txt @@ -23,42 +23,58 @@ set(UNIT_TEST_SOURCES test/sld.cpp ) -# Shared library -add_library(${EXT_NAME} SHARED ${EXT_SOURCES}) -set_target_properties(${EXT_NAME} PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION} OUTPUT_NAME iidm-${EXT_NAME}) -target_include_directories(${EXT_NAME} - INTERFACE - $ - PUBLIC - $ -) -target_link_libraries(${EXT_NAME} PUBLIC iidm) +if (BUILD_SHARED_LIBS) + # Shared library + add_library(${EXT_NAME} SHARED ${EXT_SOURCES}) + set_target_properties(${EXT_NAME} PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION} OUTPUT_NAME iidm-${EXT_NAME}) + target_include_directories(${EXT_NAME} + INTERFACE + $ + PUBLIC + $ + ) + target_link_libraries(${EXT_NAME} PUBLIC iidm) -# Static library -add_library(${EXT_NAME}-static STATIC ${EXT_SOURCES}) -set_target_properties(${EXT_NAME}-static PROPERTIES OUTPUT_NAME iidm-${EXT_NAME}) -target_include_directories(${EXT_NAME}-static - INTERFACE - $ - PUBLIC - $ -) -target_link_libraries(${EXT_NAME}-static PUBLIC iidm) + # Installation + install(TARGETS ${EXT_NAME} + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () -# Unit tests -add_executable(unit-tests-${EXT_NAME} ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-${EXT_NAME} PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-${EXT_NAME} PRIVATE ${EXT_NAME} iidm-tests) +if (BUILD_STATIC_LIBS) + # Static library + add_library(${EXT_NAME}-static STATIC ${EXT_SOURCES}) + set_target_properties(${EXT_NAME}-static PROPERTIES OUTPUT_NAME iidm-${EXT_NAME}) + target_include_directories(${EXT_NAME}-static + INTERFACE + $ + PUBLIC + $ + ) + target_link_libraries(${EXT_NAME}-static PUBLIC iidm-static) -add_test(NAME ${EXT_NAME} COMMAND unit-tests-${EXT_NAME} -- --resources=${CMAKE_CURRENT_SOURCE_DIR}/resources) + # Installation + install(TARGETS ${EXT_NAME}-static + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () -# Installation -install(TARGETS ${EXT_NAME} ${EXT_NAME}-static - EXPORT iidm-targets - LIBRARY DESTINATION ${INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${INSTALL_LIB_DIR} - RUNTIME DESTINATION ${INSTALL_BIN_DIR} -) +if (BUILD_TESTS) + # Unit tests + add_executable(unit-tests-${EXT_NAME} ${UNIT_TEST_SOURCES}) + if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-${EXT_NAME} PRIVATE BOOST_TEST_DYN_LINK) + endif () + target_link_libraries(unit-tests-${EXT_NAME} PRIVATE ${EXT_NAME}${TARGET_POSTFIX} iidm-tests${TARGET_POSTFIX}) + + add_test(NAME ${EXT_NAME} COMMAND unit-tests-${EXT_NAME} -- --resources=${CMAKE_CURRENT_SOURCE_DIR}/resources) +endif() install(DIRECTORY include/powsybl DESTINATION ${INSTALL_INCLUDE_DIR} diff --git a/extensions/sld/include/powsybl/iidm/extensions/sld/ConnectablePositionXmlSerializer.hpp b/extensions/sld/include/powsybl/iidm/extensions/sld/ConnectablePositionXmlSerializer.hpp index 7639b65f4..d63882b96 100644 --- a/extensions/sld/include/powsybl/iidm/extensions/sld/ConnectablePositionXmlSerializer.hpp +++ b/extensions/sld/include/powsybl/iidm/extensions/sld/ConnectablePositionXmlSerializer.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace powsybl { @@ -34,7 +35,7 @@ class ConnectablePositionXmlSerializer : public converter::xml::AbstractExtensio private: void readPosition(const converter::xml::NetworkXmlReaderContext& context, ConnectablePositionAdder::FeederAdder& feederAdder) const; - void writePosition(const ConnectablePosition::Feeder& feeder, converter::xml::NetworkXmlWriterContext& context, const boost::optional& index = boost::optional()) const; + void writePosition(const ConnectablePosition::Feeder& feeder, converter::xml::NetworkXmlWriterContext& context, const stdcxx::optional& index = stdcxx::optional()) const; }; } // namespace sld diff --git a/extensions/sld/resources/busbarSectionPosition.xml b/extensions/sld/resources/busbarSectionPosition.xml index b869a6edd..07dcfe354 100644 --- a/extensions/sld/resources/busbarSectionPosition.xml +++ b/extensions/sld/resources/busbarSectionPosition.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/sld/resources/connectablePositionFeeder0.xml b/extensions/sld/resources/connectablePositionFeeder0.xml index 6b58ffdb0..f36c1a530 100644 --- a/extensions/sld/resources/connectablePositionFeeder0.xml +++ b/extensions/sld/resources/connectablePositionFeeder0.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/sld/resources/connectablePositionFeeders123.xml b/extensions/sld/resources/connectablePositionFeeders123.xml index 151f972f6..b9b5dd84b 100644 --- a/extensions/sld/resources/connectablePositionFeeders123.xml +++ b/extensions/sld/resources/connectablePositionFeeders123.xml @@ -1,5 +1,5 @@ - + diff --git a/extensions/sld/src/BusbarSectionPositionAdder.cpp b/extensions/sld/src/BusbarSectionPositionAdder.cpp index fcd5c9cb9..cb97e09e4 100644 --- a/extensions/sld/src/BusbarSectionPositionAdder.cpp +++ b/extensions/sld/src/BusbarSectionPositionAdder.cpp @@ -25,10 +25,10 @@ BusbarSectionPositionAdder::BusbarSectionPositionAdder(Extendable& extendable) : } std::unique_ptr BusbarSectionPositionAdder::createExtension(Extendable& extendable) { - if (!m_busbarIndex.is_initialized()) { + if (!m_busbarIndex) { throw PowsyblException("Undefined value for busbar index"); } - if (!m_sectionIndex.is_initialized()) { + if (!m_sectionIndex) { throw PowsyblException("Undefined value for section index"); } if (stdcxx::isInstanceOf(extendable)) { diff --git a/extensions/sld/src/ConnectablePosition.cpp b/extensions/sld/src/ConnectablePosition.cpp index 2465d6727..42b83917b 100644 --- a/extensions/sld/src/ConnectablePosition.cpp +++ b/extensions/sld/src/ConnectablePosition.cpp @@ -104,35 +104,35 @@ void ConnectablePosition::check(const OptionalFeeder& feeder, const OptionalFeed } stdcxx::CReference ConnectablePosition::getFeeder() const { - return m_feeder.is_initialized() ? stdcxx::cref(*m_feeder) : stdcxx::cref(); + return m_feeder ? stdcxx::cref(*m_feeder) : stdcxx::cref(); } stdcxx::Reference ConnectablePosition::getFeeder() { - return m_feeder.is_initialized() ? stdcxx::ref(*m_feeder) : stdcxx::ref(); + return m_feeder ? stdcxx::ref(*m_feeder) : stdcxx::ref(); } stdcxx::CReference ConnectablePosition::getFeeder1() const { - return m_feeder1.is_initialized() ? stdcxx::cref(*m_feeder1) : stdcxx::cref(); + return m_feeder1 ? stdcxx::cref(*m_feeder1) : stdcxx::cref(); } stdcxx::Reference ConnectablePosition::getFeeder1() { - return m_feeder1.is_initialized() ? stdcxx::ref(*m_feeder1) : stdcxx::ref(); + return m_feeder1 ? stdcxx::ref(*m_feeder1) : stdcxx::ref(); } stdcxx::CReference ConnectablePosition::getFeeder2() const { - return m_feeder2.is_initialized() ? stdcxx::cref(*m_feeder2) : stdcxx::cref(); + return m_feeder2 ? stdcxx::cref(*m_feeder2) : stdcxx::cref(); } stdcxx::Reference ConnectablePosition::getFeeder2() { - return m_feeder2.is_initialized() ? stdcxx::ref(*m_feeder2) : stdcxx::ref(); + return m_feeder2 ? stdcxx::ref(*m_feeder2) : stdcxx::ref(); } stdcxx::CReference ConnectablePosition::getFeeder3() const { - return m_feeder3.is_initialized() ? stdcxx::cref(*m_feeder3) : stdcxx::cref(); + return m_feeder3 ? stdcxx::cref(*m_feeder3) : stdcxx::cref(); } stdcxx::Reference ConnectablePosition::getFeeder3() { - return m_feeder3.is_initialized() ? stdcxx::ref(*m_feeder3) : stdcxx::ref(); + return m_feeder3 ? stdcxx::ref(*m_feeder3) : stdcxx::ref(); } const std::string& ConnectablePosition::getName() const { diff --git a/extensions/sld/src/ConnectablePositionAdder.cpp b/extensions/sld/src/ConnectablePositionAdder.cpp index 7baee002c..2d27930fa 100644 --- a/extensions/sld/src/ConnectablePositionAdder.cpp +++ b/extensions/sld/src/ConnectablePositionAdder.cpp @@ -27,10 +27,10 @@ ConnectablePositionAdder& ConnectablePositionAdder::FeederAdder::add() { if (m_name.empty()) { throw PowsyblException("Feeder name is empty"); } - if (!m_order.is_initialized()) { + if (!m_order) { throw PowsyblException("Feeder order is not set"); } - if (!m_direction.is_initialized()) { + if (!m_direction) { throw PowsyblException("Feeder direction is not set"); } m_feeder = ConnectablePosition::Feeder(m_name, *m_order, *m_direction); diff --git a/extensions/sld/src/ConnectablePositionXmlSerializer.cpp b/extensions/sld/src/ConnectablePositionXmlSerializer.cpp index 032dfc0d8..d25a40fdb 100644 --- a/extensions/sld/src/ConnectablePositionXmlSerializer.cpp +++ b/extensions/sld/src/ConnectablePositionXmlSerializer.cpp @@ -77,7 +77,7 @@ void ConnectablePositionXmlSerializer::write(const Extension& extension, convert } } -void ConnectablePositionXmlSerializer::writePosition(const ConnectablePosition::Feeder& feeder, converter::xml::NetworkXmlWriterContext& context, const boost::optional& index) const { +void ConnectablePositionXmlSerializer::writePosition(const ConnectablePosition::Feeder& feeder, converter::xml::NetworkXmlWriterContext& context, const stdcxx::optional& index) const { std::string elementName = "feeder"; if (index) { elementName += std::to_string(*index); diff --git a/extensions/sld/test/BusbarSectionPositionTest.cpp b/extensions/sld/test/BusbarSectionPositionTest.cpp index a5ae9cf3d..16e487d59 100644 --- a/extensions/sld/test/BusbarSectionPositionTest.cpp +++ b/extensions/sld/test/BusbarSectionPositionTest.cpp @@ -43,7 +43,7 @@ Network createBusbarSectionNetwork() { VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); diff --git a/extensions/sld/test/sld.cpp b/extensions/sld/test/sld.cpp index bca4d2f64..a2f52f88f 100644 --- a/extensions/sld/test/sld.cpp +++ b/extensions/sld/test/sld.cpp @@ -8,14 +8,41 @@ #define BOOST_TEST_MODULE sld #include +#include +#include +#include #include #include +namespace xml = powsybl::iidm::converter::xml; +namespace ext = powsybl::iidm::extensions::sld; + namespace powsybl { namespace test { -BOOST_TEST_GLOBAL_FIXTURE(ExtensionFixture); +class ExtensionFixtureSld : public ResourceFixture { + public: + ExtensionFixtureSld(); + + ExtensionFixtureSld(const ExtensionFixtureSld&) = default; + + ExtensionFixtureSld(ExtensionFixtureSld&&) = default; + + ~ExtensionFixtureSld() = default; + + ExtensionFixtureSld& operator=(const ExtensionFixtureSld&) = default; + + ExtensionFixtureSld& operator=(ExtensionFixtureSld&&) = default; +}; + +ExtensionFixtureSld::ExtensionFixtureSld() { + auto& extProvider = powsybl::iidm::ExtensionProviders::getInstance(); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); +} + +BOOST_TEST_GLOBAL_FIXTURE(ExtensionFixtureSld); BOOST_TEST_GLOBAL_FIXTURE(XmlFixture); } // namespace test diff --git a/include/powsybl/iidm/AbstractComponentsManager.hpp b/include/powsybl/iidm/AbstractComponentsManager.hpp index d665ec003..1066ff844 100644 --- a/include/powsybl/iidm/AbstractComponentsManager.hpp +++ b/include/powsybl/iidm/AbstractComponentsManager.hpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/AbstractTerminalTopologyVisitor.hpp b/include/powsybl/iidm/AbstractTerminalTopologyVisitor.hpp new file mode 100644 index 000000000..06ba59fb0 --- /dev/null +++ b/include/powsybl/iidm/AbstractTerminalTopologyVisitor.hpp @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef POWSYBL_IIDM_ABSTRACTTERMINALTOPOLOGYVISITOR_HPP +#define POWSYBL_IIDM_ABSTRACTTERMINALTOPOLOGYVISITOR_HPP + +#include + +namespace powsybl { + +namespace iidm { + +class Injection; + +class AbstractTerminalTopologyVisitor : public TopologyVisitor { +public: // TopologyVisitor + void visitBattery(const Battery& battery) override; + + void visitBusbarSection(const BusbarSection& section) override; + + void visitDanglingLine(const DanglingLine& danglingLine) override; + + void visitGenerator(const Generator& generator) override; + + void visitHvdcConverterStation(const HvdcConverterStation& converterStation) override; + + void visitLine(const Line& line, const Branch::Side& side) override; + + void visitLoad(const Load& load) override; + + void visitShuntCompensator(const ShuntCompensator& sc) override; + + void visitStaticVarCompensator(const StaticVarCompensator& staticVarCompensator) override; + + void visitThreeWindingsTransformer(const ThreeWindingsTransformer& transformer, const ThreeWindingsTransformer::Side& side) override; + + void visitTwoWindingsTransformer(const TwoWindingsTransformer& transformer, const Branch::Side& side) override; + +public: + AbstractTerminalTopologyVisitor() = default; + + AbstractTerminalTopologyVisitor(const AbstractTerminalTopologyVisitor&) = default; + + AbstractTerminalTopologyVisitor(AbstractTerminalTopologyVisitor&&) noexcept = default; + + ~AbstractTerminalTopologyVisitor() noexcept override = default; + + AbstractTerminalTopologyVisitor& operator=(const AbstractTerminalTopologyVisitor&) = default; + + AbstractTerminalTopologyVisitor& operator=(AbstractTerminalTopologyVisitor&&) noexcept = default; + + virtual void visitTerminal(const Terminal& terminal) = 0; + +private: + void visitBranch(const Branch& branch, const Branch::Side& side); + + void visitInjection(const Injection& injection); +}; + +} // namespace iidm + +} // namespace powsybl + +#endif // POWSYBL_IIDM_ABSTRACTTERMINALTOPOLOGYVISITOR_HPP diff --git a/include/powsybl/iidm/Bus.hpp b/include/powsybl/iidm/Bus.hpp index 6e358df76..ce18d09fd 100644 --- a/include/powsybl/iidm/Bus.hpp +++ b/include/powsybl/iidm/Bus.hpp @@ -30,6 +30,7 @@ class ShuntCompensator; class StaticVarCompensator; class Terminal; class ThreeWindingsTransformer; +class TopologyVisitor; class TwoWindingsTransformer; class VoltageLevel; class VscConverterStation; @@ -79,6 +80,10 @@ class Bus : public Identifiable { stdcxx::range getLoads(); + double getP() const; + + double getQ() const; + stdcxx::const_range getShuntCompensators() const; stdcxx::range getShuntCompensators(); @@ -117,6 +122,10 @@ class Bus : public Identifiable { virtual Bus& setV(double v) = 0; + void visitConnectedEquipments(TopologyVisitor& visitor); + + virtual void visitConnectedOrConnectableEquipments(TopologyVisitor& visitor) = 0; + protected: Bus(const std::string& id, const std::string& name, bool fictitious); diff --git a/include/powsybl/iidm/Component.hpp b/include/powsybl/iidm/Component.hpp index eb63bac2a..7bfe65a2f 100644 --- a/include/powsybl/iidm/Component.hpp +++ b/include/powsybl/iidm/Component.hpp @@ -21,15 +21,15 @@ class Component { public: Component(Network& network, unsigned long num, unsigned long size); - Component(const Component& component) = delete; + Component(const Component&) = delete; - Component(Component&& component) noexcept = delete; + Component(Component&&) noexcept = delete; virtual ~Component() noexcept = default; - Component& operator=(const Component& component) = delete; + Component& operator=(const Component&) = delete; - Component& operator=(Component&& component) noexcept = delete; + Component& operator=(Component&&) noexcept = delete; stdcxx::const_range getBuses() const; diff --git a/include/powsybl/iidm/Connectable.hpp b/include/powsybl/iidm/Connectable.hpp index d72a3e6d1..ea868c52e 100644 --- a/include/powsybl/iidm/Connectable.hpp +++ b/include/powsybl/iidm/Connectable.hpp @@ -36,7 +36,7 @@ class Connectable : public Identifiable { std::vector > getTerminals() const; - void remove(); + virtual void remove(); protected: // MultiVariantObject void allocateVariantArrayElement(const std::set& indexes, unsigned long sourceIndex) override; diff --git a/include/powsybl/iidm/CurrentLimitsAdder.hxx b/include/powsybl/iidm/CurrentLimitsAdder.hxx index c47f10c95..71d12ea51 100644 --- a/include/powsybl/iidm/CurrentLimitsAdder.hxx +++ b/include/powsybl/iidm/CurrentLimitsAdder.hxx @@ -19,7 +19,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/DanglingLine.hpp b/include/powsybl/iidm/DanglingLine.hpp index b053b88fa..7e0a70394 100644 --- a/include/powsybl/iidm/DanglingLine.hpp +++ b/include/powsybl/iidm/DanglingLine.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/DanglingLineGeneration.hpp b/include/powsybl/iidm/DanglingLineGeneration.hpp index ecf5a9d27..4ece846f6 100644 --- a/include/powsybl/iidm/DanglingLineGeneration.hpp +++ b/include/powsybl/iidm/DanglingLineGeneration.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/Extendable.hpp b/include/powsybl/iidm/Extendable.hpp index 62a98c416..ccac9f11e 100644 --- a/include/powsybl/iidm/Extendable.hpp +++ b/include/powsybl/iidm/Extendable.hpp @@ -50,6 +50,12 @@ class Extendable { template ::value>::type> E& getExtension(); + template ::value>::type> + stdcxx::CReference getExtensionByName(const std::string& name) const; + + template ::value>::type> + stdcxx::Reference getExtensionByName(const std::string& name); + stdcxx::const_range getExtensions() const; stdcxx::range getExtensions(); diff --git a/include/powsybl/iidm/Extendable.hxx b/include/powsybl/iidm/Extendable.hxx index 71c1d38de..b48fa0c35 100644 --- a/include/powsybl/iidm/Extendable.hxx +++ b/include/powsybl/iidm/Extendable.hxx @@ -55,6 +55,20 @@ E& Extendable::getExtension() { return const_cast(static_cast(this)->getExtension()); } +template +stdcxx::CReference Extendable::getExtensionByName(const std::string& name) const { + auto it = m_extensionsByName.find(name); + if (it != m_extensionsByName.end() && stdcxx::isInstanceOf(*it->second)) { + return stdcxx::cref(dynamic_cast(*it->second)); + } + return stdcxx::cref(); +} + +template +stdcxx::Reference Extendable::getExtensionByName(const std::string& name) { + return stdcxx::ref(const_cast(this)->getExtensionByName(name)); +} + template Adder Extendable::newExtension() { return Adder(*this); diff --git a/include/powsybl/iidm/Extension.hpp b/include/powsybl/iidm/Extension.hpp index 385b5c34c..ced3dcde3 100644 --- a/include/powsybl/iidm/Extension.hpp +++ b/include/powsybl/iidm/Extension.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/ExtensionProviders.hpp b/include/powsybl/iidm/ExtensionProviders.hpp index 04662ca38..e390e95f7 100644 --- a/include/powsybl/iidm/ExtensionProviders.hpp +++ b/include/powsybl/iidm/ExtensionProviders.hpp @@ -19,7 +19,7 @@ #include #include -#include +#include namespace powsybl { @@ -49,6 +49,8 @@ class ExtensionProviders { void loadExtensions(const boost::filesystem::path& directory, const std::regex& pattern); + void registerExtension(std::unique_ptr&& provider, const boost::filesystem::path& libraryPath = boost::filesystem::path()); + private: ExtensionProviders(); @@ -58,8 +60,6 @@ class ExtensionProviders { void loadLibrary(const boost::filesystem::path& libraryPath); - void registerExtension(std::unique_ptr provider, const boost::filesystem::path& libraryPath = boost::filesystem::path()); - private: std::map m_loadedLibraries; diff --git a/include/powsybl/iidm/GeneratorAdder.hpp b/include/powsybl/iidm/GeneratorAdder.hpp index 2fdebc1f3..5fbadec51 100644 --- a/include/powsybl/iidm/GeneratorAdder.hpp +++ b/include/powsybl/iidm/GeneratorAdder.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/HalfLine.hpp b/include/powsybl/iidm/HalfLine.hpp index f4810df2f..ebd2361c0 100644 --- a/include/powsybl/iidm/HalfLine.hpp +++ b/include/powsybl/iidm/HalfLine.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/HvdcConverterStation.hpp b/include/powsybl/iidm/HvdcConverterStation.hpp index 94d464274..22521bcc2 100644 --- a/include/powsybl/iidm/HvdcConverterStation.hpp +++ b/include/powsybl/iidm/HvdcConverterStation.hpp @@ -9,7 +9,7 @@ #define POWSYBL_IIDM_HVDCCONVERTERSTATION_HPP #include -#include +#include namespace powsybl { @@ -18,6 +18,9 @@ namespace iidm { class HvdcLine; class HvdcConverterStation : public Injection { +public: // Connectable + void remove() override; + public: enum class HvdcType { VSC, diff --git a/include/powsybl/iidm/HvdcLine.hpp b/include/powsybl/iidm/HvdcLine.hpp index 9bb3daaee..7a27aee6d 100644 --- a/include/powsybl/iidm/HvdcLine.hpp +++ b/include/powsybl/iidm/HvdcLine.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace powsybl { @@ -39,7 +39,7 @@ class HvdcLine : public Identifiable { Network& getNetwork() override; public: - HvdcLine(Network& network, const std::string& id, const std::string& name, bool fictitious, double r, double nominalVoltage, double maxP, + HvdcLine(Network& network, const std::string& id, const std::string& name, bool fictitious, double r, double nominalV, double maxP, const ConvertersMode& convertersMode, double activePowerSetpoint, HvdcConverterStation& converterStation1, HvdcConverterStation& converterStation2); ~HvdcLine() noexcept override = default; @@ -62,7 +62,7 @@ class HvdcLine : public Identifiable { double getMaxP() const; - double getNominalVoltage() const; + double getNominalV() const; double getR() const; @@ -74,7 +74,7 @@ class HvdcLine : public Identifiable { HvdcLine& setMaxP(double maxP); - HvdcLine& setNominalVoltage(double nominalVoltage); + HvdcLine& setNominalV(double nominalV); HvdcLine& setR(double r); @@ -98,7 +98,7 @@ class HvdcLine : public Identifiable { double m_r; - double m_nominalVoltage; + double m_nominalV; double m_maxP; diff --git a/include/powsybl/iidm/HvdcLineAdder.hpp b/include/powsybl/iidm/HvdcLineAdder.hpp index c7a79ca95..9ecdcbc1b 100644 --- a/include/powsybl/iidm/HvdcLineAdder.hpp +++ b/include/powsybl/iidm/HvdcLineAdder.hpp @@ -36,7 +36,7 @@ class HvdcLineAdder : public IdentifiableAdder { HvdcLineAdder& setMaxP(double maxP); - HvdcLineAdder& setNominalVoltage(double nominalVoltage); + HvdcLineAdder& setNominalV(double nominalV); HvdcLineAdder& setR(double r); @@ -64,7 +64,7 @@ class HvdcLineAdder : public IdentifiableAdder { double m_r = stdcxx::nan(); - double m_nominalVoltage = stdcxx::nan(); + double m_nominalV = stdcxx::nan(); double m_maxP = stdcxx::nan(); diff --git a/include/powsybl/iidm/Identifiable.hpp b/include/powsybl/iidm/Identifiable.hpp index dc3a86cef..444142de1 100644 --- a/include/powsybl/iidm/Identifiable.hpp +++ b/include/powsybl/iidm/Identifiable.hpp @@ -8,6 +8,7 @@ #ifndef POWSYBL_IIDM_IDENTIFIABLE_HPP #define POWSYBL_IIDM_IDENTIFIABLE_HPP +#include #include #include @@ -31,7 +32,7 @@ class Identifiable : public virtual Validable, public Extendable, public MultiVa public: Identifiable(const Identifiable&) = delete; - // Move constructor of stdcxx::Properties is not marked noexcept + // NOLINTNEXTLINE(performance-noexcept-move-constructor): move constructor of stdcxx::Properties is not marked noexcept Identifiable(Identifiable&&) = default; // NOSONAR ~Identifiable() noexcept override = default; @@ -42,7 +43,21 @@ class Identifiable : public virtual Validable, public Extendable, public MultiVa void addAlias(const std::string& alias); - const std::set& getAliases() const; + void addAlias(const std::string& alias, bool ensureAliasUnicity); + + void addAlias(const std::string& alias, const std::string& aliasType); + + void addAlias(const std::string& alias, const char* aliasType); + + void addAlias(const std::string& alias, const std::string& aliasType, bool ensureAliasUnicity); + + void addAlias(const std::string& alias, const char* aliasType, bool ensureAliasUnicity); + + stdcxx::const_range getAliases() const; + + stdcxx::optional getAliasFromType(const std::string& aliasType) const; + + std::string getAliasType(const std::string& alias) const; const std::string& getId() const; @@ -98,7 +113,9 @@ class Identifiable : public virtual Validable, public Extendable, public MultiVa stdcxx::Properties m_properties; - std::set m_aliases; + std::set m_aliasesWithoutType; + + std::map m_aliasesByType; }; std::ostream& operator<<(std::ostream& stream, const Identifiable& identifiable); diff --git a/include/powsybl/iidm/IdentifiableAdder.hxx b/include/powsybl/iidm/IdentifiableAdder.hxx index dd65cff0c..7b872c401 100644 --- a/include/powsybl/iidm/IdentifiableAdder.hxx +++ b/include/powsybl/iidm/IdentifiableAdder.hxx @@ -32,7 +32,7 @@ std::string IdentifiableAdder::checkAndGetUniqueId() const { std::string uniqueId; if (m_ensureIdUnicity) { - uniqueId = util::Identifiables::getUniqueId(m_id, [&network](const std::string& id) { + uniqueId = Identifiables::getUniqueId(m_id, [&network](const std::string& id) { return static_cast(network.find(id)); }); } else { diff --git a/include/powsybl/iidm/InternalConnection.hpp b/include/powsybl/iidm/InternalConnection.hpp index 2ac1d114f..a7d3c33b5 100644 --- a/include/powsybl/iidm/InternalConnection.hpp +++ b/include/powsybl/iidm/InternalConnection.hpp @@ -20,7 +20,7 @@ class InternalConnection { public: InternalConnection(unsigned long node1, unsigned long node2); - InternalConnection(const InternalConnection& internalConnection) = default; + InternalConnection(const InternalConnection&) = default; ~InternalConnection() = default; diff --git a/include/powsybl/iidm/Network.hpp b/include/powsybl/iidm/Network.hpp index c903778e8..28f1b2f19 100644 --- a/include/powsybl/iidm/Network.hpp +++ b/include/powsybl/iidm/Network.hpp @@ -8,6 +8,8 @@ #ifndef POWSYBL_IIDM_NETWORK_HPP #define POWSYBL_IIDM_NETWORK_HPP +#include + #include #include #include @@ -16,7 +18,8 @@ #include #include #include -#include +#include +#include #include #include @@ -50,13 +53,6 @@ class TwoWindingsTransformer; class VoltageLevel; class VscConverterStation; -namespace converter { - -class ExportOptions; -class ImportOptions; - -} // namespace converter - class Network : public Container, public VariantManagerHolder { public: using BusBreakerView = network::BusBreakerView; @@ -64,15 +60,13 @@ class Network : public Container, public VariantManagerHolder { using BusView = network::BusView; public: - static Network readXml(const std::string& data); - - static Network readXml(std::istream& istream); + static Network readXml(const boost::filesystem::path& path, const converter::ImportOptions& options = converter::ImportOptions()); - static Network readXml(std::istream& istream, const converter::ImportOptions& options, const converter::Anonymizer& anonymizer); + static Network readXml(const std::string& filename, std::istream& istream, const converter::ImportOptions& options = converter::ImportOptions()); - static std::unique_ptr writeXml(std::ostream& ostream, const Network& network); + static void writeXml(const boost::filesystem::path& path, const Network& network, const converter::ExportOptions& options = converter::ExportOptions()); - static std::unique_ptr writeXml(std::ostream& ostream, const Network& network, const converter::ExportOptions& options); + static void writeXml(const std::string& filename, std::ostream& ostream, const Network& network, const converter::ExportOptions& options = converter::ExportOptions()); public: // Identifiable const Network& getNetwork() const override; @@ -108,6 +102,10 @@ class Network : public Container, public VariantManagerHolder { template ::value>::type> stdcxx::Reference find(const std::string& id); + stdcxx::CReference findHvdcLine(const HvdcConverterStation& station) const; + + stdcxx::Reference findHvdcLine(const HvdcConverterStation& station); + template ::value>::type> const T& get(const std::string& id) const; @@ -167,6 +165,8 @@ class Network : public Container, public VariantManagerHolder { ConnectedComponentsManager& getConnectedComponentsManager(); + std::set getCountries() const; + unsigned long getCountryCount() const; const DanglingLine& getDanglingLine(const std::string& id) const; @@ -205,6 +205,10 @@ class Network : public Container, public VariantManagerHolder { HvdcLine& getHvdcLine(const std::string& id); + const HvdcLine& getHvdcLine(const HvdcConverterStation& station) const; + + HvdcLine& getHvdcLine(const HvdcConverterStation& station); + unsigned long getHvdcLineCount() const; stdcxx::const_range getHvdcLines() const; @@ -375,6 +379,10 @@ class Network : public Container, public VariantManagerHolder { friend class Identifiable; + friend class VoltageLevel; + + friend class NodeBreakerVoltageLevel; + private: stdcxx::DateTime m_caseDate; diff --git a/include/powsybl/iidm/NetworkIndex.hpp b/include/powsybl/iidm/NetworkIndex.hpp index a0f41acff..e48e55518 100644 --- a/include/powsybl/iidm/NetworkIndex.hpp +++ b/include/powsybl/iidm/NetworkIndex.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/NetworkIndex.hxx b/include/powsybl/iidm/NetworkIndex.hxx index dd4782ede..813b307f6 100644 --- a/include/powsybl/iidm/NetworkIndex.hxx +++ b/include/powsybl/iidm/NetworkIndex.hxx @@ -18,7 +18,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/NetworkViews.hpp b/include/powsybl/iidm/NetworkViews.hpp index 539b3f110..b2e50fe96 100644 --- a/include/powsybl/iidm/NetworkViews.hpp +++ b/include/powsybl/iidm/NetworkViews.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/PhaseTapChangerAdder.hpp b/include/powsybl/iidm/PhaseTapChangerAdder.hpp index b9caaca44..2abc0d9cf 100644 --- a/include/powsybl/iidm/PhaseTapChangerAdder.hpp +++ b/include/powsybl/iidm/PhaseTapChangerAdder.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/PhaseTapChangerHolder.hpp b/include/powsybl/iidm/PhaseTapChangerHolder.hpp index b887f12be..a8d6875fa 100644 --- a/include/powsybl/iidm/PhaseTapChangerHolder.hpp +++ b/include/powsybl/iidm/PhaseTapChangerHolder.hpp @@ -9,7 +9,7 @@ #define POWSYBL_IIDM_PHASETAPCHANGERHOLDER_HPP #include -#include +#include namespace powsybl { @@ -36,7 +36,7 @@ class PhaseTapChangerHolder : public virtual TapChangerHolder { PhaseTapChangerHolder() noexcept = default; private: - virtual void setPhaseTapChanger(std::unique_ptr ratioTapChanger) = 0; + virtual void setPhaseTapChanger(std::unique_ptr&& phaseTapChanger) = 0; private: friend class PhaseTapChanger; diff --git a/include/powsybl/iidm/RatioTapChangerAdder.hpp b/include/powsybl/iidm/RatioTapChangerAdder.hpp index 1e86c6887..d34f1aa8c 100644 --- a/include/powsybl/iidm/RatioTapChangerAdder.hpp +++ b/include/powsybl/iidm/RatioTapChangerAdder.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/RatioTapChangerHolder.hpp b/include/powsybl/iidm/RatioTapChangerHolder.hpp index 5b77808d7..2247dd54b 100644 --- a/include/powsybl/iidm/RatioTapChangerHolder.hpp +++ b/include/powsybl/iidm/RatioTapChangerHolder.hpp @@ -9,7 +9,7 @@ #define POWSYBL_IIDM_RATIOTAPCHANGERHOLDER_HPP #include -#include +#include namespace powsybl { @@ -36,7 +36,7 @@ class RatioTapChangerHolder : public virtual TapChangerHolder { RatioTapChangerHolder() noexcept = default; private: - virtual void setRatioTapChanger(std::unique_ptr ratioTapChanger) = 0; + virtual void setRatioTapChanger(std::unique_ptr&& ratioTapChanger) = 0; private: friend class RatioTapChanger; diff --git a/include/powsybl/iidm/ShuntCompensatorAdder.hpp b/include/powsybl/iidm/ShuntCompensatorAdder.hpp index 538a18040..e5d13ea3a 100644 --- a/include/powsybl/iidm/ShuntCompensatorAdder.hpp +++ b/include/powsybl/iidm/ShuntCompensatorAdder.hpp @@ -65,7 +65,7 @@ class ShuntCompensatorAdder : public InjectionAdder { friend class shunt_compensator::ShuntCompensatorNonLinearModelAdder; private: - boost::optional m_sectionCount; + stdcxx::optional m_sectionCount; double m_targetDeadband = stdcxx::nan(); diff --git a/include/powsybl/iidm/ShuntCompensatorLinearModel.hpp b/include/powsybl/iidm/ShuntCompensatorLinearModel.hpp index 8a7fc03da..bf6f083bd 100644 --- a/include/powsybl/iidm/ShuntCompensatorLinearModel.hpp +++ b/include/powsybl/iidm/ShuntCompensatorLinearModel.hpp @@ -9,7 +9,7 @@ #define POWSYBL_IIDM_SHUNTCOMPENSATORLINEARMODEL_HPP #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/ShuntCompensatorNonLinearModel.hpp b/include/powsybl/iidm/ShuntCompensatorNonLinearModel.hpp index 3c5fc2324..f22f846b2 100644 --- a/include/powsybl/iidm/ShuntCompensatorNonLinearModel.hpp +++ b/include/powsybl/iidm/ShuntCompensatorNonLinearModel.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/StaticVarCompensator.hpp b/include/powsybl/iidm/StaticVarCompensator.hpp index 0f5fd443f..6e4f396a5 100644 --- a/include/powsybl/iidm/StaticVarCompensator.hpp +++ b/include/powsybl/iidm/StaticVarCompensator.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/StaticVarCompensatorAdder.hpp b/include/powsybl/iidm/StaticVarCompensatorAdder.hpp index 59542e409..2cf5485d0 100644 --- a/include/powsybl/iidm/StaticVarCompensatorAdder.hpp +++ b/include/powsybl/iidm/StaticVarCompensatorAdder.hpp @@ -11,7 +11,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/Substation.hpp b/include/powsybl/iidm/Substation.hpp index b31b560d0..e2cd9fcc4 100644 --- a/include/powsybl/iidm/Substation.hpp +++ b/include/powsybl/iidm/Substation.hpp @@ -17,7 +17,7 @@ #include #include #include -#include +#include namespace powsybl { @@ -71,6 +71,8 @@ class Substation : public Container { VoltageLevelAdder newVoltageLevel(); + void remove(); + Substation& setCountry(const stdcxx::optional& country); Substation& setTso(const std::string& tso); @@ -81,8 +83,12 @@ class Substation : public Container { private: void addVoltageLevel(VoltageLevel& voltageLevel); + void remove(const VoltageLevel& voltageLevel); + void setNetworkRef(Network& network); + friend class VoltageLevel; + friend class VoltageLevelAdder; friend class NetworkIndex; diff --git a/include/powsybl/iidm/Switch.hpp b/include/powsybl/iidm/Switch.hpp index 80bc0a050..9a0d39c43 100644 --- a/include/powsybl/iidm/Switch.hpp +++ b/include/powsybl/iidm/Switch.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/TapChanger.hpp b/include/powsybl/iidm/TapChanger.hpp index e0d6cf1c5..a738d5429 100644 --- a/include/powsybl/iidm/TapChanger.hpp +++ b/include/powsybl/iidm/TapChanger.hpp @@ -15,7 +15,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/Terminal.hpp b/include/powsybl/iidm/Terminal.hpp index 46514001e..620b739dc 100644 --- a/include/powsybl/iidm/Terminal.hpp +++ b/include/powsybl/iidm/Terminal.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/TerminalViews.hpp b/include/powsybl/iidm/TerminalViews.hpp index eaded2db9..c14228440 100644 --- a/include/powsybl/iidm/TerminalViews.hpp +++ b/include/powsybl/iidm/TerminalViews.hpp @@ -8,7 +8,7 @@ #ifndef POWSYBL_IIDM_TERMINALVIEWS_HPP #define POWSYBL_IIDM_TERMINALVIEWS_HPP -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/ThreeWindingsTransformer.hpp b/include/powsybl/iidm/ThreeWindingsTransformer.hpp index 8e6d87a94..5a85e2bdc 100644 --- a/include/powsybl/iidm/ThreeWindingsTransformer.hpp +++ b/include/powsybl/iidm/ThreeWindingsTransformer.hpp @@ -45,6 +45,10 @@ class ThreeWindingsTransformer : public Connectable { Leg& getLeg3(); + stdcxx::const_range getLegs() const; + + stdcxx::range getLegs(); + double getRatedU0() const; Side getSide(const Terminal& terminal) const; @@ -75,11 +79,8 @@ class ThreeWindingsTransformer : public Connectable { using Connectable::getTerminal; private: - Leg m_leg1; - - Leg m_leg2; - - Leg m_leg3; + // The legs of this transformer, in the natural order (leg1, leg2 and leg3) + std::vector m_legs; double m_ratedU0; }; diff --git a/include/powsybl/iidm/ThreeWindingsTransformerLeg.hpp b/include/powsybl/iidm/ThreeWindingsTransformerLeg.hpp index aea57a2fc..08b706ef9 100644 --- a/include/powsybl/iidm/ThreeWindingsTransformerLeg.hpp +++ b/include/powsybl/iidm/ThreeWindingsTransformerLeg.hpp @@ -102,17 +102,17 @@ class Leg : public virtual RatioTapChangerHolder, public virtual PhaseTapChanger unsigned long getRegulatingTapChangerCount() const override; private: // RatioTapChangerHolder - void setRatioTapChanger(std::unique_ptr ratioTapChanger) override; + void setRatioTapChanger(std::unique_ptr&& ratioTapChanger) override; private: // PhaseTapChangerHolder - void setPhaseTapChanger(std::unique_ptr phaseTapChanger) override; + void setPhaseTapChanger(std::unique_ptr&& phaseTapChanger) override; private: const std::string& getTypeDescription() const; void setCurrentLimits(std::nullptr_t side, std::unique_ptr limits); - void setTransformer(ThreeWindingsTransformer& transformer); + Leg& setTransformer(ThreeWindingsTransformer& transformer); friend class CurrentLimitsAdder; @@ -144,6 +144,8 @@ class Leg : public virtual RatioTapChangerHolder, public virtual PhaseTapChanger } // namespace three_windings_transformer +std::ostream& operator<<(std::ostream& stream, const three_windings_transformer::Leg& leg); + } // namespace iidm } // namespace powsybl diff --git a/include/powsybl/iidm/TopologyVisitor.hpp b/include/powsybl/iidm/TopologyVisitor.hpp new file mode 100644 index 000000000..875208ae9 --- /dev/null +++ b/include/powsybl/iidm/TopologyVisitor.hpp @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef POWSYBL_IIDM_TOPOLOGYVISITOR_HPP +#define POWSYBL_IIDM_TOPOLOGYVISITOR_HPP + +#include +#include + +namespace powsybl { + +namespace iidm { + +class Battery; +class BusbarSection; +class DanglingLine; +class Generator; +class HvdcConverterStation; +class Line; +class Load; +class StaticVarCompensator; +class ShuntCompensator; +class TwoWindingsTransformer; + +class TopologyVisitor { +public: + static void visitEquipments(const stdcxx::const_range& terminals, TopologyVisitor& visitor); + +public: + TopologyVisitor() = default; + + TopologyVisitor(const TopologyVisitor&) = default; + + TopologyVisitor(TopologyVisitor&&) noexcept = default; + + virtual ~TopologyVisitor() noexcept = default; + + TopologyVisitor& operator=(const TopologyVisitor&) = default; + + TopologyVisitor& operator=(TopologyVisitor&&) noexcept = default; + + virtual void visitBattery(const Battery& battery); + + virtual void visitBusbarSection(const BusbarSection& section); + + virtual void visitDanglingLine(const DanglingLine& danglingLine); + + virtual void visitGenerator(const Generator& generator); + + virtual void visitHvdcConverterStation(const HvdcConverterStation& converterStation); + + virtual void visitLine(const Line& line, const Branch::Side& side); + + virtual void visitLoad(const Load& load); + + virtual void visitShuntCompensator(const ShuntCompensator& sc); + + virtual void visitStaticVarCompensator(const StaticVarCompensator& staticVarCompensator); + + virtual void visitThreeWindingsTransformer(const ThreeWindingsTransformer& transformer, const ThreeWindingsTransformer::Side& side); + + virtual void visitTwoWindingsTransformer(const TwoWindingsTransformer& transformer, const Branch::Side& side); +}; + +} // namespace iidm + +} // namespace powsybl + +#endif // POWSYBL_IIDM_TOPOLOGYVISITOR_HPP diff --git a/include/powsybl/iidm/TwoWindingsTransformer.hpp b/include/powsybl/iidm/TwoWindingsTransformer.hpp index 9e5dbe223..39354e645 100644 --- a/include/powsybl/iidm/TwoWindingsTransformer.hpp +++ b/include/powsybl/iidm/TwoWindingsTransformer.hpp @@ -97,10 +97,10 @@ class TwoWindingsTransformer : public virtual Branch, public virtual RatioTapCha unsigned long getRegulatingTapChangerCount() const override; private: // RatioTapChangerHolder - void setRatioTapChanger(std::unique_ptr ratioTapChanger) override; + void setRatioTapChanger(std::unique_ptr&& ratioTapChanger) override; private: // PhaseTapChangerHolder - void setPhaseTapChanger(std::unique_ptr phaseTapChanger) override; + void setPhaseTapChanger(std::unique_ptr&& phaseTapChanger) override; private: friend class PhaseTapChanger; diff --git a/include/powsybl/iidm/ValidationUtils.hpp b/include/powsybl/iidm/ValidationUtils.hpp index 42a47c157..66fafed71 100644 --- a/include/powsybl/iidm/ValidationUtils.hpp +++ b/include/powsybl/iidm/ValidationUtils.hpp @@ -82,23 +82,14 @@ void checkOnlyOneTapChangerRegulatingEnabled(const Validable& validable, unsigne template bool checkOptional(const stdcxx::optional& value) { -#if __cplusplus >= 201703L - return value.has_value(); -#else - return value.is_initialized(); -#endif + return static_cast(value); } const double& checkOptional(const Validable& validable, const stdcxx::optional& value, const std::string& message); template const T& checkOptional(const Validable& validable, const stdcxx::optional& value, const std::string& message) { -#if __cplusplus >= 201703L - bool isInitialized = value.has_value(); -#else - bool isInitialized = value.is_initialized(); -#endif - if (!isInitialized) { + if (!value) { throw ValidationException(validable, message); } return *value; diff --git a/include/powsybl/iidm/VariantArray.hpp b/include/powsybl/iidm/VariantArray.hpp index dfcebd7e8..115a0207b 100644 --- a/include/powsybl/iidm/VariantArray.hpp +++ b/include/powsybl/iidm/VariantArray.hpp @@ -27,17 +27,17 @@ class VariantArray { public: VariantArray(Owner& owner, const VariantFactory& variantFactory); - VariantArray(const VariantArray& variantArray) = delete; + VariantArray(const VariantArray&) = delete; - VariantArray(VariantArray&& variantArray) noexcept = delete; + VariantArray(VariantArray&&) noexcept = delete; VariantArray(Owner& owner, VariantArray&& variantArray); ~VariantArray() noexcept = default; - VariantArray& operator=(const VariantArray& variantArray) = delete; + VariantArray& operator=(const VariantArray&) = delete; - VariantArray& operator=(VariantArray&& variantArray) noexcept = delete; + VariantArray& operator=(VariantArray&&) noexcept = delete; void allocateVariantArrayElement(const std::set& indexes, const VariantFactory& variantFactory); diff --git a/include/powsybl/iidm/VariantContext.hpp b/include/powsybl/iidm/VariantContext.hpp index ae84d991e..0772ffdff 100644 --- a/include/powsybl/iidm/VariantContext.hpp +++ b/include/powsybl/iidm/VariantContext.hpp @@ -21,6 +21,8 @@ class VariantContext { protected: virtual unsigned long getVariantIndex() const = 0; + virtual bool isIndexSet() const = 0; + virtual void resetIfVariantIndexIs(unsigned long index) = 0; virtual void setVariantIndex(unsigned long index) = 0; diff --git a/include/powsybl/iidm/VariantContextGuard.hpp b/include/powsybl/iidm/VariantContextGuard.hpp index c82d009cf..e9ba3bf2c 100644 --- a/include/powsybl/iidm/VariantContextGuard.hpp +++ b/include/powsybl/iidm/VariantContextGuard.hpp @@ -21,11 +21,11 @@ class VariantContextGuard { public: explicit VariantContextGuard(VariantContext& context); - VariantContextGuard(const VariantContextGuard& guard) = delete; + VariantContextGuard(const VariantContextGuard&) = delete; ~VariantContextGuard() noexcept; - VariantContextGuard& operator=(const VariantContextGuard& guard) = delete; + VariantContextGuard& operator=(const VariantContextGuard&) = delete; private: VariantContext& m_context; diff --git a/include/powsybl/iidm/VariantManager.hpp b/include/powsybl/iidm/VariantManager.hpp index becb3604d..4273f1850 100644 --- a/include/powsybl/iidm/VariantManager.hpp +++ b/include/powsybl/iidm/VariantManager.hpp @@ -42,9 +42,11 @@ class VariantManager { VariantManager& operator=(VariantManager&&) noexcept = delete; - void cloneVariant(const std::string& sourceVariantId, const std::string& targetVariantId); + void allowVariantMultiThreadAccess(bool allow); - void cloneVariant(const std::string& sourceVariantId, const std::initializer_list& targetVariantIds); + void cloneVariant(const std::string& sourceVariantId, const std::string& targetVariantId, bool mayOverwrite = false); + + void cloneVariant(const std::string& sourceVariantId, const std::initializer_list& targetVariantIds, bool mayOverwrite = false); void forEachVariant(const std::function& function); @@ -58,6 +60,8 @@ class VariantManager { const std::string& getWorkingVariantId() const; + bool isVariantMultiThreadAccessAllowed() const; + void removeVariant(const std::string& variantId); void setWorkingVariant(const std::string& variantId); @@ -66,6 +70,8 @@ class VariantManager { static constexpr unsigned long INITIAL_VARIANT_INDEX = 0; private: + void allocateVariantArrayElement(unsigned long sourceIndex, const std::set& recycled, const std::set& overwritten); + unsigned long getVariantIndex(const std::string& variantId) const; private: diff --git a/include/powsybl/iidm/VoltageLevel.hpp b/include/powsybl/iidm/VoltageLevel.hpp index 5a10176c4..3176f422f 100644 --- a/include/powsybl/iidm/VoltageLevel.hpp +++ b/include/powsybl/iidm/VoltageLevel.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace powsybl { @@ -37,6 +37,7 @@ class StaticVarCompensatorAdder; class Switch; class Substation; class Terminal; +class TopologyVisitor; class VscConverterStation; class VscConverterStationAdder; @@ -125,7 +126,7 @@ class VoltageLevel : public Container { virtual NodeBreakerView& getNodeBreakerView() = 0; - double getNominalVoltage() const; + double getNominalV() const; unsigned long getShuntCompensatorCount() const; @@ -175,15 +176,19 @@ class VoltageLevel : public Container { VscConverterStationAdder newVscConverterStation(); + void remove(); + VoltageLevel& setHighVoltageLimit(double highVoltageLimit); VoltageLevel& setLowVoltageLimit(double lowVoltageLimit); - VoltageLevel& setNominalVoltage(double nominalVoltage); + VoltageLevel& setNominalV(double nominalV); + + void visitEquipments(TopologyVisitor& visitor) const; protected: VoltageLevel(const std::string& id, const std::string& name, bool fictitious, Substation& substation, - double nominalVoltage, double lowVoltageLimit, double highVoltageLimit); + double nominalV, double lowVoltageLimit, double highVoltageLimit); virtual stdcxx::const_range getTerminals() const = 0; @@ -192,6 +197,9 @@ class VoltageLevel : public Container { private: // Identifiable const std::string& getTypeDescription() const override; +private: + virtual void removeTopology() = 0; + private: stdcxx::Reference m_substation; @@ -199,7 +207,7 @@ class VoltageLevel : public Container { double m_lowVoltageLimit; - double m_nominalVoltage; + double m_nominalV; }; } // namespace iidm diff --git a/include/powsybl/iidm/VoltageLevelAdder.hpp b/include/powsybl/iidm/VoltageLevelAdder.hpp index 58c265d35..c890a5623 100644 --- a/include/powsybl/iidm/VoltageLevelAdder.hpp +++ b/include/powsybl/iidm/VoltageLevelAdder.hpp @@ -30,7 +30,7 @@ class VoltageLevelAdder : public IdentifiableAdder { VoltageLevelAdder& setLowVoltageLimit(double lowVoltageLimit); - VoltageLevelAdder& setNominalVoltage(double nominalVoltage); + VoltageLevelAdder& setNominalV(double nominalV); VoltageLevelAdder& setTopologyKind(const TopologyKind& topologyKind); @@ -54,7 +54,7 @@ class VoltageLevelAdder : public IdentifiableAdder { double m_lowVoltageLimit = stdcxx::nan(); - double m_nominalVoltage = stdcxx::nan(); + double m_nominalV = stdcxx::nan(); stdcxx::optional m_topologyKind; diff --git a/include/powsybl/iidm/VoltageLevelViews.hpp b/include/powsybl/iidm/VoltageLevelViews.hpp index dff2401a4..f0cba0760 100644 --- a/include/powsybl/iidm/VoltageLevelViews.hpp +++ b/include/powsybl/iidm/VoltageLevelViews.hpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/converter/Anonymizer.hpp b/include/powsybl/iidm/converter/Anonymizer.hpp index 0a071dfa9..8df9edaec 100644 --- a/include/powsybl/iidm/converter/Anonymizer.hpp +++ b/include/powsybl/iidm/converter/Anonymizer.hpp @@ -8,7 +8,7 @@ #ifndef POWSYBL_IIDM_CONVERTER_ANONYMIZER_HPP #define POWSYBL_IIDM_CONVERTER_ANONYMIZER_HPP -#include +#include #include @@ -32,9 +32,9 @@ class Anonymizer { virtual std::string deanonymizeString(const std::string& anonymousStr) const = 0; - // TODO(sebalaig) Add missing methods: - // void read(BufferedReader reader); - // void write(BufferedWriter writer); + virtual void read(std::istream& stream) = 0; + + virtual void write(std::ostream& stream) const = 0; }; } // namespace converter diff --git a/include/powsybl/iidm/converter/Constants.hpp b/include/powsybl/iidm/converter/Constants.hpp index f437fff1a..858cf8c0b 100644 --- a/include/powsybl/iidm/converter/Constants.hpp +++ b/include/powsybl/iidm/converter/Constants.hpp @@ -10,7 +10,7 @@ #include -#include +#include namespace powsybl { @@ -165,6 +165,7 @@ static const char* const TIE_LINE = "tieLine"; static const char* const TOPOLOGY_KIND = "topologyKind"; static const char* const TSO = "tso"; static const char* const TWO_WINDINGS_TRANSFORMER = "twoWindingsTransformer"; +static const char* const TYPE = "type"; static const char* const UCTE_XNODE_CODE = "ucteXnodeCode"; static const char* const V = "v"; static const char* const VALUE = "value"; @@ -184,7 +185,7 @@ static const char* const X3 = "x3"; static const char* const XNODE_P_ = "xnodeP_"; static const char* const XNODE_Q_ = "xnodeQ_"; -std::string toString(const char* attribute, boost::optional index); +std::string toString(const char* attribute, stdcxx::optional index); } // namespace converter diff --git a/include/powsybl/iidm/converter/ExportOptions.hpp b/include/powsybl/iidm/converter/ExportOptions.hpp index 9f3e34883..cd6c0b148 100644 --- a/include/powsybl/iidm/converter/ExportOptions.hpp +++ b/include/powsybl/iidm/converter/ExportOptions.hpp @@ -111,13 +111,6 @@ class ExportOptions { */ const IidmVersionIncompatibilityBehavior& getIidmVersionIncompatibilityBehavior() const; - /** - * Return the XIIDM version to use - * - * @return the XIIDM version - */ - const std::string& getVersion() const; - /** * Return the maximal topology level to use * @@ -127,6 +120,13 @@ class ExportOptions { */ const TopologyLevel& getTopologyLevel() const; + /** + * Return the XIIDM version to use + * + * @return the XIIDM version + */ + const std::string& getVersion() const; + /** * Return true if one (or more) extension of the given list should be exported * diff --git a/include/powsybl/iidm/converter/FakeAnonymizer.hpp b/include/powsybl/iidm/converter/FakeAnonymizer.hpp index 2881d377b..a3e6890d1 100644 --- a/include/powsybl/iidm/converter/FakeAnonymizer.hpp +++ b/include/powsybl/iidm/converter/FakeAnonymizer.hpp @@ -17,18 +17,31 @@ namespace iidm { namespace converter { class FakeAnonymizer : public Anonymizer { +public: // Anonymizer + Country anonymizeCountry(const Country& country) override; + + std::string anonymizeString(const std::string& str) override; + + Country deanonymizeCountry(const Country& country) const override; + + std::string deanonymizeString(const std::string& anonymousStr) const override; + + void read(std::istream& stream) override; + + void write(std::ostream& stream) const override; + public: FakeAnonymizer() = default; ~FakeAnonymizer() override = default; - Country anonymizeCountry(const Country& country) override; + FakeAnonymizer(const FakeAnonymizer&) = default; - std::string anonymizeString(const std::string& str) override; + FakeAnonymizer(FakeAnonymizer&&) noexcept = default; - Country deanonymizeCountry(const Country& country) const override; + FakeAnonymizer& operator=(const FakeAnonymizer&) = default; - std::string deanonymizeString(const std::string& anonymousStr) const override; + FakeAnonymizer& operator=(FakeAnonymizer&&) noexcept = default; }; } // namespace converter diff --git a/include/powsybl/iidm/converter/SimpleAnonymizer.hpp b/include/powsybl/iidm/converter/SimpleAnonymizer.hpp new file mode 100644 index 000000000..a2ff54c84 --- /dev/null +++ b/include/powsybl/iidm/converter/SimpleAnonymizer.hpp @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef POWSYBL_IIDM_CONVERTER_SIMPLEANONYMIZER_HPP +#define POWSYBL_IIDM_CONVERTER_SIMPLEANONYMIZER_HPP + +#include + +#include + +namespace powsybl { + +namespace iidm { + +namespace converter { + +class SimpleAnonymizer : public Anonymizer { +public: // Anonymizer + Country anonymizeCountry(const Country& country) override; + + std::string anonymizeString(const std::string& str) override; + + Country deanonymizeCountry(const Country& country) const override; + + std::string deanonymizeString(const std::string& anonymousStr) const override; + + void read(std::istream& stream) override; + + void write(std::ostream& stream) const override; + +public: + static std::string getAlpha(unsigned long num); + +public: + SimpleAnonymizer() = default; + + ~SimpleAnonymizer() override = default; + + SimpleAnonymizer(const SimpleAnonymizer&) = default; + + SimpleAnonymizer(SimpleAnonymizer&&) = default; + + SimpleAnonymizer& operator=(const SimpleAnonymizer&) = default; + + SimpleAnonymizer& operator=(SimpleAnonymizer&&) = default; + + unsigned long getStringCount() const; + +private: + using Mapping = boost::bimap; + +private: + Mapping m_mapping; +}; + +} // namespace converter + +} // namespace iidm + +} // namespace powsybl + +#endif // POWSYBL_IIDM_CONVERTER_SIMPLEANONYMIZER_HPP diff --git a/include/powsybl/iidm/converter/xml/CurrentLimitsXml.hpp b/include/powsybl/iidm/converter/xml/CurrentLimitsXml.hpp index ff05c36a9..b4a969d46 100644 --- a/include/powsybl/iidm/converter/xml/CurrentLimitsXml.hpp +++ b/include/powsybl/iidm/converter/xml/CurrentLimitsXml.hpp @@ -10,10 +10,9 @@ #include -#include - #include #include +#include namespace powsybl { @@ -33,9 +32,9 @@ namespace xml { class CurrentLimitsXml { public: template - static void readCurrentLimits(CurrentLimitsAdder& adder, const powsybl::xml::XmlStreamReader& reader, const boost::optional& index = boost::optional()); + static void readCurrentLimits(CurrentLimitsAdder& adder, const powsybl::xml::XmlStreamReader& reader, const stdcxx::optional& index = stdcxx::optional()); - static void writeCurrentLimits(const CurrentLimits& limits, powsybl::xml::XmlStreamWriter& writer, const std::string& nsPrefix, const IidmXmlVersion& version, const boost::optional& index = boost::optional()); + static void writeCurrentLimits(const CurrentLimits& limits, powsybl::xml::XmlStreamWriter& writer, const std::string& nsPrefix, const IidmXmlVersion& version, const stdcxx::optional& index = stdcxx::optional()); }; } // namespace xml diff --git a/include/powsybl/iidm/converter/xml/CurrentLimitsXml.hxx b/include/powsybl/iidm/converter/xml/CurrentLimitsXml.hxx index a8eb35bab..8817ab873 100644 --- a/include/powsybl/iidm/converter/xml/CurrentLimitsXml.hxx +++ b/include/powsybl/iidm/converter/xml/CurrentLimitsXml.hxx @@ -22,13 +22,13 @@ namespace converter { namespace xml { template -void CurrentLimitsXml::readCurrentLimits(CurrentLimitsAdder& adder, const powsybl::xml::XmlStreamReader& reader, const boost::optional& index) { +void CurrentLimitsXml::readCurrentLimits(CurrentLimitsAdder& adder, const powsybl::xml::XmlStreamReader& reader, const stdcxx::optional& index) { const double& permanentLimit = reader.getOptionalAttributeValue(PERMANENT_LIMIT, stdcxx::nan()); adder.setPermanentLimit(permanentLimit); reader.readUntilEndElement(toString(CURRENT_LIMITS, index), [&adder, &reader]() { if (reader.getLocalName() == TEMPORARY_LIMIT) { const std::string& name = reader.getAttributeValue(NAME); - int acceptableDuration = reader.getOptionalAttributeValue(ACCEPTABLE_DURATION, std::numeric_limits::max()); + unsigned long acceptableDuration = reader.getOptionalAttributeValue(ACCEPTABLE_DURATION, std::numeric_limits::max()); double value = reader.getOptionalAttributeValue(VALUE, std::numeric_limits::max()); bool fictitious = reader.getOptionalAttributeValue(FICTITIOUS, false); adder.beginTemporaryLimit() diff --git a/include/powsybl/iidm/converter/xml/IidmXmlUtil.hpp b/include/powsybl/iidm/converter/xml/IidmXmlUtil.hpp index 0cde21f2b..c8703f272 100644 --- a/include/powsybl/iidm/converter/xml/IidmXmlUtil.hpp +++ b/include/powsybl/iidm/converter/xml/IidmXmlUtil.hpp @@ -89,7 +89,8 @@ class IidmXmlUtil { /** * Assert that the context's IIDM-XML version equals or is more recent than a given IIDM-XML version if the value of an attribute or the state of an equipment - * is not default (interpretable for previous versions) + * is not default (interpretable for previous versions). + * If the value is not default and no exception has been thrown, run a given runnable. * * @param valueIsNotDefault assert only if this parameter is true * @param rootElementName the name of the XML root element @@ -97,10 +98,11 @@ class IidmXmlUtil { * @param errorMessage the type of error message in case of an exception is thrown * @param minVersion the IIDM-XML version in which the element has been added * @param context the context + * @param runnable the function to run * - * @throw a {@link PowsyblException} if the context's version less recent than the minVersion + * @throw a {@link PowsyblException} if the context's version is less recent than the minVersion and valueIsNotDefault is true */ - static void assertMinimumVersionIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlReaderContext& context); + static void assertMinimumVersionAndRunIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlReaderContext& context, const std::function& runnable); /** * Assert that the context's IIDM-XML version equals or is more recent than a given IIDM-XML version if the value of an attribute or the state of an equipment @@ -115,12 +117,11 @@ class IidmXmlUtil { * * @throw a {@link PowsyblException} if the context's version less recent than the minVersion */ - static void assertMinimumVersionIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlWriterContext& context); + static void assertMinimumVersionIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlReaderContext& context); /** * Assert that the context's IIDM-XML version equals or is more recent than a given IIDM-XML version if the value of an attribute or the state of an equipment - * is not default (interpretable for previous versions). - * If the value is not default and no exception has been thrown, run a given runnable. + * is not default (interpretable for previous versions) * * @param valueIsNotDefault assert only if this parameter is true * @param rootElementName the name of the XML root element @@ -128,11 +129,10 @@ class IidmXmlUtil { * @param errorMessage the type of error message in case of an exception is thrown * @param minVersion the IIDM-XML version in which the element has been added * @param context the context - * @param runnable the function to run * - * @throw a {@link PowsyblException} if the context's version is less recent than the minVersion and valueIsNotDefault is true + * @throw a {@link PowsyblException} if the context's version less recent than the minVersion */ - static void assertMinimumVersionAndRunIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlReaderContext& context, const std::function& runnable); + static void assertMinimumVersionIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlWriterContext& context); /** * Assert that the context's IIDM-XML version equals or is more recent than a given IIDM-XML version if the value of an attribute or the state of an equipment diff --git a/include/powsybl/iidm/converter/xml/IidmXmlVersion.hpp b/include/powsybl/iidm/converter/xml/IidmXmlVersion.hpp index d60ea5f3e..9e7205cd8 100644 --- a/include/powsybl/iidm/converter/xml/IidmXmlVersion.hpp +++ b/include/powsybl/iidm/converter/xml/IidmXmlVersion.hpp @@ -47,6 +47,11 @@ class IidmXmlVersion { */ static const IidmXmlVersion& V1_3(); + /** + * IIDM V1.4 (http://www.powsybl.org) + */ + static const IidmXmlVersion& V1_4(); + public: /** * Return the list of all supported XIIDM versions @@ -86,9 +91,9 @@ class IidmXmlVersion { static const IidmXmlVersion& of(const std::string& version, const std::string& separator); public: - IidmXmlVersion(const IidmXmlVersion& version) = delete; + IidmXmlVersion(const IidmXmlVersion&) = delete; - IidmXmlVersion(IidmXmlVersion&& version) = delete; + IidmXmlVersion(IidmXmlVersion&&) = delete; ~IidmXmlVersion() = default; diff --git a/include/powsybl/iidm/converter/xml/NetworkXmlReaderContext.hpp b/include/powsybl/iidm/converter/xml/NetworkXmlReaderContext.hpp index 0229e0a26..bd0a9d9d9 100644 --- a/include/powsybl/iidm/converter/xml/NetworkXmlReaderContext.hpp +++ b/include/powsybl/iidm/converter/xml/NetworkXmlReaderContext.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -34,7 +35,7 @@ namespace xml { class NetworkXmlReaderContext { public: - NetworkXmlReaderContext(const Anonymizer& anonymizer, powsybl::xml::XmlStreamReader& reader, const ImportOptions& options, const IidmXmlVersion& version); + NetworkXmlReaderContext(std::unique_ptr&& anonymizer, powsybl::xml::XmlStreamReader& reader, const ImportOptions& options, const IidmXmlVersion& version); void addEndTask(const std::function& endTask); @@ -55,7 +56,7 @@ class NetworkXmlReaderContext { private: powsybl::xml::XmlStreamReader& m_reader; - const Anonymizer& m_anonymizer; + std::unique_ptr m_anonymizer; std::list> m_endTasks; diff --git a/include/powsybl/iidm/converter/xml/NetworkXmlWriterContext.hpp b/include/powsybl/iidm/converter/xml/NetworkXmlWriterContext.hpp index 6a8b0fb7f..2dfde347a 100644 --- a/include/powsybl/iidm/converter/xml/NetworkXmlWriterContext.hpp +++ b/include/powsybl/iidm/converter/xml/NetworkXmlWriterContext.hpp @@ -9,6 +9,7 @@ #define POWSYBL_IIDM_CONVERTER_XML_NETWORKXMLWRITERCONTEXT_HPP #include +#include #include #include @@ -36,7 +37,7 @@ namespace xml { class NetworkXmlWriterContext { public: - NetworkXmlWriterContext(Anonymizer& anonymizer, powsybl::xml::XmlStreamWriter& writer, const ExportOptions& options, const BusFilter& filter, const IidmXmlVersion& version); + NetworkXmlWriterContext(std::unique_ptr&& anonymizer, powsybl::xml::XmlStreamWriter& writer, const ExportOptions& options, const BusFilter& filter, const IidmXmlVersion& version); ~NetworkXmlWriterContext() = default; @@ -69,7 +70,7 @@ class NetworkXmlWriterContext { std::reference_wrapper m_extensionsWriter; - Anonymizer& m_anonymizer; + std::unique_ptr m_anonymizer; ExportOptions m_options; diff --git a/include/powsybl/iidm/extensions/SlackTerminal.hpp b/include/powsybl/iidm/extensions/SlackTerminal.hpp index 7b045b722..195e6652c 100644 --- a/include/powsybl/iidm/extensions/SlackTerminal.hpp +++ b/include/powsybl/iidm/extensions/SlackTerminal.hpp @@ -11,7 +11,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/extensions/SlackTerminalAdder.hpp b/include/powsybl/iidm/extensions/SlackTerminalAdder.hpp index 207d606a8..798dc7bbc 100644 --- a/include/powsybl/iidm/extensions/SlackTerminalAdder.hpp +++ b/include/powsybl/iidm/extensions/SlackTerminalAdder.hpp @@ -9,7 +9,7 @@ #define POWSYBL_IIDM_EXTENSIONS_SLACKTERMINALADDER_HPP #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/util/ConnectedComponents.hpp b/include/powsybl/iidm/util/ConnectedComponents.hpp index c4c843f30..f47eb93a6 100644 --- a/include/powsybl/iidm/util/ConnectedComponents.hpp +++ b/include/powsybl/iidm/util/ConnectedComponents.hpp @@ -9,7 +9,7 @@ #define POWSYBL_IIDM_UTIL_CONNECTEDCOMPONENTS_HPP #include -#include +#include namespace powsybl { diff --git a/include/powsybl/iidm/util/Identifiables.hpp b/include/powsybl/iidm/util/Identifiables.hpp index 0243562b2..bc1e459fd 100644 --- a/include/powsybl/iidm/util/Identifiables.hpp +++ b/include/powsybl/iidm/util/Identifiables.hpp @@ -16,27 +16,11 @@ namespace powsybl { namespace iidm { -namespace util { +namespace Identifiables { -class Identifiables { -public: - static std::string getUniqueId(const std::string& baseId, const stdcxx::Predicate& containsId); +std::string getUniqueId(const std::string& baseId, const stdcxx::Predicate& containsId); -public: - Identifiables() = delete; - - Identifiables(const Identifiables&) = delete; - - Identifiables(Identifiables&&) noexcept = delete; - - ~Identifiables() = delete; - - Identifiables& operator=(const Identifiables&) = delete; - - Identifiables& operator=(Identifiables&&) noexcept = delete; -}; - -} // namespace util +} // namespace Identifiables } // namespace iidm diff --git a/include/powsybl/iidm/util/Networks.hpp b/include/powsybl/iidm/util/Networks.hpp index 854638ec1..879b85050 100644 --- a/include/powsybl/iidm/util/Networks.hpp +++ b/include/powsybl/iidm/util/Networks.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace powsybl { @@ -21,47 +21,31 @@ namespace iidm { class VoltageLevel; class Terminal; -namespace util { +namespace Networks { -class Networks { -public: - /** - * Return a terminal for the specified node. - * If a terminal is attached to the node, return this terminal. Otherwise, this method traverses the topology and return - * the closest and equivalent terminal. - * - * @param voltageLevel The voltage level to traverse - * @param node The starting node - * - * @return A terminal for the specified node or an invalid {@link stdcxx::reference_wrapper}. - */ - static stdcxx::CReference getEquivalentTerminal(const VoltageLevel& voltageLevel, unsigned long node); - - /** - * Return the list of nodes (N/B topology) for each bus of a the Bus view - * If a node is not associated to a bus, it is not included in any list. - * - * @param voltageLevel The voltage level to traverse - * - * @return the list of nodes (N/B topology) for each bus of a Bus view - */ - static std::map> getNodesByBus(const VoltageLevel& voltageLevel); - -public: - Networks() = delete; - - Networks(const Networks&) = delete; - - Networks(Networks&&) noexcept = delete; - - ~Networks() = delete; - - Networks& operator=(const Networks&) = delete; +/** + * Return a terminal for the specified node. + * If a terminal is attached to the node, return this terminal. Otherwise, this method traverses the topology and return + * the closest and equivalent terminal. + * + * @param voltageLevel The voltage level to traverse + * @param node The starting node + * + * @return A terminal for the specified node or an invalid {@link stdcxx::reference_wrapper}. + */ +stdcxx::CReference getEquivalentTerminal(const VoltageLevel& voltageLevel, unsigned long node); - Networks& operator=(Networks&&) noexcept = delete; -}; +/** + * Return the list of nodes (N/B topology) for each bus of a the Bus view + * If a node is not associated to a bus, it is not included in any list. + * + * @param voltageLevel The voltage level to traverse + * + * @return the list of nodes (N/B topology) for each bus of a Bus view + */ +std::map> getNodesByBus(const VoltageLevel& voltageLevel); -} // namespace util +} // namespace Networks } // namespace iidm diff --git a/include/powsybl/iidm/util/Substations.hpp b/include/powsybl/iidm/util/Substations.hpp new file mode 100644 index 000000000..fd26a4ce0 --- /dev/null +++ b/include/powsybl/iidm/util/Substations.hpp @@ -0,0 +1,36 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef POWSYBL_IIDM_UTIL_SUBSTATIONS_HPP +#define POWSYBL_IIDM_UTIL_SUBSTATIONS_HPP + +namespace powsybl { + +namespace iidm { + +class Branch; +class HvdcConverterStation; +class Substation; +class ThreeWindingsTransformer; + +namespace Substations { + +void checkRemovability(const Substation& substation); + +void checkRemovability(const Substation& substation, const Branch& branch); + +void checkRemovability(const Substation& substation, const ThreeWindingsTransformer& twt); + +void checkRemovability(const Substation& substation, const HvdcConverterStation& station); + +} // namespace Substations + +} // namespace iidm + +} // namespace powsybl + +#endif // POWSYBL_IIDM_UTIL_SUBSTATIONS_HPP diff --git a/include/powsybl/iidm/util/TerminalFinder.hpp b/include/powsybl/iidm/util/TerminalFinder.hpp index f0431b5f6..7712beae9 100644 --- a/include/powsybl/iidm/util/TerminalFinder.hpp +++ b/include/powsybl/iidm/util/TerminalFinder.hpp @@ -9,10 +9,9 @@ #define POWSYBL_IIDM_UTIL_TERMINALFINDER_HPP #include -#include #include -#include +#include namespace powsybl { @@ -20,46 +19,19 @@ namespace iidm { class Terminal; -namespace util { +namespace TerminalFinder { -class TerminalFinder { -public: - using Comparator = std::function; +using Comparator = std::function; - using Predicate = std::function; +stdcxx::CReference find(const stdcxx::const_range& terminals); -public: - static TerminalFinder getDefault(); +stdcxx::Reference find(const stdcxx::range& terminals); -public: - explicit TerminalFinder(const std::vector& predicates); +stdcxx::CReference find(const Comparator& comparator, const stdcxx::const_range& terminals); - explicit TerminalFinder(const Comparator& comparator); +stdcxx::Reference find(const Comparator& comparator, const stdcxx::range& terminals); - TerminalFinder(const TerminalFinder&) = delete; - - // NOLINTNEXTLINE(performance-noexcept-move-constructor): move constructor of std::function is not marked noexcept - TerminalFinder(TerminalFinder&&) = default; - - TerminalFinder& operator=(const TerminalFinder&) = delete; - - // NOLINTNEXTLINE(performance-noexcept-move-constructor): move constructor of std::function is not marked noexcept - TerminalFinder& operator=(TerminalFinder&&) = default; - - stdcxx::CReference find(const stdcxx::const_range& terminals) const; - - stdcxx::Reference find(const stdcxx::range& terminals) const; - -private: - static Comparator getComparator(const std::vector& predicates); - - static const std::vector& getDefaultRules(); - -private: - Comparator m_comparator; -}; - -} // namespace util +} // namespace TerminalFinder } // namespace iidm diff --git a/include/powsybl/iidm/util/VoltageLevels.hpp b/include/powsybl/iidm/util/VoltageLevels.hpp new file mode 100644 index 000000000..b599a68ca --- /dev/null +++ b/include/powsybl/iidm/util/VoltageLevels.hpp @@ -0,0 +1,37 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef POWSYBL_IIDM_UTIL_VOLTAGELEVELS_HPP +#define POWSYBL_IIDM_UTIL_VOLTAGELEVELS_HPP + +#include + +#include + +namespace powsybl { + +namespace iidm { + +class VoltageLevel; + +namespace VoltageLevels { + +static const std::set MULTIPLE_TERMINALS_CONNECTABLE_TYPES = { + ConnectableType::LINE, + ConnectableType::TWO_WINDINGS_TRANSFORMER, + ConnectableType::THREE_WINDINGS_TRANSFORMER +}; + +void checkRemovability(const VoltageLevel& voltageLevel); + +} // namespace VoltageLevels + +} // namespace iidm + +} // namespace powsybl + +#endif // POWSYBL_IIDM_UTIL_VOLTAGELEVELS_HPP diff --git a/include/powsybl/math/UndirectedGraph.hpp b/include/powsybl/math/UndirectedGraph.hpp index 15ad2b9ba..e80ba56a4 100644 --- a/include/powsybl/math/UndirectedGraph.hpp +++ b/include/powsybl/math/UndirectedGraph.hpp @@ -16,7 +16,7 @@ #include #include #include -#include +#include namespace powsybl { diff --git a/include/powsybl/math/UndirectedGraphRanges.hpp b/include/powsybl/math/UndirectedGraphRanges.hpp index ec63e7f21..bf0131ee6 100644 --- a/include/powsybl/math/UndirectedGraphRanges.hpp +++ b/include/powsybl/math/UndirectedGraphRanges.hpp @@ -9,7 +9,7 @@ #define POWSYBL_IIDM_UNDIRECTEDGRAPHRANGES_HPP #include -#include +#include namespace powsybl { diff --git a/include/powsybl/network/FourSubstationsNodeBreakerFactory.hpp b/include/powsybl/network/FourSubstationsNodeBreakerFactory.hpp new file mode 100644 index 000000000..7a27b08e6 --- /dev/null +++ b/include/powsybl/network/FourSubstationsNodeBreakerFactory.hpp @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef POWSYBL_NETWORK_FOURSUBSTATIONSNODEBREAKERFACTORY_HPP +#define POWSYBL_NETWORK_FOURSUBSTATIONSNODEBREAKERFACTORY_HPP + +namespace powsybl { + +namespace iidm { + +class Network; + +} // namespace iidm + +namespace network { + +class FourSubstationsNodeBreakerFactory { +public: + static iidm::Network create(); + +public: + FourSubstationsNodeBreakerFactory() = delete; + + FourSubstationsNodeBreakerFactory(const FourSubstationsNodeBreakerFactory&) = delete; + + FourSubstationsNodeBreakerFactory(FourSubstationsNodeBreakerFactory&&) noexcept = delete; + + ~FourSubstationsNodeBreakerFactory() = delete; + + FourSubstationsNodeBreakerFactory& operator=(const FourSubstationsNodeBreakerFactory&) = delete; + + FourSubstationsNodeBreakerFactory& operator=(FourSubstationsNodeBreakerFactory&&) noexcept = delete; +}; + +} // namespace network + +} // namespace powsybl + +#endif // POWSYBL_NETWORK_FOURSUBSTATIONSNODEBREAKERFACTORY_HPP diff --git a/include/powsybl/stdcxx/instanceof.hpp b/include/powsybl/stdcxx/instanceof.hpp index 4e73f1a36..35b29e297 100644 --- a/include/powsybl/stdcxx/instanceof.hpp +++ b/include/powsybl/stdcxx/instanceof.hpp @@ -10,7 +10,7 @@ #include -#include +#include namespace stdcxx { diff --git a/include/powsybl/stdcxx/reference_wrapper.hpp b/include/powsybl/stdcxx/reference.hpp similarity index 82% rename from include/powsybl/stdcxx/reference_wrapper.hpp rename to include/powsybl/stdcxx/reference.hpp index 813af044f..9b27c7d7c 100644 --- a/include/powsybl/stdcxx/reference_wrapper.hpp +++ b/include/powsybl/stdcxx/reference.hpp @@ -5,8 +5,8 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef POWSYBL_STDCXX_REFERENCE_WRAPPER_HPP -#define POWSYBL_STDCXX_REFERENCE_WRAPPER_HPP +#ifndef POWSYBL_STDCXX_REFERENCE_HPP +#define POWSYBL_STDCXX_REFERENCE_HPP #include @@ -16,37 +16,37 @@ namespace stdcxx { template -class reference_wrapper { +class Reference { public: using type = T; public: - reference_wrapper() noexcept = default; + Reference() noexcept = default; - explicit reference_wrapper(T& reference) noexcept : + explicit Reference(T& reference) noexcept : m_pointer(std::addressof(reference)) { } - reference_wrapper(const reference_wrapper&) = default; + Reference(const Reference&) = default; - reference_wrapper(T&& reference) noexcept = delete; + Reference(T&& reference) noexcept = delete; - reference_wrapper(reference_wrapper&&) noexcept = default; + Reference(Reference&&) noexcept = default; - reference_wrapper& operator=(const reference_wrapper&) = default; + Reference& operator=(const Reference&) = default; - reference_wrapper& operator=(reference_wrapper&&) noexcept = default; + Reference& operator=(Reference&&) noexcept = default; - reference_wrapper& operator=(T& reference) { + Reference& operator=(T& reference) { m_pointer = std::addressof(reference); return *this; } - bool operator==(const reference_wrapper& reference) const { + bool operator==(const Reference& reference) const { return m_pointer == reference.m_pointer; } - bool operator!=(const reference_wrapper& reference) const { + bool operator!=(const Reference& reference) const { return m_pointer != reference.m_pointer; } @@ -85,9 +85,7 @@ class reference_wrapper { T* m_pointer = nullptr; }; -template using CReference = reference_wrapper; - -template using Reference = reference_wrapper; +template using CReference = Reference; template CReference cref() { @@ -145,7 +143,7 @@ Reference ref(const T& reference) { } /** - * Upcast / Downcast a reference_wrapper instance from U to T + * Upcast / Downcast a Reference instance from U to T */ template ::value>::type> Reference ref(const Reference& reference) { @@ -202,4 +200,4 @@ class less { } // namespace stdcxx -#endif // POWSYBL_STDCXX_REFERENCE_WRAPPER_HPP +#endif // POWSYBL_STDCXX_REFERENCE_HPP diff --git a/include/powsybl/test/ExtensionFixture.hpp b/include/powsybl/test/ExtensionFixture.hpp index ac9409489..21eca4bed 100644 --- a/include/powsybl/test/ExtensionFixture.hpp +++ b/include/powsybl/test/ExtensionFixture.hpp @@ -18,15 +18,15 @@ class ExtensionFixture : public ResourceFixture { public: ExtensionFixture(); - ExtensionFixture(const ExtensionFixture& fixture) = default; + ExtensionFixture(const ExtensionFixture&) = default; - ExtensionFixture(ExtensionFixture&& fixture) = default; + ExtensionFixture(ExtensionFixture&&) = default; ~ExtensionFixture() = default; - ExtensionFixture& operator=(const ExtensionFixture& fixture) = default; + ExtensionFixture& operator=(const ExtensionFixture&) = default; - ExtensionFixture& operator=(ExtensionFixture&& fixture) = default; + ExtensionFixture& operator=(ExtensionFixture&&) = default; }; } // namespace test diff --git a/include/powsybl/test/ResourceFixture.hpp b/include/powsybl/test/ResourceFixture.hpp index b072cf1b8..cbb520e89 100644 --- a/include/powsybl/test/ResourceFixture.hpp +++ b/include/powsybl/test/ResourceFixture.hpp @@ -10,6 +10,8 @@ #include +#include + #include namespace powsybl { @@ -21,6 +23,8 @@ class ResourceFixture : public CommandLine { ResourceFixture(); std::string getResource(const std::string& name) const; + + boost::filesystem::path getResourcePath(const std::string& name) const; }; } // namespace test diff --git a/include/powsybl/test/XmlFixture.hpp b/include/powsybl/test/XmlFixture.hpp index 63143b8ab..bb8bcead9 100644 --- a/include/powsybl/test/XmlFixture.hpp +++ b/include/powsybl/test/XmlFixture.hpp @@ -16,15 +16,15 @@ class XmlFixture { public: XmlFixture(); - XmlFixture(const XmlFixture& fixture) = default; + XmlFixture(const XmlFixture&) = default; - XmlFixture(XmlFixture&& fixture) = default; + XmlFixture(XmlFixture&&) = default; ~XmlFixture(); - XmlFixture& operator=(const XmlFixture& fixture) = default; + XmlFixture& operator=(const XmlFixture&) = default; - XmlFixture& operator=(XmlFixture&& fixture) = default; + XmlFixture& operator=(XmlFixture&&) = default; }; } // namespace test diff --git a/include/powsybl/test/converter/RoundTrip.hpp b/include/powsybl/test/converter/RoundTrip.hpp index bc27f4fd2..efd553d69 100644 --- a/include/powsybl/test/converter/RoundTrip.hpp +++ b/include/powsybl/test/converter/RoundTrip.hpp @@ -12,6 +12,8 @@ #include #include +#include + #include #include @@ -40,7 +42,7 @@ class RoundTrip { static std::string getVersionedNetwork(const std::string& filename, const iidm::converter::xml::IidmXmlVersion& version); - static std::string getVersionedNetworkPath(const std::string& filename, const iidm::converter::xml::IidmXmlVersion& version); + static boost::filesystem::path getVersionedNetworkPath(const std::string& filename, const iidm::converter::xml::IidmXmlVersion& version); static void roundTripAllPreviousVersionedXmlTest(const std::string& filename); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9c2ff720a..0742670db 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ set(IIDM_SOURCES iidm/AbstractComponentsManager.cpp iidm/AbstractMultiVariantIdentifiableExtension.cpp + iidm/AbstractTerminalTopologyVisitor.cpp iidm/Battery.cpp iidm/BatteryAdder.cpp iidm/Branch.cpp @@ -110,6 +111,7 @@ set(IIDM_SOURCES iidm/SynchronousComponentsManager.cpp iidm/Terminal.cpp iidm/TerminalBuilder.cpp + iidm/ThreadLocalMultipleVariantContext.cpp iidm/ThreeWindingsTransformer.cpp iidm/ThreeWindingsTransformerLeg.cpp iidm/ThreeWindingsTransformerLegAdder.cpp @@ -118,6 +120,7 @@ set(IIDM_SOURCES iidm/TieLineAdder.cpp iidm/TopologyKind.cpp iidm/TopologyLevel.cpp + iidm/TopologyVisitor.cpp iidm/TwoWindingsTransformer.cpp iidm/TwoWindingsTransformerAdder.cpp iidm/ValidationException.cpp @@ -136,6 +139,7 @@ set(IIDM_SOURCES iidm/converter/FakeAnonymizer.cpp iidm/converter/ImportOptions.cpp iidm/converter/Parameter.cpp + iidm/converter/SimpleAnonymizer.cpp iidm/converter/xml/AbstractExtensionXmlSerializer.cpp iidm/converter/xml/AbstractVersionableExtensionXmlSerializer.cpp @@ -183,7 +187,9 @@ set(IIDM_SOURCES iidm/util/Identifiables.cpp iidm/util/LimitViolationUtils.cpp iidm/util/Networks.cpp + iidm/util/Substations.cpp iidm/util/TerminalFinder.cpp + iidm/util/VoltageLevels.cpp logging/ConsoleLogger.cpp logging/ContainerLogger.cpp @@ -198,6 +204,7 @@ set(IIDM_SOURCES network/BatteryNetworkFactory.cpp network/EurostagFactory.cpp network/FictitiousSwitchFactory.cpp + network/FourSubstationsNodeBreakerFactory.cpp network/LoadBarExt.cpp network/LoadFooExt.cpp network/MultipleExtensionsTestNetworkFactory.cpp @@ -216,50 +223,67 @@ set(IIDM_SOURCES ) # Shared library -add_library(iidm SHARED ${IIDM_SOURCES}) -set_target_properties(iidm PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION}) -target_include_directories(iidm SYSTEM - PUBLIC - $ - $ -) -target_include_directories(iidm - INTERFACE - $ - PUBLIC - $ - $ -) -target_link_libraries(iidm PUBLIC LibXml2::LibXml2 Boost::disable_autolinking Boost::date_time Boost::dynamic_linking Boost::filesystem Boost::system ${CMAKE_DL_LIBS}) +if (BUILD_SHARED_LIBS) + add_library(iidm SHARED ${IIDM_SOURCES}) + set_target_properties(iidm PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION}) + target_include_directories(iidm SYSTEM + PUBLIC + $ + $ + ) + target_include_directories(iidm + INTERFACE + $ + PUBLIC + $ + $ + ) + target_link_libraries(iidm PUBLIC LibXml2::LibXml2 Boost::disable_autolinking Boost::date_time Boost::dynamic_linking Boost::filesystem Boost::system ${CMAKE_DL_LIBS} Threads::Threads) -# Static library -add_library(iidm-static STATIC ${IIDM_SOURCES}) -set_target_properties(iidm-static PROPERTIES OUTPUT_NAME iidm) -target_include_directories(iidm-static SYSTEM - PUBLIC - $ - $ -) -target_include_directories(iidm-static - INTERFACE - $ - PUBLIC - $ - $ -) -target_link_libraries(iidm-static PUBLIC LibXml2::LibXml2 Boost::disable_autolinking Boost::date_time Boost::dynamic_linking Boost::filesystem Boost::system ${CMAKE_DL_LIBS}) + # Installation + install(TARGETS iidm + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () -# Installation -install(TARGETS iidm iidm-static - EXPORT iidm-targets - LIBRARY DESTINATION ${INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${INSTALL_LIB_DIR} - RUNTIME DESTINATION ${INSTALL_BIN_DIR} -) +if (BUILD_STATIC_LIBS) + # Static library + add_library(iidm-static STATIC ${IIDM_SOURCES}) + set_target_properties(iidm-static PROPERTIES OUTPUT_NAME iidm) + target_include_directories(iidm-static SYSTEM + PUBLIC + $ + $ + ) + target_include_directories(iidm-static + INTERFACE + $ + PUBLIC + $ + $ + ) + if (NOT BOOST_STATIC_LIBS) + target_link_libraries(iidm-static PUBLIC Boost::dynamic_linking) + endif () + target_link_libraries(iidm-static PUBLIC LibXml2::LibXml2 Boost::disable_autolinking Boost::date_time Boost::filesystem Boost::system ${CMAKE_DL_LIBS} Threads::Threads) + + # Installation + install(TARGETS iidm-static + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/powsybl DESTINATION ${INSTALL_INCLUDE_DIR} PATTERN "test/*" EXCLUDE ) -add_subdirectory(test) +if (BUILD_TESTS) + add_subdirectory(test) +endif() diff --git a/src/iidm/AbstractComponentsManager.cpp b/src/iidm/AbstractComponentsManager.cpp index 789a8238c..e5646725d 100644 --- a/src/iidm/AbstractComponentsManager.cpp +++ b/src/iidm/AbstractComponentsManager.cpp @@ -69,7 +69,7 @@ stdcxx::CReference AbstractComponentsManager::getComponent(const stdc // update() must not be put here, but explicitly called each time before because update may // trigger a new component computation and so on a change in the value of the num component already passed // (and outdated consequently) in parameter of this method - return num.is_initialized() ? stdcxx::cref(*m_components[*num]) : stdcxx::cref(); + return num ? stdcxx::cref(*m_components[*num]) : stdcxx::cref(); } stdcxx::const_range AbstractComponentsManager::getConnectedComponents() const { diff --git a/src/iidm/AbstractTerminalTopologyVisitor.cpp b/src/iidm/AbstractTerminalTopologyVisitor.cpp new file mode 100644 index 000000000..069a7a579 --- /dev/null +++ b/src/iidm/AbstractTerminalTopologyVisitor.cpp @@ -0,0 +1,97 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace powsybl { + +namespace iidm { + +void AbstractTerminalTopologyVisitor::visitBattery(const Battery& battery) { + visitInjection(battery); +} + +void AbstractTerminalTopologyVisitor::visitBranch(const Branch& branch, const Branch::Side& side) { + visitTerminal(branch.getTerminal(side)); +} + +void AbstractTerminalTopologyVisitor::visitBusbarSection(const BusbarSection& section) { + visitInjection(section); +} + +void AbstractTerminalTopologyVisitor::visitDanglingLine(const DanglingLine& danglingLine) { + visitInjection(danglingLine); +} + +void AbstractTerminalTopologyVisitor::visitGenerator(const Generator& generator) { + visitInjection(generator); +} + +void AbstractTerminalTopologyVisitor::visitHvdcConverterStation(const HvdcConverterStation& converterStation) { + visitInjection(converterStation); +} + +void AbstractTerminalTopologyVisitor::visitInjection(const Injection& injection) { + visitTerminal(injection.getTerminal()); +} + +void AbstractTerminalTopologyVisitor::visitLine(const Line& line, const Branch::Side& side) { + visitBranch(line, side); +} + +void AbstractTerminalTopologyVisitor::visitLoad(const Load& load) { + visitInjection(load); +} + +void AbstractTerminalTopologyVisitor::visitShuntCompensator(const ShuntCompensator& sc) { + visitInjection(sc); +} + +void AbstractTerminalTopologyVisitor::visitStaticVarCompensator(const StaticVarCompensator& staticVarCompensator) { + visitInjection(staticVarCompensator); +} + +void AbstractTerminalTopologyVisitor::visitThreeWindingsTransformer(const ThreeWindingsTransformer& transformer, const ThreeWindingsTransformer::Side& side) { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + visitTerminal(transformer.getLeg1().getTerminal()); + break; + + case ThreeWindingsTransformer::Side::TWO: + visitTerminal(transformer.getLeg2().getTerminal()); + break; + + case ThreeWindingsTransformer::Side::THREE: + visitTerminal(transformer.getLeg3().getTerminal()); + break; + + default: + throw AssertionError(stdcxx::format("Unexpected 3WT side %1%", side)); + } +} + +void AbstractTerminalTopologyVisitor::visitTwoWindingsTransformer(const TwoWindingsTransformer& transformer, const Branch::Side& side) { + visitBranch(transformer, side); +} + +} // namespace iidm + +} // namespace powsybl diff --git a/src/iidm/Bus.cpp b/src/iidm/Bus.cpp index d8e3eaf6d..9007b8ba8 100644 --- a/src/iidm/Bus.cpp +++ b/src/iidm/Bus.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -99,6 +100,70 @@ Network& Bus::getNetwork() { return getVoltageLevel().getNetwork(); } +double Bus::getP() const { + if (getConnectedTerminalCount() == 0) { + return stdcxx::nan(); + } + double p = 0; + for (const Terminal& terminal : getConnectedTerminals()) { + const Connectable& connectable = terminal.getConnectable(); + switch (connectable.getType()) { + case ConnectableType::BUSBAR_SECTION: + case ConnectableType::SHUNT_COMPENSATOR: + case ConnectableType::STATIC_VAR_COMPENSATOR: + case ConnectableType::LINE: + case ConnectableType::TWO_WINDINGS_TRANSFORMER: + case ConnectableType::THREE_WINDINGS_TRANSFORMER: + case ConnectableType::DANGLING_LINE: + // skip + break; + case ConnectableType::GENERATOR: + case ConnectableType::BATTERY: + case ConnectableType::LOAD: + case ConnectableType::HVDC_CONVERTER_STATION: + if (!std::isnan(terminal.getP())) { + p += terminal.getP(); + } + break; + default: + throw AssertionError(stdcxx::format("Unexpected connectable type: %1%", connectable.getType())); + } + } + return p; +} + +double Bus::getQ() const { + if (getConnectedTerminalCount() == 0) { + return stdcxx::nan(); + } + double q = 0; + for (const Terminal& terminal : getConnectedTerminals()) { + const Connectable& connectable = terminal.getConnectable(); + switch (connectable.getType()) { + case ConnectableType::BUSBAR_SECTION: + case ConnectableType::LINE: + case ConnectableType::TWO_WINDINGS_TRANSFORMER: + case ConnectableType::THREE_WINDINGS_TRANSFORMER: + case ConnectableType::DANGLING_LINE: + // skip + break; + case ConnectableType::GENERATOR: + case ConnectableType::BATTERY: + case ConnectableType::LOAD: + case ConnectableType::SHUNT_COMPENSATOR: + case ConnectableType::STATIC_VAR_COMPENSATOR: + case ConnectableType::HVDC_CONVERTER_STATION: + if (!std::isnan(terminal.getQ())) { + q += terminal.getQ(); + } + break; + default: + throw AssertionError(stdcxx::format("Unexpected connectable type: %1%", connectable.getType())); + } + } + return q; +} + stdcxx::const_range Bus::getShuntCompensators() const { return getAll(); } @@ -155,6 +220,10 @@ bool Bus::isInMainSynchronousComponent() const { return static_cast(sc) && (sc.get().getNum() == ComponentConstants::MAIN_NUM); } +void Bus::visitConnectedEquipments(TopologyVisitor& visitor) { + TopologyVisitor::visitEquipments(getConnectedTerminals(), visitor); +} + } // namespace iidm } // namespace powsybl diff --git a/src/iidm/BusBreakerVoltageLevel.cpp b/src/iidm/BusBreakerVoltageLevel.cpp index 8baf75ebf..566ee30c1 100644 --- a/src/iidm/BusBreakerVoltageLevel.cpp +++ b/src/iidm/BusBreakerVoltageLevel.cpp @@ -23,8 +23,8 @@ namespace powsybl { namespace iidm { BusBreakerVoltageLevel::BusBreakerVoltageLevel(const std::string& id, const std::string& name, bool fictitious, Substation& substation, - double nominalVoltage, double lowVoltageLimit, double highVoltagelimit) : - VoltageLevel(id, name, fictitious, substation, nominalVoltage, lowVoltageLimit, highVoltagelimit), + double nominalV, double lowVoltageLimit, double highVoltagelimit) : + VoltageLevel(id, name, fictitious, substation, nominalV, lowVoltageLimit, highVoltagelimit), m_variants(*this, [this]() { return stdcxx::make_unique(*this); }), m_busBreakerView(*this), m_busView(*this) { @@ -161,7 +161,7 @@ stdcxx::CReference BusBreakerVoltageLevel::getConfiguredBus(const stdcxx::Reference bus; const auto& v = getVertex(busId, throwException); - if (v.is_initialized()) { + if (v) { bus = m_graph.getVertexObject(*v); if (bus.get().getId() != busId) { throw PowsyblException(stdcxx::format("Invalid bus id (expected: '%1%', actual: '%2%')", busId, bus.get().getId())); @@ -221,7 +221,7 @@ stdcxx::Reference BusBreakerVoltageLevel::getSwitch(const std::string& s stdcxx::Reference aSwitch; const auto& e = getEdge(switchId, throwException); - if (e.is_initialized()) { + if (e) { aSwitch = m_graph.getEdgeObject(*e); if (aSwitch.get().getId() != switchId) { throw PowsyblException(stdcxx::format("Invalid switch id (expected: '%1%', actual: '%2%')", switchId, aSwitch.get().getId())); @@ -354,6 +354,11 @@ void BusBreakerVoltageLevel::removeSwitch(const std::string& switchId) { getNetwork().remove(aSwitch.get()); } +void BusBreakerVoltageLevel::removeTopology() { + removeAllSwitches(); + removeAllBuses(); +} + } // namespace iidm } // namespace powsybl diff --git a/src/iidm/BusBreakerVoltageLevel.hpp b/src/iidm/BusBreakerVoltageLevel.hpp index 569f3a033..17f7ae49f 100644 --- a/src/iidm/BusBreakerVoltageLevel.hpp +++ b/src/iidm/BusBreakerVoltageLevel.hpp @@ -57,7 +57,7 @@ class BusBreakerVoltageLevel : public VoltageLevel { public: BusBreakerVoltageLevel(const std::string& id, const std::string& name, bool fictitious, Substation& substation, - double nominalVoltage, double lowVoltageLimit, double highVoltagelimit); + double nominalV, double lowVoltageLimit, double highVoltagelimit); ~BusBreakerVoltageLevel() noexcept override = default; @@ -84,6 +84,8 @@ class BusBreakerVoltageLevel : public VoltageLevel { NodeBreakerView& getNodeBreakerView() override; + void removeTopology() override; + private: void checkTerminal(Terminal& terminal) const; diff --git a/src/iidm/BusBreakerVoltageLevelBusCache.hpp b/src/iidm/BusBreakerVoltageLevelBusCache.hpp index 46b36b04b..3c8f152b5 100644 --- a/src/iidm/BusBreakerVoltageLevelBusCache.hpp +++ b/src/iidm/BusBreakerVoltageLevelBusCache.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include "MergedBus.hpp" diff --git a/src/iidm/BusBreakerVoltageLevelTopology.cpp b/src/iidm/BusBreakerVoltageLevelTopology.cpp index 75166fb0d..debc17e07 100644 --- a/src/iidm/BusBreakerVoltageLevelTopology.cpp +++ b/src/iidm/BusBreakerVoltageLevelTopology.cpp @@ -12,7 +12,7 @@ #include #include #include -#include +#include #include #include "BusBreakerVoltageLevel.hpp" diff --git a/src/iidm/BusBreakerVoltageLevelTopology.hpp b/src/iidm/BusBreakerVoltageLevelTopology.hpp index 26527eac8..45c71c275 100644 --- a/src/iidm/BusBreakerVoltageLevelTopology.hpp +++ b/src/iidm/BusBreakerVoltageLevelTopology.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include #include "BusBreakerVoltageLevelBusCache.hpp" #include "MergedBus.hpp" diff --git a/src/iidm/BusTerminal.hpp b/src/iidm/BusTerminal.hpp index 08a1673fd..0699309f2 100644 --- a/src/iidm/BusTerminal.hpp +++ b/src/iidm/BusTerminal.hpp @@ -50,15 +50,15 @@ class BusTerminal : public Terminal { public: BusTerminal(VoltageLevel& voltageLevel, const std::string& connectableBusId, bool connected); - BusTerminal(const BusTerminal& nodeTerminal) = delete; + BusTerminal(const BusTerminal&) = delete; - BusTerminal(BusTerminal&& nodeTerminal) = delete; + BusTerminal(BusTerminal&&) = delete; ~BusTerminal() noexcept override = default; - BusTerminal& operator=(const BusTerminal& nodeTerminal) = delete; + BusTerminal& operator=(const BusTerminal&) = delete; - BusTerminal& operator=(BusTerminal&& nodeTerminal) = delete; + BusTerminal& operator=(BusTerminal&&) = delete; const std::string& getConnectableBusId() const; diff --git a/src/iidm/CalculatedBus.cpp b/src/iidm/CalculatedBus.cpp index 2870c32d1..f7d9e41bd 100644 --- a/src/iidm/CalculatedBus.cpp +++ b/src/iidm/CalculatedBus.cpp @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include "NodeBreakerVoltageLevel.hpp" #include "NodeTerminal.hpp" @@ -158,6 +160,11 @@ Bus& CalculatedBus::setV(double v) { return *this; } +void CalculatedBus::visitConnectedOrConnectableEquipments(TopologyVisitor& visitor) { + const auto& mapper = stdcxx::upcast; + TopologyVisitor::visitEquipments(m_terminals | boost::adaptors::transformed(mapper), visitor); +} + } // namespace iidm } // namespace powsybl diff --git a/src/iidm/CalculatedBus.hpp b/src/iidm/CalculatedBus.hpp index 13ef84c55..5583f7400 100644 --- a/src/iidm/CalculatedBus.hpp +++ b/src/iidm/CalculatedBus.hpp @@ -12,7 +12,7 @@ #include #include -#include +#include namespace powsybl { @@ -56,6 +56,8 @@ class CalculatedBus : public Bus { Bus& setV(double v) override; + void visitConnectedOrConnectableEquipments(TopologyVisitor& visitor) override; + public: /** * Create a new CalculatedBus from a list of NodeTerminal references diff --git a/src/iidm/ConfiguredBus.cpp b/src/iidm/ConfiguredBus.cpp index 4499ef6f8..d49de45d7 100644 --- a/src/iidm/ConfiguredBus.cpp +++ b/src/iidm/ConfiguredBus.cpp @@ -14,10 +14,12 @@ #include #include #include +#include #include #include #include #include +#include #include "BusBreakerVoltageLevel.hpp" #include "BusTerminal.hpp" @@ -209,6 +211,11 @@ Bus& ConfiguredBus::setV(double v) { return *this; } +void ConfiguredBus::visitConnectedOrConnectableEquipments(TopologyVisitor& visitor) { + const auto& mapper = stdcxx::upcast; + TopologyVisitor::visitEquipments(getTerminals() | boost::adaptors::transformed(mapper), visitor); +} + } // namespace iidm } // namespace powsybl diff --git a/src/iidm/ConfiguredBus.hpp b/src/iidm/ConfiguredBus.hpp index e5f98f686..3ff6cb8a3 100644 --- a/src/iidm/ConfiguredBus.hpp +++ b/src/iidm/ConfiguredBus.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include namespace powsybl { @@ -56,6 +56,8 @@ class ConfiguredBus : public Bus { Bus& setV(double v) override; + void visitConnectedOrConnectableEquipments(TopologyVisitor& visitor) override; + public: ConfiguredBus(const std::string& id, const std::string& name, bool fictitious, BusBreakerVoltageLevel& voltageLevel); diff --git a/src/iidm/DanglingLineAdder.cpp b/src/iidm/DanglingLineAdder.cpp index 49a8d6b20..3ab1eb9de 100644 --- a/src/iidm/DanglingLineAdder.cpp +++ b/src/iidm/DanglingLineAdder.cpp @@ -30,7 +30,7 @@ DanglingLine& DanglingLineAdder::add() { checkG(*this, m_g); checkB(*this, m_b); - std::unique_ptr ptrGeneration = m_generationAdder.is_initialized() ? m_generationAdder->build() : nullptr; + std::unique_ptr ptrGeneration = m_generationAdder ? m_generationAdder->build() : nullptr; std::unique_ptr ptrDanglingLine = stdcxx::make_unique(getNetwork(), checkAndGetUniqueId(), getName(), isFictitious(), m_p0, m_q0, m_r, m_x, m_g, m_b, m_ucteXnodeCode, std::move(ptrGeneration)); diff --git a/src/iidm/Extendable.cpp b/src/iidm/Extendable.cpp index b17db5517..00a30e857 100644 --- a/src/iidm/Extendable.cpp +++ b/src/iidm/Extendable.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/src/iidm/ExtensionProviders.cpp b/src/iidm/ExtensionProviders.cpp index 4d49f3e34..cf0d07c3c 100644 --- a/src/iidm/ExtensionProviders.cpp +++ b/src/iidm/ExtensionProviders.cpp @@ -114,7 +114,7 @@ void ExtensionProviders::loadLibrary(const boost::filesystem::path& li } template -void ExtensionProviders::registerExtension(std::unique_ptr provider, const boost::filesystem::path& libraryPath) { +void ExtensionProviders::registerExtension(std::unique_ptr&& provider, const boost::filesystem::path& libraryPath) { logging::Logger& logger = logging::LoggerFactory::getLogger(); const std::string& extensionName = provider->getExtensionName(); diff --git a/src/iidm/HvdcConverterStation.cpp b/src/iidm/HvdcConverterStation.cpp index 21b816dce..b89bd825d 100644 --- a/src/iidm/HvdcConverterStation.cpp +++ b/src/iidm/HvdcConverterStation.cpp @@ -31,6 +31,13 @@ double HvdcConverterStation::getLossFactor() const { return m_lossFactor; } +void HvdcConverterStation::remove() { + if (m_hvdcLine) { + throw ValidationException(*this, stdcxx::format("Impossible to remove this converter station (still attached to '%1%')", m_hvdcLine.get().getId())); + } + Injection::remove(); +} + void HvdcConverterStation::setHvdcLine(const stdcxx::Reference& hvdcLine) { m_hvdcLine = hvdcLine; } diff --git a/src/iidm/HvdcLine.cpp b/src/iidm/HvdcLine.cpp index bacfa73e7..1c0e66b61 100644 --- a/src/iidm/HvdcLine.cpp +++ b/src/iidm/HvdcLine.cpp @@ -15,13 +15,13 @@ namespace powsybl { namespace iidm { -HvdcLine::HvdcLine(Network& network, const std::string& id, const std::string& name, bool fictitious, double r, double nominalVoltage, double maxP, +HvdcLine::HvdcLine(Network& network, const std::string& id, const std::string& name, bool fictitious, double r, double nominalV, double maxP, const ConvertersMode& convertersMode, double activePowerSetpoint, HvdcConverterStation& converterStation1, HvdcConverterStation& converterStation2) : Identifiable(id, name, fictitious), m_converterStation1(attach(converterStation1)), m_converterStation2(attach(converterStation2)), m_r(checkR(*this, r)), - m_nominalVoltage(checkNominalVoltage(*this, nominalVoltage)), + m_nominalV(checkNominalVoltage(*this, nominalV)), m_maxP(checkHvdcMaxP(*this, maxP)), m_convertersMode(network.getVariantManager().getVariantArraySize(), checkConvertersMode(*this, convertersMode)), m_activePowerSetpoint(network.getVariantManager().getVariantArraySize(), checkHvdcActivePowerSetpoint(*this, activePowerSetpoint)) { @@ -99,8 +99,8 @@ Network& HvdcLine::getNetwork() { return const_cast(static_cast(this)->getNetwork()); } -double HvdcLine::getNominalVoltage() const { - return m_nominalVoltage; +double HvdcLine::getNominalV() const { + return m_nominalV; } double HvdcLine::getR() const { @@ -150,8 +150,8 @@ HvdcLine& HvdcLine::setMaxP(double maxP) { return *this; } -HvdcLine& HvdcLine::setNominalVoltage(double nominalVoltage) { - m_nominalVoltage = checkNominalVoltage(*this, nominalVoltage); +HvdcLine& HvdcLine::setNominalV(double nominalV) { + m_nominalV = checkNominalVoltage(*this, nominalV); return *this; } diff --git a/src/iidm/HvdcLineAdder.cpp b/src/iidm/HvdcLineAdder.cpp index 076ab5554..c24ca9c4c 100644 --- a/src/iidm/HvdcLineAdder.cpp +++ b/src/iidm/HvdcLineAdder.cpp @@ -26,14 +26,14 @@ HvdcLine& HvdcLineAdder::add() { checkR(*this, m_r); checkOptional(*this, m_convertersMode, "converter mode is invalid"); checkConvertersMode(*this, *m_convertersMode); - checkNominalVoltage(*this, m_nominalVoltage); + checkNominalVoltage(*this, m_nominalV); checkHvdcActivePowerSetpoint(*this, m_activePowerSetpoint); checkHvdcMaxP(*this, m_maxP); HvdcConverterStation& converterStation1 = getConverterStation(m_converterStationId1, 1U); HvdcConverterStation& converterStation2 = getConverterStation(m_converterStationId2, 2U); - std::unique_ptr ptrHvdcLine = stdcxx::make_unique(getNetwork(), checkAndGetUniqueId(), getName(), isFictitious(), m_r, m_nominalVoltage, m_maxP, *m_convertersMode, m_activePowerSetpoint, + std::unique_ptr ptrHvdcLine = stdcxx::make_unique(getNetwork(), checkAndGetUniqueId(), getName(), isFictitious(), m_r, m_nominalV, m_maxP, *m_convertersMode, m_activePowerSetpoint, converterStation1, converterStation2); auto& line = m_network.checkAndAdd(std::move(ptrHvdcLine)); @@ -89,8 +89,8 @@ HvdcLineAdder& HvdcLineAdder::setMaxP(double maxP) { return *this; } -HvdcLineAdder& HvdcLineAdder::setNominalVoltage(double nominalVoltage) { - m_nominalVoltage = nominalVoltage; +HvdcLineAdder& HvdcLineAdder::setNominalV(double nominalV) { + m_nominalV = nominalV; return *this; } diff --git a/src/iidm/Identifiable.cpp b/src/iidm/Identifiable.cpp index 2a4995ad1..2d6ba11c8 100644 --- a/src/iidm/Identifiable.cpp +++ b/src/iidm/Identifiable.cpp @@ -7,6 +7,9 @@ #include +#include +#include + #include #include #include @@ -31,9 +34,42 @@ Identifiable::Identifiable(const std::string& id, const std::string& name, bool } void Identifiable::addAlias(const std::string& alias) { - if (getNetwork().getIndex().addAlias(*this, alias)) { - m_aliases.emplace(alias); + addAlias(alias, false); +} + +void Identifiable::addAlias(const std::string& alias, bool ensureAliasUnicity) { + addAlias(alias, "", ensureAliasUnicity); +} + +void Identifiable::addAlias(const std::string& alias, const std::string& aliasType) { + addAlias(alias, aliasType, false); +} + +void Identifiable::addAlias(const std::string& alias, const char* aliasType) { + addAlias(alias, std::string(aliasType), false); +} + +void Identifiable::addAlias(const std::string& alias, const std::string& aliasType, bool ensureAliasUnicity) { + std::string uniqueAlias = alias; + if (ensureAliasUnicity) { + uniqueAlias = Identifiables::getUniqueId(alias, [this](const std::string& idOrAlias) { + return static_cast(getNetwork().find(idOrAlias)); + }); } + if (!aliasType.empty() && m_aliasesByType.find(aliasType) != m_aliasesByType.end()) { + throw PowsyblException(stdcxx::format("%1% already has an alias of type %2%", m_id, aliasType)); + } + if (getNetwork().getIndex().addAlias(*this, uniqueAlias)) { + if (aliasType.empty()) { + m_aliasesWithoutType.emplace(uniqueAlias); + } else { + m_aliasesByType[aliasType] = uniqueAlias; + } + } +} + +void Identifiable::addAlias(const std::string& alias, const char* aliasType, bool ensureAliasUnicity) { + addAlias(alias, std::string(aliasType), ensureAliasUnicity); } void Identifiable::allocateVariantArrayElement(const std::set& indexes, unsigned long sourceIndex) { @@ -60,8 +96,26 @@ void Identifiable::extendVariantArraySize(unsigned long initVariantArraySize, un } } -const std::set& Identifiable::getAliases() const { - return m_aliases; +stdcxx::const_range Identifiable::getAliases() const { + return boost::range::join(m_aliasesWithoutType, m_aliasesByType | boost::adaptors::map_values); +} + +stdcxx::optional Identifiable::getAliasFromType(const std::string& aliasType) const { + if (aliasType.empty()) { + throw PowsyblException(stdcxx::format("Alias type must not be empty")); + } + auto it = m_aliasesByType.find(aliasType); + return it != m_aliasesByType.end() ? it->second : stdcxx::optional(); +} + +std::string Identifiable::getAliasType(const std::string& alias) const { + if (m_aliasesWithoutType.find(alias) != m_aliasesWithoutType.end()) { + return ""; + } + auto it = std::find_if(m_aliasesByType.begin(), m_aliasesByType.end(), [&alias](const std::pair& entry) { + return entry.second == alias; + }); + return it != m_aliasesByType.end() ? it->first : ""; } const std::string& Identifiable::getId() const { @@ -93,7 +147,7 @@ stdcxx::const_range Identifiable::getPropertyNames() const { } bool Identifiable::hasAliases() const { - return !m_aliases.empty(); + return !m_aliasesWithoutType.empty() || !m_aliasesByType.empty(); } bool Identifiable::hasProperty() const { @@ -118,7 +172,14 @@ void Identifiable::reduceVariantArraySize(unsigned long number) { void Identifiable::removeAlias(const std::string& alias) { getNetwork().getIndex().removeAlias(*this, alias); - m_aliases.erase(alias); + auto it = std::find_if(m_aliasesByType.begin(), m_aliasesByType.end(), [&alias](const std::pair& entry) { + return entry.second == alias; + }); + if (it != m_aliasesByType.end()) { + m_aliasesByType.erase(it); + } else { + m_aliasesWithoutType.erase(alias); + } } void Identifiable::setFictitious(bool fictitious) { diff --git a/src/iidm/MergedBus.cpp b/src/iidm/MergedBus.cpp index 6813f8603..965a46903 100644 --- a/src/iidm/MergedBus.cpp +++ b/src/iidm/MergedBus.cpp @@ -182,6 +182,13 @@ Bus& MergedBus::setV(double v) { return *this; } +void MergedBus::visitConnectedOrConnectableEquipments(TopologyVisitor& visitor) { + checkValidity(); + for (ConfiguredBus& bus : m_buses) { + bus.visitConnectedOrConnectableEquipments(visitor); + } +} + } // namespace iidm } // namespace powsybl diff --git a/src/iidm/MergedBus.hpp b/src/iidm/MergedBus.hpp index 23c0dffac..f44ef7c4c 100644 --- a/src/iidm/MergedBus.hpp +++ b/src/iidm/MergedBus.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include "ConfiguredBus.hpp" @@ -65,6 +65,8 @@ class MergedBus : public Bus { Bus& setV(double v) override; + void visitConnectedOrConnectableEquipments(TopologyVisitor& visitor) override; + public: /** * Create a new MergedBus from a list of ConfiguredBus references diff --git a/src/iidm/MultipleVariantContext.cpp b/src/iidm/MultipleVariantContext.cpp index a5b6ae82f..f68fe71fb 100644 --- a/src/iidm/MultipleVariantContext.cpp +++ b/src/iidm/MultipleVariantContext.cpp @@ -5,7 +5,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include +#include "MultipleVariantContext.hpp" #include @@ -18,12 +18,16 @@ MultipleVariantContext::MultipleVariantContext(unsigned long index) : } unsigned long MultipleVariantContext::getVariantIndex() const { - if (!m_index.is_initialized()) { + if (!m_index) { throw PowsyblException("Variant index not set"); } return m_index.get(); } +bool MultipleVariantContext::isIndexSet() const { + return static_cast(m_index); +} + void MultipleVariantContext::resetIfVariantIndexIs(unsigned long index) { if (m_index == index) { m_index.reset(); diff --git a/include/powsybl/iidm/MultipleVariantContext.hpp b/src/iidm/MultipleVariantContext.hpp similarity index 74% rename from include/powsybl/iidm/MultipleVariantContext.hpp rename to src/iidm/MultipleVariantContext.hpp index e7a772470..b4888a7ea 100644 --- a/include/powsybl/iidm/MultipleVariantContext.hpp +++ b/src/iidm/MultipleVariantContext.hpp @@ -19,11 +19,21 @@ class MultipleVariantContext : public VariantContext { public: explicit MultipleVariantContext(unsigned long index); + MultipleVariantContext(const MultipleVariantContext&) = default; + + MultipleVariantContext(MultipleVariantContext&&) noexcept = default; + ~MultipleVariantContext() noexcept override = default; + MultipleVariantContext& operator=(const MultipleVariantContext&) = default; + + MultipleVariantContext& operator=(MultipleVariantContext&&) noexcept = default; + protected: // VariantContext unsigned long getVariantIndex() const override; + bool isIndexSet() const override; + void resetIfVariantIndexIs(unsigned long index) override; void setVariantIndex(unsigned long index) override; diff --git a/src/iidm/Network.cpp b/src/iidm/Network.cpp index d631da21d..38215d516 100644 --- a/src/iidm/Network.cpp +++ b/src/iidm/Network.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -44,26 +45,28 @@ namespace powsybl { namespace iidm { -Network Network::readXml(const std::string& data) { - std::stringstream stream(data); - return readXml(stream); -} - -Network Network::readXml(std::istream& istream) { - return readXml(istream, converter::ImportOptions(), converter::FakeAnonymizer()); +Network Network::readXml(const boost::filesystem::path& path, const converter::ImportOptions& options) { + boost::filesystem::ifstream is(path); + if (!is.is_open()) { + throw PowsyblException(stdcxx::format("Unable to open file '%1%' for reading", path.string())); + } + return converter::xml::NetworkXml::read(path.string(), is, options); } -Network Network::readXml(std::istream& istream, const converter::ImportOptions& options, const converter::Anonymizer& anonymizer) { - return converter::xml::NetworkXml::read(istream, options, anonymizer); +Network Network::readXml(const std::string& filename, std::istream& istream, const converter::ImportOptions& options) { + return converter::xml::NetworkXml::read(filename, istream, options); } -std::unique_ptr Network::writeXml(std::ostream& ostream, const Network& network) { - converter::ExportOptions options; - return writeXml(ostream, network, options); +void Network::writeXml(const boost::filesystem::path& path, const Network& network, const converter::ExportOptions& options) { + boost::filesystem::ofstream os(path); + if (!os.is_open()) { + throw PowsyblException(stdcxx::format("Unable to open file '%1%' for writing", path.string())); + } + converter::xml::NetworkXml::write(path.string(), os, network, options); } -std::unique_ptr Network::writeXml(std::ostream& ostream, const Network& network, const converter::ExportOptions& options) { - return converter::xml::NetworkXml::write(ostream, network, options); +void Network::writeXml(const std::string& filename, std::ostream& ostream, const Network& network, const converter::ExportOptions& options) { + converter::xml::NetworkXml::write(filename, ostream, network, options); } Network::Network(const std::string& id, const std::string& sourceFormat) : @@ -107,6 +110,18 @@ void Network::extendVariantArraySize(unsigned long initVariantArraySize, unsigne m_variants.extendVariantArraySize(initVariantArraySize, number, [this, sourceIndex]() { return m_variants.copy(sourceIndex); }); } +stdcxx::CReference Network::findHvdcLine(const HvdcConverterStation& station) const { + const auto& filter = [&station](const HvdcLine& hvdcLine) { + return stdcxx::areSame(hvdcLine.getConverterStation1().get(), station) || stdcxx::areSame(hvdcLine.getConverterStation2().get(), station); + }; + auto hvdcLines = getHvdcLines() | boost::adaptors::filtered(filter); + return hvdcLines.empty() ? stdcxx::cref() : stdcxx::cref(*hvdcLines.begin()); +} + +stdcxx::Reference Network::findHvdcLine(const HvdcConverterStation& station) { + return stdcxx::ref(const_cast(this)->findHvdcLine(station)); +} + const Battery& Network::getBattery(const std::string& id) const { return get(id); } @@ -203,16 +218,19 @@ ConnectedComponentsManager& Network::getConnectedComponentsManager() { return m_variants.get().getConnectedComponentsManager(); } -unsigned long Network::getCountryCount() const { - std::unordered_set> countries; +std::set Network::getCountries() const { + std::set countries; for (const auto& substation : getSubstations()) { const stdcxx::optional& country = substation.getCountry(); if (country) { countries.emplace(*country); } } + return countries; +} - return countries.size(); +unsigned long Network::getCountryCount() const { + return getCountries().size(); } const DanglingLine& Network::getDanglingLine(const std::string& id) const { @@ -291,6 +309,18 @@ HvdcLine& Network::getHvdcLine(const std::string& id) { return get(id); } +const HvdcLine& Network::getHvdcLine(const HvdcConverterStation& station) const { + auto hvdcLine = findHvdcLine(station); + if (!hvdcLine) { + throw PowsyblException(stdcxx::format("Unable to find to the HVDC line for station '%1%'", station.getId())); + } + return hvdcLine.get(); +} + +HvdcLine& Network::getHvdcLine(const HvdcConverterStation& station) { + return const_cast(static_cast(this)->getHvdcLine(station)); +} + unsigned long Network::getHvdcLineCount() const { return getObjectCount(); } @@ -623,7 +653,6 @@ void Network::remove(Identifiable& identifiable) { m_networkIndex.remove(identifiable); } - Network& Network::setCaseDate(const stdcxx::DateTime& caseDate) { m_caseDate = caseDate; return *this; diff --git a/src/iidm/NodeBreakerVoltageLevel.cpp b/src/iidm/NodeBreakerVoltageLevel.cpp index 436c4abd0..241c231f1 100644 --- a/src/iidm/NodeBreakerVoltageLevel.cpp +++ b/src/iidm/NodeBreakerVoltageLevel.cpp @@ -20,8 +20,8 @@ namespace powsybl { namespace iidm { NodeBreakerVoltageLevel::NodeBreakerVoltageLevel(const std::string& id, const std::string& name, bool fictitious, Substation& substation, - double nominalVoltage, double lowVoltageLimit, double highVoltagelimit) : - VoltageLevel(id, name, fictitious, substation, nominalVoltage, lowVoltageLimit, highVoltagelimit), + double nominalV, double lowVoltageLimit, double highVoltagelimit) : + VoltageLevel(id, name, fictitious, substation, nominalV, lowVoltageLimit, highVoltagelimit), m_busNamingStrategy(*this), m_variants(*this, [this]() { return stdcxx::make_unique(*this); }), m_nodeBreakerView(*this), @@ -93,7 +93,7 @@ bool NodeBreakerVoltageLevel::connect(Terminal& terminal) { return static_cast(refTerminal) && refTerminal.get().getConnectable().get().getType() == ConnectableType::BUSBAR_SECTION; }; node_breaker_voltage_level::Graph::EdgeVisitor isOpenedDisconnector = [](const stdcxx::Reference& aSwitch) { - return aSwitch.get().getKind() == SwitchKind::DISCONNECTOR && aSwitch.get().isOpen(); + return aSwitch && aSwitch.get().getKind() == SwitchKind::DISCONNECTOR && aSwitch.get().isOpen(); }; const auto& paths = m_graph.findAllPaths(node, isBusbarSection, isOpenedDisconnector); @@ -101,9 +101,9 @@ bool NodeBreakerVoltageLevel::connect(Terminal& terminal) { if (!paths.empty()) { const auto& shortestPath = paths[0]; for (unsigned long e : shortestPath) { - Switch& aSwitch = m_graph.getEdgeObject(e).get(); - if (aSwitch.getKind() == SwitchKind::BREAKER && aSwitch.isOpen()) { - aSwitch.setOpen(false); + const auto& aSwitch = m_graph.getEdgeObject(e); + if (aSwitch && aSwitch.get().getKind() == SwitchKind::BREAKER && aSwitch.get().isOpen()) { + aSwitch.get().setOpen(false); connected = true; } } @@ -124,6 +124,8 @@ void NodeBreakerVoltageLevel::detach(Terminal& terminal) { assert(node < m_graph.getVertexCount()); assert(stdcxx::areSame(m_graph.getVertexObject(node).get(), nodeTerminal)); + invalidateCache(); + // remove the link terminal <-> graph vertex m_graph.setVertexObject(node, stdcxx::ref()); clean(); @@ -139,7 +141,7 @@ bool NodeBreakerVoltageLevel::disconnect(Terminal& terminal) { return static_cast(refTerminal) && refTerminal.get().getConnectable().get().getType() == ConnectableType::BUSBAR_SECTION; }; node_breaker_voltage_level::Graph::EdgeVisitor isOpenedDisconnector = [](const stdcxx::Reference& aSwitch) { - return aSwitch.get().getKind() == SwitchKind::DISCONNECTOR && aSwitch.get().isOpen(); + return aSwitch && aSwitch.get().getKind() == SwitchKind::DISCONNECTOR && aSwitch.get().isOpen(); }; const auto& paths = m_graph.findAllPaths(node, isBusbarSection, isOpenedDisconnector); @@ -150,10 +152,10 @@ bool NodeBreakerVoltageLevel::disconnect(Terminal& terminal) { for (const auto& path : paths) { bool pathOpen = false; for (unsigned long e : path) { - Switch& aSwitch = m_graph.getEdgeObject(e).get(); - if (aSwitch.getKind() == SwitchKind::BREAKER) { - if (!aSwitch.isOpen()) { - aSwitch.setOpen(true); + const auto& aSwitch = m_graph.getEdgeObject(e); + if (aSwitch && aSwitch.get().getKind() == SwitchKind::BREAKER) { + if (!aSwitch.get().isOpen()) { + aSwitch.get().setOpen(true); } // Open one breaker is sufficient to disconnect the terminal pathOpen = true; @@ -257,7 +259,7 @@ stdcxx::CReference NodeBreakerVoltageLevel::getSwitch(const std::string& stdcxx::Reference aSwitch; const auto& e = getEdge(switchId, false); - if (e.is_initialized()) { + if (e) { aSwitch = m_graph.getEdgeObject(*e); if (aSwitch.get().getId() != switchId) { throw PowsyblException(stdcxx::format("Invalid switch id (expected: '%1%', actual: '%2%')", switchId, aSwitch.get().getId())); @@ -363,6 +365,14 @@ void NodeBreakerVoltageLevel::removeSwitch(const std::string& switchId) { getNetwork().remove(aSwitch.get()); } +void NodeBreakerVoltageLevel::removeTopology() { + for (Switch& s : m_graph.getEdgeObjects()) { + getNetwork().getIndex().remove(s); + } + m_graph.removeAllEdges(); + m_switches.clear(); +} + } // namespace iidm } // namespace powsybl diff --git a/src/iidm/NodeBreakerVoltageLevel.hpp b/src/iidm/NodeBreakerVoltageLevel.hpp index e8ebade78..d36958e7c 100644 --- a/src/iidm/NodeBreakerVoltageLevel.hpp +++ b/src/iidm/NodeBreakerVoltageLevel.hpp @@ -65,7 +65,7 @@ class NodeBreakerVoltageLevel : public VoltageLevel { public: NodeBreakerVoltageLevel(const std::string& id, const std::string& name, bool fictitious, Substation& substation, - double nominalVoltage, double lowVoltageLimit, double highVoltagelimit); + double nominalV, double lowVoltageLimit, double highVoltagelimit); ~NodeBreakerVoltageLevel() noexcept override = default; @@ -89,6 +89,9 @@ class NodeBreakerVoltageLevel : public VoltageLevel { stdcxx::range getTerminals() override; +private: // VoltageLevel + void removeTopology() override; + private: void checkTerminal(Terminal& terminal) const; diff --git a/src/iidm/NodeBreakerVoltageLevelBusCache.hpp b/src/iidm/NodeBreakerVoltageLevelBusCache.hpp index 875779f66..ba2d346a7 100644 --- a/src/iidm/NodeBreakerVoltageLevelBusCache.hpp +++ b/src/iidm/NodeBreakerVoltageLevelBusCache.hpp @@ -14,7 +14,7 @@ #include #include -#include +#include #include "CalculatedBus.hpp" diff --git a/src/iidm/NodeBreakerVoltageLevelTopology.cpp b/src/iidm/NodeBreakerVoltageLevelTopology.cpp index 9a0d4d732..abfc9b196 100644 --- a/src/iidm/NodeBreakerVoltageLevelTopology.cpp +++ b/src/iidm/NodeBreakerVoltageLevelTopology.cpp @@ -67,7 +67,7 @@ stdcxx::Reference CalculatedBusBreakerTopology::getBus2(const std } stdcxx::Reference CalculatedBusBreakerTopology::getRetainedSwitch(const stdcxx::optional& e) const { - if (static_cast(e)) { + if (e) { const auto& aSwitch = getVoltageLevel().getGraph().getEdgeObject(*e); if (aSwitch.get().isRetained()) { return aSwitch; diff --git a/src/iidm/NodeBreakerVoltageLevelTopology.hpp b/src/iidm/NodeBreakerVoltageLevelTopology.hpp index 1a8868f9f..8ddb3e84d 100644 --- a/src/iidm/NodeBreakerVoltageLevelTopology.hpp +++ b/src/iidm/NodeBreakerVoltageLevelTopology.hpp @@ -13,7 +13,7 @@ #include #include -#include +#include #include "NodeBreakerVoltageLevelBusCache.hpp" #include "NodeBreakerVoltageLevelGraph.hpp" diff --git a/src/iidm/NodeTerminal.hpp b/src/iidm/NodeTerminal.hpp index f86dc2185..d767e2288 100644 --- a/src/iidm/NodeTerminal.hpp +++ b/src/iidm/NodeTerminal.hpp @@ -47,15 +47,15 @@ class NodeTerminal : public Terminal { public: NodeTerminal(VoltageLevel& voltageLevel, unsigned long node); - NodeTerminal(const NodeTerminal& nodeTerminal) = delete; + NodeTerminal(const NodeTerminal&) = delete; - NodeTerminal(NodeTerminal&& nodeTerminal) = delete; + NodeTerminal(NodeTerminal&&) = delete; ~NodeTerminal() noexcept override = default; - NodeTerminal& operator=(const NodeTerminal& nodeTerminal) = delete; + NodeTerminal& operator=(const NodeTerminal&) = delete; - NodeTerminal& operator=(NodeTerminal&& nodeTerminal) = delete; + NodeTerminal& operator=(NodeTerminal&&) = delete; const stdcxx::optional& getConnectedComponentNumber() const; diff --git a/src/iidm/Substation.cpp b/src/iidm/Substation.cpp index 1a3ba3cab..f0d550c7d 100644 --- a/src/iidm/Substation.cpp +++ b/src/iidm/Substation.cpp @@ -10,11 +10,14 @@ #include #include +#include #include #include #include #include #include +#include +#include #include namespace powsybl { @@ -124,6 +127,40 @@ VoltageLevelAdder Substation::newVoltageLevel() { return VoltageLevelAdder(*this); } +void Substation::remove() { + Substations::checkRemovability(*this); + + for (VoltageLevel& vl : m_voltageLevels) { + // Remove all branches, transformers and HVDC lines + for (Connectable& connectable : vl.getConnectables()) { + ConnectableType type = connectable.getType(); + if (VoltageLevels::MULTIPLE_TERMINALS_CONNECTABLE_TYPES.find(type) != VoltageLevels::MULTIPLE_TERMINALS_CONNECTABLE_TYPES.end()) { + connectable.remove(); + } else if (type == ConnectableType::HVDC_CONVERTER_STATION) { + const auto& hvdcLine = getNetwork().findHvdcLine(dynamic_cast(connectable)); + if (hvdcLine) { + hvdcLine.get().remove(); + } + } + } + + // Then remove the voltage level (bus, switches and injections) from the network + vl.remove(); + } + + // Remove this substation from the network + getNetwork().remove(*this); +} + +void Substation::remove(const VoltageLevel& voltageLevel) { + auto it = std::find_if(m_voltageLevels.begin(), m_voltageLevels.end(), [&voltageLevel](const std::reference_wrapper& vl) { + return stdcxx::areSame(voltageLevel, vl.get()); + }); + if (it != m_voltageLevels.end()) { + m_voltageLevels.erase(it); + } +} + Substation& Substation::setCountry(const stdcxx::optional& country) { m_country = country; return *this; diff --git a/src/iidm/ThreadLocalMultipleVariantContext.cpp b/src/iidm/ThreadLocalMultipleVariantContext.cpp new file mode 100644 index 000000000..3eb7ab0ca --- /dev/null +++ b/src/iidm/ThreadLocalMultipleVariantContext.cpp @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include "ThreadLocalMultipleVariantContext.hpp" + +#include + +#include +#include + +namespace powsybl { + +namespace iidm { + +thread_local stdcxx::optional ThreadLocalMultipleVariantContext::m_index; + +unsigned long ThreadLocalMultipleVariantContext::getVariantIndex() const { + if (m_index) { + return *m_index; + } + throw PowsyblException(stdcxx::format("Variant index not set for current thread %1%", std::this_thread::get_id())); +} + +bool ThreadLocalMultipleVariantContext::isIndexSet() const { + return static_cast(m_index); +} + +void ThreadLocalMultipleVariantContext::reset() { + m_index.reset(); +} + +void ThreadLocalMultipleVariantContext::resetIfVariantIndexIs(unsigned long index) { + if (m_index && m_index == index) { + m_index.reset(); + } +} + +void ThreadLocalMultipleVariantContext::setVariantIndex(unsigned long index) { + m_index = index; +} + +} // namespace iidm + +} // namespace powsybl diff --git a/src/iidm/ThreadLocalMultipleVariantContext.hpp b/src/iidm/ThreadLocalMultipleVariantContext.hpp new file mode 100644 index 000000000..0c8d9a157 --- /dev/null +++ b/src/iidm/ThreadLocalMultipleVariantContext.hpp @@ -0,0 +1,51 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef POWSYBL_IIDM_THREADLOCALMULTIPLEVARIANTCONTEXT_HPP +#define POWSYBL_IIDM_THREADLOCALMULTIPLEVARIANTCONTEXT_HPP + +#include +#include + +namespace powsybl { + +namespace iidm { + +class ThreadLocalMultipleVariantContext : public VariantContext { +public: // VariantContext + unsigned long getVariantIndex() const override; + + bool isIndexSet() const override; + + void resetIfVariantIndexIs(unsigned long index) override; + + void setVariantIndex(unsigned long index) override; + +public: + ThreadLocalMultipleVariantContext() = default; + + ThreadLocalMultipleVariantContext(const ThreadLocalMultipleVariantContext&) = default; + + ThreadLocalMultipleVariantContext(ThreadLocalMultipleVariantContext&&) noexcept = default; + + ~ThreadLocalMultipleVariantContext() noexcept override = default; + + ThreadLocalMultipleVariantContext& operator=(const ThreadLocalMultipleVariantContext&) = default; + + ThreadLocalMultipleVariantContext& operator=(ThreadLocalMultipleVariantContext&&) noexcept = default; + + void reset(); + +private: + static thread_local stdcxx::optional m_index; +}; + +} // namespace iidm + +} // namespace powsybl + +#endif // POWSYBL_IIDM_THREADLOCALMULTIPLEVARIANTCONTEXT_HPP diff --git a/src/iidm/ThreeWindingsTransformer.cpp b/src/iidm/ThreeWindingsTransformer.cpp index db4968387..7e8f9b923 100644 --- a/src/iidm/ThreeWindingsTransformer.cpp +++ b/src/iidm/ThreeWindingsTransformer.cpp @@ -18,106 +18,81 @@ namespace iidm { ThreeWindingsTransformer::ThreeWindingsTransformer(const std::string& id, const std::string& name, bool fictitious, Leg&& leg1, Leg&& leg2, Leg&& leg3, double ratedU0) : Connectable(id, name, fictitious, ConnectableType::THREE_WINDINGS_TRANSFORMER), - m_leg1(std::move(leg1)), - m_leg2(std::move(leg2)), - m_leg3(std::move(leg3)), m_ratedU0(ratedU0) { - m_leg1.setTransformer(*this); - m_leg2.setTransformer(*this); - m_leg3.setTransformer(*this); + m_legs.emplace_back(std::move(leg1.setTransformer(*this))); + m_legs.emplace_back(std::move(leg2.setTransformer(*this))); + m_legs.emplace_back(std::move(leg3.setTransformer(*this))); } void ThreeWindingsTransformer::allocateVariantArrayElement(const std::set& indexes, unsigned long sourceIndex) { Connectable::allocateVariantArrayElement(indexes, sourceIndex); - if (m_leg1.hasRatioTapChanger()) { - m_leg1.getRatioTapChanger().allocateVariantArrayElement(indexes, sourceIndex); - } - if (m_leg1.hasPhaseTapChanger()) { - m_leg1.getPhaseTapChanger().allocateVariantArrayElement(indexes, sourceIndex); - } - if (m_leg2.hasRatioTapChanger()) { - m_leg2.getRatioTapChanger().allocateVariantArrayElement(indexes, sourceIndex); - } - if (m_leg2.hasPhaseTapChanger()) { - m_leg2.getPhaseTapChanger().allocateVariantArrayElement(indexes, sourceIndex); - } - if (m_leg3.hasRatioTapChanger()) { - m_leg3.getRatioTapChanger().allocateVariantArrayElement(indexes, sourceIndex); - } - if (m_leg3.hasPhaseTapChanger()) { - m_leg3.getPhaseTapChanger().allocateVariantArrayElement(indexes, sourceIndex); + for (Leg& leg : m_legs) { + if (leg.hasRatioTapChanger()) { + leg.getRatioTapChanger().allocateVariantArrayElement(indexes, sourceIndex); + } + if (leg.hasPhaseTapChanger()) { + leg.getPhaseTapChanger().allocateVariantArrayElement(indexes, sourceIndex); + } } } void ThreeWindingsTransformer::deleteVariantArrayElement(unsigned long index) { Connectable::deleteVariantArrayElement(index); - if (m_leg1.hasRatioTapChanger()) { - m_leg1.getRatioTapChanger().deleteVariantArrayElement(index); - } - if (m_leg1.hasPhaseTapChanger()) { - m_leg1.getPhaseTapChanger().deleteVariantArrayElement(index); - } - if (m_leg2.hasRatioTapChanger()) { - m_leg2.getRatioTapChanger().deleteVariantArrayElement(index); - } - if (m_leg2.hasPhaseTapChanger()) { - m_leg2.getPhaseTapChanger().deleteVariantArrayElement(index); - } - if (m_leg3.hasRatioTapChanger()) { - m_leg3.getRatioTapChanger().deleteVariantArrayElement(index); - } - if (m_leg3.hasPhaseTapChanger()) { - m_leg3.getPhaseTapChanger().deleteVariantArrayElement(index); + for (Leg& leg : m_legs) { + if (leg.hasRatioTapChanger()) { + leg.getRatioTapChanger().deleteVariantArrayElement(index); + } + if (leg.hasPhaseTapChanger()) { + leg.getPhaseTapChanger().deleteVariantArrayElement(index); + } } } void ThreeWindingsTransformer::extendVariantArraySize(unsigned long initVariantArraySize, unsigned long number, unsigned long sourceIndex) { Connectable::extendVariantArraySize(initVariantArraySize, number, sourceIndex); - if (m_leg1.hasRatioTapChanger()) { - m_leg1.getRatioTapChanger().extendVariantArraySize(initVariantArraySize, number, sourceIndex); - } - if (m_leg1.hasPhaseTapChanger()) { - m_leg1.getPhaseTapChanger().extendVariantArraySize(initVariantArraySize, number, sourceIndex); - } - if (m_leg2.hasRatioTapChanger()) { - m_leg2.getRatioTapChanger().extendVariantArraySize(initVariantArraySize, number, sourceIndex); - } - if (m_leg2.hasPhaseTapChanger()) { - m_leg2.getPhaseTapChanger().extendVariantArraySize(initVariantArraySize, number, sourceIndex); - } - if (m_leg3.hasRatioTapChanger()) { - m_leg3.getRatioTapChanger().extendVariantArraySize(initVariantArraySize, number, sourceIndex); - } - if (m_leg3.hasPhaseTapChanger()) { - m_leg3.getPhaseTapChanger().extendVariantArraySize(initVariantArraySize, number, sourceIndex); + for (Leg& leg : m_legs) { + if (leg.hasRatioTapChanger()) { + leg.getRatioTapChanger().extendVariantArraySize(initVariantArraySize, number, sourceIndex); + } + if (leg.hasPhaseTapChanger()) { + leg.getPhaseTapChanger().extendVariantArraySize(initVariantArraySize, number, sourceIndex); + } } } const ThreeWindingsTransformer::Leg& ThreeWindingsTransformer::getLeg1() const { - return m_leg1; + return m_legs[0]; } ThreeWindingsTransformer::Leg& ThreeWindingsTransformer::getLeg1() { - return m_leg1; + return m_legs[0]; } const ThreeWindingsTransformer::Leg& ThreeWindingsTransformer::getLeg2() const { - return m_leg2; + return m_legs[1]; } ThreeWindingsTransformer::Leg& ThreeWindingsTransformer::getLeg2() { - return m_leg2; + return m_legs[1]; } const ThreeWindingsTransformer::Leg& ThreeWindingsTransformer::getLeg3() const { - return m_leg3; + return m_legs[2]; } ThreeWindingsTransformer::Leg& ThreeWindingsTransformer::getLeg3() { - return m_leg3; + return m_legs[2]; +} + +stdcxx::const_range ThreeWindingsTransformer::getLegs() const { + return m_legs; +} + +stdcxx::range ThreeWindingsTransformer::getLegs() { + return m_legs; } double ThreeWindingsTransformer::getRatedU0() const { @@ -125,34 +100,34 @@ double ThreeWindingsTransformer::getRatedU0() const { } ThreeWindingsTransformer::Side ThreeWindingsTransformer::getSide(const Terminal& terminal) const { - if (stdcxx::areSame(m_leg1.getTerminal(), terminal)) { + if (stdcxx::areSame(m_legs[0].getTerminal(), terminal)) { return Side::ONE; } - if (stdcxx::areSame(m_leg2.getTerminal(), terminal)) { + if (stdcxx::areSame(m_legs[1].getTerminal(), terminal)) { return Side::TWO; } - if (stdcxx::areSame(m_leg3.getTerminal(), terminal)) { + if (stdcxx::areSame(m_legs[2].getTerminal(), terminal)) { return Side::THREE; } throw AssertionError("The terminal is not connected to this three windings transformer"); } const Substation& ThreeWindingsTransformer::getSubstation() const { - return m_leg1.getTerminal().getVoltageLevel().getSubstation(); + return m_legs[0].getTerminal().getVoltageLevel().getSubstation(); } Substation& ThreeWindingsTransformer::getSubstation() { - return m_leg1.getTerminal().getVoltageLevel().getSubstation(); + return m_legs[0].getTerminal().getVoltageLevel().getSubstation(); } const Terminal& ThreeWindingsTransformer::getTerminal(const Side& side) const { switch (side) { case Side::ONE: - return m_leg1.getTerminal(); + return m_legs[0].getTerminal(); case Side::TWO: - return m_leg2.getTerminal(); + return m_legs[1].getTerminal(); case Side::THREE: - return m_leg3.getTerminal(); + return m_legs[2].getTerminal(); default: throw AssertionError(stdcxx::format("Unexpected side value: %1%", side)); } @@ -173,23 +148,13 @@ const std::string& ThreeWindingsTransformer::getTypeDescription() const { void ThreeWindingsTransformer::reduceVariantArraySize(unsigned long number) { Connectable::reduceVariantArraySize(number); - if (m_leg1.hasRatioTapChanger()) { - m_leg1.getRatioTapChanger().reduceVariantArraySize(number); - } - if (m_leg1.hasPhaseTapChanger()) { - m_leg1.getPhaseTapChanger().reduceVariantArraySize(number); - } - if (m_leg2.hasRatioTapChanger()) { - m_leg2.getRatioTapChanger().reduceVariantArraySize(number); - } - if (m_leg2.hasPhaseTapChanger()) { - m_leg2.getPhaseTapChanger().reduceVariantArraySize(number); - } - if (m_leg3.hasRatioTapChanger()) { - m_leg3.getRatioTapChanger().reduceVariantArraySize(number); - } - if (m_leg3.hasPhaseTapChanger()) { - m_leg3.getPhaseTapChanger().reduceVariantArraySize(number); + for (Leg& leg : m_legs) { + if (leg.hasRatioTapChanger()) { + leg.getRatioTapChanger().reduceVariantArraySize(number); + } + if (leg.hasPhaseTapChanger()) { + leg.getPhaseTapChanger().reduceVariantArraySize(number); + } } } diff --git a/src/iidm/ThreeWindingsTransformerAdder.cpp b/src/iidm/ThreeWindingsTransformerAdder.cpp index 07fa80427..ddfabd6e1 100644 --- a/src/iidm/ThreeWindingsTransformerAdder.cpp +++ b/src/iidm/ThreeWindingsTransformerAdder.cpp @@ -23,21 +23,21 @@ ThreeWindingsTransformerAdder::ThreeWindingsTransformerAdder(Substation& substat ThreeWindingsTransformer& ThreeWindingsTransformerAdder::add() { logging::Logger& logger = logging::LoggerFactory::getLogger(); - if (!m_adder1.is_initialized()) { + if (!m_adder1) { throw ValidationException(*this, "leg 1 is not defined"); } ThreeWindingsTransformer::Leg leg1 = m_adder1->build(); VoltageLevel& voltageLevel1 = m_adder1->checkAndGetVoltageLevel(); std::unique_ptr ptrTerminal1 = m_adder1->checkAndGetTerminal(voltageLevel1); - if (!m_adder2.is_initialized()) { + if (!m_adder2) { throw ValidationException(*this, "leg 2 is not defined"); } ThreeWindingsTransformer::Leg leg2 = m_adder2->build(); VoltageLevel& voltageLevel2 = m_adder2->checkAndGetVoltageLevel(); std::unique_ptr ptrTerminal2 = m_adder2->checkAndGetTerminal(voltageLevel2); - if (!m_adder3.is_initialized()) { + if (!m_adder3) { throw ValidationException(*this, "leg 3 is not defined"); } ThreeWindingsTransformer::Leg leg3 = m_adder3->build(); diff --git a/src/iidm/ThreeWindingsTransformerLeg.cpp b/src/iidm/ThreeWindingsTransformerLeg.cpp index e3fdf313c..0aada2eef 100644 --- a/src/iidm/ThreeWindingsTransformerLeg.cpp +++ b/src/iidm/ThreeWindingsTransformerLeg.cpp @@ -192,16 +192,17 @@ Leg& Leg::setX(double x) { return *this; } -void Leg::setPhaseTapChanger(std::unique_ptr phaseTapChanger) { +void Leg::setPhaseTapChanger(std::unique_ptr&& phaseTapChanger) { m_phaseTapChanger = std::move(phaseTapChanger); } -void Leg::setRatioTapChanger(std::unique_ptr ratioTapChanger) { +void Leg::setRatioTapChanger(std::unique_ptr&& ratioTapChanger) { m_ratioTapChanger = std::move(ratioTapChanger); } -void Leg::setTransformer(ThreeWindingsTransformer& transformer) { +Leg& Leg::setTransformer(ThreeWindingsTransformer& transformer) { m_transformer = transformer; + return *this; } std::string Leg::toString() const { @@ -210,6 +211,12 @@ std::string Leg::toString() const { } // namespace three_windings_transformer +std::ostream& operator<<(std::ostream& stream, const three_windings_transformer::Leg& leg) { + stream << leg.toString(); + + return stream; +} + } // namespace iidm } // namespace powsybl diff --git a/src/iidm/ThreeWindingsTransformerLegAdder.cpp b/src/iidm/ThreeWindingsTransformerLegAdder.cpp index b89e74196..4ad46f31a 100644 --- a/src/iidm/ThreeWindingsTransformerLegAdder.cpp +++ b/src/iidm/ThreeWindingsTransformerLegAdder.cpp @@ -79,13 +79,7 @@ VoltageLevel& LegAdder::checkAndGetVoltageLevel() { } std::string LegAdder::getMessageHeader() const { - static std::array s_messageHeaders {{ - u8"3 windings transformer leg1: ", - u8"3 windings transformer leg2: ", - u8"3 windings transformer leg3: " - }}; - - return s_messageHeaders[m_legNumber - 1]; + return stdcxx::format("3 windings transformer leg%1% in substation %2%: ", m_legNumber, m_parent.getSubstation()); } LegAdder& LegAdder::setB(double b) { diff --git a/src/iidm/TieLineAdder.cpp b/src/iidm/TieLineAdder.cpp index 328a5fb91..1167fb170 100644 --- a/src/iidm/TieLineAdder.cpp +++ b/src/iidm/TieLineAdder.cpp @@ -29,10 +29,10 @@ TieLine& TieLineAdder::add() { checkNotEmpty(*this, m_ucteXnodeCode, "ucteXnodeCode is not set"); - if (!m_halfLineAdder1.is_initialized()) { + if (!m_halfLineAdder1) { throw ValidationException(*this, "half line 1 is not set"); } - if (!m_halfLineAdder2.is_initialized()) { + if (!m_halfLineAdder2) { throw ValidationException(*this, "half line 2 is not set"); } diff --git a/src/iidm/TopologyVisitor.cpp b/src/iidm/TopologyVisitor.cpp new file mode 100644 index 000000000..aae5a4dd5 --- /dev/null +++ b/src/iidm/TopologyVisitor.cpp @@ -0,0 +1,135 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace powsybl { + +namespace iidm { + +void TopologyVisitor::visitBattery(const Battery& /*battery*/) { + // nothing to do +} + +void TopologyVisitor::visitBusbarSection(const BusbarSection& /*section*/) { + // nothing to do +} + +void TopologyVisitor::visitDanglingLine(const DanglingLine& /*danglingLine*/) { + // nothing to do +} + +void TopologyVisitor::visitEquipments(const stdcxx::const_range& terminals, TopologyVisitor& visitor) { + for (const Terminal& terminal : terminals) { + const Connectable& connectable = terminal.getConnectable(); + switch (connectable.getType()) { + case ConnectableType::BUSBAR_SECTION: + visitor.visitBusbarSection(dynamic_cast(connectable)); + break; + + case ConnectableType::LINE: { + const auto& line = dynamic_cast(connectable); + visitor.visitLine(line, line.getSide(terminal)); + break; + } + + case ConnectableType::GENERATOR: + visitor.visitGenerator(dynamic_cast(connectable)); + break; + + case ConnectableType::BATTERY: + visitor.visitBattery(dynamic_cast(connectable)); + break; + + case ConnectableType::SHUNT_COMPENSATOR: + visitor.visitShuntCompensator(dynamic_cast(connectable)); + break; + + case ConnectableType::TWO_WINDINGS_TRANSFORMER: { + const auto& twt = dynamic_cast(connectable); + visitor.visitTwoWindingsTransformer(twt, twt.getSide(terminal)); + break; + } + + case ConnectableType::THREE_WINDINGS_TRANSFORMER: { + const auto& twt = dynamic_cast(connectable); + visitor.visitThreeWindingsTransformer(twt, twt.getSide(terminal)); + break; + } + + case ConnectableType::LOAD: + visitor.visitLoad(dynamic_cast(connectable)); + break; + + case ConnectableType::DANGLING_LINE: + visitor.visitDanglingLine(dynamic_cast(connectable)); + break; + + case ConnectableType::STATIC_VAR_COMPENSATOR: + visitor.visitStaticVarCompensator(dynamic_cast(connectable)); + break; + + case ConnectableType::HVDC_CONVERTER_STATION: + visitor.visitHvdcConverterStation(dynamic_cast(connectable)); + break; + + default: + throw AssertionError(stdcxx::format("Unexpected connectable type %1%", connectable.getType())); + } + } +} + +void TopologyVisitor::visitGenerator(const Generator& /*generator*/) { + // nothing to do +} + +void TopologyVisitor::visitHvdcConverterStation(const HvdcConverterStation& /*converterStation*/) { + // nothing to do +} + +void TopologyVisitor::visitLine(const Line& /*line*/, const Branch::Side& /*side*/) { + // nothing to do +} + +void TopologyVisitor::visitLoad(const Load& /*load*/) { + // nothing to do +} + +void TopologyVisitor::visitShuntCompensator(const ShuntCompensator& /*sc*/) { + // nothing to do +} + +void TopologyVisitor::visitStaticVarCompensator(const StaticVarCompensator& /*staticVarCompensator*/) { + // nothing to do +} + +void TopologyVisitor::visitThreeWindingsTransformer(const ThreeWindingsTransformer& /*transformer*/, const ThreeWindingsTransformer::Side& /*side*/) { + // nothing to do +} + +void TopologyVisitor::visitTwoWindingsTransformer(const TwoWindingsTransformer& /*transformer*/, const Branch::Side& /*side*/) { + // nothing to do +} + +} // namespace iidm + +} // namespace powsybl diff --git a/src/iidm/TwoWindingsTransformer.cpp b/src/iidm/TwoWindingsTransformer.cpp index dbb2292d5..3bd2cec84 100644 --- a/src/iidm/TwoWindingsTransformer.cpp +++ b/src/iidm/TwoWindingsTransformer.cpp @@ -178,7 +178,7 @@ TwoWindingsTransformer& TwoWindingsTransformer::setG(double g) { return *this; } -void TwoWindingsTransformer::setPhaseTapChanger(std::unique_ptr phaseTapChanger) { +void TwoWindingsTransformer::setPhaseTapChanger(std::unique_ptr&& phaseTapChanger) { m_phaseTapChanger = std::move(phaseTapChanger); } @@ -202,7 +202,7 @@ TwoWindingsTransformer& TwoWindingsTransformer::setRatedU2(double ratedU2) { return *this; } -void TwoWindingsTransformer::setRatioTapChanger(std::unique_ptr ratioTapChanger) { +void TwoWindingsTransformer::setRatioTapChanger(std::unique_ptr&& ratioTapChanger) { m_ratioTapChanger = std::move(ratioTapChanger); } diff --git a/src/iidm/ValidationUtils.cpp b/src/iidm/ValidationUtils.cpp index 3e1f43091..470ebc1b6 100644 --- a/src/iidm/ValidationUtils.cpp +++ b/src/iidm/ValidationUtils.cpp @@ -186,7 +186,7 @@ double checkLinearBPerSection(const Validable& validable, double bPerSection) { } unsigned long checkMaximumSectionCount(const Validable& validable, const stdcxx::optional& maximumSectionCount) { - if (!maximumSectionCount.is_initialized()) { + if (!maximumSectionCount) { throw ValidationException(validable, "the maximum number of section is not set"); } if (*maximumSectionCount == 0UL) { @@ -263,12 +263,7 @@ void checkOnlyOneTapChangerRegulatingEnabled(const Validable& validable, unsigne } const double& checkOptional(const Validable& validable, const stdcxx::optional& value, const std::string& message) { -#if __cplusplus >= 201703L - bool isInitialized = value.has_value(); -#else - bool isInitialized = value.is_initialized(); -#endif - if (!isInitialized || std::isnan(*value)) { + if (!value || std::isnan(*value)) { throw ValidationException(validable, message); } return *value; @@ -347,7 +342,7 @@ double checkRatedS(const Validable& validable, double ratedS) { double checkRatedU(const Validable& validable, double ratedU, const stdcxx::optional& num) { if (std::isnan(ratedU)) { - std::string strNum = num.is_initialized() ? std::to_string(num.get()) : ""; + std::string strNum = num ? std::to_string(*num) : ""; throw ValidationException(validable, stdcxx::format("rated U%1% is invalid", strNum)); } return ratedU; @@ -385,7 +380,7 @@ void checkRegulatingTerminal(const Validable& validable, const stdcxx::Reference } void checkSections(const Validable& validable, const stdcxx::optional& currentSectionCount, unsigned long maximumSectionCount) { - if (!currentSectionCount.is_initialized()) { + if (!currentSectionCount) { throw ValidationException(validable, "section count is not set"); } if (maximumSectionCount == 0UL) { diff --git a/src/iidm/VariantManager.cpp b/src/iidm/VariantManager.cpp index 946d4bf08..c38ad1d8b 100644 --- a/src/iidm/VariantManager.cpp +++ b/src/iidm/VariantManager.cpp @@ -10,12 +10,14 @@ #include #include -#include #include #include #include #include +#include "MultipleVariantContext.hpp" +#include "ThreadLocalMultipleVariantContext.hpp" + namespace powsybl { namespace iidm { @@ -37,11 +39,47 @@ VariantManager::VariantManager(Network& network, VariantManager&& variantManager m_variantArraySize(variantManager.m_variantArraySize) { } -void VariantManager::cloneVariant(const std::string& sourceVariantId, const std::string& targetVariantId) { - cloneVariant(sourceVariantId, { targetVariantId }); +void VariantManager::allocateVariantArrayElement(unsigned long sourceIndex, const std::set& recycled, const std::set& overwritten) { + logging::Logger& logger = logging::LoggerFactory::getLogger(); + if (!recycled.empty()) { + for (auto& multiVariantObject : m_network.getStatefulObjects()) { + multiVariantObject.allocateVariantArrayElement(recycled, sourceIndex); + } + logger.trace("Recycling variant array indexes %1%", stdcxx::toString(recycled)); + } + if (!overwritten.empty()) { + for (auto& multiVariantObject : m_network.getStatefulObjects()) { + multiVariantObject.allocateVariantArrayElement(overwritten, sourceIndex); + } + logger.trace("Overwriting variant array indexes %1%", stdcxx::toString(overwritten)); + } } -void VariantManager::cloneVariant(const std::string& sourceVariantId, const std::initializer_list& targetVariantIds) { +void VariantManager::allowVariantMultiThreadAccess(bool allow) { + if (allow && !stdcxx::isInstanceOf(m_variantContext)) { + std::unique_ptr newVariantContext = stdcxx::make_unique(); + // For multithreaded VariantContext, don't set the variantIndex to a default + // value if it is not set, so that missing initializations fail fast. + if (m_variantContext->isIndexSet()) { + newVariantContext->setVariantIndex(m_variantContext->getVariantIndex()); + } + m_variantContext.swap(newVariantContext); + } else if (!allow && !stdcxx::isInstanceOf(*m_variantContext)) { + if (m_variantContext->isIndexSet()) { + m_variantContext = stdcxx::make_unique(m_variantContext->getVariantIndex()); + } else { + // For singlethreaded VariantContext, set the variantIndex to a default value + // if it is not set, because missing initialization error are rare. + m_variantContext = stdcxx::make_unique(INITIAL_VARIANT_INDEX); + } + } +} + +void VariantManager::cloneVariant(const std::string& sourceVariantId, const std::string& targetVariantId, bool mayOverwrite) { + cloneVariant(sourceVariantId, { targetVariantId }, mayOverwrite); +} + +void VariantManager::cloneVariant(const std::string& sourceVariantId, const std::initializer_list& targetVariantIds, bool mayOverwrite) { logging::Logger& logger = logging::LoggerFactory::getLogger(); if (targetVariantIds.size() == 0) { @@ -56,11 +94,16 @@ void VariantManager::cloneVariant(const std::string& sourceVariantId, const std: unsigned long initVariantArraySize = m_variantArraySize; unsigned long extendedCount = 0; std::set recycled; + std::set overwritten; for (const auto& targetVariantId : targetVariantIds) { if (m_variantsById.find(targetVariantId) != m_variantsById.end()) { - throw PowsyblException(stdcxx::format("Target variant '%1%' already exists", targetVariantId)); + if (mayOverwrite) { + overwritten.emplace(m_variantsById[targetVariantId]); + } else { + throw PowsyblException(stdcxx::format("Target variant '%1%' already exists", targetVariantId)); + } } - if (m_unusedIndexes.empty()) { + else if (m_unusedIndexes.empty()) { // extend variant array size m_variantsById.insert(std::make_pair(targetVariantId, m_variantArraySize)); ++m_variantArraySize; @@ -75,12 +118,8 @@ void VariantManager::cloneVariant(const std::string& sourceVariantId, const std: } } - if (!recycled.empty()) { - for (auto& multiVariantObject : m_network.getStatefulObjects()) { - multiVariantObject.allocateVariantArrayElement(recycled, sourceIndex); - } - logger.trace("Recycling variant array indexes %1%", stdcxx::toString(recycled)); - } + allocateVariantArrayElement(sourceIndex, recycled, overwritten); + if (extendedCount > 0) { for (auto& multiVariantObject : m_network.getStatefulObjects()) { multiVariantObject.extendVariantArraySize(initVariantArraySize, extendedCount, sourceIndex); @@ -156,6 +195,10 @@ const std::string& VariantManager::getWorkingVariantId() const { return it->first; } +bool VariantManager::isVariantMultiThreadAccessAllowed() const { + return stdcxx::isInstanceOf(*m_variantContext); +} + void VariantManager::removeVariant(const std::string& variantId) { logging::Logger& logger = logging::LoggerFactory::getLogger(); diff --git a/src/iidm/VoltageLevel.cpp b/src/iidm/VoltageLevel.cpp index 9c98f75a3..2784484c9 100644 --- a/src/iidm/VoltageLevel.cpp +++ b/src/iidm/VoltageLevel.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -21,23 +22,25 @@ #include #include #include +#include #include #include #include +#include namespace powsybl { namespace iidm { VoltageLevel::VoltageLevel(const std::string& id, const std::string& name, bool fictitious, Substation& substation, - double nominalVoltage, double lowVoltageLimit, double highVoltageLimit) : + double nominalV, double lowVoltageLimit, double highVoltageLimit) : Container(id, name, fictitious, Container::Type::VOLTAGE_LEVEL), m_substation(substation), m_highVoltageLimit(highVoltageLimit), m_lowVoltageLimit(lowVoltageLimit), - m_nominalVoltage(nominalVoltage) { + m_nominalV(nominalV) { - checkNominalVoltage(*this, m_nominalVoltage); + checkNominalVoltage(*this, m_nominalV); checkVoltageLimits(*this, m_lowVoltageLimit, m_highVoltageLimit); } @@ -117,8 +120,8 @@ Network& VoltageLevel::getNetwork() { return getSubstation().getNetwork(); } -double VoltageLevel::getNominalVoltage() const { - return m_nominalVoltage; +double VoltageLevel::getNominalV() const { + return m_nominalV; } unsigned long VoltageLevel::getShuntCompensatorCount() const { @@ -203,6 +206,22 @@ VscConverterStationAdder VoltageLevel::newVscConverterStation() { return VscConverterStationAdder(*this); } +void VoltageLevel::remove() { + VoltageLevels::checkRemovability(*this); + + // Remove all connectables + for (Connectable& connectable : getConnectables()) { + connectable.remove(); + } + + // Remove the topology + removeTopology(); + + // Remove this voltage level from the network + getSubstation().remove(*this); + getNetwork().getIndex().remove(*this); +} + VoltageLevel& VoltageLevel::setHighVoltageLimit(double highVoltageLimit) { checkVoltageLimits(*this, m_lowVoltageLimit, highVoltageLimit); m_highVoltageLimit = highVoltageLimit; @@ -215,11 +234,15 @@ VoltageLevel& VoltageLevel::setLowVoltageLimit(double lowVoltageLimit) { return *this; } -VoltageLevel& VoltageLevel::setNominalVoltage(double nominalVoltage) { - m_nominalVoltage = checkNominalVoltage(*this, nominalVoltage); +VoltageLevel& VoltageLevel::setNominalV(double nominalV) { + m_nominalV = checkNominalVoltage(*this, nominalV); return *this; } +void VoltageLevel::visitEquipments(TopologyVisitor& visitor) const { + TopologyVisitor::visitEquipments(getTerminals(), visitor); +} + } // namespace iidm } // namespace powsybl diff --git a/src/iidm/VoltageLevelAdder.cpp b/src/iidm/VoltageLevelAdder.cpp index ef0271cd3..1a5585d4c 100644 --- a/src/iidm/VoltageLevelAdder.cpp +++ b/src/iidm/VoltageLevelAdder.cpp @@ -24,7 +24,7 @@ VoltageLevelAdder::VoltageLevelAdder(Substation& substation) : VoltageLevel& VoltageLevelAdder::add() { // TODO(thiebarr) : check that there are not another voltage level with same base voltage - checkNominalVoltage(*this, m_nominalVoltage); + checkNominalVoltage(*this, m_nominalV); checkVoltageLimits(*this, m_lowVoltageLimit, m_highVoltageLimit); checkOptional(*this, m_topologyKind, "TopologyKind is not set"); @@ -32,12 +32,12 @@ VoltageLevel& VoltageLevelAdder::add() { switch (*m_topologyKind) { case TopologyKind::NODE_BREAKER: voltageLevel = stdcxx::ref(getNetwork().checkAndAdd( - stdcxx::make_unique(checkAndGetUniqueId(), getName(), isFictitious(), m_substation, m_nominalVoltage, m_lowVoltageLimit, m_highVoltageLimit))); + stdcxx::make_unique(checkAndGetUniqueId(), getName(), isFictitious(), m_substation, m_nominalV, m_lowVoltageLimit, m_highVoltageLimit))); break; case TopologyKind::BUS_BREAKER: voltageLevel = stdcxx::ref(getNetwork().checkAndAdd( - stdcxx::make_unique(checkAndGetUniqueId(), getName(), isFictitious(), m_substation, m_nominalVoltage, m_lowVoltageLimit, m_highVoltageLimit))); + stdcxx::make_unique(checkAndGetUniqueId(), getName(), isFictitious(), m_substation, m_nominalV, m_lowVoltageLimit, m_highVoltageLimit))); break; default: @@ -72,8 +72,8 @@ VoltageLevelAdder& VoltageLevelAdder::setLowVoltageLimit(double lowVoltageLimit) return *this; } -VoltageLevelAdder& VoltageLevelAdder::setNominalVoltage(double nominalVoltage) { - m_nominalVoltage = nominalVoltage; +VoltageLevelAdder& VoltageLevelAdder::setNominalV(double nominalV) { + m_nominalV = nominalV; return *this; } diff --git a/src/iidm/converter/Constants.cpp b/src/iidm/converter/Constants.cpp index fb234e4b5..11e83301e 100644 --- a/src/iidm/converter/Constants.cpp +++ b/src/iidm/converter/Constants.cpp @@ -13,7 +13,7 @@ namespace iidm { namespace converter { -std::string toString(const char* attribute, boost::optional index) { +std::string toString(const char* attribute, stdcxx::optional index) { std::string str = attribute; if (index) { str += std::to_string(*index); diff --git a/src/iidm/converter/ExportOptions.cpp b/src/iidm/converter/ExportOptions.cpp index c6202b109..5c6eb77cc 100644 --- a/src/iidm/converter/ExportOptions.cpp +++ b/src/iidm/converter/ExportOptions.cpp @@ -105,15 +105,14 @@ const ExportOptions::IidmVersionIncompatibilityBehavior& ExportOptions::getIidmV return m_iidmVersionIncompatibilityBehavior; } +const TopologyLevel& ExportOptions::getTopologyLevel() const { + return m_topologyLevel; +} const std::string& ExportOptions::getVersion() const { return m_version; } -const TopologyLevel& ExportOptions::getTopologyLevel() const { - return m_topologyLevel; -} - bool ExportOptions::hasAtLeastOneExtension(const stdcxx::const_range& extensions) const { if (m_extensions.empty()) { return true; diff --git a/src/iidm/converter/FakeAnonymizer.cpp b/src/iidm/converter/FakeAnonymizer.cpp index bc20bf664..c91c42ca0 100644 --- a/src/iidm/converter/FakeAnonymizer.cpp +++ b/src/iidm/converter/FakeAnonymizer.cpp @@ -29,6 +29,14 @@ std::string FakeAnonymizer::deanonymizeString(const std::string& anonymousStr) c return anonymousStr; } +void FakeAnonymizer::read(std::istream& /*stream*/) { + // Nothing to do +} + +void FakeAnonymizer::write(std::ostream& /*stream*/) const { + // Nothing to do +} + } // namespace converter } // namespace iidm diff --git a/src/iidm/converter/SimpleAnonymizer.cpp b/src/iidm/converter/SimpleAnonymizer.cpp new file mode 100644 index 000000000..95c6f2cdf --- /dev/null +++ b/src/iidm/converter/SimpleAnonymizer.cpp @@ -0,0 +1,100 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include + +#include + +#include +#include + +namespace powsybl { + +namespace iidm { + +namespace converter { + +Country SimpleAnonymizer::anonymizeCountry(const Country& country) { + return country; +} + +std::string SimpleAnonymizer::anonymizeString(const std::string& str) { + if (str.empty()) { + return ""; + } + + auto it = m_mapping.left.find(str); + if (it != m_mapping.left.end()) { + return it->second; + } + const std::string& anonymizedStr = getAlpha(m_mapping.size() + 1); + m_mapping.insert(Mapping::value_type(str, anonymizedStr)); + return anonymizedStr; +} + +Country SimpleAnonymizer::deanonymizeCountry(const Country& country) const { + return country; +} + +std::string SimpleAnonymizer::deanonymizeString(const std::string& anonymousStr) const { + if (anonymousStr.empty()) { + return ""; + } + + auto it = m_mapping.right.find(anonymousStr); + if (it == m_mapping.right.end()) { + throw PowsyblException(stdcxx::format("Mapping not found for anonymized string '%1%'", anonymousStr)); + } + return it->second; +} + +std::string SimpleAnonymizer::getAlpha(unsigned long num) { + std::string result; + unsigned long n = num; + while (n > 0U) { + n--; + unsigned long remainder = n % 26; + auto digit = static_cast(remainder + 'A'); + result.insert(result.begin(), digit); + n = (n - remainder) / 26; + } + return result; +} + +unsigned long SimpleAnonymizer::getStringCount() const { + return m_mapping.size(); +} + +void SimpleAnonymizer::read(std::istream& stream) { + std::string line; + while (std::getline(stream, line)) + { + std::vector cells; + boost::split(cells, line, boost::is_any_of(";")); + + if (cells.size() != 2) { + throw PowsyblException(stdcxx::format("Invalid line '%1%'", line)); + } + + m_mapping.insert(Mapping::value_type(cells[0], cells[1])); + } +} + +void SimpleAnonymizer::write(std::ostream& stream) const { + for (const auto& pair : m_mapping.left) { + stream << pair.first << ';' << pair.second << std::endl; + } +} + +} // namespace converter + +} // namespace iidm + +} // namespace powsybl diff --git a/src/iidm/converter/xml/AbstractConnectableXml.hpp b/src/iidm/converter/xml/AbstractConnectableXml.hpp index 03b4b5f30..86b8d07b0 100644 --- a/src/iidm/converter/xml/AbstractConnectableXml.hpp +++ b/src/iidm/converter/xml/AbstractConnectableXml.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include "AbstractIdentifiableXml.hpp" @@ -38,9 +39,9 @@ template class AbstractConnectableXml : public AbstractIdentifiableXml { public: template - static void readCurrentLimits(CurrentLimitsAdder& adder, const powsybl::xml::XmlStreamReader& reader, const boost::optional& index = boost::optional()); + static void readCurrentLimits(CurrentLimitsAdder& adder, const powsybl::xml::XmlStreamReader& reader, const stdcxx::optional& index = stdcxx::optional()); - static void writeCurrentLimits(const CurrentLimits& limits, powsybl::xml::XmlStreamWriter& writer, const IidmXmlVersion& version, const boost::optional& index = boost::optional()); + static void writeCurrentLimits(const CurrentLimits& limits, powsybl::xml::XmlStreamWriter& writer, const IidmXmlVersion& version, const stdcxx::optional& index = stdcxx::optional()); protected: static void readNodeOrBus(BranchAdder& adder, const NetworkXmlReaderContext& context); @@ -49,11 +50,11 @@ class AbstractConnectableXml : public AbstractIdentifiableXml& index = boost::optional()); + static void readPQ(Terminal& terminal, const powsybl::xml::XmlStreamReader& reader, const stdcxx::optional& index = stdcxx::optional()); - static void writeNodeOrBus(const Terminal& terminal, NetworkXmlWriterContext& context, const boost::optional& index = boost::optional()); + static void writeNodeOrBus(const Terminal& terminal, NetworkXmlWriterContext& context, const stdcxx::optional& index = stdcxx::optional()); - static void writePQ(const Terminal& terminal, powsybl::xml::XmlStreamWriter& writer, const boost::optional& index = boost::optional()); + static void writePQ(const Terminal& terminal, powsybl::xml::XmlStreamWriter& writer, const stdcxx::optional& index = stdcxx::optional()); protected: AbstractConnectableXml() = default; @@ -61,9 +62,9 @@ class AbstractConnectableXml : public AbstractIdentifiableXml& bus, const stdcxx::CReference& connectableBus, NetworkXmlWriterContext& context, const boost::optional& index = boost::optional()); + static void writeBus(const stdcxx::CReference& bus, const stdcxx::CReference& connectableBus, NetworkXmlWriterContext& context, const stdcxx::optional& index = stdcxx::optional()); - static void writeNode(const Terminal& terminal, NetworkXmlWriterContext& context, const boost::optional& index = boost::optional()); + static void writeNode(const Terminal& terminal, NetworkXmlWriterContext& context, const stdcxx::optional& index = stdcxx::optional()); }; } // namespace xml diff --git a/src/iidm/converter/xml/AbstractConnectableXml.hxx b/src/iidm/converter/xml/AbstractConnectableXml.hxx index 14670a290..5d0329204 100644 --- a/src/iidm/converter/xml/AbstractConnectableXml.hxx +++ b/src/iidm/converter/xml/AbstractConnectableXml.hxx @@ -27,7 +27,7 @@ namespace xml { template template -void AbstractConnectableXml::readCurrentLimits(CurrentLimitsAdder& adder, const powsybl::xml::XmlStreamReader& reader, const boost::optional& index) { +void AbstractConnectableXml::readCurrentLimits(CurrentLimitsAdder& adder, const powsybl::xml::XmlStreamReader& reader, const stdcxx::optional& index) { CurrentLimitsXml::readCurrentLimits(adder, reader, index); } @@ -50,7 +50,7 @@ void AbstractConnectableXml::readNodeOrBus(BranchAdder::readNodeOrBus(BranchAdder @@ -99,14 +99,14 @@ void AbstractConnectableXml::readNodeOrBus(int index, Thre } template -void AbstractConnectableXml::readPQ(Terminal& terminal, const powsybl::xml::XmlStreamReader& reader, const boost::optional& index) { +void AbstractConnectableXml::readPQ(Terminal& terminal, const powsybl::xml::XmlStreamReader& reader, const stdcxx::optional& index) { const double& p = reader.getOptionalAttributeValue(toString(P, index), stdcxx::nan()); const double& q = reader.getOptionalAttributeValue(toString(Q, index), stdcxx::nan()); terminal.setP(p).setQ(q); } template -void AbstractConnectableXml::writeBus(const stdcxx::CReference& bus, const stdcxx::CReference& connectableBus, NetworkXmlWriterContext& context, const boost::optional& index) { +void AbstractConnectableXml::writeBus(const stdcxx::CReference& bus, const stdcxx::CReference& connectableBus, NetworkXmlWriterContext& context, const stdcxx::optional& index) { if (bus) { context.getWriter().writeAttribute(toString(BUS, index), context.getAnonymizer().anonymizeString(bus.get().getId())); } @@ -116,17 +116,17 @@ void AbstractConnectableXml::writeBus(const stdcxx::CRefer } template -void AbstractConnectableXml::writeCurrentLimits(const CurrentLimits& limits, powsybl::xml::XmlStreamWriter& writer, const IidmXmlVersion& version, const boost::optional& index) { +void AbstractConnectableXml::writeCurrentLimits(const CurrentLimits& limits, powsybl::xml::XmlStreamWriter& writer, const IidmXmlVersion& version, const stdcxx::optional& index) { CurrentLimitsXml::writeCurrentLimits(limits, writer, version.getPrefix(), version, index); } template -void AbstractConnectableXml::writeNode(const Terminal& terminal, NetworkXmlWriterContext& context, const boost::optional& index) { +void AbstractConnectableXml::writeNode(const Terminal& terminal, NetworkXmlWriterContext& context, const stdcxx::optional& index) { context.getWriter().writeAttribute(toString(NODE, index), terminal.getNodeBreakerView().getNode()); } template -void AbstractConnectableXml::writeNodeOrBus(const Terminal& terminal, NetworkXmlWriterContext& context, const boost::optional& index) { +void AbstractConnectableXml::writeNodeOrBus(const Terminal& terminal, NetworkXmlWriterContext& context, const stdcxx::optional& index) { const TopologyLevel& topologyLevel = getMinTopologyLevel(terminal.getVoltageLevel().getTopologyKind(), context.getOptions().getTopologyLevel()); switch (topologyLevel) { case TopologyLevel::NODE_BREAKER: @@ -142,13 +142,13 @@ void AbstractConnectableXml::writeNodeOrBus(const Terminal throw powsybl::xml::XmlStreamException(stdcxx::format("Unexpected TopologyLevel value: ", topologyLevel)); } - if (index.is_initialized()) { + if (index) { context.getWriter().writeAttribute(toString(VOLTAGE_LEVEL_ID, index), context.getAnonymizer().anonymizeString(terminal.getVoltageLevel().getId())); } } template -void AbstractConnectableXml::writePQ(const Terminal& terminal, powsybl::xml::XmlStreamWriter& writer, const boost::optional& index) { +void AbstractConnectableXml::writePQ(const Terminal& terminal, powsybl::xml::XmlStreamWriter& writer, const stdcxx::optional& index) { writer.writeOptionalAttribute(toString(P, index), terminal.getP()); writer.writeOptionalAttribute(toString(Q, index), terminal.getQ()); } diff --git a/src/iidm/converter/xml/AliasesXml.cpp b/src/iidm/converter/xml/AliasesXml.cpp index b644a319e..d1dc33b8e 100644 --- a/src/iidm/converter/xml/AliasesXml.cpp +++ b/src/iidm/converter/xml/AliasesXml.cpp @@ -26,13 +26,23 @@ namespace converter { namespace xml { void AliasesXml::read(Identifiable& identifiable, const NetworkXmlReaderContext& context) { - identifiable.addAlias(context.getAnonymizer().deanonymizeString(context.getReader().readCharacters())); + std::string aliasType; + IidmXmlUtil::runFromMinimumVersion(IidmXmlVersion::V1_4(), context.getVersion(), [&context, &aliasType]() { + aliasType = context.getReader().getOptionalAttributeValue(TYPE, ""); + }); + identifiable.addAlias(context.getAnonymizer().deanonymizeString(context.getReader().readCharacters()), aliasType); } void AliasesXml::write(const Identifiable& identifiable, const std::string& rootElementName, NetworkXmlWriterContext& context) { IidmXmlUtil::assertMinimumVersionIfNotDefault(identifiable.hasAliases(), rootElementName, ALIAS, ErrorMessage::NOT_DEFAULT_NOT_SUPPORTED, IidmXmlVersion::V1_3(), context); for (const std::string& alias : identifiable.getAliases()) { context.getWriter().writeStartElement(context.getVersion().getPrefix(), ALIAS); + IidmXmlUtil::runFromMinimumVersion(IidmXmlVersion::V1_4(), context.getVersion(), [&context, &alias, &identifiable]() { + const auto& typeAlias = identifiable.getAliasType(alias); + if (!typeAlias.empty()) { + context.getWriter().writeAttribute(TYPE, typeAlias); + } + }); context.getWriter().writeCharacters(context.getAnonymizer().anonymizeString(alias)); context.getWriter().writeEndElement(); } diff --git a/src/iidm/converter/xml/CurrentLimitsXml.cpp b/src/iidm/converter/xml/CurrentLimitsXml.cpp index 328138961..96ee3a255 100644 --- a/src/iidm/converter/xml/CurrentLimitsXml.cpp +++ b/src/iidm/converter/xml/CurrentLimitsXml.cpp @@ -17,12 +17,12 @@ namespace converter { namespace xml { -void CurrentLimitsXml::writeCurrentLimits(const CurrentLimits& limits, powsybl::xml::XmlStreamWriter& writer, const std::string& nsPrefix, const IidmXmlVersion& version, const boost::optional& index) { +void CurrentLimitsXml::writeCurrentLimits(const CurrentLimits& limits, powsybl::xml::XmlStreamWriter& writer, const std::string& nsPrefix, const IidmXmlVersion& version, const stdcxx::optional& index) { if (!std::isnan(limits.getPermanentLimit()) || !limits.getTemporaryLimits().empty()) { writer.writeStartElement(nsPrefix, toString(CURRENT_LIMITS, index)); writer.writeAttribute(PERMANENT_LIMIT, limits.getPermanentLimit()); - constexpr unsigned long undefinedAcceptableDuration = std::numeric_limits::max(); + constexpr unsigned long undefinedAcceptableDuration = std::numeric_limits::max(); for (const auto& tl : limits.getTemporaryLimits()) { writer.writeStartElement(version.getPrefix(), TEMPORARY_LIMIT); diff --git a/src/iidm/converter/xml/DanglingLineXml.cpp b/src/iidm/converter/xml/DanglingLineXml.cpp index 3eae4de92..f6c27150d 100644 --- a/src/iidm/converter/xml/DanglingLineXml.cpp +++ b/src/iidm/converter/xml/DanglingLineXml.cpp @@ -39,7 +39,7 @@ DanglingLine& DanglingLineXml::readRootElementAttributes(DanglingLineAdder& adde const auto& b = context.getReader().getAttributeValue(B); IidmXmlUtil::runFromMinimumVersion(IidmXmlVersion::V1_3(), context.getVersion(), [&context, &adder]() { const auto& voltageRegulationOnStr = context.getReader().getOptionalAttributeValue(GENERATION_VOLTAGE_REGULATION_ON); - if (voltageRegulationOnStr.is_initialized()) { + if (voltageRegulationOnStr) { double minP = context.getReader().getOptionalAttributeValue(GENERATION_MIN_P, stdcxx::nan()); double maxP = context.getReader().getOptionalAttributeValue(GENERATION_MAX_P, stdcxx::nan()); bool voltageRegulationOn = *voltageRegulationOnStr; @@ -80,7 +80,7 @@ void DanglingLineXml::readSubElements(DanglingLine& dl, NetworkXmlReaderContext& IidmXmlUtil::assertMinimumVersion(stdcxx::format("%1%.generation", DANGLING_LINE), "reactiveLimits", ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_3(), context); ReactiveLimitsXml::getInstance().read(dl.getGeneration(), context); } else { - AbstractIdentifiableXml::readSubElements(dl, context); + AbstractConnectableXml::readSubElements(dl, context); } }); } diff --git a/src/iidm/converter/xml/GeneratorXml.cpp b/src/iidm/converter/xml/GeneratorXml.cpp index c0a853237..8dbaa4025 100644 --- a/src/iidm/converter/xml/GeneratorXml.cpp +++ b/src/iidm/converter/xml/GeneratorXml.cpp @@ -70,7 +70,7 @@ void GeneratorXml::readSubElements(Generator& generator, NetworkXmlReaderContext context.getReader().getLocalName() == MIN_MAX_REACTIVE_LIMITS) { ReactiveLimitsXml::getInstance().read(generator, context); } else { - AbstractIdentifiableXml::readSubElements(generator, context); + AbstractConnectableXml::readSubElements(generator, context); } }); } diff --git a/src/iidm/converter/xml/HvdcLineXml.cpp b/src/iidm/converter/xml/HvdcLineXml.cpp index b25fa1d32..c59f78d4b 100644 --- a/src/iidm/converter/xml/HvdcLineXml.cpp +++ b/src/iidm/converter/xml/HvdcLineXml.cpp @@ -39,7 +39,7 @@ HvdcLine& HvdcLineXml::readRootElementAttributes(HvdcLineAdder& adder, NetworkXm const std::string& converterStation1 = context.getReader().getAttributeValue(CONVERTER_STATION1); const std::string& converterStation2 = context.getReader().getAttributeValue(CONVERTER_STATION2); return adder.setR(r) - .setNominalVoltage(nominalV) // called setNominalV() in Java code + .setNominalV(nominalV) .setConvertersMode(convertersMode) .setActivePowerSetpoint(activePowerSetpoint) .setMaxP(maxP) @@ -56,7 +56,7 @@ void HvdcLineXml::readSubElements(HvdcLine& line, NetworkXmlReaderContext& conte void HvdcLineXml::writeRootElementAttributes(const HvdcLine& line, const Network& /*network*/, NetworkXmlWriterContext& context) const { context.getWriter().writeAttribute(R, line.getR()); - context.getWriter().writeAttribute(NOMINAL_V, line.getNominalVoltage()); + context.getWriter().writeAttribute(NOMINAL_V, line.getNominalV()); context.getWriter().writeAttribute(CONVERTERS_MODE, Enum::toString(line.getConvertersMode())); context.getWriter().writeAttribute(ACTIVE_POWER_SETPOINT, line.getActivePowerSetpoint()); context.getWriter().writeAttribute(MAX_P, line.getMaxP()); diff --git a/src/iidm/converter/xml/IidmXmlUtil.cpp b/src/iidm/converter/xml/IidmXmlUtil.cpp index 550867ff8..d47836e44 100644 --- a/src/iidm/converter/xml/IidmXmlUtil.cpp +++ b/src/iidm/converter/xml/IidmXmlUtil.cpp @@ -81,22 +81,22 @@ void IidmXmlUtil::assertMinimumVersion(const std::string& rootElementName, const } } -void IidmXmlUtil::assertMinimumVersionIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlReaderContext& context) { +void IidmXmlUtil::assertMinimumVersionAndRunIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlReaderContext& context, const std::function& runnable) { if (valueIsNotDefault) { assertMinimumVersion(rootElementName, elementName, errorMessage, minVersion, context); + runnable(); } } -void IidmXmlUtil::assertMinimumVersionIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlWriterContext& context) { +void IidmXmlUtil::assertMinimumVersionIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlReaderContext& context) { if (valueIsNotDefault) { assertMinimumVersion(rootElementName, elementName, errorMessage, minVersion, context); } } -void IidmXmlUtil::assertMinimumVersionAndRunIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlReaderContext& context, const std::function& runnable) { +void IidmXmlUtil::assertMinimumVersionIfNotDefault(bool valueIsNotDefault, const std::string& rootElementName, const std::string& elementName, const char* errorMessage, const IidmXmlVersion& minVersion, const NetworkXmlWriterContext& context) { if (valueIsNotDefault) { assertMinimumVersion(rootElementName, elementName, errorMessage, minVersion, context); - runnable(); } } diff --git a/src/iidm/converter/xml/IidmXmlVersion.cpp b/src/iidm/converter/xml/IidmXmlVersion.cpp index 49160ed24..4a2d646aa 100644 --- a/src/iidm/converter/xml/IidmXmlVersion.cpp +++ b/src/iidm/converter/xml/IidmXmlVersion.cpp @@ -64,14 +64,15 @@ const IidmXmlVersions& IidmXmlVersion::all() { std::cref(IidmXmlVersion::V1_0()), std::cref(IidmXmlVersion::V1_1()), std::cref(IidmXmlVersion::V1_2()), - std::cref(IidmXmlVersion::V1_3()) + std::cref(IidmXmlVersion::V1_3()), + std::cref(IidmXmlVersion::V1_4()) }}; return s_versions; } const IidmXmlVersion& IidmXmlVersion::CURRENT_IIDM_XML_VERSION() { - return V1_3(); + return V1_4(); } const IidmXmlVersion& IidmXmlVersion::fromNamespaceURI(const std::string& namespaceURI) { @@ -139,6 +140,11 @@ const IidmXmlVersion& IidmXmlVersion::V1_3() { return V1_3; } +const IidmXmlVersion& IidmXmlVersion::V1_4() { + static IidmXmlVersion V1_4("powsybl.org", {{1, 4}}); + return V1_4; +} + } // namespace xml } // namespace converter diff --git a/src/iidm/converter/xml/LineXml.cpp b/src/iidm/converter/xml/LineXml.cpp index 824518da2..e7611e877 100644 --- a/src/iidm/converter/xml/LineXml.cpp +++ b/src/iidm/converter/xml/LineXml.cpp @@ -57,7 +57,7 @@ void LineXml::readSubElements(Line& line, NetworkXmlReaderContext& context) cons CurrentLimitsAdder adder = line.newCurrentLimits2(); readCurrentLimits(adder, context.getReader(), 2); } else { - AbstractIdentifiableXml::readSubElements(line, context); + AbstractConnectableXml::readSubElements(line, context); } }); } diff --git a/src/iidm/converter/xml/LoadXml.cpp b/src/iidm/converter/xml/LoadXml.cpp index b165117d2..c235a3efe 100644 --- a/src/iidm/converter/xml/LoadXml.cpp +++ b/src/iidm/converter/xml/LoadXml.cpp @@ -51,7 +51,7 @@ Load& LoadXml::readRootElementAttributes(LoadAdder& loadAdder, NetworkXmlReaderC void LoadXml::readSubElements(Load& load, NetworkXmlReaderContext& context) const { context.getReader().readUntilEndElement(LOAD, [this, &load, &context]() { - AbstractIdentifiableXml::readSubElements(load, context); + AbstractConnectableXml::readSubElements(load, context); }); } diff --git a/src/iidm/converter/xml/NetworkXml.cpp b/src/iidm/converter/xml/NetworkXml.cpp index b1b0c6f2a..e810a60b0 100644 --- a/src/iidm/converter/xml/NetworkXml.cpp +++ b/src/iidm/converter/xml/NetworkXml.cpp @@ -9,10 +9,13 @@ #include +#include + #include #include #include #include +#include #include #include #include @@ -162,17 +165,18 @@ void writeExtensionNamespaces(const Network& network, NetworkXmlWriterContext& c void writeExtension(const Extension& extension, NetworkXmlWriterContext& context) { powsybl::xml::XmlStreamWriter& writer = context.getExtensionsWriter(); stdcxx::CReference serializer = getExtensionSerializer(context.getOptions(), extension.getName()); + if (!serializer) { + throw AssertionError(stdcxx::format("Extension XML Serializer of %1% should not be null", extension.getName())); + } - if (serializer) { - const std::string& version = context.getExtensionVersion(extension.getName()); - if (!version.empty()) { - serializer.get().checkExtensionVersionSupported(version); - } - - writer.writeStartElement(serializer.get().getNamespacePrefix(), extension.getName()); - serializer.get().write(extension, context); - writer.writeEndElement(); + const std::string& version = context.getExtensionVersion(extension.getName()); + if (!version.empty()) { + serializer.get().checkExtensionVersionSupported(version); } + + writer.writeStartElement(serializer.get().getNamespacePrefix(), extension.getName()); + serializer.get().write(extension, context); + writer.writeEndElement(); } void writeExtensions(const Network& network, NetworkXmlWriterContext& context) { @@ -191,7 +195,7 @@ void writeExtensions(const Network& network, NetworkXmlWriterContext& context) { } } -Network NetworkXml::read(std::istream& is, const ImportOptions& options, const Anonymizer& anonymizer) { +Network NetworkXml::read(const std::string& filename, std::istream& is, const ImportOptions& options) { logging::Logger& logger = logging::LoggerFactory::getLogger(); auto startTime = std::chrono::high_resolution_clock::now(); @@ -216,7 +220,21 @@ Network NetworkXml::read(std::istream& is, const ImportOptions& options, const A throw powsybl::xml::XmlStreamException(err.what()); } - NetworkXmlReaderContext context(anonymizer, reader, options, version); + boost::filesystem::path csvPath = boost::filesystem::path(filename).replace_extension("csv"); + std::unique_ptr anonymizer; + + if (boost::filesystem::exists(csvPath)) { + anonymizer = stdcxx::make_unique(); + boost::filesystem::ifstream csvStream(csvPath); + if (!csvStream.is_open()) { + throw PowsyblException(stdcxx::format("Unable to open file '%1%' for reading", csvPath.filename().string())); + } + anonymizer->read(csvStream); + } else { + anonymizer = stdcxx::make_unique(); + } + + NetworkXmlReaderContext context(std::move(anonymizer), reader, options, version); const auto& extensionProviders = ExtensionProviders::getInstance(); context.buildExtensionNamespaceUriList(extensionProviders.getProviders()); @@ -259,21 +277,19 @@ Network NetworkXml::read(std::istream& is, const ImportOptions& options, const A return network; } -std::unique_ptr NetworkXml::write(std::ostream& ostream, const Network& network, const ExportOptions& options) { +void NetworkXml::write(const std::string& filename, std::ostream& os, const Network& network, const ExportOptions& options) { logging::Logger& logger = logging::LoggerFactory::getLogger(); auto startTime = std::chrono::high_resolution_clock::now(); - powsybl::xml::XmlStreamWriter writer(ostream, options.isIndent()); + powsybl::xml::XmlStreamWriter writer(os, options.isIndent()); - // FIXME(sebalaig): for now on, only one kind of anonymizer = FakeAnonymizer - // later, a real anonymizer will be instantiated depending on options.isAnonymized() - std::unique_ptr anonymizer(stdcxx::make_unique()); + std::unique_ptr anonymizer = options.isAnonymized() ? stdcxx::make_unique() : stdcxx::make_unique(); const BusFilter& filter = BusFilter::create(network, options); const IidmXmlVersion& version = options.getVersion().empty() ? IidmXmlVersion::CURRENT_IIDM_XML_VERSION() : IidmXmlVersion::of(options.getVersion(), "."); - NetworkXmlWriterContext context(*anonymizer, writer, options, filter, version); + NetworkXmlWriterContext context(std::move(anonymizer), writer, options, filter, version); writer.writeStartDocument(powsybl::xml::DEFAULT_ENCODING, "1.0"); @@ -316,11 +332,18 @@ std::unique_ptr NetworkXml::write(std::ostream& ostream, const Netwo writer.writeEndElement(); writer.writeEndDocument(); + if (options.isAnonymized()) { + boost::filesystem::path csvPath = boost::filesystem::path(filename).replace_extension("csv"); + boost::filesystem::ofstream csvStream(csvPath); + if (!csvStream.is_open()) { + throw PowsyblException(stdcxx::format("Unable to open file '%1%' for writing", csvPath.string())); + } + context.getAnonymizer().write(csvStream); + } + auto endTime = std::chrono::high_resolution_clock::now(); std::chrono::duration diff = endTime - startTime; logger.debug("XIIDM export done in %1% ms", diff.count() * 1000.0); - - return anonymizer; } } // namespace xml diff --git a/src/iidm/converter/xml/NetworkXml.hpp b/src/iidm/converter/xml/NetworkXml.hpp index 759322b83..2622a612f 100644 --- a/src/iidm/converter/xml/NetworkXml.hpp +++ b/src/iidm/converter/xml/NetworkXml.hpp @@ -10,6 +10,7 @@ #include #include +#include namespace powsybl { @@ -27,9 +28,9 @@ namespace xml { class NetworkXml { public: - static Network read(std::istream& is, const ImportOptions& options, const Anonymizer& anonymizer); + static Network read(const std::string& filename, std::istream& is, const ImportOptions& options); - static std::unique_ptr write(std::ostream& ostream, const Network& network, const ExportOptions& options); + static void write(const std::string& filename, std::ostream& os, const Network& network, const ExportOptions& options); public: NetworkXml() = delete; diff --git a/src/iidm/converter/xml/NetworkXmlReaderContext.cpp b/src/iidm/converter/xml/NetworkXmlReaderContext.cpp index 61ef2d306..ec089c13b 100644 --- a/src/iidm/converter/xml/NetworkXmlReaderContext.cpp +++ b/src/iidm/converter/xml/NetworkXmlReaderContext.cpp @@ -7,6 +7,7 @@ #include +#include #include namespace powsybl { @@ -17,9 +18,9 @@ namespace converter { namespace xml { -NetworkXmlReaderContext::NetworkXmlReaderContext(const Anonymizer& anonymizer, powsybl::xml::XmlStreamReader& reader, const ImportOptions& options, const IidmXmlVersion& version) : +NetworkXmlReaderContext::NetworkXmlReaderContext(std::unique_ptr&& anonymizer, powsybl::xml::XmlStreamReader& reader, const ImportOptions& options, const IidmXmlVersion& version) : m_reader(reader), - m_anonymizer(anonymizer), + m_anonymizer(std::move(anonymizer)), m_options(options), m_version(version) { @@ -43,7 +44,7 @@ bool NetworkXmlReaderContext::containsExtensionNamespaceUri(const std::string& e } const Anonymizer& NetworkXmlReaderContext::getAnonymizer() const { - return m_anonymizer; + return *m_anonymizer; } const std::list>& NetworkXmlReaderContext::getEndTasks() const { diff --git a/src/iidm/converter/xml/NetworkXmlWriterContext.cpp b/src/iidm/converter/xml/NetworkXmlWriterContext.cpp index 1af28bbce..6567929f7 100644 --- a/src/iidm/converter/xml/NetworkXmlWriterContext.cpp +++ b/src/iidm/converter/xml/NetworkXmlWriterContext.cpp @@ -8,6 +8,7 @@ #include #include +#include namespace powsybl { @@ -17,10 +18,10 @@ namespace converter { namespace xml { -NetworkXmlWriterContext::NetworkXmlWriterContext(Anonymizer& anonymizer, powsybl::xml::XmlStreamWriter& writer, const ExportOptions& options, const BusFilter& filter, const IidmXmlVersion& version) : +NetworkXmlWriterContext::NetworkXmlWriterContext(std::unique_ptr&& anonymizer, powsybl::xml::XmlStreamWriter& writer, const ExportOptions& options, const BusFilter& filter, const IidmXmlVersion& version) : m_writer(writer), m_extensionsWriter(writer), - m_anonymizer(anonymizer), + m_anonymizer(std::move(anonymizer)), m_options(options), m_version(version), m_filter(filter) { @@ -32,11 +33,11 @@ void NetworkXmlWriterContext::addExportedEquipment(const Identifiable& identifia } const Anonymizer& NetworkXmlWriterContext::getAnonymizer() const { - return m_anonymizer; + return *m_anonymizer; } Anonymizer& NetworkXmlWriterContext::getAnonymizer() { - return m_anonymizer; + return *m_anonymizer; } const std::set& NetworkXmlWriterContext::getExportedEquipments() const { diff --git a/src/iidm/converter/xml/ShuntCompensatorXml.cpp b/src/iidm/converter/xml/ShuntCompensatorXml.cpp index aea377aab..06095d972 100644 --- a/src/iidm/converter/xml/ShuntCompensatorXml.cpp +++ b/src/iidm/converter/xml/ShuntCompensatorXml.cpp @@ -7,6 +7,8 @@ #include "ShuntCompensatorXml.hpp" +#include + #include #include #include @@ -62,7 +64,7 @@ void ShuntCompensatorXml::readElement(const std::string& id, ShuntCompensatorAdd std::string regId; std::string regSide; stdcxx::Properties properties; - std::set aliases; + std::map aliases; context.getReader().readUntilEndElement(SHUNT, [&context, &adder, ®Id, ®Side, &properties, &id, &aliases]() { if (context.getReader().getLocalName() == REGULATING_TERMINAL) { regId = context.getAnonymizer().deanonymizeString(context.getReader().getAttributeValue(ID)); @@ -73,7 +75,9 @@ void ShuntCompensatorXml::readElement(const std::string& id, ShuntCompensatorAdd properties.set(name, value); } else if (context.getReader().getLocalName() == ALIAS) { IidmXmlUtil::assertMinimumVersion(SHUNT, ALIAS, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_3(), context); - aliases.emplace(context.getReader().readUntilEndElement(ALIAS)); + const auto& aliasType = context.getReader().getOptionalAttributeValue(TYPE, ""); + const auto& alias = context.getAnonymizer().deanonymizeString(context.getReader().readCharacters()); + aliases[alias] = aliasType; } else if (context.getReader().getLocalName() == SHUNT_LINEAR_MODEL) { IidmXmlUtil::assertMinimumVersion(SHUNT, SHUNT_LINEAR_MODEL, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_3(), context); auto bPerSection = context.getReader().getAttributeValue(B_PER_SECTION); @@ -116,7 +120,7 @@ void ShuntCompensatorXml::readElement(const std::string& id, ShuntCompensatorAdd sc.setProperty(it.first, it.second); } for (const auto& alias : aliases) { - sc.addAlias(alias); + sc.addAlias(alias.first, alias.second); } sc.getTerminal().setP(p).setQ(q); } diff --git a/src/iidm/converter/xml/SubstationXml.cpp b/src/iidm/converter/xml/SubstationXml.cpp index 0bbd1e703..3a3b9ca93 100644 --- a/src/iidm/converter/xml/SubstationXml.cpp +++ b/src/iidm/converter/xml/SubstationXml.cpp @@ -42,8 +42,8 @@ const char* SubstationXml::getRootElementName() const { Substation& SubstationXml::readRootElementAttributes(SubstationAdder& adder, NetworkXmlReaderContext& context) const { const std::string& countryCode = context.getReader().getOptionalAttributeValue(COUNTRY, ""); if (!countryCode.empty()) { - const auto& country = Enum::fromString(context.getAnonymizer().deanonymizeString(countryCode)); - adder.setCountry(country); + const auto& country = Enum::fromString(countryCode); + adder.setCountry(context.getAnonymizer().deanonymizeCountry(country)); } const std::string& tso = context.getReader().getOptionalAttributeValue(TSO, ""); @@ -81,7 +81,7 @@ void SubstationXml::readSubElements(Substation& substation, NetworkXmlReaderCont void SubstationXml::writeRootElementAttributes(const Substation& substation, const Network& /*network*/, NetworkXmlWriterContext& context) const { const auto& country = substation.getCountry(); if (country) { - context.getWriter().writeAttribute(COUNTRY, context.getAnonymizer().anonymizeString(Enum::toString(*country))); + context.getWriter().writeAttribute(COUNTRY, Enum::toString(context.getAnonymizer().anonymizeCountry(*country))); } if (!substation.getTso().empty()) { diff --git a/src/iidm/converter/xml/ThreeWindingsTransformerXml.cpp b/src/iidm/converter/xml/ThreeWindingsTransformerXml.cpp index 6ec101bea..5221af3b4 100644 --- a/src/iidm/converter/xml/ThreeWindingsTransformerXml.cpp +++ b/src/iidm/converter/xml/ThreeWindingsTransformerXml.cpp @@ -123,7 +123,7 @@ void ThreeWindingsTransformerXml::readSubElements(ThreeWindingsTransformer& twt, IidmXmlUtil::assertMinimumVersion(THREE_WINDINGS_TRANSFORMER, PHASE_TAP_CHANGER3, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), context); readPhaseTapChanger(3, twt.getLeg3(), context); } else { - AbstractIdentifiableXml::readSubElements(twt, context); + AbstractTransformerXml::readSubElements(twt, context); } }); } diff --git a/src/iidm/converter/xml/TieLineXml.cpp b/src/iidm/converter/xml/TieLineXml.cpp index 295eb58a6..6bde4484c 100644 --- a/src/iidm/converter/xml/TieLineXml.cpp +++ b/src/iidm/converter/xml/TieLineXml.cpp @@ -80,7 +80,7 @@ void TieLineXml::readSubElements(TieLine& line, NetworkXmlReaderContext& context CurrentLimitsAdder adder = line.newCurrentLimits2(); readCurrentLimits(adder, context.getReader(), 2); } else { - AbstractIdentifiableXml::readSubElements(line, context); + AbstractConnectableXml::readSubElements(line, context); } }); } diff --git a/src/iidm/converter/xml/TwoWindingsTransformerXml.cpp b/src/iidm/converter/xml/TwoWindingsTransformerXml.cpp index 3464396db..d398b33d0 100644 --- a/src/iidm/converter/xml/TwoWindingsTransformerXml.cpp +++ b/src/iidm/converter/xml/TwoWindingsTransformerXml.cpp @@ -64,7 +64,7 @@ void TwoWindingsTransformerXml::readSubElements(TwoWindingsTransformer& twt, Net } else if (context.getReader().getLocalName() == PHASE_TAP_CHANGER) { readPhaseTapChanger(twt, context); } else { - AbstractIdentifiableXml::readSubElements(twt, context); + AbstractTransformerXml::readSubElements(twt, context); } }); } diff --git a/src/iidm/converter/xml/VoltageLevelXml.cpp b/src/iidm/converter/xml/VoltageLevelXml.cpp index b809b34d4..dd4524c46 100644 --- a/src/iidm/converter/xml/VoltageLevelXml.cpp +++ b/src/iidm/converter/xml/VoltageLevelXml.cpp @@ -109,11 +109,11 @@ void VoltageLevelXml::readNodeBreakerTopology(VoltageLevel& voltageLevel, Networ } VoltageLevel& VoltageLevelXml::readRootElementAttributes(VoltageLevelAdder& adder, NetworkXmlReaderContext& context) const { - auto nominalVoltage = context.getReader().getAttributeValue(NOMINAL_V); + auto nominalV = context.getReader().getAttributeValue(NOMINAL_V); double lowVoltageLimit = context.getReader().getOptionalAttributeValue(LOW_VOLTAGE_LIMIT, stdcxx::nan()); double highVoltageLimit = context.getReader().getOptionalAttributeValue(HIGH_VOLTAGE_LIMIT, stdcxx::nan()); const auto& topologyKing = Enum::fromString(context.getReader().getAttributeValue(TOPOLOGY_KIND)); - return adder.setNominalVoltage(nominalVoltage) + return adder.setNominalV(nominalV) .setLowVoltageLimit(lowVoltageLimit) .setHighVoltageLimit(highVoltageLimit) .setTopologyKind(topologyKing) @@ -244,7 +244,7 @@ void VoltageLevelXml::writeNodeBreakerTopology(const VoltageLevel& voltageLevel, writeNodeBreakerTopologyInternalConnections(voltageLevel, context); IidmXmlUtil::runFromMinimumVersion(IidmXmlVersion::V1_1(), context.getVersion(), [&context, &voltageLevel]() { - const auto& nodesByBus = util::Networks::getNodesByBus(voltageLevel); + const auto& nodesByBus = Networks::getNodesByBus(voltageLevel); for (const auto& pair : nodesByBus) { const stdcxx::CReference& bus = voltageLevel.getBusView().getBus(pair.first); if (bus && (!std::isnan(bus.get().getV()) || !std::isnan(bus.get().getAngle()))) { @@ -263,7 +263,7 @@ void VoltageLevelXml::writeNodeBreakerTopologyInternalConnections(const VoltageL } void VoltageLevelXml::writeRootElementAttributes(const VoltageLevel& voltageLevel, const Substation& /*substation*/, NetworkXmlWriterContext& context) const { - context.getWriter().writeAttribute(NOMINAL_V, voltageLevel.getNominalVoltage()); + context.getWriter().writeAttribute(NOMINAL_V, voltageLevel.getNominalV()); context.getWriter().writeOptionalAttribute(LOW_VOLTAGE_LIMIT, voltageLevel.getLowVoltageLimit()); context.getWriter().writeOptionalAttribute(HIGH_VOLTAGE_LIMIT, voltageLevel.getHighVoltageLimit()); const TopologyLevel& topologyLevel = getMinTopologyLevel(voltageLevel.getTopologyKind(), context.getOptions().getTopologyLevel()); diff --git a/src/iidm/converter/xml/VscConverterStationXml.cpp b/src/iidm/converter/xml/VscConverterStationXml.cpp index 1d617dd00..6c131b5fd 100644 --- a/src/iidm/converter/xml/VscConverterStationXml.cpp +++ b/src/iidm/converter/xml/VscConverterStationXml.cpp @@ -52,7 +52,7 @@ void VscConverterStationXml::readSubElements(VscConverterStation& converterStati context.getReader().getLocalName() == MIN_MAX_REACTIVE_LIMITS) { ReactiveLimitsXml::getInstance().read(converterStation, context); } else { - AbstractIdentifiableXml::readSubElements(converterStation, context); + AbstractConnectableXml::readSubElements(converterStation, context); } }); } diff --git a/src/iidm/extensions/SlackTerminal.cpp b/src/iidm/extensions/SlackTerminal.cpp index 5e4ed5f3d..b0f1ca321 100644 --- a/src/iidm/extensions/SlackTerminal.cpp +++ b/src/iidm/extensions/SlackTerminal.cpp @@ -41,7 +41,7 @@ void SlackTerminal::assertExtendable(const stdcxx::Reference& extend void SlackTerminal::attach(Bus& bus) { VoltageLevel& vl = bus.getVoltageLevel(); - stdcxx::Reference terminal = util::TerminalFinder::getDefault().find(bus.getConnectedTerminals()); + stdcxx::Reference terminal = TerminalFinder::find(bus.getConnectedTerminals()); if (!terminal) { throw PowsyblException(stdcxx::format("Unable to find a terminal in the bus %1%", bus.getId())); } diff --git a/src/iidm/util/Identifiables.cpp b/src/iidm/util/Identifiables.cpp index 18c236969..b2ac3709f 100644 --- a/src/iidm/util/Identifiables.cpp +++ b/src/iidm/util/Identifiables.cpp @@ -14,10 +14,10 @@ namespace powsybl { namespace iidm { -namespace util { +namespace Identifiables { -std::string Identifiables::getUniqueId(const std::string& baseId, const stdcxx::Predicate& containsId) { - logging::Logger& logger = logging::LoggerFactory::getLogger(); +std::string getUniqueId(const std::string& baseId, const stdcxx::Predicate& containsId) { + logging::Logger& logger = logging::LoggerFactory::getLogger("Identifiables"); std::string checkedBaseId; if (!baseId.empty()) { @@ -41,7 +41,7 @@ std::string Identifiables::getUniqueId(const std::string& baseId, const stdcxx:: return uniqueId; } -} // namespace util +} // namespace Identifiables } // namespace iidm diff --git a/src/iidm/util/LimitViolationUtils.cpp b/src/iidm/util/LimitViolationUtils.cpp index a3a444daa..36704bc84 100644 --- a/src/iidm/util/LimitViolationUtils.cpp +++ b/src/iidm/util/LimitViolationUtils.cpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace powsybl { diff --git a/src/iidm/util/Networks.cpp b/src/iidm/util/Networks.cpp index 979168971..df42d0278 100644 --- a/src/iidm/util/Networks.cpp +++ b/src/iidm/util/Networks.cpp @@ -17,9 +17,9 @@ namespace powsybl { namespace iidm { -namespace util { +namespace Networks { -stdcxx::CReference Networks::getEquivalentTerminal(const VoltageLevel& voltageLevel, unsigned long node) { +stdcxx::CReference getEquivalentTerminal(const VoltageLevel& voltageLevel, unsigned long node) { if (voltageLevel.getTopologyKind() != TopologyKind::NODE_BREAKER) { throw PowsyblException(stdcxx::format("The voltage level %1% is not described in Node/Breaker topology", voltageLevel.getId())); } @@ -42,7 +42,7 @@ stdcxx::CReference Networks::getEquivalentTerminal(const VoltageLevel& return equivalentTerminal; } -std::map> Networks::getNodesByBus(const VoltageLevel& voltageLevel) { +std::map> getNodesByBus(const VoltageLevel& voltageLevel) { if (voltageLevel.getTopologyKind() != TopologyKind::NODE_BREAKER) { throw PowsyblException(stdcxx::format("The voltage level %1% is not described in Node/Breaker topology", voltageLevel.getId())); } @@ -70,7 +70,7 @@ std::map> Networks::getNodesByBus(const Vol return nodesByBus; } -} // namespace util +} // namespace Networks } // namespace iidm diff --git a/src/iidm/util/Substations.cpp b/src/iidm/util/Substations.cpp new file mode 100644 index 000000000..f78ef8806 --- /dev/null +++ b/src/iidm/util/Substations.cpp @@ -0,0 +1,75 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace powsybl { + +namespace iidm { + +namespace Substations { + +PowsyblException createIsolationException(const Substation& substation) { + return PowsyblException(stdcxx::format("The substation %1% is still connected to another substation", substation.getId())); +} + +void checkRemovability(const Substation& substation) { + for (const VoltageLevel& vl : substation.getVoltageLevels()) { + for (const Connectable& connectable : vl.getConnectables()) { + if (stdcxx::isInstanceOf(connectable)) { + checkRemovability(substation, dynamic_cast(connectable)); + } else if (stdcxx::isInstanceOf(connectable)) { + checkRemovability(substation, dynamic_cast(connectable)); + } else if (stdcxx::isInstanceOf(connectable)) { + checkRemovability(substation, dynamic_cast(connectable)); + } + } + } +} + +void checkRemovability(const Substation& substation, const Branch& branch) { + const Substation& s1 = branch.getTerminal1().getVoltageLevel().getSubstation(); + const Substation& s2 = branch.getTerminal2().getVoltageLevel().getSubstation(); + if (!stdcxx::areSame(s1, substation) || !stdcxx::areSame(s2, substation)) { + throw createIsolationException(substation); + } +} + +void checkRemovability(const Substation& substation, const ThreeWindingsTransformer& twt) { + const Substation& s1 = twt.getLeg1().getTerminal().getVoltageLevel().getSubstation(); + const Substation& s2 = twt.getLeg2().getTerminal().getVoltageLevel().getSubstation(); + const Substation& s3 = twt.getLeg3().getTerminal().getVoltageLevel().getSubstation(); + if (!stdcxx::areSame(s1, substation) || !stdcxx::areSame(s2, substation) || !stdcxx::areSame(s3, substation)) { + throw createIsolationException(substation); + } +} + +void checkRemovability(const Substation& substation, const HvdcConverterStation& station) { + const auto& hvdcLine = substation.getNetwork().findHvdcLine(station); + if (hvdcLine) { + const Substation& s1 = hvdcLine.get().getConverterStation1().get().getTerminal().getVoltageLevel().getSubstation(); + const Substation& s2 = hvdcLine.get().getConverterStation2().get().getTerminal().getVoltageLevel().getSubstation(); + if (!stdcxx::areSame(s1, substation) || !stdcxx::areSame(s2, substation)) { + throw createIsolationException(substation); + } + } +} + +} // namespace Substations + +} // namespace iidm + +} // namespace powsybl diff --git a/src/iidm/util/TerminalFinder.cpp b/src/iidm/util/TerminalFinder.cpp index 163b41456..459ebd42f 100644 --- a/src/iidm/util/TerminalFinder.cpp +++ b/src/iidm/util/TerminalFinder.cpp @@ -7,6 +7,8 @@ #include +#include + #include #include #include @@ -18,27 +20,11 @@ namespace powsybl { namespace iidm { -namespace util { - -TerminalFinder::TerminalFinder(const std::vector& predicates) : - m_comparator(getComparator(predicates)) { -} +namespace TerminalFinder { -TerminalFinder::TerminalFinder(const Comparator& comparator) : - m_comparator(comparator) { -} +using Predicate = std::function; -stdcxx::CReference TerminalFinder::find(const stdcxx::const_range& terminals) const { - auto it = std::max_element(terminals.begin(), terminals.end(), m_comparator); - return it != terminals.end() ? stdcxx::cref(*it) : stdcxx::cref(); -} - -stdcxx::Reference TerminalFinder::find(const stdcxx::range& terminals) const { - auto it = std::max_element(terminals.begin(), terminals.end(), m_comparator); - return it != terminals.end() ? stdcxx::ref(*it) : stdcxx::ref(); -} - -TerminalFinder::Comparator TerminalFinder::getComparator(const std::vector& predicates) { +Comparator getComparator(const std::vector& predicates) { return [&predicates](const Terminal& t1, const Terminal& t2) { if (stdcxx::areSame(t1, t2)) { return false; @@ -52,11 +38,7 @@ TerminalFinder::Comparator TerminalFinder::getComparator(const std::vector& TerminalFinder::getDefaultRules() { +const std::vector& getDefaultRules() { static std::vector s_rules = { [](const Terminal& t) { return stdcxx::isInstanceOf(t.getConnectable()); }, [](const Terminal& t) { return stdcxx::isInstanceOf(t.getConnectable()); }, @@ -67,7 +49,25 @@ const std::vector& TerminalFinder::getDefaultRules() return s_rules; } -} // namespace util +stdcxx::CReference find(const stdcxx::const_range& terminals) { + return find(getComparator(getDefaultRules()), terminals); +} + +stdcxx::Reference find(const stdcxx::range& terminals) { + return find(getComparator(getDefaultRules()), terminals); +} + +stdcxx::CReference find(const Comparator& comparator, const stdcxx::const_range& terminals) { + auto it = std::max_element(terminals.begin(), terminals.end(), comparator); + return it != terminals.end() ? stdcxx::cref(*it) : stdcxx::cref(); +} + +stdcxx::Reference find(const Comparator& comparator, const stdcxx::range& terminals) { + auto it = std::max_element(terminals.begin(), terminals.end(), comparator); + return it != terminals.end() ? stdcxx::ref(*it) : stdcxx::ref(); +} + +} // namespace TerminalFinder } // namespace iidm diff --git a/src/iidm/util/VoltageLevels.cpp b/src/iidm/util/VoltageLevels.cpp new file mode 100644 index 000000000..905000a6f --- /dev/null +++ b/src/iidm/util/VoltageLevels.cpp @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace powsybl { + +namespace iidm { + +namespace VoltageLevels { + +void checkRemovability(const VoltageLevel& voltageLevel) { + const Network& network = voltageLevel.getNetwork(); + for (const Connectable& connectable : voltageLevel.getConnectables()) { + const ConnectableType& type = connectable.getType(); + if (MULTIPLE_TERMINALS_CONNECTABLE_TYPES.find(type) != MULTIPLE_TERMINALS_CONNECTABLE_TYPES.end()) { + // Reject lines, 2WT and 3WT + throw AssertionError(stdcxx::format("The voltage level '%1%' cannot be removed because of a remaining %2%", voltageLevel.getId(), type)); + } + if (type == ConnectableType::HVDC_CONVERTER_STATION && network.findHvdcLine(dynamic_cast(connectable))) { + // Reject all converter stations connected to a HVDC line + throw AssertionError(stdcxx::format("The voltage level '%1%' cannot be removed because of a remaining HVDC line", voltageLevel.getId())); + } + } +} + +} // namespace VoltageLevels + +} // namespace iidm + +} // namespace powsybl diff --git a/src/math/GraphUtil.cpp b/src/math/GraphUtil.cpp index 96eb2734b..c1f60aefe 100644 --- a/src/math/GraphUtil.cpp +++ b/src/math/GraphUtil.cpp @@ -25,7 +25,7 @@ void computeConnectedComponents(unsigned long v1, unsigned long c, std::vector& ls = adjacencyList[v1]; for (unsigned long v2 : ls) { - if (!componentNumber[v2].is_initialized()) { + if (!componentNumber[v2]) { computeConnectedComponents(v2, c, componentSize, adjacencyList, componentNumber); } } @@ -41,7 +41,7 @@ ConnectedComponentsComputationResult computeConnectedComponents(const AdjacencyL // Fill componentSize and componentNumber based on the adjacency list unsigned long c = 0; for (unsigned long v = 0; v < adjacencyList.size(); v++) { - if (!componentNumber[v].is_initialized()) { + if (!componentNumber[v]) { computeConnectedComponents(v, c, componentSize, adjacencyList, componentNumber); c++; } diff --git a/src/network/BatteryNetworkFactory.cpp b/src/network/BatteryNetworkFactory.cpp index 8a423e24d..b71ed9871 100644 --- a/src/network/BatteryNetworkFactory.cpp +++ b/src/network/BatteryNetworkFactory.cpp @@ -48,12 +48,12 @@ iidm::Network BatteryNetworkFactory::create() { // 2 VoltageLevels iidm::VoltageLevel& vlgen = p1.newVoltageLevel() .setId("VLGEN") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) .add(); iidm::VoltageLevel& vlbat = p2.newVoltageLevel() .setId("VLBAT") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) .add(); diff --git a/src/network/EurostagFactory.cpp b/src/network/EurostagFactory.cpp index 015b70ab2..fbe7434df 100644 --- a/src/network/EurostagFactory.cpp +++ b/src/network/EurostagFactory.cpp @@ -38,22 +38,22 @@ iidm::Network EurostagFactory::createTutorial1Network() { .add(); iidm::VoltageLevel& vlgen = p1.newVoltageLevel() .setId("VLGEN") - .setNominalVoltage(24.0) + .setNominalV(24.0) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) .add(); iidm::VoltageLevel& vlhv1 = p1.newVoltageLevel() .setId("VLHV1") - .setNominalVoltage(380.0) + .setNominalV(380.0) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) .add(); iidm::VoltageLevel& vlhv2 = p2.newVoltageLevel() .setId("VLHV2") - .setNominalVoltage(380.0) + .setNominalV(380.0) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) .add(); iidm::VoltageLevel& vlload = p2.newVoltageLevel() .setId("VLLOAD") - .setNominalVoltage(150.0) + .setNominalV(150.0) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) .add(); iidm::Bus& ngen = vlgen.getBusBreakerView().newBus() diff --git a/src/network/FictitiousSwitchFactory.cpp b/src/network/FictitiousSwitchFactory.cpp index 02c66dd4c..80798798d 100644 --- a/src/network/FictitiousSwitchFactory.cpp +++ b/src/network/FictitiousSwitchFactory.cpp @@ -60,7 +60,7 @@ iidm::Network FictitiousSwitchFactory::create() { .add(); iidm::VoltageLevel& vlC = s.newVoltageLevel() .setId("C") - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(0.0) .setTopologyKind(iidm::TopologyKind::NODE_BREAKER) .add(); @@ -76,7 +76,7 @@ iidm::Network FictitiousSwitchFactory::create() { iidm::VoltageLevel& vlN = s.newVoltageLevel() .setId("N") - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(220.0) .setHighVoltageLimit(245.00002) .setTopologyKind(iidm::TopologyKind::NODE_BREAKER) diff --git a/src/network/FourSubstationsNodeBreakerFactory.cpp b/src/network/FourSubstationsNodeBreakerFactory.cpp new file mode 100644 index 000000000..3f8f38690 --- /dev/null +++ b/src/network/FourSubstationsNodeBreakerFactory.cpp @@ -0,0 +1,651 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace powsybl { + +namespace network { + +static void createSwitch(iidm::VoltageLevel& vl, const std::string& id, const iidm::SwitchKind& kind, bool open, unsigned long node1, unsigned long node2) { + vl.getNodeBreakerView().newSwitch() + .setId(id) + .setName(id) + .setKind(kind) + .setRetained(kind == iidm::SwitchKind::BREAKER) + .setOpen(open) + .setFictitious(false) + .setNode1(node1) + .setNode2(node2) + .add(); +} + +iidm::Network FourSubstationsNodeBreakerFactory::create() { + iidm::Network network("fourSubstations", "test"); + network.setCaseDate(stdcxx::DateTime::parse("2017-06-25T17:43:00.000+01:00")); + network.setForecastDistance(0); + + // First substation + // It is constituted of 2 voltage levels + // The second voltage levels comprises two busbar sections + iidm::Substation& s1 = network.newSubstation() + .setId("S1") + .add(); + iidm::VoltageLevel& s1vl1 = s1.newVoltageLevel() + .setId("S1VL1") + .setNominalV(225.0) + .setLowVoltageLimit(220.0) + .setHighVoltageLimit(240.0) + .setTopologyKind(iidm::TopologyKind::NODE_BREAKER) + .add(); + iidm::BusbarSection& busbarSectionS1VL1 = s1vl1.getNodeBreakerView().newBusbarSection() + .setId("S1VL1_BBS") + .setName("S1VL1_BBS") + .setNode(0) + .add(); + iidm::VoltageLevel& s1vl2 = s1.newVoltageLevel() + .setId("S1VL2") + .setNominalV(400.0) + .setLowVoltageLimit(390.0) + .setHighVoltageLimit(440.0) + .setTopologyKind(iidm::TopologyKind::NODE_BREAKER) + .add(); + iidm::BusbarSection& busbarSectionS1VL21 = s1vl2.getNodeBreakerView().newBusbarSection() + .setId("S1VL2_BBS1") + .setName("S1VL2_BBS1") + .setNode(0) + .add(); + iidm::BusbarSection& busbarSectionS1VL22 = s1vl2.getNodeBreakerView().newBusbarSection() + .setId("S1VL2_BBS2") + .setName("S1VL2_BBS2") + .setNode(1) + .add(); + + // Second substation + iidm::Substation& s2 = network.newSubstation() + .setId("S2") + .add(); + iidm::VoltageLevel& s2vl1 = s2.newVoltageLevel() + .setId("S2VL1") + .setNominalV(400.0) + .setLowVoltageLimit(390.0) + .setHighVoltageLimit(440.0) + .setTopologyKind(iidm::TopologyKind::NODE_BREAKER) + .add(); + iidm::BusbarSection& busbarSectionS2VL1 = s2vl1.getNodeBreakerView().newBusbarSection() + .setId("S2VL1_BBS") + .setName("S2VL1_BBS") + .setNode(0) + .add(); + + // Third substation + iidm::Substation& s3 = network.newSubstation() + .setId("S3") + .add(); + iidm::VoltageLevel& s3vl1 = s3.newVoltageLevel() + .setId("S3VL1") + .setNominalV(400.0) + .setLowVoltageLimit(390.0) + .setHighVoltageLimit(440.0) + .setTopologyKind(iidm::TopologyKind::NODE_BREAKER) + .add(); + iidm::BusbarSection& busbarSectionS3VL1 = s3vl1.getNodeBreakerView().newBusbarSection() + .setId("S3VL1_BBS") + .setName("S3VL1_BBS") + .setNode(0) + .add(); + + // Fourth substation + iidm::Substation& s4 = network.newSubstation() + .setId("S4") + .add(); + iidm::VoltageLevel& s4vl1 = s4.newVoltageLevel() + .setId("S4VL1") + .setNominalV(400.0) + .setLowVoltageLimit(390.0) + .setHighVoltageLimit(440.0) + .setTopologyKind(iidm::TopologyKind::NODE_BREAKER) + .add(); + iidm::BusbarSection& busbarSectionS4VL1 = s4vl1.getNodeBreakerView().newBusbarSection() + .setId("S4VL1_BBS") + .setName("S4VL1_BBS") + .setNode(0) + .add(); + + // Connect a load on the first voltage level of substation 1 + createSwitch(s1vl1, "S1VL1_BBS_LD1_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 1); + createSwitch(s1vl1, "S1VL1_LD1_BREAKER", iidm::SwitchKind::BREAKER, false, 1, 2); + iidm::Load& load1 = s1vl1.newLoad() + .setId("LD1") + .setLoadType(iidm::LoadType::UNDEFINED) + .setP0(80) + .setQ0(10) + .setNode(2) + .add(); + load1.getTerminal().setP(80.0).setQ(10.0); + + // Connect a TWT between the two voltage levels of substation 1, on the bus bar section 1 of the second voltage level + // TWT could be connected to bbs 2 of the second VL through a second disconnector, which is open at the moment + createSwitch(s1vl1, "S1VL1_BBS_TWT_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 3); + createSwitch(s1vl1, "S1VL1_TWT_BREAKER", iidm::SwitchKind::BREAKER, false, 3, 4); + createSwitch(s1vl2, "S1VL2_BBS1_TWT_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 2); + createSwitch(s1vl2, "S1VL2_BBS2_TWT_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 1, 2); + createSwitch(s1vl2, "S1VL2_TWT_BREAKER", iidm::SwitchKind::BREAKER, false, 2, 3); + + iidm::TwoWindingsTransformer& twt = s1.newTwoWindingsTransformer() + .setId("TWT") + .setR(2.0) + .setX(14.745) + .setG(0.0) + .setB(3.2E-5) + .setRatedU1(225.0) + .setRatedU2(400.0) + .setNode1(4) + .setVoltageLevel1("S1VL1") + .setNode2(3) + .setVoltageLevel2("S1VL2") + .add(); + twt.newCurrentLimits1() + .setPermanentLimit(1031.0) + .add(); + twt.newCurrentLimits2() + .setPermanentLimit(1031.0) + .add(); + twt.newPhaseTapChanger() + .setLowTapPosition(0) + .setTapPosition(15) + .setRegulationMode(iidm::PhaseTapChanger::RegulationMode::FIXED_TAP) + .setRegulating(false) + .setRegulationTerminal(stdcxx::ref(twt.getTerminal(iidm::Branch::Side::ONE))) + .beginStep().setR(39.78473).setX(29.784725).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-42.8).endStep() + .beginStep().setR(31.720245).setX(21.720242).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-40.18).endStep() + .beginStep().setR(23.655737).setX(13.655735).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-37.54).endStep() + .beginStep().setR(16.263271).setX(6.263268).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-34.9).endStep() + .beginStep().setR(9.542847).setX(4.542842).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-32.26).endStep() + .beginStep().setR(3.4944773).setX(3.4944773).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-29.6).endStep() + .beginStep().setR(-1.8818557).setX(-1.8818527).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-26.94).endStep() + .beginStep().setR(-7.258195).setX(-3.2581954).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-24.26).endStep() + .beginStep().setR(-11.962485).setX(-7.962484).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-21.58).endStep() + .beginStep().setR(-15.994745).setX(-11.994745).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-18.9).endStep() + .beginStep().setR(-19.354952).setX(-15.354952).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-16.22).endStep() + .beginStep().setR(-22.043127).setX(-22.043129).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-13.52).endStep() + .beginStep().setR(-24.73129).setX(-24.731287).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-10.82).endStep() + .beginStep().setR(-26.747417).setX(-26.747417).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-8.12).endStep() + .beginStep().setR(-28.091503).setX(-28.091503).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-5.42).endStep() + .beginStep().setR(-28.763538).setX(-28.763536).setG(0.0).setB(0.0).setRho(1.0).setAlpha(-2.7).endStep() + .beginStep().setR(-28.763538).setX(-28.763536).setG(0.0).setB(0.0).setRho(1.0).setAlpha(0.0).endStep() + .beginStep().setR(-28.763538).setX(-28.763536).setG(0.0).setB(0.0).setRho(1.0).setAlpha(2.7).endStep() + .beginStep().setR(-28.091503).setX(-28.091503).setG(0.0).setB(0.0).setRho(1.0).setAlpha(5.42).endStep() + .beginStep().setR(-26.747417).setX(-26.747417).setG(0.0).setB(0.0).setRho(1.0).setAlpha(8.12).endStep() + .beginStep().setR(-24.73129).setX(-24.731287).setG(0.0).setB(0.0).setRho(1.0).setAlpha(10.82).endStep() + .beginStep().setR(-22.043127).setX(-22.043129).setG(0.0).setB(0.0).setRho(1.0).setAlpha(13.52).endStep() + .beginStep().setR(-19.354952).setX(-19.354952).setG(0.0).setB(0.0).setRho(1.0).setAlpha(16.22).endStep() + .beginStep().setR(-15.994745).setX(-15.994745).setG(0.0).setB(0.0).setRho(1.0).setAlpha(18.9).endStep() + .beginStep().setR(-11.962485).setX(-11.962484).setG(0.0).setB(0.0).setRho(1.0).setAlpha(21.58).endStep() + .beginStep().setR(-7.258195).setX(-7.2581954).setG(0.0).setB(0.0).setRho(1.0).setAlpha(24.26).endStep() + .beginStep().setR(-1.8818557).setX(-1.8818527).setG(0.0).setB(0.0).setRho(1.0).setAlpha(26.94).endStep() + .beginStep().setR(3.4944773).setX(3.4944773).setG(0.0).setB(0.0).setRho(1.0).setAlpha(29.6).endStep() + .beginStep().setR(9.542847).setX(9.542842).setG(0.0).setB(0.0).setRho(1.0).setAlpha(32.26).endStep() + .beginStep().setR(16.263271).setX(16.263268).setG(0.0).setB(0.0).setRho(1.0).setAlpha(34.9).endStep() + .beginStep().setR(23.655737).setX(23.655735).setG(0.0).setB(0.0).setRho(1.0).setAlpha(37.54).endStep() + .beginStep().setR(31.720245).setX(31.720242).setG(0.0).setB(0.0).setRho(1.0).setAlpha(40.18).endStep() + .beginStep().setR(39.78473).setX(39.784725).setG(0.0).setB(0.0).setRho(1.0).setAlpha(42.8).endStep() + .add(); + twt.getTerminal1().setP(-80.0).setQ(-10.0); + twt.getTerminal2().setP(80.0809).setQ(5.4857); + + // Connect a VSC station to BBS2 of the second voltage level of substation 1, with a possibility to connect it to BBS1 + createSwitch(s1vl2, "S1VL2_BBS1_VSC1_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 0, 4); + createSwitch(s1vl2, "S1VL2_BBS2_VSC1_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 1, 4); + createSwitch(s1vl2, "S1VL2_VSC1_BREAKER", iidm::SwitchKind::BREAKER, false, 4, 5); + iidm::VscConverterStation& vsc1 = s1vl2.newVscConverterStation() + .setId("VSC1") + .setName("VSC1") + .setNode(5) + .setLossFactor(1.1) + .setReactivePowerSetpoint(500) + .setVoltageSetpoint(400) + .setVoltageRegulatorOn(true) + .add(); + vsc1.newReactiveCapabilityCurve() + .beginPoint() + .setP(-100.0) + .setMinQ(-550.0) + .setMaxQ(570.0) + .endPoint() + .beginPoint() + .setP(100.0) + .setMinQ(-550.0) + .setMaxQ(570.0) + .endPoint() + .add(); + vsc1.getTerminal().setP(10.1100).setQ(-512.0814); + + // Connect three hydro generators on the bbs 1 of the second voltage level of substation 1, with a possibility to connect them onto bbs 2 + createSwitch(s1vl2, "S1VL2_BBS1_GH1_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 6); + createSwitch(s1vl2, "S1VL2_BBS1_GH2_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 8); + createSwitch(s1vl2, "S1VL2_BBS1_GH3_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 10); + createSwitch(s1vl2, "S1VL2_BBS2_GH1_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 1, 6); + createSwitch(s1vl2, "S1VL2_BBS2_GH2_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 1, 8); + createSwitch(s1vl2, "S1VL2_BBS2_GH3_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 1, 10); + createSwitch(s1vl2, "S1VL2_GH1_BREAKER", iidm::SwitchKind::BREAKER, false, 6, 7); + createSwitch(s1vl2, "S1VL2_GH2_BREAKER", iidm::SwitchKind::BREAKER, false, 8, 9); + createSwitch(s1vl2, "S1VL2_GH3_BREAKER", iidm::SwitchKind::BREAKER, false, 10, 11); + + iidm::Generator& generatorHydro1 = s1vl2.newGenerator() + .setId("GH1") + .setEnergySource(iidm::EnergySource::HYDRO) + .setMinP(0.0) + .setMaxP(100.0) + .setVoltageRegulatorOn(true) + .setTargetP(85.3570) + .setTargetV(400.0) + .setTargetQ(512.081) + .setNode(7) + .add(); + generatorHydro1.newReactiveCapabilityCurve() + .beginPoint() + .setP(0.0) + .setMinQ(-769.3) + .setMaxQ(860.0) + .endPoint() + .beginPoint() + .setP(100.0) + .setMinQ(-864.55) + .setMaxQ(946.25) + .endPoint() + .add(); + generatorHydro1.getTerminal().setP(-85.3570).setQ(-512.0814); + + iidm::Generator& generatorHydro2 = s1vl2.newGenerator() + .setId("GH2") + .setEnergySource(iidm::EnergySource::HYDRO) + .setMinP(0.0) + .setMaxP(200.0) + .setVoltageRegulatorOn(true) + .setTargetP(90) + .setTargetV(400.0) + .setTargetQ(512.081) + .setNode(9) + .add(); + generatorHydro2.newReactiveCapabilityCurve() + .beginPoint() + .setP(0.0) + .setMinQ(-556.8) + .setMaxQ(557.4) + .endPoint() + .beginPoint() + .setP(200.0) + .setMinQ(-553.514) + .setMaxQ(536.4) + .endPoint() + .add(); + generatorHydro2.getTerminal().setP(-90.0).setQ(-512.0814); + + iidm::Generator& generatorHydro3 = s1vl2.newGenerator() + .setId("GH3") + .setEnergySource(iidm::EnergySource::HYDRO) + .setMinP(0.0) + .setMaxP(200.0) + .setVoltageRegulatorOn(true) + .setTargetP(155.714) + .setTargetV(400) + .setTargetQ(512.081) + .setNode(11) + .add(); + generatorHydro3.newReactiveCapabilityCurve() + .beginPoint() + .setP(0.0) + .setMinQ(-680.6) + .setMaxQ(688.1) + .endPoint() + .beginPoint() + .setP(200.0) + .setMinQ(-681.725) + .setMaxQ(716.3500004) + .endPoint() + .add(); + generatorHydro3.getTerminal().setP(-155.7140).setQ(-512.0814); + + // Connect three loads on the bbs 2, with a possibility to connect them onto bbs 1 + createSwitch(s1vl2, "S1VL2_BBS1_LD2_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 0, 12); + createSwitch(s1vl2, "S1VL2_BBS1_LD3_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 0, 14); + createSwitch(s1vl2, "S1VL2_BBS1_LD4_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 0, 16); + createSwitch(s1vl2, "S1VL2_BBS2_LD2_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 1, 12); + createSwitch(s1vl2, "S1VL2_BBS2_LD3_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 1, 14); + createSwitch(s1vl2, "S1VL2_BBS2_LD4_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 1, 16); + createSwitch(s1vl2, "S1VL2_LD2_BREAKER", iidm::SwitchKind::BREAKER, false, 12, 13); + createSwitch(s1vl2, "S1VL2_LD3_BREAKER", iidm::SwitchKind::BREAKER, false, 14, 15); + createSwitch(s1vl2, "S1VL2_LD4_BREAKER", iidm::SwitchKind::BREAKER, false, 16, 17); + + iidm::Load& load2 = s1vl2.newLoad() + .setId("LD2") + .setLoadType(iidm::LoadType::UNDEFINED) + .setP0(60) + .setQ0(5) + .setNode(13) + .add(); + load2.getTerminal().setP(60.0).setQ(5.0); + + iidm::Load& load3 = s1vl2.newLoad() + .setId("LD3") + .setLoadType(iidm::LoadType::UNDEFINED) + .setP0(60) + .setQ0(5) + .setNode(15) + .add(); + load3.getTerminal().setP(60.0).setQ(5.0); + + iidm::Load& load4 = s1vl2.newLoad() + .setId("LD4") + .setLoadType(iidm::LoadType::UNDEFINED) + .setP0(40) + .setQ0(5) + .setNode(17) + .add(); + load4.getTerminal().setP(40.0).setQ(5.0); + + // Connect a shunt on the BBS1, with a possibility to connect it to BBS2 + createSwitch(s1vl2, "S1VL2_BBS1_SHUNT_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 18); + createSwitch(s1vl2, "S1VL2_BBS2_SHUNT_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 1, 18); + createSwitch(s1vl2, "S1VL2_SHUNT_BREAKER", iidm::SwitchKind::BREAKER, false, 18, 19); + + iidm::ShuntCompensator& shunt = s1vl2.newShuntCompensator() + .setId("SHUNT") + .setNode(19) + .setSectionCount(1) + .newLinearModel().setMaximumSectionCount(1).setBPerSection(-0.012).add() + .add(); + shunt.getTerminal().setQ(1920.0); + + createSwitch(s1vl2, "S1VL2_BBS1_LCC1_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, true, 0, 20); + createSwitch(s1vl2, "S1VL2_BBS2_LCC1_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 1, 20); + createSwitch(s1vl2, "S1VL2_LCC1_BREAKER", iidm::SwitchKind::BREAKER, false, 20, 21); + + iidm::LccConverterStation& lcc1 = s1vl2.newLccConverterStation() + .setId("LCC1") + .setName("LCC1") + .setNode(21) + .setLossFactor(1.1) + .setPowerFactor(0.6) + .add(); + lcc1.getTerminal().setP(80.8800); + + // Add a coupler between the two busbar sections + createSwitch(s1vl2, "S1VL2_BBS1_COUPLER_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 22); + createSwitch(s1vl2, "S1VL2_BBS2_COUPLER_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 1, 23); + createSwitch(s1vl2, "S1VL2_COUPLER", iidm::SwitchKind::BREAKER, false, 22, 23); + + // Connect a thermal generator on the second substation + createSwitch(s2vl1, "S2VL1_BBS_GTH1_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 1); + createSwitch(s2vl1, "S2VL1_GTH1_BREAKER", iidm::SwitchKind::BREAKER, false, 1, 2); + iidm::Generator& generatorThermal1 = s2vl1.newGenerator() + .setId("GTH1") + .setEnergySource(iidm::EnergySource::THERMAL) + .setMinP(0.0) + .setMaxP(100.0) + .setVoltageRegulatorOn(false) + .setTargetP(100.0) + .setTargetV(400) + .setTargetQ(70) + .setNode(2) + .add(); + generatorThermal1.newReactiveCapabilityCurve() + .beginPoint() + .setP(0.0) + .setMinQ(-76.8) + .setMaxQ(77.4) + .endPoint() + .beginPoint() + .setP(100.0) + .setMinQ(-73.514) + .setMaxQ(76.4) + .endPoint() + .add(); + generatorThermal1.getTerminal().setP(-100.0).setQ(-70.0); + + // Connect a second VSC station on the second substation + createSwitch(s2vl1, "S2VL1_BBS_VSC2_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 3); + createSwitch(s2vl1, "S2VL1_VSC2_BREAKER", iidm::SwitchKind::BREAKER, false, 3, 4); + iidm::VscConverterStation& vsc2 = s2vl1.newVscConverterStation() + .setId("VSC2") + .setName("VSC2") + .setNode(4) + .setLossFactor(1.1) + .setReactivePowerSetpoint(120) + .setVoltageSetpoint(0) + .setVoltageRegulatorOn(false) + .add(); + vsc2.newMinMaxReactiveLimits() + .setMinQ(-400.0) + .setMaxQ(500.0) + .add(); + vsc2.getTerminal().setP(-9.8900).setQ(-120.0); + + // The substations 1 and 2 are linked through an HVDC line + network.newHvdcLine() + .setId("HVDC1") + .setName("HVDC1") + .setConverterStationId1("VSC1") + .setConverterStationId2("VSC2") + .setR(1) + .setNominalV(400) + .setConvertersMode(iidm::HvdcLine::ConvertersMode::SIDE_1_RECTIFIER_SIDE_2_INVERTER) + .setMaxP(300.0) + .setActivePowerSetpoint(10) + .add(); + + // The substations 2 and 3 are connected through a line + createSwitch(s2vl1, "S2VL1_BBS_LINES2S3_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 5); + createSwitch(s2vl1, "S2VL1_LINES2S3_BREAKER", iidm::SwitchKind::BREAKER, false, 5, 6); + createSwitch(s3vl1, "S3VL1_BBS_LINES2S3_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 1); + createSwitch(s3vl1, "S3VL1_LINES2S3_BREAKER", iidm::SwitchKind::BREAKER, false, 1, 2); + iidm::Line& lineS2S3 = network.newLine() + .setId("LINE_S2S3") + .setR(0.009999999) + .setX(19.100000024) + .setG1(0.0) + .setB1(0.0) + .setG2(0.0) + .setB2(0.0) + .setNode1(6) + .setVoltageLevel1("S2VL1") + .setNode2(2) + .setVoltageLevel2("S3VL1") + .add(); + lineS2S3.getTerminal1().setP(109.8893).setQ(190.0229); + lineS2S3.getTerminal2().setP(-109.8864).setQ(-184.5171); + + // Connect a load onto the third substation + createSwitch(s3vl1, "S3VL1_BBS_LD5_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 3); + createSwitch(s3vl1, "S3VL1_LD5_BREAKER", iidm::SwitchKind::BREAKER, false, 3, 4); + iidm::Load& load5 = s3vl1.newLoad() + .setId("LD5") + .setLoadType(iidm::LoadType::UNDEFINED) + .setP0(200) + .setQ0(5) + .setNode(4) + .add(); + load5.getTerminal().setP(200.0).setQ(5.0); + + // Connect a thermal generator onto the third substation + createSwitch(s3vl1, "S3VL1_BBS_GTH2_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 5); + createSwitch(s3vl1, "S3VL1_GTH2_BREAKER", iidm::SwitchKind::BREAKER, false, 5, 6); + iidm::Generator& generatorThermal2 = s3vl1.newGenerator() + .setId("GTH2") + .setEnergySource(iidm::EnergySource::THERMAL) + .setMinP(0.0) + .setMaxP(400.0) + .setVoltageRegulatorOn(true) + .setTargetP(250.9944) + .setTargetV(400) + .setTargetQ(71.8487) + .setNode(6) + .add(); + generatorThermal2.newReactiveCapabilityCurve() + .beginPoint() + .setP(0.0) + .setMinQ(-169.3) + .setMaxQ(200.0) + .endPoint() + .beginPoint() + .setP(400.0) + .setMinQ(-174.55) + .setMaxQ(176.25) + .endPoint() + .add(); + generatorThermal2.getTerminal().setP(-250.9944).setQ(71.8487); + + // The stations 3 and 4 are linked by a line + createSwitch(s3vl1, "S3VL1_BBS_LINES3S4_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 7); + createSwitch(s3vl1, "S3VL1_LINES3S4_BREAKER", iidm::SwitchKind::BREAKER, false, 7, 8); + createSwitch(s4vl1, "S4VL1_BBS_LINES3S4_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 5); + createSwitch(s4vl1, "S4VL1_LINES3S4_BREAKER", iidm::SwitchKind::BREAKER, false, 5, 6); + iidm::Line& lineS3S4 = network.newLine() + .setId("LINE_S3S4") + .setR(0.009999999) + .setX(13.100000024) + .setG1(0.0) + .setB1(0.0) + .setG2(0.0) + .setB2(0.0) + .setNode1(8) + .setVoltageLevel1("S3VL1") + .setNode2(6) + .setVoltageLevel2("S4VL1") + .add(); + lineS3S4.getTerminal1().setP(240.0036).setQ(2.1751); + lineS3S4.getTerminal2().setP(-240.0).setQ(2.5415); + lineS3S4.newCurrentLimits1() + .setPermanentLimit(931.0) + .add(); + lineS3S4.newCurrentLimits2() + .setPermanentLimit(931.0) + .beginTemporaryLimit() + .setName("IST") + .setValue(1640.0) + .setFictitious(true) + .setAcceptableDuration(std::numeric_limits::max()) + .endTemporaryLimit() + .beginTemporaryLimit() + .setName("LD71") + .setValue(std::numeric_limits::max()) + .setAcceptableDuration(60) + .endTemporaryLimit() + .add(); + + // Connect an LCC station to the third substation + createSwitch(s3vl1, "S3VL1_BBS_LCC2_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 9); + createSwitch(s3vl1, "S3VL1_LCC2_BREAKER", iidm::SwitchKind::BREAKER, false, 9, 10); + iidm::LccConverterStation& lcc2 = s3vl1.newLccConverterStation() + .setId("LCC2") + .setName("LCC2") + .setNode(10) + .setLossFactor(1.1) + .setPowerFactor(0.6) + .add(); + lcc2.getTerminal().setP(-79.1200); + + // The substations 1 and 3 are linked by an HVDC line + network.newHvdcLine() + .setId("HVDC2") + .setName("HVDC2") + .setConverterStationId1("LCC1") + .setConverterStationId2("LCC2") + .setR(1) + .setNominalV(400) + .setConvertersMode(iidm::HvdcLine::ConvertersMode::SIDE_1_RECTIFIER_SIDE_2_INVERTER) + .setMaxP(300.0) + .setActivePowerSetpoint(80) + .add(); + + // Connect a load to the fourth substation + createSwitch(s4vl1, "S4VL1_BBS_LD6_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 1); + createSwitch(s4vl1, "S4VL1_LD6_BREAKER", iidm::SwitchKind::BREAKER, false, 1, 2); + iidm::Load& load6 = s4vl1.newLoad() + .setId("LD6") + .setLoadType(iidm::LoadType::UNDEFINED) + .setP0(240) + .setQ0(10) + .setNode(2) + .add(); + load6.getTerminal().setP(240.0).setQ(10.0); + + // Connect a static var compensator to the fourth substation + createSwitch(s4vl1, "S4VL1_BBS_SVC_DISCONNECTOR", iidm::SwitchKind::DISCONNECTOR, false, 0, 3); + createSwitch(s4vl1, "S4VL1_SVC_BREAKER", iidm::SwitchKind::BREAKER, false, 3, 4); + iidm::StaticVarCompensator& svc = s4vl1.newStaticVarCompensator() + .setId("SVC") + .setNode(4) + .setBmin(-5e-2) + .setBmax(5e-2) + .setRegulationMode(iidm::StaticVarCompensator::RegulationMode::VOLTAGE) + .setVoltageSetpoint(400) + .add(); + svc.getTerminal().setQ(-12.5415); + + busbarSectionS1VL1.getTerminal().getBusView().getBus().get() + .setV(224.6139) + .setAngle(2.2822); + busbarSectionS1VL21.getTerminal().getBusView().getBus().get() + .setV(400.0) + .setAngle(0.0); + busbarSectionS1VL22.getTerminal().getBusView().getBus().get() + .setV(400.0) + .setAngle(0.0); + busbarSectionS2VL1.getTerminal().getBusView().getBus().get() + .setV(408.8470) + .setAngle(0.7347); + busbarSectionS3VL1.getTerminal().getBusView().getBus().get() + .setV(400.0) + .setAngle(0.0); + busbarSectionS4VL1.getTerminal().getBusView().getBus().get() + .setV(400.0) + .setAngle(-1.1259); + + return network; +} + +} // namespace network + +} // namespace powsybl diff --git a/src/network/MultipleExtensionsTestNetworkFactory.cpp b/src/network/MultipleExtensionsTestNetworkFactory.cpp index dddb1f334..cef60f897 100644 --- a/src/network/MultipleExtensionsTestNetworkFactory.cpp +++ b/src/network/MultipleExtensionsTestNetworkFactory.cpp @@ -29,7 +29,7 @@ iidm::Network MultipleExtensionsTestNetworkFactory::create() { iidm::VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) - .setNominalVoltage(20.0F) + .setNominalV(20.0F) .setLowVoltageLimit(15.0F) .setHighVoltageLimit(25.0F) .add(); diff --git a/src/network/ThreeWindingsTransformerNetworkFactory.cpp b/src/network/ThreeWindingsTransformerNetworkFactory.cpp index 9c71822e8..8d9597cf6 100644 --- a/src/network/ThreeWindingsTransformerNetworkFactory.cpp +++ b/src/network/ThreeWindingsTransformerNetworkFactory.cpp @@ -38,7 +38,7 @@ iidm::Network ThreeWindingsTransformerNetworkFactory::create() { .add(); iidm::VoltageLevel& vl1 = substation.newVoltageLevel() .setId("VL_132") - .setNominalVoltage(132.0) + .setNominalV(132.0) .setLowVoltageLimit(118.8) .setHighVoltageLimit(145.2) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) @@ -59,7 +59,7 @@ iidm::Network ThreeWindingsTransformerNetworkFactory::create() { iidm::VoltageLevel& vl2 = substation.newVoltageLevel() .setId("VL_33") - .setNominalVoltage(33.0) + .setNominalV(33.0) .setLowVoltageLimit(29.7) .setHighVoltageLimit(36.3) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) @@ -80,7 +80,7 @@ iidm::Network ThreeWindingsTransformerNetworkFactory::create() { iidm::VoltageLevel& vl3 = substation.newVoltageLevel() .setId("VL_11") - .setNominalVoltage(11.0) + .setNominalV(11.0) .setLowVoltageLimit(9.9) .setHighVoltageLimit(12.1) .setTopologyKind(iidm::TopologyKind::BUS_BREAKER) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index ced8750a5..e6b6d07f6 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -14,35 +14,47 @@ set(IIDM_TEST_SOURCES converter/RoundTrip.cpp ) -# Shared library -add_library(iidm-tests SHARED ${IIDM_TEST_SOURCES}) -target_include_directories(iidm-tests - INTERFACE - $ - PRIVATE - $ - $ -) -target_link_libraries(iidm-tests PUBLIC iidm Boost::filesystem Boost::program_options Boost::system Boost::unit_test_framework PRIVATE LibXml2::LibXml2) +if (BUILD_SHARED_LIBS) + # Shared library + add_library(iidm-tests SHARED ${IIDM_TEST_SOURCES}) + target_include_directories(iidm-tests + INTERFACE + $ + PRIVATE + $ + $ + ) + target_link_libraries(iidm-tests PUBLIC iidm Boost::filesystem Boost::program_options Boost::system Boost::unit_test_framework PRIVATE LibXml2::LibXml2) -# Static library -add_library(iidm-tests-static STATIC ${IIDM_TEST_SOURCES}) -target_include_directories(iidm-tests-static - INTERFACE - $ - PUBLIC - $ - $ -) -target_link_libraries(iidm-tests-static PUBLIC iidm-static Boost::filesystem Boost::program_options Boost::system Boost::unit_test_framework PRIVATE LibXml2::LibXml2) + # Installation + install(TARGETS iidm-tests + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () -# Installation -install(TARGETS iidm-tests iidm-tests-static - EXPORT iidm-targets - LIBRARY DESTINATION ${INSTALL_LIB_DIR} - ARCHIVE DESTINATION ${INSTALL_LIB_DIR} - RUNTIME DESTINATION ${INSTALL_BIN_DIR} -) +if (BUILD_STATIC_LIBS) + # Static library + add_library(iidm-tests-static STATIC ${IIDM_TEST_SOURCES}) + target_include_directories(iidm-tests-static + INTERFACE + $ + PUBLIC + $ + $ + ) + target_link_libraries(iidm-tests-static PUBLIC iidm-static Boost::filesystem Boost::program_options Boost::system Boost::unit_test_framework PRIVATE LibXml2::LibXml2) + + # Installation + install(TARGETS iidm-tests-static + EXPORT iidm-targets + LIBRARY DESTINATION ${INSTALL_LIB_DIR} + ARCHIVE DESTINATION ${INSTALL_LIB_DIR} + RUNTIME DESTINATION ${INSTALL_BIN_DIR} + ) +endif () install(DIRECTORY ${CMAKE_SOURCE_DIR}/include/powsybl/test DESTINATION ${INSTALL_INCLUDE_DIR}/powsybl diff --git a/src/test/ResourceFixture.cpp b/src/test/ResourceFixture.cpp index 13248bab7..4feb4cf7c 100644 --- a/src/test/ResourceFixture.cpp +++ b/src/test/ResourceFixture.cpp @@ -29,8 +29,7 @@ ResourceFixture::ResourceFixture() { } std::string ResourceFixture::getResource(const std::string& name) const { - boost::filesystem::path path(getOptionValue("resources").as()); - path /= name; + const boost::filesystem::path& path = getResourcePath(name); if (!boost::filesystem::exists(path)) { throw powsybl::AssertionError(stdcxx::format("Unable to find the resource: %1%", path.string())); @@ -47,6 +46,12 @@ std::string ResourceFixture::getResource(const std::string& name) const { return buffer.str(); } +boost::filesystem::path ResourceFixture::getResourcePath(const std::string& name) const { + boost::filesystem::path path(getOptionValue("resources").as()); + path /= name; + return path; +} + } // namespace test } // namespace powsybl diff --git a/src/test/converter/RoundTrip.cpp b/src/test/converter/RoundTrip.cpp index 272e5d60f..5f51f32b0 100644 --- a/src/test/converter/RoundTrip.cpp +++ b/src/test/converter/RoundTrip.cpp @@ -40,11 +40,13 @@ std::string RoundTrip::getVersionDir(const iidm::converter::xml::IidmXmlVersion& std::string RoundTrip::getVersionedNetwork(const std::string& filename, const iidm::converter::xml::IidmXmlVersion& version) { ResourceFixture fixture; - return fixture.getResource(getVersionedNetworkPath(filename, version)); + return fixture.getResource(getVersionDir(version) + filename); } -std::string RoundTrip::getVersionedNetworkPath(const std::string& filename, const iidm::converter::xml::IidmXmlVersion& version) { - return getVersionDir(version) + filename; +boost::filesystem::path RoundTrip::getVersionedNetworkPath(const std::string& filename, const iidm::converter::xml::IidmXmlVersion& version) { + ResourceFixture fixture; + + return fixture.getResourcePath(getVersionDir(version) + filename); } void RoundTrip::roundTripAllPreviousVersionedXmlTest(const std::string& filename) { @@ -65,19 +67,20 @@ void RoundTrip::roundTripVersionedXmlFromMinToCurrentVersionTest(const std::stri } void RoundTrip::roundTripVersionedXmlTest(const std::string& filename, const iidm::converter::xml::IidmXmlVersion& version) { - const auto& writer = [&version](const iidm::Network& n, std::ostream& stream) { + const auto& writer = [&version, &filename](const iidm::Network& n, std::ostream& stream) { iidm::converter::ExportOptions options; options.setVersion(version.toString(".")); - iidm::Network::writeXml(stream, n, options); + iidm::Network::writeXml(filename, stream, n, options); }; - const auto& reader = [](const std::string& xml) { - std::istringstream stream(xml); - return iidm::Network::readXml(stream); + const auto& reader = [&filename](const std::string& xmlBytes) { + std::istringstream stream(xmlBytes); + return iidm::Network::readXml(filename, stream); }; const std::string& expected = getVersionedNetwork(filename, version); - iidm::Network network = iidm::Network::readXml(expected); + std::istringstream stream(expected); + iidm::Network network = iidm::Network::readXml(filename, stream); run(network, writer, reader, compareXml, expected); } @@ -95,13 +98,15 @@ iidm::Network RoundTrip::run(const iidm::Network& network, const Writer& out, co } iidm::Network RoundTrip::runXml(const iidm::Network& network, const std::string& ref) { - const auto& writer = [](const iidm::Network& n, std::ostream& stream) { - iidm::Network::writeXml(stream, n); + const std::string& filename = stdcxx::format("%1%.xiidm", network.getId()); + + const auto& writer = [&filename](const iidm::Network& n, std::ostream& stream) { + iidm::Network::writeXml(filename, stream, n); }; - const auto& reader = [](const std::string& xml) { - std::istringstream stream(xml); - return iidm::Network::readXml(stream); + const auto& reader = [&filename](const std::string& xmlBytes) { + std::istringstream stream(xmlBytes); + return iidm::Network::readXml(filename, stream); }; return run(network, writer, reader, compareXml, ref); diff --git a/src/xml/XmlStreamReader.cpp b/src/xml/XmlStreamReader.cpp index 8a1517482..914a81f2e 100644 --- a/src/xml/XmlStreamReader.cpp +++ b/src/xml/XmlStreamReader.cpp @@ -209,32 +209,32 @@ stdcxx::optional XmlStreamReader::getOptionalAttributeValue(const s bool XmlStreamReader::getOptionalAttributeValue(const std::string& attributeName, bool defaultValue) const { const auto& value = getOptionalAttributeValue(attributeName); - return value.is_initialized() ? *value : defaultValue; + return value ? *value : defaultValue; } std::string XmlStreamReader::getOptionalAttributeValue(const std::string& attributeName, const char* defaultValue) const { const auto& value = getOptionalAttributeValue(attributeName); - return value.is_initialized() ? *value : defaultValue; + return value ? *value : defaultValue; } int XmlStreamReader::getOptionalAttributeValue(const std::string& attributeName, int defaultValue) const { const auto& value = getOptionalAttributeValue(attributeName); - return value.is_initialized() ? *value : defaultValue; + return value ? *value : defaultValue; } double XmlStreamReader::getOptionalAttributeValue(const std::string& attributeName, double defaultValue) const { const auto& value = getOptionalAttributeValue(attributeName); - return value.is_initialized() ? *value : defaultValue; + return value ? *value : defaultValue; } unsigned long XmlStreamReader::getOptionalAttributeValue(const std::string& attributeName, unsigned long defaultValue) const { const auto& value = getOptionalAttributeValue(attributeName); - return value.is_initialized() ? *value : defaultValue; + return value ? *value : defaultValue; } std::string XmlStreamReader::getOptionalAttributeValue(const std::string& attributeName, const std::string& defaultValue) const { const auto& value = getOptionalAttributeValue(attributeName); - return value.is_initialized() ? *value : defaultValue; + return value ? *value : defaultValue; } std::string XmlStreamReader::getPrefix() const { diff --git a/test/iidm/AliasesTest.cpp b/test/iidm/AliasesTest.cpp index e1c6482bd..a1b048c9e 100644 --- a/test/iidm/AliasesTest.cpp +++ b/test/iidm/AliasesTest.cpp @@ -37,7 +37,7 @@ static Network createNetwork() { .add(); VoltageLevel& voltageLevel1 = substation1.newVoltageLevel() .setId("voltageLevel1") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::NODE_BREAKER) .add(); VoltageLevel::NodeBreakerView& topology1 = voltageLevel1.getNodeBreakerView(); @@ -111,10 +111,39 @@ BOOST_AUTO_TEST_CASE(canAddAliases) { BOOST_CHECK(load.getAliases().empty()); load.addAlias("Load alias"); - BOOST_CHECK_EQUAL(1, load.getAliases().size()); - BOOST_CHECK(load.getAliases().find("Load alias") != load.getAliases().end()); + const auto& aliases = load.getAliases(); + BOOST_CHECK_EQUAL(1, boost::size(aliases)); + BOOST_CHECK(std::find(aliases.begin(), aliases.end(), "Load alias") != aliases.end()); BOOST_CHECK_NO_THROW(network.getLoad("Load alias")); BOOST_CHECK(stdcxx::areSame(network.getLoad("Load alias"), load)); + BOOST_CHECK(network.getLoad("load1").getAliasType("Load alias").empty()); +} + +BOOST_AUTO_TEST_CASE(canAddAliasesWithTypes) { + Network network = createNetwork(); + Load& load = network.getLoad("load1"); + BOOST_CHECK(load.getAliases().empty()); + BOOST_CHECK(!load.getAliasFromType("alias type")); + load.addAlias("Load alias", "alias type"); + + POWSYBL_ASSERT_THROW(load.addAlias("Load alias", "alias type"), PowsyblException, "load1 already has an alias of type alias type"); + + load.addAlias("Load alias"); + + const auto& aliases = load.getAliases(); + BOOST_CHECK_EQUAL(1, boost::size(aliases)); + BOOST_CHECK(std::find(aliases.begin(), aliases.end(), "Load alias") != aliases.end()); + BOOST_CHECK(load.getAliasFromType("alias type")); + BOOST_CHECK(std::find(aliases.begin(), aliases.end(), "Load alias") != aliases.end()); + BOOST_CHECK_EQUAL("Load alias", *load.getAliasFromType("alias type")); + BOOST_CHECK_NO_THROW(network.getLoad("Load alias")); + BOOST_CHECK(stdcxx::areSame(load, network.getLoad("Load alias"))); + BOOST_CHECK_EQUAL("alias type", load.getAliasType("Load alias")); + + load.addAlias("Another alias2"); + BOOST_CHECK_EQUAL(2, boost::size(load.getAliases())); + load.removeAlias("Another alias2"); + BOOST_CHECK(load.getAliasFromType("alias type")); } BOOST_AUTO_TEST_CASE(canRemoveAliases) { @@ -124,8 +153,9 @@ BOOST_AUTO_TEST_CASE(canRemoveAliases) { BOOST_CHECK(load.getAliases().empty()); load.addAlias("Load alias"); - BOOST_CHECK_EQUAL(1, load.getAliases().size()); - BOOST_CHECK(load.getAliases().find("Load alias") != load.getAliases().end()); + const auto& aliases = load.getAliases(); + BOOST_CHECK_EQUAL(1, boost::size(aliases)); + BOOST_CHECK(std::find(aliases.begin(), aliases.end(), "Load alias") != aliases.end()); load.removeAlias("Load alias"); BOOST_CHECK(!load.hasAliases()); @@ -148,8 +178,34 @@ BOOST_AUTO_TEST_CASE(silentlyIgnoreAffectingTwiceSameIdToAnObject) { load.addAlias("Load alias"); load.addAlias("Load alias"); - BOOST_CHECK_EQUAL(1, load.getAliases().size()); - BOOST_CHECK(load.getAliases().find("Load alias") != load.getAliases().end()); + const auto& aliases = load.getAliases(); + BOOST_CHECK_EQUAL(1, boost::size(aliases)); + BOOST_CHECK(std::find(aliases.begin(), aliases.end(), "Load alias") != aliases.end()); +} + +BOOST_AUTO_TEST_CASE(ensureAliasUnicityFromId) { + Network network = createNetwork(); + Load& load = network.getLoad("load1"); + load.addAlias("generator1", true); + const auto& aliases = load.getAliases(); + BOOST_CHECK(std::find(aliases.begin(), aliases.end(), "generator1") == aliases.end()); + BOOST_CHECK(std::find(aliases.begin(), aliases.end(), "generator1#0") != aliases.end()); +} + +BOOST_AUTO_TEST_CASE(ensureAliasUnicityFromAlias) { + Network network = createNetwork(); + Load& load = network.getLoad("load1"); + Generator& generator = network.getGenerator("generator1"); + + load.addAlias("alias"); + generator.addAlias("alias", true); + + const auto& loadAliases = load.getAliases(); + BOOST_CHECK(std::find(loadAliases.begin(), loadAliases.end(), "alias") != loadAliases.end()); + + const auto& generatorAliases = generator.getAliases(); + BOOST_CHECK(std::find(generatorAliases.begin(), generatorAliases.end(), "alias") == generatorAliases.end()); + BOOST_CHECK(std::find(generatorAliases.begin(), generatorAliases.end(), "alias#0") != generatorAliases.end()); } BOOST_AUTO_TEST_CASE(failWhenDuplicatedAlias) { @@ -191,6 +247,25 @@ BOOST_AUTO_TEST_CASE(FindIdentifiableFromAlias) { BOOST_CHECK(stdcxx::areSame(load, network.find("Load alias").get())); } +BOOST_AUTO_TEST_CASE(emptyAliasType) { + Network network = createNetwork(); + Load& load = network.getLoad("load1"); + + load.addAlias("Load alias#0"); + BOOST_CHECK_EQUAL(1, boost::size(load.getAliases())); + BOOST_CHECK(load.getAliasType("").empty()); + + load.addAlias("Load alias#0", true); + BOOST_CHECK_EQUAL(2, boost::size(load.getAliases())); + POWSYBL_ASSERT_THROW(load.getAliasFromType(""), PowsyblException, "Alias type must not be empty"); + BOOST_CHECK(!load.getAliasFromType("fake")); + BOOST_CHECK(load.getAliasType("").empty()); + + load.addAlias("Load alias#1", ""); + BOOST_CHECK_EQUAL(3, boost::size(load.getAliases())); + BOOST_CHECK_EQUAL("", load.getAliasType("Load alias#1")); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace iidm diff --git a/test/iidm/BatteryTest.cpp b/test/iidm/BatteryTest.cpp index ab91df297..29bfc1878 100644 --- a/test/iidm/BatteryTest.cpp +++ b/test/iidm/BatteryTest.cpp @@ -36,7 +36,7 @@ Network createBatteryTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); diff --git a/test/iidm/BusBreakerVoltageLevelTest.cpp b/test/iidm/BusBreakerVoltageLevelTest.cpp index 337cb8f1e..75a5350ff 100644 --- a/test/iidm/BusBreakerVoltageLevelTest.cpp +++ b/test/iidm/BusBreakerVoltageLevelTest.cpp @@ -251,7 +251,7 @@ BOOST_AUTO_TEST_CASE(CalculatedBusTopologyTest) { VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -294,7 +294,7 @@ BOOST_AUTO_TEST_CASE(CalculatedBusTopologyTest) { VoltageLevel& vl2 = s.newVoltageLevel() .setId("VL2") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -387,7 +387,7 @@ BOOST_AUTO_TEST_CASE(TerminalTest) { VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -410,7 +410,7 @@ BOOST_AUTO_TEST_CASE(TerminalTest) { VoltageLevel& vl2 = s.newVoltageLevel() .setId("VL2") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); diff --git a/test/iidm/BusTest.cpp b/test/iidm/BusTest.cpp index 5f0b78d6e..b3bf4948d 100644 --- a/test/iidm/BusTest.cpp +++ b/test/iidm/BusTest.cpp @@ -5,11 +5,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include + #include +#include #include #include #include +#include #include #include #include @@ -33,7 +37,14 @@ #include #include #include +#include +#include #include +#include +#include +#include + +#include "NetworkFactory.hpp" namespace powsybl { @@ -48,7 +59,7 @@ Network create() { VoltageLevel& vl1 = s.newVoltageLevel() .setId("VL1") - .setNominalVoltage(400.0) + .setNominalV(400.0) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); @@ -58,7 +69,7 @@ Network create() { VoltageLevel& vl2 = s.newVoltageLevel() .setId("VL2") - .setNominalVoltage(400.0) + .setNominalV(400.0) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); @@ -68,7 +79,7 @@ Network create() { VoltageLevel& vl3 = s.newVoltageLevel() .setId("VL3") - .setNominalVoltage(400.0) + .setNominalV(400.0) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); @@ -81,6 +92,71 @@ Network create() { BOOST_AUTO_TEST_SUITE(BusTestSuite) +BOOST_AUTO_TEST_CASE(testSetterGetter) { + Network network("test", "test"); + Substation& substation = network.newSubstation() + .setCountry(Country::AF) + .setTso("tso") + .setName("sub") + .setId("subId") + .add(); + VoltageLevel& voltageLevel = substation.newVoltageLevel() + .setTopologyKind(TopologyKind::BUS_BREAKER) + .setId("bbVL") + .setName("bbVL_name") + .setNominalV(200.0) + .add(); + // ConfiguredBus + Bus& bus = voltageLevel.getBusBreakerView() + .newBus() + .setName("bus1Name") + .setId("bus1") + .add(); + + BOOST_CHECK_EQUAL("bus1", network.getBusBreakerView().getBus("bus1").get().getId()); + BOOST_CHECK_EQUAL("bus1", bus.getId()); + BOOST_CHECK_EQUAL("bus1Name", bus.getNameOrId()); + + LccConverterStation& lccConverterStation = voltageLevel.newLccConverterStation() + .setId("lcc") + .setName("lcc") + .setBus("bus1") + .setLossFactor(0.011) + .setPowerFactor(0.5) + .setConnectableBus("bus1") + .add(); + VscConverterStation& vscConverterStation = voltageLevel.newVscConverterStation() + .setId("vsc") + .setName("vsc") + .setBus("bus1") + .setLossFactor(0.011) + .setVoltageRegulatorOn(false) + .setReactivePowerSetpoint(1.0) + .setConnectableBus("bus1") + .add(); + BOOST_CHECK_EQUAL(HvdcConverterStation::HvdcType::LCC, lccConverterStation.getHvdcType()); + BOOST_CHECK_EQUAL(HvdcConverterStation::HvdcType::VSC, vscConverterStation.getHvdcType()); + double p1 = 1.0; + double q1 = 2.0; + double p2 = 10.0; + double q2 = 20.0; + lccConverterStation.getTerminal().setP(p1); + lccConverterStation.getTerminal().setQ(q1); + vscConverterStation.getTerminal().setP(p2); + vscConverterStation.getTerminal().setQ(q2); + + BOOST_CHECK(stdcxx::areSame(voltageLevel, bus.getVoltageLevel())); + BOOST_CHECK(stdcxx::areSame(network, bus.getNetwork())); + POWSYBL_ASSERT_THROW(bus.setV(-1.0), PowsyblException, "Bus 'bus1': voltage cannot be < 0"); + bus.setV(200.0); + BOOST_CHECK_CLOSE(200.0, bus.getV(), std::numeric_limits::epsilon()); + bus.setAngle(30.0); + BOOST_CHECK_CLOSE(30.0, bus.getAngle(), std::numeric_limits::epsilon()); + + BOOST_CHECK_CLOSE(p1 + p2, bus.getP(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(q1 + q2, bus.getQ(), std::numeric_limits::epsilon()); +} + BOOST_AUTO_TEST_CASE(range_batteries) { Network network = create(); auto& bus = network.get("Bus1"); @@ -374,6 +450,250 @@ BOOST_AUTO_TEST_CASE(range_vscConverterStations) { BOOST_CHECK_EQUAL(1, boost::size(cVL.getVscConverterStations())); } +class TerminalTopologyVisitor : public AbstractTerminalTopologyVisitor { +public: + TerminalTopologyVisitor() = default; + + const std::map>& getConnectables() const { + return m_equipments; + } + + void visitTerminal(const Terminal& terminal) override { + m_equipments[terminal.getConnectable().get().getType()].emplace(terminal.getConnectable().get().getId()); + } + +private: + std::map> m_equipments; +}; + +BOOST_AUTO_TEST_CASE(TerminalVisitorEurostag) { + Network network = powsybl::network::EurostagFactory::createTutorial1Network(); + + TerminalTopologyVisitor connectableEquipmentsVisitor; + + network.get("NHV2").visitConnectedOrConnectableEquipments(connectableEquipmentsVisitor); + BOOST_CHECK_EQUAL(2, boost::size(connectableEquipmentsVisitor.getConnectables())); + + std::set connectedLines_NHV2 = { "NHV1_NHV2_1", "NHV1_NHV2_2" }; + BOOST_CHECK(connectedLines_NHV2 == connectableEquipmentsVisitor.getConnectables().find(ConnectableType::LINE)->second); + + std::set connected2WT_NHV2 = { "NHV2_NLOAD" }; + BOOST_CHECK(connected2WT_NHV2 == connectableEquipmentsVisitor.getConnectables().find(ConnectableType::TWO_WINDINGS_TRANSFORMER)->second); + + TerminalTopologyVisitor connectedEquipmentsVisitor; + Line& line = network.getLine("NHV1_NHV2_1"); + line.getTerminal1().disconnect(); + + network.get("NHV1").visitConnectedEquipments(connectedEquipmentsVisitor); + BOOST_CHECK_EQUAL(2, boost::size(connectedEquipmentsVisitor.getConnectables())); + + std::set connectedLines_NHV1 = { "NHV1_NHV2_2" }; + BOOST_CHECK(connectedLines_NHV1 == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::LINE)->second); + + std::set connected2WT_NHV1 = { "NGEN_NHV1" }; + BOOST_CHECK(connected2WT_NHV1 == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::TWO_WINDINGS_TRANSFORMER)->second); +} + +BOOST_AUTO_TEST_CASE(TerminalVisitorAllBbk) { + Network network = create(); + + VoltageLevel& vl = network.getVoltageLevel("VL1"); + + vl.newBattery() + .setId("BATTERY") + .setBus("Bus1") + .setP0(0.0) + .setQ0(0.0) + .setMinP(0.0) + .setMaxP(100.0) + .add(); + + vl.newStaticVarCompensator() + .setId("SVC") + .setBus("Bus1") + .setBmin(0.0) + .setBmax(10.0) + .setRegulationMode(StaticVarCompensator::RegulationMode::OFF) + .add(); + + vl.newVscConverterStation() + .setId("VSC_S") + .setBus("Bus1") + .setLossFactor(0.6) + .setVoltageRegulatorOn(false) + .setReactivePowerSetpoint(50.0) + .add(); + + vl.newShuntCompensator() + .setId("SHUNT") + .setBus("Bus1") + .setSectionCount(1) + .newLinearModel() + .setBPerSection(0.25) + .setGPerSection(0.75) + .setMaximumSectionCount(3) + .add() + .add(); + + vl.newLoad() + .setId("LOAD") + .setBus("Bus1") + .setP0(0.0) + .setQ0(0.0) + .add(); + + network.newLine() + .setId("LINE") + .setVoltageLevel1("VL1") + .setBus1("Bus1") + .setVoltageLevel2("VL2") + .setBus2("Bus2") + .setR(1.0) + .setX(0.1) + .setB1(0.00005) + .setB2(0.00005) + .setG1(0.00005) + .setG2(0.00005) + .add(); + + vl.newLccConverterStation() + .setId("LCC_S") + .setBus("Bus1") + .setLossFactor(0.6) + .setPowerFactor(1.0) + .add(); + + vl.newGenerator() + .setId("GENERATOR") + .setBus("Bus1") + .setMinP(0) + .setMaxP(100) + .setTargetP(90) + .setTargetQ(35) + .setVoltageRegulatorOn(false) + .add(); + + vl.newDanglingLine() + .setId("DANGLINE_LINE") + .setBus("Bus1") + .setP0(0.0) + .setQ0(0.0) + .setR(1.0) + .setX(0.1) + .setG(0.00005) + .setB(0.00005) + .add(); + + network.getSubstation("S").newTwoWindingsTransformer() + .setId("2WT") + .setVoltageLevel1("VL1") + .setBus1("Bus1") + .setVoltageLevel2("VL2") + .setBus2("Bus2") + .setR(1.0) + .setX(0.1) + .setB(0.00005) + .setG(0.00005) + .setRatedU1(1.0) + .setRatedU2(1.0) + .add(); + + network.getSubstation("S").newThreeWindingsTransformer() + .setId("3WT") + .newLeg1() + .setVoltageLevel("VL1") + .setBus("Bus1") + .setR(1.0) + .setX(0.1) + .setB(0.00005) + .setG(0.00005) + .setRatedU(1.0) + .add() + .newLeg2() + .setVoltageLevel("VL2") + .setBus("Bus2") + .setR(1.1) + .setX(0.11) + .setG(0.0) + .setB(0.0) + .setRatedU(1.1) + .add() + .newLeg3() + .setVoltageLevel("VL3") + .setBus("Bus3") + .setR(1.2) + .setX(0.12) + .setG(0.0) + .setB(0.0) + .setRatedU(1.2) + .add() + .add(); + + TerminalTopologyVisitor connectedEquipmentsVisitor; + + network.get("Bus1").visitConnectedEquipments(connectedEquipmentsVisitor); + BOOST_CHECK_EQUAL(10, boost::size(connectedEquipmentsVisitor.getConnectables())); + + std::set connectedLines = { "LINE" }; + BOOST_CHECK(connectedLines == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::LINE)->second); + + std::set connected2WT = { "2WT" }; + BOOST_CHECK(connected2WT == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::TWO_WINDINGS_TRANSFORMER)->second); + + std::set connected3WT = { "3WT" }; + BOOST_CHECK(connected3WT == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::THREE_WINDINGS_TRANSFORMER)->second); + + std::set connectedGenerators = { "GENERATOR" }; + BOOST_CHECK(connectedGenerators == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::GENERATOR)->second); + + std::set connectedBatteries = { "BATTERY" }; + BOOST_CHECK(connectedBatteries == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::BATTERY)->second); + + std::set connectedLoads = { "LOAD" }; + BOOST_CHECK(connectedLoads == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::LOAD)->second); + + std::set connectedShunts = { "SHUNT" }; + BOOST_CHECK(connectedShunts == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::SHUNT_COMPENSATOR)->second); + + std::set connectedDanglingLines = { "DANGLINE_LINE" }; + BOOST_CHECK(connectedDanglingLines == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::DANGLING_LINE)->second); + + std::set connectedSvc = { "SVC" }; + BOOST_CHECK(connectedSvc == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::STATIC_VAR_COMPENSATOR)->second); + + std::set connectedHvdc = { "VSC_S", "LCC_S" }; + BOOST_CHECK(connectedHvdc == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::HVDC_CONVERTER_STATION)->second); + + // visit Bus2 + TerminalTopologyVisitor bus2Visitor; + network.get("Bus2").visitConnectedEquipments(bus2Visitor); + std::set connected3WT_Buses12 = { "3WT" }; + BOOST_CHECK(connected3WT_Buses12 == bus2Visitor.getConnectables().find(ConnectableType::THREE_WINDINGS_TRANSFORMER)->second); + + // visit Bus3 + TerminalTopologyVisitor bus3Visitor; + network.get("Bus3").visitConnectedEquipments(bus3Visitor); + std::set connected3WT_Buses123 = { "3WT" }; + BOOST_CHECK(connected3WT_Buses123 == bus3Visitor.getConnectables().find(ConnectableType::THREE_WINDINGS_TRANSFORMER)->second); + + // visit VoltageLevel + TerminalTopologyVisitor voltageLevelVisitor; + vl.visitEquipments(voltageLevelVisitor); + BOOST_CHECK_EQUAL(10, boost::size(voltageLevelVisitor.getConnectables())); +} + +BOOST_FIXTURE_TEST_CASE(TerminalVisitorBusbarSection, test::ResourceFixture) { + Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath("fictitiousSwitchRef.xml", converter::xml::IidmXmlVersion::V1_4())); + + TerminalTopologyVisitor connectedEquipmentsVisitor; + + network.getBusbarSection("D").getTerminal().getBusBreakerView().getBus().get().visitConnectedOrConnectableEquipments(connectedEquipmentsVisitor); + BOOST_CHECK_EQUAL(1, boost::size(connectedEquipmentsVisitor.getConnectables())); + + std::set connectedBbs = { "D" }; + BOOST_CHECK(connectedBbs == connectedEquipmentsVisitor.getConnectables().find(ConnectableType::BUSBAR_SECTION)->second); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace iidm diff --git a/test/iidm/CMakeLists.txt b/test/iidm/CMakeLists.txt index f8f078863..78bd10a4d 100644 --- a/test/iidm/CMakeLists.txt +++ b/test/iidm/CMakeLists.txt @@ -17,6 +17,7 @@ set(UNIT_TEST_SOURCES CurrentLimitsTest.cpp DanglingLineTest.cpp EnergySourceTest.cpp + ExtensionTest.cpp ExtensionAdderTest.cpp GeneratorTest.cpp HvdcLineTest.cpp @@ -39,6 +40,7 @@ set(UNIT_TEST_SOURCES ThreeWindingsTransformerTest.cpp TieLineTest.cpp TwoWindingsTransformerTest.cpp + VariantManagerTest.cpp VoltageLevelTest.cpp VscConverterStationTest.cpp @@ -46,6 +48,7 @@ set(UNIT_TEST_SOURCES converter/ExportOptionsTest.cpp converter/FakeAnonymizerTest.cpp converter/ImportOptionsTest.cpp + converter/SimpleAnonymizerTest.cpp extensions/LoadDetailTest.cpp extensions/SlackTerminalTest.cpp @@ -54,8 +57,10 @@ set(UNIT_TEST_SOURCES ) add_executable(unit-tests-iidm ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-iidm PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-iidm PRIVATE iidm-tests) +if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-iidm PRIVATE BOOST_TEST_DYN_LINK) +endif () +target_link_libraries(unit-tests-iidm PRIVATE iidm-tests${TARGET_POSTFIX}) add_test(NAME iidm COMMAND unit-tests-iidm -- --resources=${CMAKE_SOURCE_DIR}/test/resources) diff --git a/test/iidm/ComponentsTest.cpp b/test/iidm/ComponentsTest.cpp index 99cc14687..ca2131dce 100644 --- a/test/iidm/ComponentsTest.cpp +++ b/test/iidm/ComponentsTest.cpp @@ -35,7 +35,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl1 = substation.newVoltageLevel() .setId("VL1") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); Bus& vl1Bus1 = vl1.getBusBreakerView().newBus() @@ -52,7 +52,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl2 = substation.newVoltageLevel() .setId("VL2") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .add(); Bus& vl2Bus1 = vl2.getBusBreakerView().newBus() @@ -69,7 +69,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl3 = substation.newVoltageLevel() .setId("VL3") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(90.0) + .setNominalV(90.0) .add(); Bus& vl3Bus1 = vl3.getBusBreakerView().newBus() @@ -117,7 +117,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl4 = substation2.newVoltageLevel() .setId("VL4") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); Bus& vl4Bus1 = vl4.getBusBreakerView().newBus() @@ -134,7 +134,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl5 = substation2.newVoltageLevel() .setId("VL5") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .add(); Bus& vl5Bus1 = vl5.getBusBreakerView().newBus() @@ -183,7 +183,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl6 = substation3.newVoltageLevel() .setId("VL6") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); Bus& vl6Bus1 = vl6.getBusBreakerView().newBus() @@ -242,7 +242,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl7 = substation4.newVoltageLevel() .setId("VL7") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); Bus& vl7Bus1 = vl7.getBusBreakerView().newBus() @@ -270,14 +270,14 @@ Network createComponentsTestNetworkBB() { .setConverterStationId1("LCC1") .setConverterStationId2("LCC2") .setMaxP(12.0) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setR(14.0) .add(); VoltageLevel& vl8 = substation4.newVoltageLevel() .setId("VL8") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .add(); Bus& vl8Bus1 = vl8.getBusBreakerView().newBus() @@ -298,7 +298,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl9 = substation5.newVoltageLevel() .setId("VL9") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); Bus& vl9Bus1 = vl9.getBusBreakerView().newBus() @@ -329,7 +329,7 @@ Network createComponentsTestNetworkBB() { VoltageLevel& vl10 = substation5.newVoltageLevel() .setId("VL10") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .add(); Bus& vl10Bus1 = vl10.getBusBreakerView().newBus() @@ -369,7 +369,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl1 = substation.newVoltageLevel() .setId("VL1") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); vl1.newLoad() @@ -390,7 +390,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl2 = substation.newVoltageLevel() .setId("VL2") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .add(); vl2.newLoad() @@ -419,7 +419,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl3 = substation.newVoltageLevel() .setId("VL3") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(90.0) + .setNominalV(90.0) .add(); vl3.newLoad() @@ -472,7 +472,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl4 = substation2.newVoltageLevel() .setId("VL4") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); vl4.newLoad() @@ -501,7 +501,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl5 = substation2.newVoltageLevel() .setId("VL5") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .add(); vl5.newLoad() @@ -562,7 +562,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl6 = substation3.newVoltageLevel() .setId("VL6") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); vl6.newLoad() @@ -635,7 +635,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl7 = substation4.newVoltageLevel() .setId("VL7") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); vl7.newLoad() @@ -677,14 +677,14 @@ Network createComponentsTestNetworkNB() { .setConverterStationId1("VSC1") .setConverterStationId2("VSC2") .setMaxP(12.0) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setR(14.0) .add(); VoltageLevel& vl8 = substation4.newVoltageLevel() .setId("VL8") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .add(); vl8.newLoad() @@ -709,7 +709,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl9 = substation5.newVoltageLevel() .setId("VL9") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .add(); vl9.newLoad() @@ -744,7 +744,7 @@ Network createComponentsTestNetworkNB() { VoltageLevel& vl10 = substation5.newVoltageLevel() .setId("VL10") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .add(); vl10.newLoad() @@ -791,7 +791,7 @@ Network createMultiConnectedComponentsNetwork() { .add(); VoltageLevel& vl1 = s1.newVoltageLevel() .setId("B") - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(0.0) .setTopologyKind(TopologyKind::NODE_BREAKER) .add(); @@ -822,7 +822,7 @@ Network createMultiConnectedComponentsNetwork() { .add(); VoltageLevel& vl2 = s2.newVoltageLevel() .setId("G") - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(0.0) .setTopologyKind(TopologyKind::NODE_BREAKER) .add(); @@ -891,7 +891,7 @@ Network createNetworkWithHvdcLine() { .add(); VoltageLevel& vl1 = s1.newVoltageLevel() .setId("VL1") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl1.getBusBreakerView().newBus() @@ -903,7 +903,7 @@ Network createNetworkWithHvdcLine() { .add(); VoltageLevel& vl2 = s2.newVoltageLevel() .setId("VL2") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::NODE_BREAKER) .add(); vl2.getNodeBreakerView().newBusbarSection() @@ -969,7 +969,7 @@ Network createNetworkWithHvdcLine() { .setConverterStationId1("C1") .setConverterStationId2("C2") .setR(1) - .setNominalVoltage(400) + .setNominalV(400) .setConvertersMode(HvdcLine::ConvertersMode::SIDE_1_INVERTER_SIDE_2_RECTIFIER) .setMaxP(300.0) .setActivePowerSetpoint(280) diff --git a/test/iidm/CurrentLimitsTest.cpp b/test/iidm/CurrentLimitsTest.cpp index 21c9c8988..e0a462ec0 100644 --- a/test/iidm/CurrentLimitsTest.cpp +++ b/test/iidm/CurrentLimitsTest.cpp @@ -40,7 +40,7 @@ Network createCurrentLimitsTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -53,7 +53,7 @@ Network createCurrentLimitsTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -73,7 +73,7 @@ Network createCurrentLimitsTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -86,7 +86,7 @@ Network createCurrentLimitsTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); diff --git a/test/iidm/DanglingLineTest.cpp b/test/iidm/DanglingLineTest.cpp index 6b5e08938..cca4f38d5 100644 --- a/test/iidm/DanglingLineTest.cpp +++ b/test/iidm/DanglingLineTest.cpp @@ -33,7 +33,7 @@ Network createDanglingLineTestNetwork(bool withGeneration) { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); diff --git a/test/iidm/ExtensionTest.cpp b/test/iidm/ExtensionTest.cpp new file mode 100644 index 000000000..7b800ad63 --- /dev/null +++ b/test/iidm/ExtensionTest.cpp @@ -0,0 +1,48 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include + +namespace powsybl { + +namespace iidm { + +BOOST_AUTO_TEST_SUITE(ExtensionTestSuite) + +BOOST_AUTO_TEST_CASE(getExtensionByName) { + Network network = powsybl::network::EurostagFactory::createTutorial1Network(); + Load& load = network.getLoad("LOAD"); + load.addExtension(stdcxx::make_unique(load)); + const Load& cLoad = load; + + BOOST_CHECK(!cLoad.getExtensionByName("test")); + BOOST_CHECK(!load.getExtensionByName("test")); + + BOOST_CHECK(cLoad.getExtensionByName("loadFoo")); + BOOST_CHECK(load.getExtensionByName("loadFoo")); + + BOOST_CHECK(!cLoad.getExtensionByName("loadFoo")); + BOOST_CHECK(!load.getExtensionByName("loadFoo")); + + auto cExt = cLoad.getExtensionByName("loadFoo"); + auto ext = load.getExtensionByName("loadFoo"); + BOOST_CHECK(cExt); + BOOST_CHECK(ext); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace iidm + +} // namespace powsybl diff --git a/test/iidm/GeneratorTest.cpp b/test/iidm/GeneratorTest.cpp index 01cd78b2b..1e34362ab 100644 --- a/test/iidm/GeneratorTest.cpp +++ b/test/iidm/GeneratorTest.cpp @@ -36,7 +36,7 @@ Network createGeneratorTestNetwork() { VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .setFictitious(false) diff --git a/test/iidm/HvdcLineTest.cpp b/test/iidm/HvdcLineTest.cpp index f575feb38..1795d81fb 100644 --- a/test/iidm/HvdcLineTest.cpp +++ b/test/iidm/HvdcLineTest.cpp @@ -35,7 +35,7 @@ Network createHvdcLineTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -75,7 +75,7 @@ Network createHvdcLineTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -112,7 +112,7 @@ Network createHvdcLineTestNetwork() { .setConverterStationId1("LCC1") .setConverterStationId2("LCC2") .setMaxP(12.0) - .setNominalVoltage(13.0) + .setNominalV(13.0) .setR(14.0) .add(); @@ -141,7 +141,7 @@ BOOST_AUTO_TEST_CASE(adder) { adder.setConvertersMode(HvdcLine::ConvertersMode::SIDE_1_INVERTER_SIDE_2_RECTIFIER); POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "hvdcLine 'HVDC1': Nominal voltage is undefined"); - adder.setNominalVoltage(30.0); + adder.setNominalV(30.0); POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "hvdcLine 'HVDC1': invalid value (nan) for active power setpoint"); adder.setActivePowerSetpoint(40.0); @@ -169,7 +169,8 @@ BOOST_AUTO_TEST_CASE(adder) { } BOOST_AUTO_TEST_CASE(constructor) { - const Network& network = createHvdcLineTestNetwork(); + Network network = createHvdcLineTestNetwork(); + const Network& cNetwork = network; BOOST_CHECK_EQUAL(1UL, boost::size(network.getHvdcLines())); const HvdcLine& hvdc = network.getHvdcLine("HVDC1"); @@ -180,9 +181,30 @@ BOOST_AUTO_TEST_CASE(constructor) { BOOST_CHECK_EQUAL("LCC1", hvdc.getConverterStation1().get().getId()); BOOST_CHECK_EQUAL("LCC2", hvdc.getConverterStation2().get().getId()); BOOST_CHECK_CLOSE(12.0, hvdc.getMaxP(), std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(13.0, hvdc.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(13.0, hvdc.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(14.0, hvdc.getR(), std::numeric_limits::epsilon()); BOOST_TEST(stdcxx::areSame(network, hvdc.getNetwork())); + + const LccConverterStation& lcc1 = network.getLccConverterStation("LCC1"); + const LccConverterStation& lcc2 = network.getLccConverterStation("LCC2"); + const VscConverterStation& vsc1 = network.getVscConverterStation("VSC1"); + const VscConverterStation& vsc2 = network.getVscConverterStation("VSC2"); + + BOOST_CHECK(stdcxx::areSame(hvdc, network.getHvdcLine(lcc1))); + BOOST_CHECK(stdcxx::areSame(hvdc, network.getHvdcLine(lcc2))); + BOOST_CHECK(stdcxx::areSame(hvdc, cNetwork.getHvdcLine(lcc1))); + BOOST_CHECK(stdcxx::areSame(hvdc, cNetwork.getHvdcLine(lcc2))); + POWSYBL_ASSERT_THROW(network.getHvdcLine(vsc1), PowsyblException, "Unable to find to the HVDC line for station 'VSC1'"); + POWSYBL_ASSERT_THROW(network.getHvdcLine(vsc2), PowsyblException, "Unable to find to the HVDC line for station 'VSC2'"); + + BOOST_CHECK(stdcxx::areSame(hvdc, network.findHvdcLine(lcc1).get())); + BOOST_CHECK(stdcxx::areSame(hvdc, network.findHvdcLine(lcc2).get())); + BOOST_CHECK(stdcxx::areSame(hvdc, cNetwork.findHvdcLine(lcc1).get())); + BOOST_CHECK(stdcxx::areSame(hvdc, cNetwork.findHvdcLine(lcc2).get())); + BOOST_CHECK(!network.findHvdcLine(vsc1)); + BOOST_CHECK(!network.findHvdcLine(vsc2)); + BOOST_CHECK(!cNetwork.findHvdcLine(vsc1)); + BOOST_CHECK(!cNetwork.findHvdcLine(vsc2)); } BOOST_AUTO_TEST_CASE(integrity) { @@ -220,9 +242,9 @@ BOOST_AUTO_TEST_CASE(integrity) { BOOST_CHECK_CLOSE(200.0, hvdc.getMaxP(), std::numeric_limits::epsilon()); POWSYBL_ASSERT_THROW(hvdc.setMaxP(stdcxx::nan()), ValidationException, "hvdcLine 'HVDC1': invalid value (nan) for maximum P"); - BOOST_TEST(stdcxx::areSame(hvdc, hvdc.setNominalVoltage(300.0))); - BOOST_CHECK_CLOSE(300.0, hvdc.getNominalVoltage(), std::numeric_limits::epsilon()); - POWSYBL_ASSERT_THROW(hvdc.setNominalVoltage(stdcxx::nan()), ValidationException, "hvdcLine 'HVDC1': Nominal voltage is undefined"); + BOOST_TEST(stdcxx::areSame(hvdc, hvdc.setNominalV(300.0))); + BOOST_CHECK_CLOSE(300.0, hvdc.getNominalV(), std::numeric_limits::epsilon()); + POWSYBL_ASSERT_THROW(hvdc.setNominalV(stdcxx::nan()), ValidationException, "hvdcLine 'HVDC1': Nominal voltage is undefined"); BOOST_TEST(stdcxx::areSame(hvdc, hvdc.setR(400.0))); BOOST_CHECK_CLOSE(400.0, hvdc.getR(), std::numeric_limits::epsilon()); @@ -257,9 +279,9 @@ BOOST_AUTO_TEST_CASE(multivariant) { BOOST_CHECK_EQUAL("LCC1", hvdc.getConverterStation1().get().getId()); BOOST_CHECK_EQUAL("LCC2", hvdc.getConverterStation2().get().getId()); BOOST_CHECK_CLOSE(12.0, hvdc.getMaxP(), std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(13.0, hvdc.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(13.0, hvdc.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(14.0, hvdc.getR(), std::numeric_limits::epsilon()); - hvdc.setActivePowerSetpoint(100.0).setR(200.0).setMaxP(300.0).setConvertersMode(HvdcLine::ConvertersMode::SIDE_1_INVERTER_SIDE_2_RECTIFIER).setNominalVoltage(400.0); + hvdc.setActivePowerSetpoint(100.0).setR(200.0).setMaxP(300.0).setConvertersMode(HvdcLine::ConvertersMode::SIDE_1_INVERTER_SIDE_2_RECTIFIER).setNominalV(400.0); BOOST_CHECK_EQUAL("HVDC1", hvdc.getId()); BOOST_CHECK_CLOSE(100.0, hvdc.getActivePowerSetpoint(), std::numeric_limits::epsilon()); @@ -267,7 +289,7 @@ BOOST_AUTO_TEST_CASE(multivariant) { BOOST_CHECK_EQUAL("LCC1", hvdc.getConverterStation1().get().getId()); BOOST_CHECK_EQUAL("LCC2", hvdc.getConverterStation2().get().getId()); BOOST_CHECK_CLOSE(300.0, hvdc.getMaxP(), std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(400.0, hvdc.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(400.0, hvdc.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(200.0, hvdc.getR(), std::numeric_limits::epsilon()); network.getVariantManager().setWorkingVariant("s2"); @@ -277,9 +299,9 @@ BOOST_AUTO_TEST_CASE(multivariant) { BOOST_CHECK_EQUAL("LCC1", hvdc.getConverterStation1().get().getId()); BOOST_CHECK_EQUAL("LCC2", hvdc.getConverterStation2().get().getId()); BOOST_CHECK_CLOSE(300.0, hvdc.getMaxP(), std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(400.0, hvdc.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(400.0, hvdc.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(200.0, hvdc.getR(), std::numeric_limits::epsilon()); - hvdc.setActivePowerSetpoint(150.0).setR(250.0).setMaxP(350.0).setConvertersMode(HvdcLine::ConvertersMode::SIDE_1_INVERTER_SIDE_2_RECTIFIER).setNominalVoltage(450.0); + hvdc.setActivePowerSetpoint(150.0).setR(250.0).setMaxP(350.0).setConvertersMode(HvdcLine::ConvertersMode::SIDE_1_INVERTER_SIDE_2_RECTIFIER).setNominalV(450.0); BOOST_CHECK_EQUAL("HVDC1", hvdc.getId()); BOOST_CHECK_CLOSE(150.0, hvdc.getActivePowerSetpoint(), std::numeric_limits::epsilon()); @@ -287,7 +309,7 @@ BOOST_AUTO_TEST_CASE(multivariant) { BOOST_CHECK_EQUAL("LCC1", hvdc.getConverterStation1().get().getId()); BOOST_CHECK_EQUAL("LCC2", hvdc.getConverterStation2().get().getId()); BOOST_CHECK_CLOSE(350.0, hvdc.getMaxP(), std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(450.0, hvdc.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(450.0, hvdc.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(250.0, hvdc.getR(), std::numeric_limits::epsilon()); network.getVariantManager().setWorkingVariant(VariantManager::getInitialVariantId()); @@ -297,7 +319,7 @@ BOOST_AUTO_TEST_CASE(multivariant) { BOOST_CHECK_EQUAL("LCC1", hvdc.getConverterStation1().get().getId()); BOOST_CHECK_EQUAL("LCC2", hvdc.getConverterStation2().get().getId()); BOOST_CHECK_CLOSE(350.0, hvdc.getMaxP(), std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(450.0, hvdc.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(450.0, hvdc.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(250.0, hvdc.getR(), std::numeric_limits::epsilon()); network.getVariantManager().removeVariant("s1"); @@ -311,7 +333,7 @@ BOOST_AUTO_TEST_CASE(multivariant) { BOOST_CHECK_EQUAL("LCC1", hvdc.getConverterStation1().get().getId()); BOOST_CHECK_EQUAL("LCC2", hvdc.getConverterStation2().get().getId()); BOOST_CHECK_CLOSE(350.0, hvdc.getMaxP(), std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(450.0, hvdc.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(450.0, hvdc.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(250.0, hvdc.getR(), std::numeric_limits::epsilon()); network.getVariantManager().removeVariant("s3"); diff --git a/test/iidm/LineTest.cpp b/test/iidm/LineTest.cpp index 73f54bf5c..256a24f0d 100644 --- a/test/iidm/LineTest.cpp +++ b/test/iidm/LineTest.cpp @@ -36,7 +36,7 @@ Network createLineTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -49,7 +49,7 @@ Network createLineTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -69,7 +69,7 @@ Network createLineTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -82,7 +82,7 @@ Network createLineTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); diff --git a/test/iidm/NetworkFactory.cpp b/test/iidm/NetworkFactory.cpp index 5fc4feae6..8bf1e4f5c 100644 --- a/test/iidm/NetworkFactory.cpp +++ b/test/iidm/NetworkFactory.cpp @@ -34,7 +34,7 @@ Network createHvdcConverterStationTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -79,7 +79,7 @@ Network createNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -102,7 +102,7 @@ Network createNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -120,7 +120,7 @@ Terminal& getTerminalFromNetwork2() { VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); diff --git a/test/iidm/NetworkTest.cpp b/test/iidm/NetworkTest.cpp index 0b36d982d..2ad68a524 100644 --- a/test/iidm/NetworkTest.cpp +++ b/test/iidm/NetworkTest.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -46,7 +47,7 @@ Network createTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -59,7 +60,7 @@ Network createTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -95,7 +96,7 @@ Network createTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -146,7 +147,7 @@ Network createTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -245,7 +246,7 @@ Network createTestNodeBreakerNetwork() { .setId("VL5") .setName("VL5_NAME") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -378,6 +379,9 @@ BOOST_AUTO_TEST_CASE(country) { BOOST_CHECK_EQUAL(4, network.getSubstationCount()); BOOST_CHECK_EQUAL(2, network.getCountryCount()); + const std::set& countries = { Country::ES, Country::FR }; + BOOST_CHECK(countries == network.getCountries()); + network.getSubstation("S2").setCountry(stdcxx::optional()); BOOST_CHECK_EQUAL(1, network.getCountryCount()); } diff --git a/test/iidm/NodeBreakerVoltageLevelTest.cpp b/test/iidm/NodeBreakerVoltageLevelTest.cpp index 1175d5c27..5b57adcf2 100644 --- a/test/iidm/NodeBreakerVoltageLevelTest.cpp +++ b/test/iidm/NodeBreakerVoltageLevelTest.cpp @@ -41,7 +41,7 @@ Network createCalculatedBusSwitchTestNetwork() { VoltageLevel& vl = s1.newVoltageLevel() .setId("B") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(0.0) .setHighVoltageLimit(250.0) .add(); @@ -75,7 +75,7 @@ Network createCalculatedBusSwitchTestNetwork() { VoltageLevel& vl2 = s2.newVoltageLevel() .setId("G") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(0.0) .setHighVoltageLimit(250.0) .add(); @@ -144,7 +144,7 @@ Network createCalculatedBusSwitchTestNetwork() { VoltageLevel& vl3 = s3.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -189,7 +189,7 @@ void createNetwork(Network& network) { .add(); VoltageLevel& vl = s.newVoltageLevel() .setId(S5_10K_V) - .setNominalVoltage(10.0) + .setNominalV(10.0) .setTopologyKind(TopologyKind::NODE_BREAKER) .add(); vl.getNodeBreakerView().newBusbarSection() @@ -257,7 +257,7 @@ void createNetwork(Network& network) { .add(); s4.newVoltageLevel() .setId("S4 10kV") - .setNominalVoltage(10.0) + .setNominalV(10.0) .setTopologyKind(TopologyKind::NODE_BREAKER) .add(); network.newLine() @@ -564,7 +564,7 @@ BOOST_AUTO_TEST_CASE(calculatedBusBreakerTopology) { VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -614,7 +614,7 @@ BOOST_AUTO_TEST_CASE(calculatedBusBreakerTopology) { VoltageLevel& vl2 = s.newVoltageLevel() .setId("VL2") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -742,7 +742,7 @@ BOOST_AUTO_TEST_CASE(CalculatedBusTopology) { VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -789,7 +789,7 @@ BOOST_AUTO_TEST_CASE(CalculatedBusTopology) { VoltageLevel& vl2 = s.newVoltageLevel() .setId("VL2") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -859,7 +859,7 @@ BOOST_AUTO_TEST_CASE(CalculatedBusTopology2) { VoltageLevel& vl = s.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .add(); auto& l1 = vl.newLoad() @@ -884,7 +884,7 @@ BOOST_AUTO_TEST_CASE(CalculatedBusTopology3) { VoltageLevel& vl1 = s1.newVoltageLevel() .setId("VL") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(1.0) + .setNominalV(1.0) .add(); vl1.getNodeBreakerView().newBusbarSection() @@ -998,7 +998,7 @@ BOOST_AUTO_TEST_CASE(TerminalTest) { .setId("VL") .setName("VL_name") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -1020,11 +1020,16 @@ BOOST_AUTO_TEST_CASE(TerminalTest) { vl.getNodeBreakerView().newBreaker() .setId("SWB1") .setNode1(1) - .setNode2(2) + .setNode2(99) .setRetained(false) .setOpen(false) .add(); + vl.getNodeBreakerView().newInternalConnection() + .setNode1(99) + .setNode2(2) + .add(); + Load& l1 = vl.newLoad() .setId("LOAD1") .setNode(2) @@ -1062,7 +1067,7 @@ BOOST_AUTO_TEST_CASE(TerminalTest) { VoltageLevel& vl2 = s.newVoltageLevel() .setId("VL2") .setTopologyKind(TopologyKind::NODE_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); @@ -1084,7 +1089,7 @@ BOOST_AUTO_TEST_CASE(TerminalTest) { VoltageLevel& vl3 = s.newVoltageLevel() .setId("VL3") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(400.0) + .setNominalV(400.0) .setLowVoltageLimit(380.0) .setHighVoltageLimit(420.0) .add(); diff --git a/test/iidm/PhaseTapChangerTest.cpp b/test/iidm/PhaseTapChangerTest.cpp index 1e2640810..3530cbb0a 100644 --- a/test/iidm/PhaseTapChangerTest.cpp +++ b/test/iidm/PhaseTapChangerTest.cpp @@ -43,7 +43,7 @@ Network createPhaseTapChangerTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -66,7 +66,7 @@ Network createPhaseTapChangerTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -96,7 +96,7 @@ Network createPhaseTapChangerTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -109,7 +109,7 @@ Network createPhaseTapChangerTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); diff --git a/test/iidm/RatioTapChangerTest.cpp b/test/iidm/RatioTapChangerTest.cpp index b5d0b89b4..d4a6f3862 100644 --- a/test/iidm/RatioTapChangerTest.cpp +++ b/test/iidm/RatioTapChangerTest.cpp @@ -43,7 +43,7 @@ Network createRatioTapChangerTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -66,7 +66,7 @@ Network createRatioTapChangerTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -96,7 +96,7 @@ Network createRatioTapChangerTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -109,7 +109,7 @@ Network createRatioTapChangerTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); diff --git a/test/iidm/ShuntCompensatorTest.cpp b/test/iidm/ShuntCompensatorTest.cpp index a4583392c..ff7b34474 100644 --- a/test/iidm/ShuntCompensatorTest.cpp +++ b/test/iidm/ShuntCompensatorTest.cpp @@ -37,7 +37,7 @@ Network createShuntCompensatorTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); diff --git a/test/iidm/StaticVarCompensatorTest.cpp b/test/iidm/StaticVarCompensatorTest.cpp index 19c834c93..bdbea9a5a 100644 --- a/test/iidm/StaticVarCompensatorTest.cpp +++ b/test/iidm/StaticVarCompensatorTest.cpp @@ -36,7 +36,7 @@ Network createStaticVarCompensatorTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -69,7 +69,7 @@ Network createSvcNetwork() { .add(); VoltageLevel& vl1 = s1.newVoltageLevel() .setId("VL1") - .setNominalVoltage(380) + .setNominalV(380) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl1.getBusBreakerView().newBus() @@ -91,7 +91,7 @@ Network createSvcNetwork() { .add(); VoltageLevel& vl2 = s2.newVoltageLevel() .setId("VL2") - .setNominalVoltage(380) + .setNominalV(380) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl2.getBusBreakerView().newBus() diff --git a/test/iidm/SubstationTest.cpp b/test/iidm/SubstationTest.cpp index c430040e1..3cf403226 100644 --- a/test/iidm/SubstationTest.cpp +++ b/test/iidm/SubstationTest.cpp @@ -8,12 +8,15 @@ #include #include +#include +#include #include #include #include #include #include #include +#include #include #include @@ -37,7 +40,7 @@ Network createSubstationTransformerCountTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -50,7 +53,7 @@ Network createSubstationTransformerCountTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -63,7 +66,7 @@ Network createSubstationTransformerCountTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -83,7 +86,7 @@ Network createSubstationTransformerCountTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -443,6 +446,66 @@ BOOST_AUTO_TEST_CASE(threeWindingsTransformerCount) { BOOST_CHECK_EQUAL(5UL, substation.getThreeWindingsTransformerCount()); } +BOOST_AUTO_TEST_CASE(remove) { + Network network = powsybl::network::FourSubstationsNodeBreakerFactory::create(); + Substation& s1 = network.getSubstation("S1"); + Substation& s2 = network.getSubstation("S2"); + Substation& s3 = network.getSubstation("S3"); + Substation& s4 = network.getSubstation("S4"); + + POWSYBL_ASSERT_THROW(s1.remove(), PowsyblException, "The substation S1 is still connected to another substation"); + POWSYBL_ASSERT_THROW(s2.remove(), PowsyblException, "The substation S2 is still connected to another substation"); + POWSYBL_ASSERT_THROW(s3.remove(), PowsyblException, "The substation S3 is still connected to another substation"); + POWSYBL_ASSERT_THROW(s4.remove(), PowsyblException, "The substation S4 is still connected to another substation"); + + VoltageLevel& s1VL1 = network.getVoltageLevel("S1VL1"); + + POWSYBL_ASSERT_THROW(s1VL1.remove(), AssertionError, "The voltage level 'S1VL1' cannot be removed because of a remaining TWO_WINDINGS_TRANSFORMER"); + + POWSYBL_ASSERT_THROW(s1VL1.remove(), AssertionError, "The voltage level 'S1VL1' cannot be removed because of a remaining TWO_WINDINGS_TRANSFORMER"); + network.getTwoWindingsTransformer("TWT").remove(); + + s1VL1.remove(); + POWSYBL_ASSERT_THROW(s1.remove(), PowsyblException, "The substation S1 is still connected to another substation"); + + VoltageLevel& s2vl1 = network.getVoltageLevel("S2VL1"); + POWSYBL_ASSERT_THROW(s2vl1.remove(), AssertionError, "The voltage level 'S2VL1' cannot be removed because of a remaining HVDC line"); + + VoltageLevel& s3VL1 = network.getVoltageLevel("S3VL1"); + POWSYBL_ASSERT_THROW(s3VL1.remove(), AssertionError, "The voltage level 'S3VL1' cannot be removed because of a remaining LINE"); + + VoltageLevel& s4VL1 = network.getVoltageLevel("S4VL1"); + POWSYBL_ASSERT_THROW(s4VL1.remove(), AssertionError, "The voltage level 'S4VL1' cannot be removed because of a remaining LINE"); + + // s3 and s4 are linked through LINE_S3S4 + network.getLine("LINE_S3S4").remove(); + + // s4 is removable + s4.remove(); + + // s2 and s3 are linked by Line LINE_S2S3 + network.getLine("LINE_S2S3").remove(); + + POWSYBL_ASSERT_THROW(network.getVscConverterStation("VSC1").remove(), PowsyblException, "vscConverterStation 'VSC1': Impossible to remove this converter station (still attached to 'HVDC1')"); + + // s3 linked to s1 thought HVDC2 + network.getHvdcLine("HVDC2").remove(); + network.getLccConverterStation("LCC1").remove(); + network.getLccConverterStation("LCC2").remove(); + + // s3 is isolated => removable + s3.remove(); + + // s1 and s2 are linked by HVDC1 + network.getHvdcLine("HVDC1").remove(); + network.getVscConverterStation("VSC1").remove(); + network.getVscConverterStation("VSC2").remove(); + + // s1 and s2 are isolated => removable + s1.remove(); + s2.remove(); +} + BOOST_AUTO_TEST_SUITE_END() } // namespace iidm diff --git a/test/iidm/ThreeWindingsTransformerTest.cpp b/test/iidm/ThreeWindingsTransformerTest.cpp index ea3e802b7..bbd18731c 100644 --- a/test/iidm/ThreeWindingsTransformerTest.cpp +++ b/test/iidm/ThreeWindingsTransformerTest.cpp @@ -12,6 +12,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,6 +30,10 @@ namespace powsybl { namespace iidm { +bool operator!=(const ThreeWindingsTransformer::Leg& leg1, const ThreeWindingsTransformer::Leg& leg2) { + return !stdcxx::areSame(leg1, leg2); +} + Network createThreeWindingsTransformerTestNetwork() { Network network("test", "test"); Substation& substation = network.newSubstation() @@ -41,7 +47,7 @@ Network createThreeWindingsTransformerTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -64,7 +70,7 @@ Network createThreeWindingsTransformerTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -87,7 +93,7 @@ Network createThreeWindingsTransformerTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -107,7 +113,7 @@ Network createThreeWindingsTransformerTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -155,34 +161,106 @@ Network createThreeWindingsTransformerTestNetwork() { return network; } +void addPhaseTapChangerLeg2(ThreeWindingsTransformer& transformer, Terminal& terminal) { + transformer.getLeg2().newPhaseTapChanger() + .setTapPosition(2L) + .setLowTapPosition(1L) + .beginStep() + .setAlpha(9.0) + .setB(10.0) + .setG(11.0) + .setR(12.0) + .setRho(13.0) + .setX(14.0) + .endStep() + .beginStep() + .setAlpha(14.5) + .setB(15.0) + .setG(16.0) + .setR(17.0) + .setRho(18.0) + .setX(19.0) + .endStep() + .beginStep() + .setAlpha(20.5) + .setB(20.0) + .setG(21.0) + .setR(22.0) + .setRho(23.0) + .setX(24.0) + .endStep() + .setRegulationMode(PhaseTapChanger::RegulationMode::ACTIVE_POWER_CONTROL) + .setRegulating(true) + .setRegulationTerminal(stdcxx::ref(terminal)) + .setRegulationValue(25.0) + .setTargetDeadband(0.0) + .add(); +} + +void addPhaseTapChangerLeg3(ThreeWindingsTransformer& transformer, Terminal& terminal) { + transformer.getLeg3().newPhaseTapChanger() + .setTapPosition(-2L) + .setLowTapPosition(-3L) + .beginStep() + .setAlpha(-9.0) + .setB(-10.0) + .setG(-11.0) + .setR(-12.0) + .setRho(-13.0) + .setX(-14.0) + .endStep() + .beginStep() + .setAlpha(-14.5) + .setB(-15.0) + .setG(-16.0) + .setR(-17.0) + .setRho(-18.0) + .setX(-19.0) + .endStep() + .beginStep() + .setAlpha(-20.5) + .setB(-20.0) + .setG(-21.0) + .setR(-22.0) + .setRho(-23.0) + .setX(-24.0) + .endStep() + .setRegulationMode(PhaseTapChanger::RegulationMode::ACTIVE_POWER_CONTROL) + .setRegulating(false) + .setRegulationTerminal(stdcxx::ref(terminal)) + .setRegulationValue(25.0) + .setTargetDeadband(0.0) + .add(); +} + void addRatioTapChangerLeg2(ThreeWindingsTransformer& transformer, Terminal& terminal) { transformer.getLeg2().newRatioTapChanger() .setTapPosition(2L) .setLowTapPosition(1L) .beginStep() - .setB(10.0) - .setG(11.0) - .setR(12.0) - .setRho(13.0) - .setX(14.0) + .setB(10.0) + .setG(11.0) + .setR(12.0) + .setRho(13.0) + .setX(14.0) .endStep() .beginStep() - .setB(15.0) - .setG(16.0) - .setR(17.0) - .setRho(18.0) - .setX(19.0) + .setB(15.0) + .setG(16.0) + .setR(17.0) + .setRho(18.0) + .setX(19.0) .endStep() .beginStep() - .setB(20.0) - .setG(21.0) - .setR(22.0) - .setRho(23.0) - .setX(24.0) + .setB(20.0) + .setG(21.0) + .setR(22.0) + .setRho(23.0) + .setX(24.0) .endStep() .setLoadTapChangingCapabilities(true) .setRegulating(true) - .setRegulationTerminal(stdcxx::ref(terminal)) + .setRegulationTerminal(stdcxx::ref(terminal)) .setTargetV(25.0) .setTargetDeadband(1.0) .add(); @@ -193,29 +271,29 @@ void addRatioTapChangerLeg3(ThreeWindingsTransformer& transformer, Terminal& ter .setTapPosition(-2L) .setLowTapPosition(-3L) .beginStep() - .setB(-10.0) - .setG(-11.0) - .setR(-12.0) - .setRho(-13.0) - .setX(-14.0) + .setB(-10.0) + .setG(-11.0) + .setR(-12.0) + .setRho(-13.0) + .setX(-14.0) .endStep() .beginStep() - .setB(-15.0) - .setG(-16.0) - .setR(-17.0) - .setRho(-18.0) - .setX(-19.0) + .setB(-15.0) + .setG(-16.0) + .setR(-17.0) + .setRho(-18.0) + .setX(-19.0) .endStep() .beginStep() - .setB(-20.0) - .setG(-21.0) - .setR(-22.0) - .setRho(-23.0) - .setX(-24.0) + .setB(-20.0) + .setG(-21.0) + .setR(-22.0) + .setRho(-23.0) + .setX(-24.0) .endStep() .setLoadTapChangingCapabilities(true) .setRegulating(false) - .setRegulationTerminal(stdcxx::ref(terminal)) + .setRegulationTerminal(stdcxx::ref(terminal)) .setTargetV(26.0) .setTargetDeadband(2.0) .add(); @@ -329,6 +407,14 @@ BOOST_AUTO_TEST_CASE(constructor) { BOOST_TEST(stdcxx::areSame(cTerminal3, cLeg3.getTerminal())); BOOST_TEST(stdcxx::areSame(network, leg3.getNetwork())); BOOST_TEST(stdcxx::areSame(network, cLeg3.getNetwork())); + + std::vector> expected = {leg1, leg2, leg3}; + + const auto& legs = transformer.getLegs(); + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), legs.begin(), legs.end()); + + const auto& cLegs = cTransformer.getLegs(); + BOOST_CHECK_EQUAL_COLLECTIONS(expected.begin(), expected.end(), cLegs.begin(), cLegs.end()); } BOOST_AUTO_TEST_CASE(integrity) { @@ -544,31 +630,31 @@ BOOST_AUTO_TEST_CASE(adders) { ThreeWindingsTransformerAdder::LegAdder l1Adder = adder.newLeg1(); POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer 'TWT': leg 1 is not defined"); - POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1: r is not set"); + POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: r is not set"); l1Adder.setR(1.0); - POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1: x is not set"); + POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: x is not set"); l1Adder.setX(1.1); - POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1: g is not set"); + POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: g is not set"); l1Adder.setG(1.3); - POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1: b is not set"); + POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: b is not set"); l1Adder.setB(1.4); - POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1: rated U is not set"); + POWSYBL_ASSERT_THROW(l1Adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: rated U is not set"); BOOST_CHECK_NO_THROW(l1Adder.setRatedU(1.2).add()); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1: voltage level is not set"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: voltage level is not set"); l1Adder.setVoltageLevel("INVALID").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1: voltage level 'INVALID' not found"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: voltage level 'INVALID' not found"); l1Adder.setVoltageLevel("VL1").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1: voltage level shall belong to the substation 'S2'"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: voltage level shall belong to the substation 'S2'"); l1Adder.setVoltageLevel("VL4").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1: connectable bus is not set"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: connectable bus is not set"); l1Adder.setConnectableBus("VL4_BUS1").add(); adder.newLeg1() @@ -581,7 +667,7 @@ BOOST_AUTO_TEST_CASE(adders) { .setConnectableBus("VL4_BUS1") .setNode(1UL) .add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1: connection node and connection bus are exclusives"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg1 in substation S2: connection node and connection bus are exclusives"); adder.newLeg1() .setR(1.0) .setX(1.1) @@ -596,28 +682,28 @@ BOOST_AUTO_TEST_CASE(adders) { ThreeWindingsTransformerAdder::LegAdder l2Adder = adder.newLeg2(); POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer 'TWT': leg 2 is not defined"); - POWSYBL_ASSERT_THROW(l2Adder.add(), ValidationException, "3 windings transformer leg2: r is not set"); + POWSYBL_ASSERT_THROW(l2Adder.add(), ValidationException, "3 windings transformer leg2 in substation S2: r is not set"); l2Adder.setR(2.0); - POWSYBL_ASSERT_THROW(l2Adder.add(), ValidationException, "3 windings transformer leg2: x is not set"); + POWSYBL_ASSERT_THROW(l2Adder.add(), ValidationException, "3 windings transformer leg2 in substation S2: x is not set"); l2Adder.setX(2.1); - POWSYBL_ASSERT_THROW(l2Adder.add(), ValidationException, "3 windings transformer leg2: rated U is not set"); + POWSYBL_ASSERT_THROW(l2Adder.add(), ValidationException, "3 windings transformer leg2 in substation S2: rated U is not set"); BOOST_CHECK_NO_THROW(l2Adder.setRatedU(2.2).add()); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2: voltage level is not set"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2 in substation S2: voltage level is not set"); l2Adder.setVoltageLevel("INVALID").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2: voltage level 'INVALID' not found"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2 in substation S2: voltage level 'INVALID' not found"); l2Adder.setVoltageLevel("VL1").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2: voltage level shall belong to the substation 'S2'"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2 in substation S2: voltage level shall belong to the substation 'S2'"); l2Adder.setVoltageLevel("VL4").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2: connectable bus is not set"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2 in substation S2: connectable bus is not set"); l2Adder.setConnectableBus("VL4_BUS1"); - POWSYBL_ASSERT_THROW(l2Adder.setRatedS(-1.0).add(), ValidationException, "3 windings transformer leg2: Invalid rated S value: -1"); + POWSYBL_ASSERT_THROW(l2Adder.setRatedS(-1.0).add(), ValidationException, "3 windings transformer leg2 in substation S2: Invalid rated S value: -1"); l2Adder.setRatedS(1.0).add(); adder.newLeg2() @@ -630,7 +716,7 @@ BOOST_AUTO_TEST_CASE(adders) { .setConnectableBus("VL4_BUS1") .setNode(1UL) .add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2: connection node and connection bus are exclusives"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg2 in substation S2: connection node and connection bus are exclusives"); adder.newLeg2() .setR(2.0) .setX(2.1) @@ -645,25 +731,25 @@ BOOST_AUTO_TEST_CASE(adders) { ThreeWindingsTransformerAdder::LegAdder l3Adder = adder.newLeg3(); POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer 'TWT': leg 3 is not defined"); - POWSYBL_ASSERT_THROW(l3Adder.add(), ValidationException, "3 windings transformer leg3: r is not set"); + POWSYBL_ASSERT_THROW(l3Adder.add(), ValidationException, "3 windings transformer leg3 in substation S2: r is not set"); l3Adder.setR(3.0); - POWSYBL_ASSERT_THROW(l3Adder.add(), ValidationException, "3 windings transformer leg3: x is not set"); + POWSYBL_ASSERT_THROW(l3Adder.add(), ValidationException, "3 windings transformer leg3 in substation S2: x is not set"); l3Adder.setX(3.1); - POWSYBL_ASSERT_THROW(l3Adder.add(), ValidationException, "3 windings transformer leg3: rated U is not set"); + POWSYBL_ASSERT_THROW(l3Adder.add(), ValidationException, "3 windings transformer leg3 in substation S2: rated U is not set"); BOOST_CHECK_NO_THROW(l3Adder.setRatedU(3.2).add()); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3: voltage level is not set"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3 in substation S2: voltage level is not set"); l3Adder.setVoltageLevel("INVALID").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3: voltage level 'INVALID' not found"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3 in substation S2: voltage level 'INVALID' not found"); l3Adder.setVoltageLevel("VL1").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3: voltage level shall belong to the substation 'S2'"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3 in substation S2: voltage level shall belong to the substation 'S2'"); l3Adder.setVoltageLevel("VL4").add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3: connectable bus is not set"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3 in substation S2: connectable bus is not set"); l3Adder.setConnectableBus("VL4_BUS1"); adder.newLeg3() @@ -676,7 +762,7 @@ BOOST_AUTO_TEST_CASE(adders) { .setConnectableBus("VL4_BUS1") .setNode(1UL) .add(); - POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3: connection node and connection bus are exclusives"); + POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "3 windings transformer leg3 in substation S2: connection node and connection bus are exclusives"); adder.newLeg3() .setR(3.0) .setX(3.1) @@ -709,7 +795,7 @@ BOOST_AUTO_TEST_CASE(adders) { BOOST_CHECK_CLOSE(2.2, twt.getLeg1().getG(), std::numeric_limits::epsilon()); } -BOOST_AUTO_TEST_CASE(multivariant) { +BOOST_AUTO_TEST_CASE(multivariantRTC) { Network network = createThreeWindingsTransformerTestNetwork(); ThreeWindingsTransformer& transformer = network.getThreeWindingsTransformer("3WT_VL1_VL2_VL3"); Terminal& terminal = network.getLoad("LOAD1").getTerminal(); @@ -973,6 +1059,246 @@ BOOST_AUTO_TEST_CASE(multivariant) { BOOST_CHECK_EQUAL(1UL, network.getVariantManager().getVariantArraySize()); } +BOOST_AUTO_TEST_CASE(multivariantPTC) { + Network network = createThreeWindingsTransformerTestNetwork(); + ThreeWindingsTransformer& transformer = network.getThreeWindingsTransformer("3WT_VL1_VL2_VL3"); + Terminal& terminal = network.getLoad("LOAD1").getTerminal(); + Terminal& terminal2 = network.getLoad("LOAD2").getTerminal(); + addPhaseTapChangerLeg2(transformer, terminal); + addPhaseTapChangerLeg3(transformer, terminal2); + + ThreeWindingsTransformer::Leg& leg1 = transformer.getLeg1(); + ThreeWindingsTransformer::Leg& leg2 = transformer.getLeg2(); + ThreeWindingsTransformer::Leg& leg3 = transformer.getLeg3(); + PhaseTapChanger& phaseTapChangerLeg2 = leg2.getPhaseTapChanger(); + PhaseTapChanger& phaseTapChangerLeg3 = leg3.getPhaseTapChanger(); + + network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), {"s1", "s2"}); + BOOST_CHECK_EQUAL(3UL, network.getVariantManager().getVariantArraySize()); + + network.getVariantManager().setWorkingVariant("s1"); + + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg1", leg1.toString()); + BOOST_CHECK_CLOSE(1.3, leg1.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.4, leg1.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.6, leg1.getG(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.7, leg1.getB(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.1, leg1.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg1.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg2", leg2.toString()); + BOOST_CHECK_CLOSE(2.3, leg2.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.4, leg2.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.1, leg2.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg2.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg3", leg3.toString()); + BOOST_CHECK_CLOSE(3.3, leg3.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.4, leg3.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.1, leg3.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg3.getCurrentLimits()); + + BOOST_CHECK_EQUAL(1L, phaseTapChangerLeg2.getLowTapPosition()); + BOOST_CHECK_EQUAL(3L, phaseTapChangerLeg2.getHighTapPosition()); + BOOST_CHECK_EQUAL(2L, phaseTapChangerLeg2.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg2.getStepCount()); + BOOST_TEST(phaseTapChangerLeg2.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal, phaseTapChangerLeg2.getRegulationTerminal().get())); + + BOOST_CHECK_EQUAL(-3L, phaseTapChangerLeg3.getLowTapPosition()); + BOOST_CHECK_EQUAL(-1L, phaseTapChangerLeg3.getHighTapPosition()); + BOOST_CHECK_EQUAL(-2L, phaseTapChangerLeg3.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg3.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg3.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal2, phaseTapChangerLeg3.getRegulationTerminal().get())); + + leg1.setR(1.31).setX(1.41).setG(1.61).setB(1.71).setRatedU(1.11); + leg2.setR(2.31).setX(2.41).setRatedU(2.11); + leg3.setR(3.31).setX(3.41).setRatedU(3.11); + phaseTapChangerLeg2.setTapPosition(1L).setRegulating(false).setRegulationTerminal(stdcxx::ref(terminal2)); + phaseTapChangerLeg3.setTapPosition(-3L).setRegulating(false).setRegulationTerminal(stdcxx::ref(terminal)); + + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg1", leg1.toString()); + BOOST_CHECK_CLOSE(1.31, leg1.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.41, leg1.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.61, leg1.getG(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.71, leg1.getB(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.11, leg1.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg1.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg2", leg2.toString()); + BOOST_CHECK_CLOSE(2.31, leg2.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.41, leg2.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.11, leg2.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg2.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg3", leg3.toString()); + BOOST_CHECK_CLOSE(3.31, leg3.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.41, leg3.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.11, leg3.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg3.getCurrentLimits()); + + BOOST_CHECK_EQUAL(1L, phaseTapChangerLeg2.getLowTapPosition()); + BOOST_CHECK_EQUAL(3L, phaseTapChangerLeg2.getHighTapPosition()); + BOOST_CHECK_EQUAL(1L, phaseTapChangerLeg2.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg2.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg2.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal2, phaseTapChangerLeg2.getRegulationTerminal().get())); + + BOOST_CHECK_EQUAL(-3L, phaseTapChangerLeg3.getLowTapPosition()); + BOOST_CHECK_EQUAL(-1L, phaseTapChangerLeg3.getHighTapPosition()); + BOOST_CHECK_EQUAL(-3L, phaseTapChangerLeg3.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg3.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg3.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal, phaseTapChangerLeg3.getRegulationTerminal().get())); + + network.getVariantManager().setWorkingVariant("s2"); + + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg1", leg1.toString()); + BOOST_CHECK_CLOSE(1.31, leg1.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.41, leg1.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.61, leg1.getG(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.71, leg1.getB(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.11, leg1.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg1.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg2", leg2.toString()); + BOOST_CHECK_CLOSE(2.31, leg2.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.41, leg2.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.11, leg2.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg2.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg3", leg3.toString()); + BOOST_CHECK_CLOSE(3.31, leg3.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.41, leg3.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.11, leg3.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg3.getCurrentLimits()); + + BOOST_CHECK_EQUAL(1L, phaseTapChangerLeg2.getLowTapPosition()); + BOOST_CHECK_EQUAL(3L, phaseTapChangerLeg2.getHighTapPosition()); + BOOST_CHECK_EQUAL(2L, phaseTapChangerLeg2.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg2.getStepCount()); + BOOST_TEST(phaseTapChangerLeg2.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal2, phaseTapChangerLeg2.getRegulationTerminal().get())); + + BOOST_CHECK_EQUAL(-3L, phaseTapChangerLeg3.getLowTapPosition()); + BOOST_CHECK_EQUAL(-1L, phaseTapChangerLeg3.getHighTapPosition()); + BOOST_CHECK_EQUAL(-2L, phaseTapChangerLeg3.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg3.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg3.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal, phaseTapChangerLeg3.getRegulationTerminal().get())); + + leg1.setRatedU(1.12).setR(1.32).setX(1.42).setG(1.62).setB(1.72); + leg2.setRatedU(2.12).setR(2.32).setX(2.42); + leg3.setRatedU(3.12).setR(3.32).setX(3.42); + phaseTapChangerLeg2.setTapPosition(3L).setRegulationTerminal(stdcxx::ref(terminal)).setRegulating(false); + phaseTapChangerLeg3.setTapPosition(-1L).setRegulationTerminal(stdcxx::ref(terminal2)).setRegulating(false); + + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg1", leg1.toString()); + BOOST_CHECK_CLOSE(1.32, leg1.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.42, leg1.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.62, leg1.getG(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.72, leg1.getB(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.12, leg1.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg1.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg2", leg2.toString()); + BOOST_CHECK_CLOSE(2.32, leg2.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.42, leg2.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.12, leg2.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg2.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg3", leg3.toString()); + BOOST_CHECK_CLOSE(3.32, leg3.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.42, leg3.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.12, leg3.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg3.getCurrentLimits()); + + BOOST_CHECK_EQUAL(1L, phaseTapChangerLeg2.getLowTapPosition()); + BOOST_CHECK_EQUAL(3L, phaseTapChangerLeg2.getHighTapPosition()); + BOOST_CHECK_EQUAL(3L, phaseTapChangerLeg2.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg2.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg2.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal, phaseTapChangerLeg2.getRegulationTerminal().get())); + + BOOST_CHECK_EQUAL(-3L, phaseTapChangerLeg3.getLowTapPosition()); + BOOST_CHECK_EQUAL(-1L, phaseTapChangerLeg3.getHighTapPosition()); + BOOST_CHECK_EQUAL(-1L, phaseTapChangerLeg3.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg3.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg3.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal2, phaseTapChangerLeg3.getRegulationTerminal().get())); + + network.getVariantManager().setWorkingVariant(VariantManager::getInitialVariantId()); + + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg1", leg1.toString()); + BOOST_CHECK_CLOSE(1.32, leg1.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.42, leg1.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.62, leg1.getG(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.72, leg1.getB(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.12, leg1.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg1.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg2", leg2.toString()); + BOOST_CHECK_CLOSE(2.32, leg2.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.42, leg2.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.12, leg2.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg2.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg3", leg3.toString()); + BOOST_CHECK_CLOSE(3.32, leg3.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.42, leg3.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.12, leg3.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg3.getCurrentLimits()); + + BOOST_CHECK_EQUAL(1L, phaseTapChangerLeg2.getLowTapPosition()); + BOOST_CHECK_EQUAL(3L, phaseTapChangerLeg2.getHighTapPosition()); + BOOST_CHECK_EQUAL(2L, phaseTapChangerLeg2.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg2.getStepCount()); + BOOST_TEST(phaseTapChangerLeg2.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal, phaseTapChangerLeg2.getRegulationTerminal().get())); + + BOOST_CHECK_EQUAL(-3L, phaseTapChangerLeg3.getLowTapPosition()); + BOOST_CHECK_EQUAL(-1L, phaseTapChangerLeg3.getHighTapPosition()); + BOOST_CHECK_EQUAL(-2L, phaseTapChangerLeg3.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg3.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg3.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal2, phaseTapChangerLeg3.getRegulationTerminal().get())); + + network.getVariantManager().removeVariant("s1"); + BOOST_CHECK_EQUAL(3UL, network.getVariantManager().getVariantArraySize()); + + network.getVariantManager().cloneVariant("s2", "s3"); + network.getVariantManager().setWorkingVariant("s3"); + + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg1", leg1.toString()); + BOOST_CHECK_CLOSE(1.32, leg1.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.42, leg1.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.62, leg1.getG(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.72, leg1.getB(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(1.12, leg1.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg1.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg2", leg2.toString()); + BOOST_CHECK_CLOSE(2.32, leg2.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.42, leg2.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(2.12, leg2.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg2.getCurrentLimits()); + BOOST_CHECK_EQUAL("3WT_VL1_VL2_VL3 leg3", leg3.toString()); + BOOST_CHECK_CLOSE(3.32, leg3.getR(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.42, leg3.getX(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(3.12, leg3.getRatedU(), std::numeric_limits::epsilon()); + BOOST_TEST(!leg3.getCurrentLimits()); + + BOOST_CHECK_EQUAL(1L, phaseTapChangerLeg2.getLowTapPosition()); + BOOST_CHECK_EQUAL(3L, phaseTapChangerLeg2.getHighTapPosition()); + BOOST_CHECK_EQUAL(3L, phaseTapChangerLeg2.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg2.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg2.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal, phaseTapChangerLeg2.getRegulationTerminal().get())); + + BOOST_CHECK_EQUAL(-3L, phaseTapChangerLeg3.getLowTapPosition()); + BOOST_CHECK_EQUAL(-1L, phaseTapChangerLeg3.getHighTapPosition()); + BOOST_CHECK_EQUAL(-1L, phaseTapChangerLeg3.getTapPosition()); + BOOST_CHECK_EQUAL(3, phaseTapChangerLeg3.getStepCount()); + BOOST_TEST(!phaseTapChangerLeg3.isRegulating()); + BOOST_TEST(stdcxx::areSame(terminal2, phaseTapChangerLeg3.getRegulationTerminal().get())); + + network.getVariantManager().removeVariant("s3"); + BOOST_CHECK_EQUAL(3UL, network.getVariantManager().getVariantArraySize()); + + network.getVariantManager().removeVariant("s2"); + BOOST_CHECK_EQUAL(1UL, network.getVariantManager().getVariantArraySize()); +} + BOOST_AUTO_TEST_CASE(voltageLevel) { Network network = createThreeWindingsTransformerTestNetwork(); Load& load = network.getLoad("LOAD1"); diff --git a/test/iidm/TieLineTest.cpp b/test/iidm/TieLineTest.cpp index 76d54de23..e4716bb38 100644 --- a/test/iidm/TieLineTest.cpp +++ b/test/iidm/TieLineTest.cpp @@ -36,7 +36,7 @@ Network createTieLineTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -49,7 +49,7 @@ Network createTieLineTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -69,7 +69,7 @@ Network createTieLineTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -82,7 +82,7 @@ Network createTieLineTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); diff --git a/test/iidm/TwoWindingsTransformerTest.cpp b/test/iidm/TwoWindingsTransformerTest.cpp index a43a7ab15..1a16cb3d7 100644 --- a/test/iidm/TwoWindingsTransformerTest.cpp +++ b/test/iidm/TwoWindingsTransformerTest.cpp @@ -42,7 +42,7 @@ Network createTwoWindingsTransformerTestNetwork() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -65,7 +65,7 @@ Network createTwoWindingsTransformerTestNetwork() { .setId("VL2") .setName("VL2_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); @@ -95,7 +95,7 @@ Network createTwoWindingsTransformerTestNetwork() { .setId("VL3") .setName("VL3_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -108,7 +108,7 @@ Network createTwoWindingsTransformerTestNetwork() { .setId("VL4") .setName("VL4_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(225.0) + .setNominalV(225.0) .setLowVoltageLimit(200.0) .setHighVoltageLimit(260.0) .add(); diff --git a/test/iidm/VariantManagerTest.cpp b/test/iidm/VariantManagerTest.cpp new file mode 100644 index 000000000..96fac0f73 --- /dev/null +++ b/test/iidm/VariantManagerTest.cpp @@ -0,0 +1,187 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include +#include + +#include "NetworkFactory.hpp" + +namespace powsybl { + +namespace iidm { + +BOOST_AUTO_TEST_SUITE(VariantManagerTestSuite) + +BOOST_AUTO_TEST_CASE(cloneVariant) { + Network network = createNetwork(); + + BOOST_CHECK_EQUAL(1UL, network.getVariantManager().getVariantArraySize()); + + Load& load1 = network.getLoad("LOAD1"); + BOOST_CHECK_CLOSE(50, load1.getP0(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(40, load1.getQ0(), std::numeric_limits::epsilon()); + + network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), {"s1"}); + BOOST_CHECK_EQUAL(2UL, network.getVariantManager().getVariantArraySize()); + + POWSYBL_ASSERT_THROW(network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), "s1"), PowsyblException, "Target variant 's1' already exists"); + BOOST_CHECK_EQUAL(2UL, network.getVariantManager().getVariantArraySize()); + + POWSYBL_ASSERT_THROW(network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), {"s1", "s2"}), PowsyblException, "Target variant 's1' already exists"); + BOOST_CHECK_EQUAL(2UL, network.getVariantManager().getVariantArraySize()); + + network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), "s2"); + BOOST_CHECK_EQUAL(3UL, network.getVariantManager().getVariantArraySize()); + + network.getVariantManager().setWorkingVariant("s2"); + BOOST_CHECK_CLOSE(50, load1.getP0(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(40, load1.getQ0(), std::numeric_limits::epsilon()); + load1.setP0(150); + load1.setQ0(120); + BOOST_CHECK_CLOSE(150, load1.getP0(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(120, load1.getQ0(), std::numeric_limits::epsilon()); + + network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), "s2", true); + BOOST_CHECK_EQUAL(3UL, network.getVariantManager().getVariantArraySize()); + BOOST_CHECK_CLOSE(50, load1.getP0(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(40, load1.getQ0(), std::numeric_limits::epsilon()); + + network.getVariantManager().removeVariant("s2"); + BOOST_CHECK_EQUAL(2UL, network.getVariantManager().getVariantArraySize()); + + network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), {"s1", "s2"}, true); + BOOST_CHECK_EQUAL(3UL, network.getVariantManager().getVariantArraySize()); + network.getVariantManager().setWorkingVariant("s1"); + BOOST_CHECK_CLOSE(50, load1.getP0(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(40, load1.getQ0(), std::numeric_limits::epsilon()); + network.getVariantManager().setWorkingVariant("s2"); + BOOST_CHECK_CLOSE(50, load1.getP0(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(40, load1.getQ0(), std::numeric_limits::epsilon()); +} + +BOOST_AUTO_TEST_CASE(multithread) { + Network network = createNetwork(); + + Load& load1 = network.getLoad("LOAD1"); + + BOOST_CHECK(!network.getVariantManager().isVariantMultiThreadAccessAllowed()); + + const unsigned long NB_VARIANTS = 100000UL; + + std::vector variantsArray; + for (unsigned long i = 0UL; i < NB_VARIANTS; ++i) { + const std::string& variantName = std::to_string(i); + network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), variantName, true); + variantsArray.emplace_back(variantName); + } + + // comment these 2 lines to reproduce the fact that default variant manager is not thread safe + network.getVariantManager().allowVariantMultiThreadAccess(true); + BOOST_CHECK(network.getVariantManager().isVariantMultiThreadAccessAllowed()); + + BOOST_CHECK_EQUAL(0UL, network.getVariantManager().getVariantIndex()); + BOOST_CHECK_EQUAL(VariantManager::getInitialVariantId(), network.getVariantManager().getWorkingVariantId()); + + const auto& updateEvenVariants = [&network, &load1, &variantsArray]() { + for (unsigned long i = 0UL; i < variantsArray.size(); ++i) { + if (i % 2 == 0) { + network.getVariantManager().setWorkingVariant(variantsArray.at(i)); + load1.setP0(3.0 * i); + load1.setQ0(5.0 * i); + } + } + }; + + const auto& updateOddVariants = [&network, &load1, &variantsArray]() { + for (unsigned long i = 0UL; i < variantsArray.size(); ++i) { + if (i % 2 != 0) { + network.getVariantManager().setWorkingVariant(variantsArray.at(i)); + load1.setP0(2.0 * i); + load1.setQ0(4.0 * i); + } + } + }; + + std::thread launcherS1(updateEvenVariants); + std::thread launcherS2(updateOddVariants); + launcherS1.join(); + launcherS2.join(); + + unsigned long index = 0UL; + for (const std::string& variant : variantsArray) { + network.getVariantManager().setWorkingVariant(variant); + if (index % 2 == 0) { + BOOST_CHECK_CLOSE(3 * index, load1.getP0(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(5 * index, load1.getQ0(), std::numeric_limits::epsilon()); + } else { + BOOST_CHECK_CLOSE(2 * index, load1.getP0(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(4 * index, load1.getQ0(), std::numeric_limits::epsilon()); + } + index++; + } +} + +BOOST_AUTO_TEST_CASE(testVariantIndexKept) { + Network network = createNetwork(); + + network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), "S1", true); + network.getVariantManager().setWorkingVariant("S1"); + network.getVariantManager().allowVariantMultiThreadAccess(true); + BOOST_CHECK_EQUAL("S1", network.getVariantManager().getWorkingVariantId()); + + const auto& updateVariantFunction = [&network]() { + network.getVariantManager().allowVariantMultiThreadAccess(true); + }; + + std::thread launcher(updateVariantFunction); + launcher.join(); + + BOOST_CHECK_EQUAL("S1", network.getVariantManager().getWorkingVariantId()); + network.getVariantManager().allowVariantMultiThreadAccess(false); + BOOST_CHECK_EQUAL("S1", network.getVariantManager().getWorkingVariantId()); +} + +BOOST_AUTO_TEST_CASE(testMultipleSetAllowMultiThreadTrue) { + Network network = createNetwork(); + + network.getVariantManager().cloneVariant(VariantManager::getInitialVariantId(), "S1", true); + network.getVariantManager().allowVariantMultiThreadAccess(true); + + const auto& updateVariantFunction = [&network]() { + network.getVariantManager().allowVariantMultiThreadAccess(true); + + const std::string& message = stdcxx::format("Variant index not set for current thread %1%", std::this_thread::get_id()); + POWSYBL_ASSERT_THROW(network.getVariantManager().getVariantIndex(), PowsyblException, message.c_str()); + + network.getVariantManager().setWorkingVariant("S1"); + BOOST_CHECK_EQUAL("S1", network.getVariantManager().getWorkingVariantId()); + + network.getVariantManager().removeVariant("S1"); + POWSYBL_ASSERT_THROW(network.getVariantManager().getVariantIndex(), PowsyblException, message.c_str()); + + network.getVariantManager().setWorkingVariant(VariantManager::getInitialVariantId()); + }; + + std::thread launcher(updateVariantFunction); + launcher.join(); + + BOOST_CHECK_EQUAL(VariantManager::getInitialVariantId(), network.getVariantManager().getWorkingVariantId()); + network.getVariantManager().allowVariantMultiThreadAccess(false); + BOOST_CHECK_EQUAL(VariantManager::getInitialVariantId(), network.getVariantManager().getWorkingVariantId()); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace iidm + +} // namespace powsybl diff --git a/test/iidm/VoltageLevelTest.cpp b/test/iidm/VoltageLevelTest.cpp index fd1c9bd86..84318adf6 100644 --- a/test/iidm/VoltageLevelTest.cpp +++ b/test/iidm/VoltageLevelTest.cpp @@ -42,7 +42,7 @@ Network createLineTestNetwork2() { .setId("VL1") .setName("VL1_NAME") .setTopologyKind(TopologyKind::BUS_BREAKER) - .setNominalVoltage(380.0) + .setNominalV(380.0) .setLowVoltageLimit(340.0) .setHighVoltageLimit(420.0) .add(); @@ -86,13 +86,13 @@ BOOST_AUTO_TEST_CASE(constructor) { BOOST_CHECK_EQUAL(TopologyKind::BUS_BREAKER, vl1.getTopologyKind()); BOOST_CHECK_CLOSE(340, vl1.getLowVoltageLimit(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(420, vl1.getHighVoltageLimit(), std::numeric_limits::epsilon()); - BOOST_CHECK_CLOSE(380, vl1.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(380, vl1.getNominalV(), std::numeric_limits::epsilon()); Substation& s1 = network.getSubstation("S1"); VoltageLevelAdder adder = s1.newVoltageLevel().setId("VL1"); POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "Voltage level 'VL1': Nominal voltage is undefined"); - adder.setNominalVoltage(50).setLowVoltageLimit(-100); + adder.setNominalV(50).setLowVoltageLimit(-100); POWSYBL_ASSERT_THROW(adder.add(), ValidationException, "Voltage level 'VL1': Low voltage limit is < 0"); adder.setLowVoltageLimit(100).setHighVoltageLimit(-10); @@ -126,15 +126,15 @@ BOOST_AUTO_TEST_CASE(integrity) { POWSYBL_ASSERT_THROW(network.getVoltageLevel("LOAD1"), PowsyblException, "Identifiable 'LOAD1' is not a powsybl::iidm::VoltageLevel"); VoltageLevel& vl1 = network.getVoltageLevel("VL1"); - BOOST_CHECK_EQUAL(380, vl1.getNominalVoltage()); + BOOST_CHECK_EQUAL(380, vl1.getNominalV()); BOOST_CHECK_EQUAL(340, vl1.getLowVoltageLimit()); BOOST_CHECK_EQUAL(420, vl1.getHighVoltageLimit()); - POWSYBL_ASSERT_THROW(vl1.setNominalVoltage(-10), ValidationException, "Voltage level 'VL1': Nominal voltage is <= 0"); - POWSYBL_ASSERT_THROW(vl1.setNominalVoltage(0), ValidationException, "Voltage level 'VL1': Nominal voltage is <= 0"); - POWSYBL_ASSERT_THROW(vl1.setNominalVoltage(stdcxx::nan()), ValidationException, "Voltage level 'VL1': Nominal voltage is undefined"); - BOOST_TEST(stdcxx::areSame(vl1, vl1.setNominalVoltage(100))); - BOOST_CHECK_EQUAL(100, vl1.getNominalVoltage()); + POWSYBL_ASSERT_THROW(vl1.setNominalV(-10), ValidationException, "Voltage level 'VL1': Nominal voltage is <= 0"); + POWSYBL_ASSERT_THROW(vl1.setNominalV(0), ValidationException, "Voltage level 'VL1': Nominal voltage is <= 0"); + POWSYBL_ASSERT_THROW(vl1.setNominalV(stdcxx::nan()), ValidationException, "Voltage level 'VL1': Nominal voltage is undefined"); + BOOST_TEST(stdcxx::areSame(vl1, vl1.setNominalV(100))); + BOOST_CHECK_EQUAL(100, vl1.getNominalV()); POWSYBL_ASSERT_THROW(vl1.setLowVoltageLimit(-10), ValidationException, "Voltage level 'VL1': Low voltage limit is < 0"); POWSYBL_ASSERT_THROW(vl1.setLowVoltageLimit(440), ValidationException, "Voltage level 'VL1': Inconsistent voltage limit range [440, 420]"); diff --git a/test/iidm/converter/SimpleAnonymizerTest.cpp b/test/iidm/converter/SimpleAnonymizerTest.cpp new file mode 100644 index 000000000..4bf5299ad --- /dev/null +++ b/test/iidm/converter/SimpleAnonymizerTest.cpp @@ -0,0 +1,95 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace powsybl { + +namespace iidm { + +namespace converter { + +BOOST_AUTO_TEST_SUITE(SimpleAnonymizerTestSuite) + +BOOST_AUTO_TEST_CASE(SimpleAnonymizationTest) { + SimpleAnonymizer anonymizer; + + BOOST_CHECK_EQUAL(Country::FR, anonymizer.anonymizeCountry(Country::FR)); + BOOST_CHECK_EQUAL(Country::BE, anonymizer.anonymizeCountry(Country::BE)); + BOOST_CHECK_EQUAL(Country::FR, anonymizer.deanonymizeCountry(Country::FR)); + BOOST_CHECK_EQUAL(Country::BE, anonymizer.deanonymizeCountry(Country::BE)); + + BOOST_CHECK_EQUAL("A", anonymizer.anonymizeString("test")); + BOOST_CHECK_EQUAL("B", anonymizer.anonymizeString("a")); + BOOST_CHECK_EQUAL("C", anonymizer.anonymizeString("b")); + BOOST_CHECK_EQUAL("", anonymizer.anonymizeString("")); + + BOOST_CHECK_EQUAL("test", anonymizer.deanonymizeString("A")); + BOOST_CHECK_EQUAL("a", anonymizer.deanonymizeString("B")); + BOOST_CHECK_EQUAL("b", anonymizer.deanonymizeString("C")); + BOOST_CHECK_EQUAL("", anonymizer.deanonymizeString("")); + + BOOST_CHECK_EQUAL(3, anonymizer.getStringCount()); + + POWSYBL_ASSERT_THROW(anonymizer.deanonymizeString("FAKE"), PowsyblException, "Mapping not found for anonymized string 'FAKE'"); + + std::stringstream csvStream; + anonymizer.write(csvStream); + + const std::string& ref = "a;B\n" + "b;C\n" + "test;A\n"; + + BOOST_CHECK_EQUAL(ref, csvStream.str()); +} + +BOOST_AUTO_TEST_CASE(anonymizedRoadTrip) { + const std::string& filename = "eurostag-tutorial-example1.xml"; + std::stringstream refStream(test::converter::RoundTrip::getVersionedNetwork(filename, xml::IidmXmlVersion::CURRENT_IIDM_XML_VERSION())); + Network refNetwork = Network::readXml(filename, refStream); + + // write anonymously + stdcxx::Properties properties; + properties.set(ExportOptions::ANONYMISED, "true"); + std::stringstream anonymizedStream; + const std::string& anonymizedFilename = "eurostag-tutorial-example1-anonymous.xml"; + Network::writeXml(anonymizedFilename, anonymizedStream, refNetwork, ExportOptions(properties)); + + BOOST_CHECK(anonymizedStream.str().find("VLGEN") == std::string::npos); + + // read anonymized network + Network deanonymized = Network::readXml(anonymizedFilename, anonymizedStream); + + // write deanonymized network + std::stringstream deanonymizedStream; + const std::string& deanonymizedFilename = "eurostag-tutorial-example1-deanonymized.xml"; + Network::writeXml(deanonymizedFilename, deanonymizedStream, deanonymized); + + BOOST_CHECK_EQUAL(refStream.str(), deanonymizedStream.str()); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace converter + +} // namespace iidm + +} // namespace powsybl diff --git a/test/iidm/converter/xml/CMakeLists.txt b/test/iidm/converter/xml/CMakeLists.txt index dbace8cee..92118dc80 100644 --- a/test/iidm/converter/xml/CMakeLists.txt +++ b/test/iidm/converter/xml/CMakeLists.txt @@ -23,6 +23,7 @@ set(UNIT_TEST_SOURCES BatteryRoundTripTest.cpp EurostagTest.cpp FictitiousSwitchTest.cpp + FourSubstationsNodeBreakerTest.cpp HvdcRoundTripTest.cpp IdentifiableExtensionXmlSerializerTest.cpp IidmXmlUtilTest.cpp @@ -44,31 +45,38 @@ set(UNIT_TEST_SOURCES xiidm.cpp ) -# Shared library -add_library(${EXT_NAME} SHARED ${EXT_SOURCES}) -set_target_properties(${EXT_NAME} PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION} OUTPUT_NAME iidm-${EXT_NAME}) -target_include_directories(${EXT_NAME} - INTERFACE - $ - PUBLIC - $ -) -target_link_libraries(${EXT_NAME} PUBLIC iidm) +if (BUILD_SHARED_LIBS) + # Shared library + add_library(${EXT_NAME} SHARED ${EXT_SOURCES}) + set_target_properties(${EXT_NAME} PROPERTIES SOVERSION ${IIDM_SOVERSION} VERSION ${IIDM_VERSION} OUTPUT_NAME iidm-${EXT_NAME}) + target_include_directories(${EXT_NAME} + INTERFACE + $ + PUBLIC + $ + ) + target_link_libraries(${EXT_NAME} PUBLIC iidm) +endif () + +if (BUILD_STATIC_LIBS) + # Static library + add_library(${EXT_NAME}-static STATIC ${EXT_SOURCES}) + set_target_properties(${EXT_NAME}-static PROPERTIES OUTPUT_NAME iidm-${EXT_NAME}) + target_include_directories(${EXT_NAME}-static + INTERFACE + $ + PUBLIC + $ + ) + target_link_libraries(${EXT_NAME}-static PUBLIC iidm-static) +endif () -# Static library -add_library(${EXT_NAME}-static STATIC ${EXT_SOURCES}) -set_target_properties(${EXT_NAME}-static PROPERTIES OUTPUT_NAME iidm-${EXT_NAME}) -target_include_directories(${EXT_NAME}-static - INTERFACE - $ - PUBLIC - $ -) -target_link_libraries(${EXT_NAME}-static PUBLIC iidm) # Unit tests add_executable(unit-tests-iidm-xml ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-iidm-xml PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-iidm-xml PRIVATE ${EXT_NAME} iidm-tests) +if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-iidm-xml PRIVATE BOOST_TEST_DYN_LINK) +endif () +target_link_libraries(unit-tests-iidm-xml PRIVATE ${EXT_NAME}${TARGET_POSTFIX} iidm-tests${TARGET_POSTFIX}) add_test(NAME iidm-xml COMMAND unit-tests-iidm-xml -- --resources=${CMAKE_SOURCE_DIR}/test/resources) diff --git a/test/iidm/converter/xml/FourSubstationsNodeBreakerTest.cpp b/test/iidm/converter/xml/FourSubstationsNodeBreakerTest.cpp new file mode 100644 index 000000000..f92981e4b --- /dev/null +++ b/test/iidm/converter/xml/FourSubstationsNodeBreakerTest.cpp @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2021, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include + +namespace powsybl { + +namespace iidm { + +namespace converter { + +namespace xml { + +BOOST_AUTO_TEST_SUITE(FourSubstationTestSuite) + +BOOST_AUTO_TEST_CASE(create) { + powsybl::network::FourSubstationsNodeBreakerFactory::create(); +} + +BOOST_FIXTURE_TEST_CASE(FourSubstationRunTrip, test::ResourceFixture) { + test::converter::RoundTrip::roundTripVersionedXmlTest("fourSubstationsNbk.xml", IidmXmlVersion::CURRENT_IIDM_XML_VERSION()); + + // Tests for backward compatibility + test::converter::RoundTrip::roundTripVersionedXmlFromMinToCurrentVersionTest("fourSubstationsNbk.xml", IidmXmlVersion::V1_4()); +} + +BOOST_AUTO_TEST_SUITE_END() + +} // namespace xml + +} // namespace converter + +} // namespace iidm + +} // namespace powsybl diff --git a/test/iidm/converter/xml/IdentifiableExtensionXmlSerializerTest.cpp b/test/iidm/converter/xml/IdentifiableExtensionXmlSerializerTest.cpp index 558fcaa46..cd9c625e3 100644 --- a/test/iidm/converter/xml/IdentifiableExtensionXmlSerializerTest.cpp +++ b/test/iidm/converter/xml/IdentifiableExtensionXmlSerializerTest.cpp @@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE(TerminalExtension) { Load& load = network.getLoad("LOAD"); load.addExtension(stdcxx::make_unique(load)); - Network network2 = Network::readXml(test::converter::RoundTrip::getVersionedNetwork("eurostag-tutorial-example1-with-terminalMock-ext.xml", IidmXmlVersion::CURRENT_IIDM_XML_VERSION())); + Network network2 = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath("eurostag-tutorial-example1-with-terminalMock-ext.xml", IidmXmlVersion::CURRENT_IIDM_XML_VERSION())); Load& load2 = network2.getLoad("LOAD"); const auto& terminalMockExt = load2.getExtension(); BOOST_TEST(stdcxx::areSame(load2.getTerminal(), terminalMockExt.getTerminal())); @@ -65,15 +65,13 @@ BOOST_AUTO_TEST_CASE(TerminalExtension) { } BOOST_AUTO_TEST_CASE(IncompatibleExtensionVersion) { - const std::string& strNetwork = test::converter::RoundTrip::getVersionedNetwork("eurostag-tutorial-example1-with-bad-loadMockExt.xml", IidmXmlVersion::V1_1()); - - POWSYBL_ASSERT_THROW(Network::readXml(strNetwork), PowsyblException, "IIDM-XML version of network (1.1) is not compatible with the loadMock extension's namespace URI"); + const auto& path = test::converter::RoundTrip::getVersionedNetworkPath("eurostag-tutorial-example1-with-bad-loadMockExt.xml", IidmXmlVersion::V1_1()); + POWSYBL_ASSERT_THROW(Network::readXml(path), PowsyblException, "IIDM-XML version of network (1.1) is not compatible with the loadMock extension's namespace URI"); } BOOST_AUTO_TEST_CASE(UnsupportedExtensionVersion) { - const std::string& strNetwork = test::converter::RoundTrip::getVersionedNetwork("eurostag-tutorial-example1-with-bad-loadQuxExt.xml", IidmXmlVersion::V1_1()); - - POWSYBL_ASSERT_THROW(Network::readXml(strNetwork), PowsyblException, "IIDM-XML version of network (1.1) is not supported by the loadQux extension's XML serializer"); + const auto& path = test::converter::RoundTrip::getVersionedNetworkPath("eurostag-tutorial-example1-with-bad-loadQuxExt.xml", IidmXmlVersion::V1_1()); + POWSYBL_ASSERT_THROW(Network::readXml(path), PowsyblException, "IIDM-XML version of network (1.1) is not supported by the loadQux extension's XML serializer"); } BOOST_AUTO_TEST_CASE(MultipleExtensionRoundTrip) { @@ -81,7 +79,8 @@ BOOST_AUTO_TEST_CASE(MultipleExtensionRoundTrip) { } BOOST_AUTO_TEST_CASE(NotLatestVersionTerminalExtension) { - const auto& network = Network::readXml(test::converter::RoundTrip::getVersionedNetwork("eurostag-tutorial-example1-with-loadMockExt-1_2.xml", IidmXmlVersion::V1_1())); + const std::string& filename = "eurostag-tutorial-example1-with-loadMockExt-1_2.xml"; + const auto& network = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath(filename, IidmXmlVersion::V1_1())); // properties specify that IIDM-XML network version to export is 1.1 // FIXME(mathbag): Implement properties @@ -93,17 +92,17 @@ BOOST_AUTO_TEST_CASE(NotLatestVersionTerminalExtension) { options.addExtensionVersion("loadMock", "1.1"); std::stringstream buffer; - Network::writeXml(buffer, network, options); + Network::writeXml(filename, buffer, network, options); // check that loadMock has been serialized in v1.1 test::converter::RoundTrip::compareXml(test::converter::RoundTrip::getVersionedNetwork("eurostag-tutorial-example1-with-loadMockExt-1_1.xml", IidmXmlVersion::V1_1()), buffer.str()); } BOOST_AUTO_TEST_CASE(ThrowErrorIncompatibleExtensionVersion) { - const auto& strNetwork = test::converter::RoundTrip::getVersionedNetwork("eurostag-tutorial-example1-with-bad-loadMockExt.xml", IidmXmlVersion::V1_1()); + const auto& path = test::converter::RoundTrip::getVersionedNetworkPath("eurostag-tutorial-example1-with-bad-loadMockExt.xml", IidmXmlVersion::V1_1()); // should fail while trying to import a file in IIDM-XML network version 1.1 and loadMock in v1.0 (not compatible) - POWSYBL_ASSERT_THROW(Network::readXml(strNetwork), PowsyblException, "IIDM-XML version of network (1.1) is not compatible with the loadMock extension's namespace URI"); + POWSYBL_ASSERT_THROW(Network::readXml(path), PowsyblException, "IIDM-XML version of network (1.1) is not compatible with the loadMock extension's namespace URI"); } BOOST_AUTO_TEST_CASE(ThrowErrorUnsupportedExtensionVersion1) { @@ -114,14 +113,15 @@ BOOST_AUTO_TEST_CASE(ThrowErrorUnsupportedExtensionVersion1) { // should fail while trying to import a file with loadBar in v1.1 (does not exist, considered as not supported) std::ostringstream buffer; - POWSYBL_ASSERT_THROW(Network::writeXml(buffer, network, options), PowsyblException, "The version 1.1 of the loadBar extension's XML serializer is not supported"); + const std::string& filename = stdcxx::format("%1%.xiidm", network.getId()); + POWSYBL_ASSERT_THROW(Network::writeXml(filename, buffer, network, options), PowsyblException, "The version 1.1 of the loadBar extension's XML serializer is not supported"); } BOOST_AUTO_TEST_CASE(ThrowErrorUnsupportedExtensionVersion2) { - const auto& strNetwork = test::converter::RoundTrip::getVersionedNetwork("eurostag-tutorial-example1-with-bad-loadQuxExt.xml", IidmXmlVersion::V1_1()); + const auto& path = test::converter::RoundTrip::getVersionedNetworkPath("eurostag-tutorial-example1-with-bad-loadQuxExt.xml", IidmXmlVersion::V1_1()); // should fail while trying to import a file in IIDM-XML network version 1.1 and loadMock in v1.0 (not compatible) - POWSYBL_ASSERT_THROW(Network::readXml(strNetwork), PowsyblException, "IIDM-XML version of network (1.1) is not supported by the loadQux extension's XML serializer"); + POWSYBL_ASSERT_THROW(Network::readXml(path), PowsyblException, "IIDM-XML version of network (1.1) is not supported by the loadQux extension's XML serializer"); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/iidm/converter/xml/IidmXmlUtilTest.cpp b/test/iidm/converter/xml/IidmXmlUtilTest.cpp index 7329a9122..935fd382e 100644 --- a/test/iidm/converter/xml/IidmXmlUtilTest.cpp +++ b/test/iidm/converter/xml/IidmXmlUtilTest.cpp @@ -38,7 +38,8 @@ BOOST_AUTO_TEST_CASE(testReadMaximumVersion) { std::stringstream ss; ss << networkStr; powsybl::xml::XmlStreamReader reader(ss); - NetworkXmlReaderContext context(FakeAnonymizer(), reader, ImportOptions(), IidmXmlVersion::V1_1()); + std::unique_ptr anonymizer = stdcxx::make_unique(); + NetworkXmlReaderContext context(std::move(anonymizer), reader, ImportOptions(), IidmXmlVersion::V1_1()); POWSYBL_ASSERT_THROW(IidmXmlUtil::assertMaximumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_0(), context), PowsyblException, "root.element is not supported for IIDM-XML version 1.1. IIDM-XML version should be <= 1.0"); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMaximumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), context)); @@ -47,18 +48,18 @@ BOOST_AUTO_TEST_CASE(testReadMaximumVersion) { BOOST_AUTO_TEST_CASE(testWriteMaximumVersion) { std::stringstream ss; - FakeAnonymizer anonymizer; + std::unique_ptr anonymizer = stdcxx::make_unique(); powsybl::xml::XmlStreamWriter writer(ss, true); ExportOptions options = ExportOptions().setVersion("1.1"); Network network("test", "test"); BusFilter busFilter = BusFilter::create(network, options); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::THROW_EXCEPTION); - NetworkXmlWriterContext contextThrow(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_1()); + NetworkXmlWriterContext contextThrow(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_1()); POWSYBL_ASSERT_THROW(IidmXmlUtil::assertMaximumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_0(), contextThrow), PowsyblException, "root.element is not supported for IIDM-XML version 1.1. IIDM-XML version should be <= 1.0"); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::LOG_ERROR); - NetworkXmlWriterContext contextLog(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_1()); + NetworkXmlWriterContext contextLog(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_1()); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMaximumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_0(), contextLog)); } @@ -66,7 +67,8 @@ BOOST_AUTO_TEST_CASE(testReadStrictMaximumVersion) { std::stringstream ss; ss << networkStr; powsybl::xml::XmlStreamReader reader(ss); - NetworkXmlReaderContext context(FakeAnonymizer(), reader, ImportOptions(), IidmXmlVersion::V1_1()); + std::unique_ptr anonymizer = stdcxx::make_unique(); + NetworkXmlReaderContext context(std::move(anonymizer), reader, ImportOptions(), IidmXmlVersion::V1_1()); POWSYBL_ASSERT_THROW(IidmXmlUtil::assertStrictMaximumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), context), PowsyblException, "root.element is not supported for IIDM-XML version 1.1. IIDM-XML version should be < 1.1"); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertStrictMaximumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_2(), context)); @@ -74,18 +76,18 @@ BOOST_AUTO_TEST_CASE(testReadStrictMaximumVersion) { BOOST_AUTO_TEST_CASE(testWriteStrictMaximumVersion) { std::stringstream ss; - FakeAnonymizer anonymizer; + std::unique_ptr anonymizer = stdcxx::make_unique(); powsybl::xml::XmlStreamWriter writer(ss, true); ExportOptions options = ExportOptions().setVersion("1.1"); Network network("test", "test"); BusFilter busFilter = BusFilter::create(network, options); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::THROW_EXCEPTION); - NetworkXmlWriterContext contextThrow(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_1()); + NetworkXmlWriterContext contextThrow(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_1()); POWSYBL_ASSERT_THROW(IidmXmlUtil::assertStrictMaximumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_0(), contextThrow), PowsyblException, "root.element is not supported for IIDM-XML version 1.1. IIDM-XML version should be < 1.0"); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::LOG_ERROR); - NetworkXmlWriterContext contextLog(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_1()); + NetworkXmlWriterContext contextLog(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_1()); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertStrictMaximumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_0(), contextLog)); } @@ -93,7 +95,8 @@ BOOST_AUTO_TEST_CASE(testReadMinimumVersion) { std::stringstream ss; ss << networkStr; powsybl::xml::XmlStreamReader reader(ss); - NetworkXmlReaderContext context(FakeAnonymizer(), reader, ImportOptions(), IidmXmlVersion::V1_1()); + std::unique_ptr anonymizer = stdcxx::make_unique(); + NetworkXmlReaderContext context(std::move(anonymizer), reader, ImportOptions(), IidmXmlVersion::V1_1()); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMinimumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_0(), context)); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMinimumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), context)); @@ -102,18 +105,18 @@ BOOST_AUTO_TEST_CASE(testReadMinimumVersion) { BOOST_AUTO_TEST_CASE(testWriteMinimumVersion) { std::stringstream ss; - FakeAnonymizer anonymizer; + std::unique_ptr anonymizer = stdcxx::make_unique(); powsybl::xml::XmlStreamWriter writer(ss, true); ExportOptions options = ExportOptions().setVersion("1.0"); Network network("test", "test"); BusFilter busFilter = BusFilter::create(network, options); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::THROW_EXCEPTION); - NetworkXmlWriterContext contextThrow(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_0()); + NetworkXmlWriterContext contextThrow(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_0()); POWSYBL_ASSERT_THROW(IidmXmlUtil::assertMinimumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), contextThrow), PowsyblException, "root.element is not supported for IIDM-XML version 1.0. IIDM-XML version should be >= 1.1"); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::LOG_ERROR); - NetworkXmlWriterContext contextLog(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_0()); + NetworkXmlWriterContext contextLog(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_0()); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMinimumVersion(ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), contextLog)); } @@ -121,7 +124,8 @@ BOOST_AUTO_TEST_CASE(testReadMinimumVersionIfNotDefault) { std::stringstream ss; ss << networkStr; powsybl::xml::XmlStreamReader reader(ss); - NetworkXmlReaderContext context(FakeAnonymizer(), reader, ImportOptions(), IidmXmlVersion::V1_1()); + std::unique_ptr anonymizer = stdcxx::make_unique(); + NetworkXmlReaderContext context(std::move(anonymizer), reader, ImportOptions(), IidmXmlVersion::V1_1()); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMinimumVersionIfNotDefault(true, ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_0(), context)); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMinimumVersionIfNotDefault(true, ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), context)); @@ -133,28 +137,28 @@ BOOST_AUTO_TEST_CASE(testReadMinimumVersionIfNotDefault) { BOOST_AUTO_TEST_CASE(testWriteMinimumVersionIfNotDefault) { std::stringstream ss; - FakeAnonymizer anonymizer; + std::unique_ptr anonymizer = stdcxx::make_unique(); powsybl::xml::XmlStreamWriter writer(ss, true); ExportOptions options = ExportOptions().setVersion("1.0"); Network network("test", "test"); BusFilter busFilter = BusFilter::create(network, options); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::THROW_EXCEPTION); - NetworkXmlWriterContext contextThrow(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_0()); + NetworkXmlWriterContext contextThrow(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_0()); POWSYBL_ASSERT_THROW(IidmXmlUtil::assertMinimumVersionIfNotDefault(true, ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), contextThrow), PowsyblException, "root.element is not supported for IIDM-XML version 1.0. IIDM-XML version should be >= 1.1"); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::LOG_ERROR); - NetworkXmlWriterContext contextLog(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_0()); + NetworkXmlWriterContext contextLog(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_0()); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMinimumVersionIfNotDefault(true, ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), contextLog)); } BOOST_AUTO_TEST_CASE(testReadMinimumVersionAndRunIfNotDefault) { std::stringstream ss; ss << networkStr; - FakeAnonymizer anonymizer; + std::unique_ptr anonymizer = stdcxx::make_unique(); powsybl::xml::XmlStreamReader reader(ss); ImportOptions options; - NetworkXmlReaderContext context(anonymizer, reader, options, IidmXmlVersion::V1_1()); + NetworkXmlReaderContext context(std::move(anonymizer), reader, options, IidmXmlVersion::V1_1()); int variable = 0; auto runnable = [&variable]() { @@ -177,18 +181,18 @@ BOOST_AUTO_TEST_CASE(testReadMinimumVersionAndRunIfNotDefault) { BOOST_AUTO_TEST_CASE(testWriteMinimumVersionAndRunIfNotDefault) { std::stringstream ss; - FakeAnonymizer anonymizer; + std::unique_ptr anonymizer = stdcxx::make_unique(); powsybl::xml::XmlStreamWriter writer(ss, true); ExportOptions options = ExportOptions().setVersion("1.0"); Network network("test", "test"); BusFilter busFilter = BusFilter::create(network, options); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::THROW_EXCEPTION); - NetworkXmlWriterContext contextThrow(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_0()); + NetworkXmlWriterContext contextThrow(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_0()); POWSYBL_ASSERT_THROW(IidmXmlUtil::assertMinimumVersionAndRunIfNotDefault(true, ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), contextThrow, [](){}), PowsyblException, "root.element is not supported for IIDM-XML version 1.0. IIDM-XML version should be >= 1.1"); options.setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::LOG_ERROR); - NetworkXmlWriterContext contextLog(anonymizer, writer, options, busFilter, IidmXmlVersion::V1_0()); + NetworkXmlWriterContext contextLog(std::move(anonymizer), writer, options, busFilter, IidmXmlVersion::V1_0()); BOOST_CHECK_NO_THROW(IidmXmlUtil::assertMinimumVersionAndRunIfNotDefault(true, ROOT, ELEMENT, ErrorMessage::NOT_SUPPORTED, IidmXmlVersion::V1_1(), contextLog, [](){})); } diff --git a/test/iidm/converter/xml/LinesRoundTripTest.cpp b/test/iidm/converter/xml/LinesRoundTripTest.cpp index c137cd24e..a1680686e 100644 --- a/test/iidm/converter/xml/LinesRoundTripTest.cpp +++ b/test/iidm/converter/xml/LinesRoundTripTest.cpp @@ -38,7 +38,7 @@ Network createDlGenerationLinear() { .add(); VoltageLevel& voltageLevel = substation.newVoltageLevel() .setId("VL") - .setNominalVoltage(100.0) + .setNominalV(100.0) .setLowVoltageLimit(80.0) .setHighVoltageLimit(120.0) .setTopologyKind(TopologyKind::BUS_BREAKER) @@ -121,14 +121,15 @@ BOOST_FIXTURE_TEST_CASE(DanglingLineWithGenerationTest, test::ResourceFixture) { test::converter::RoundTrip::testForAllPreviousVersions(IidmXmlVersion::V1_3(), [&network](const iidm::converter::xml::IidmXmlVersion& version) { std::stringstream ss; ExportOptions options = ExportOptions().setVersion(version.toString(".")); - POWSYBL_ASSERT_THROW(Network::writeXml(ss, network, options), PowsyblException, stdcxx::format("danglingLine.generation is not null and not supported for IIDM-XML version %1%. IIDM-XML version should be >= 1.3", version.toString(".")).c_str()); + const std::string& filename = stdcxx::format("%1%.xiidm", network.getId()); + POWSYBL_ASSERT_THROW(Network::writeXml(filename, ss, network, options), PowsyblException, stdcxx::format("danglingLine.generation is not null and not supported for IIDM-XML version %1%. IIDM-XML version should be >= 1.3", version.toString(".")).c_str()); }); // check it doesn't fail for all versions < 1.3 if IidmVersionIncompatibilityBehavior is to log error test::converter::RoundTrip::testForAllPreviousVersions(IidmXmlVersion::V1_3(), [&network](const iidm::converter::xml::IidmXmlVersion& version) { ExportOptions options = ExportOptions().setVersion(version.toString(".")).setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::LOG_ERROR); const auto& writer = [&options](const iidm::Network& n, std::ostream& stream) { - iidm::Network::writeXml(stream, n, options); + iidm::Network::writeXml(stdcxx::format("%1%.xiidm", n.getId()), stream, n, options); }; test::converter::RoundTrip::writeXmlTest(network, writer, test::converter::RoundTrip::getVersionedNetwork("danglingLineWithGeneration.xml", version)); }); diff --git a/test/iidm/converter/xml/NetworkXmlReaderContextTest.cpp b/test/iidm/converter/xml/NetworkXmlReaderContextTest.cpp index 334360796..e31706085 100644 --- a/test/iidm/converter/xml/NetworkXmlReaderContextTest.cpp +++ b/test/iidm/converter/xml/NetworkXmlReaderContextTest.cpp @@ -29,10 +29,9 @@ BOOST_AUTO_TEST_CASE(Constructor) { ""; powsybl::xml::XmlStreamReader reader(istream); ImportOptions importOptions; - FakeAnonymizer anonymizer; - NetworkXmlReaderContext context(anonymizer, reader, importOptions, IidmXmlVersion::CURRENT_IIDM_XML_VERSION()); + std::unique_ptr anonymizer = stdcxx::make_unique(); + NetworkXmlReaderContext context(std::move(anonymizer), reader, importOptions, IidmXmlVersion::CURRENT_IIDM_XML_VERSION()); BOOST_CHECK_EQUAL(importOptions.isThrowExceptionIfExtensionNotFound(), context.getOptions().isThrowExceptionIfExtensionNotFound()); - BOOST_CHECK(stdcxx::areSame(anonymizer, context.getAnonymizer())); BOOST_CHECK(stdcxx::areSame(reader, context.getReader())); } diff --git a/test/iidm/converter/xml/NetworkXmlTest.cpp b/test/iidm/converter/xml/NetworkXmlTest.cpp index 42bedac15..01cedd077 100644 --- a/test/iidm/converter/xml/NetworkXmlTest.cpp +++ b/test/iidm/converter/xml/NetworkXmlTest.cpp @@ -49,7 +49,8 @@ BOOST_AUTO_TEST_CASE(StartByComments) { " " ""; - const Network& network = Network::readXml(networkStr); + std::istringstream stream(networkStr); + const Network& network = Network::readXml("network.xiidm", stream); assertNetwork(network); } @@ -63,7 +64,8 @@ BOOST_AUTO_TEST_CASE(Basic) { " sourceFormat=\"test\">" ""; - const Network& network = Network::readXml(networkStr); + std::istringstream stream(networkStr); + const Network& network = Network::readXml("network.xiidm", stream); assertNetwork(network); } @@ -77,7 +79,8 @@ BOOST_AUTO_TEST_CASE(NoPrefix) { " sourceFormat=\"test\">" ""; - const Network& network = Network::readXml(networkStr); + std::istringstream stream(networkStr); + const Network& network = Network::readXml("network.xiidm", stream); assertNetwork(network); } @@ -91,7 +94,8 @@ BOOST_AUTO_TEST_CASE(SpecialChars) { " sourceFormat=\"test\">" ""; - const Network& network = Network::readXml(networkStr); + std::istringstream stream(networkStr); + const Network& network = Network::readXml("network.xiidm", stream); BOOST_CHECK_EQUAL("ø/Ø - ö/Ö - æ/Æ - ä/Ä - Ã¥/Ã… (aa/Aa)", network.getId()); } @@ -110,21 +114,21 @@ BOOST_AUTO_TEST_CASE(FromParameters) { stdcxx::Properties properties; properties.set(ImportOptions::THROW_EXCEPTION_IF_EXTENSION_NOT_FOUND, "true"); - FakeAnonymizer anonymizer; - const Network& network = Network::readXml(stream, ImportOptions(properties), anonymizer); + const Network& network = Network::readXml("network.xiidm", stream, ImportOptions(properties)); std::stringstream ostream; - Network::writeXml(ostream, network, ExportOptions(properties)); + const std::string& filename = stdcxx::format("%1%.xiidm", network.getId()); + Network::writeXml(filename, ostream, network, ExportOptions(properties)); properties.set(ExportOptions::TOPOLOGY_LEVEL, "true"); - POWSYBL_ASSERT_THROW(Network::writeXml(ostream, network, ExportOptions(properties)), AssertionError, "Unexpected TopologyLevel name: true"); + POWSYBL_ASSERT_THROW(Network::writeXml(filename, ostream, network, ExportOptions(properties)), AssertionError, "Unexpected TopologyLevel name: true"); properties.remove(ExportOptions::TOPOLOGY_LEVEL); std::set extensions; extensions.insert("extension1"); extensions.insert("extension2"); properties.set(ExportOptions::EXTENSIONS_LIST, boost::algorithm::join(extensions, ",")); - Network::writeXml(ostream, network, ExportOptions(properties)); + Network::writeXml(filename, ostream, network, ExportOptions(properties)); } BOOST_AUTO_TEST_CASE(WriteFromParametersCheckExtensions) { @@ -132,9 +136,10 @@ BOOST_AUTO_TEST_CASE(WriteFromParametersCheckExtensions) { stdcxx::Properties properties; std::stringstream ostream; + const std::string& filename = stdcxx::format("%1%.xiidm", network.getId()); properties.set(ExportOptions::EXTENSIONS_LIST, "loadBar"); - Network::writeXml(ostream, network, ExportOptions(properties)); + Network::writeXml(filename, ostream, network, ExportOptions(properties)); const std::string& loadBarOnly = ostream.str(); BOOST_TEST(loadBarOnly.find("loadBar") != std::string::npos); BOOST_TEST(loadBarOnly.find("loadFoo") == std::string::npos); @@ -142,7 +147,7 @@ BOOST_AUTO_TEST_CASE(WriteFromParametersCheckExtensions) { ostream.str(""); ostream.clear(); properties.set(ExportOptions::EXTENSIONS_LIST, "loadFoo"); - Network::writeXml(ostream, network, ExportOptions(properties)); + Network::writeXml(filename, ostream, network, ExportOptions(properties)); const std::string& loadFooOnly = ostream.str(); BOOST_TEST(loadFooOnly.find("loadBar") == std::string::npos); BOOST_TEST(loadFooOnly.find("loadFoo") != std::string::npos); @@ -150,13 +155,13 @@ BOOST_AUTO_TEST_CASE(WriteFromParametersCheckExtensions) { ostream.str(""); ostream.clear(); properties.remove(ExportOptions::EXTENSIONS_LIST); - Network::writeXml(ostream, network, ExportOptions(properties)); + Network::writeXml(filename, ostream, network, ExportOptions(properties)); const std::string& loadAllExtsOutput = ostream.str(); BOOST_TEST(loadAllExtsOutput.find("loadBar") != std::string::npos); BOOST_TEST(loadAllExtsOutput.find("loadFoo") != std::string::npos); std::stringstream referenceStream; - Network::writeXml(referenceStream, network); + Network::writeXml(filename, referenceStream, network); const std::string& refOutput = referenceStream.str(); BOOST_TEST(refOutput.find("loadBar") != std::string::npos); BOOST_TEST(refOutput.find("loadFoo") != std::string::npos); @@ -166,32 +171,32 @@ BOOST_AUTO_TEST_CASE(WriteFromParametersCheckExtensions) { BOOST_AUTO_TEST_CASE(ReadFromParametersCheckExtensions) { stdcxx::Properties properties; - FakeAnonymizer anonymizer; std::stringstream inputStream; Network network = powsybl::network::MultipleExtensionsTestNetworkFactory::MultipleExtensionsTestNetworkFactory::create(); - Network::writeXml(inputStream, network); + const std::string& filename = stdcxx::format("%1%.xiidm", network.getId()); + Network::writeXml(filename, inputStream, network); std::string refString = inputStream.str(); properties.set(ImportOptions::EXTENSIONS_LIST, "loadFoo"); inputStream.str(refString); inputStream.clear(); - Network fooNetwork = Network::readXml(inputStream, ImportOptions(properties), anonymizer); + Network fooNetwork = Network::readXml(filename, inputStream, ImportOptions(properties)); BOOST_CHECK_EQUAL(1UL, boost::size(fooNetwork.getLoad("LOAD").getExtensions())); BOOST_CHECK_EQUAL(1UL, boost::size(fooNetwork.getLoad("LOAD2").getExtensions())); properties.set(ImportOptions::EXTENSIONS_LIST, "loadBar"); inputStream.str(refString); inputStream.clear(); - Network barNetwork = Network::readXml(inputStream, ImportOptions(properties), anonymizer); + Network barNetwork = Network::readXml(filename, inputStream, ImportOptions(properties)); BOOST_CHECK_EQUAL(1UL, boost::size(barNetwork.getLoad("LOAD").getExtensions())); BOOST_CHECK_EQUAL(0UL, boost::size(barNetwork.getLoad("LOAD2").getExtensions())); properties.remove(ImportOptions::EXTENSIONS_LIST); inputStream.str(refString); inputStream.clear(); - Network allExtNetwork = Network::readXml(inputStream, ImportOptions(properties), anonymizer); + Network allExtNetwork = Network::readXml(filename, inputStream, ImportOptions(properties)); BOOST_CHECK_EQUAL(2UL, boost::size(allExtNetwork.getLoad("LOAD").getExtensions())); BOOST_CHECK_EQUAL(1UL, boost::size(allExtNetwork.getLoad("LOAD2").getExtensions())); } diff --git a/test/iidm/converter/xml/NetworkXmlWriterContextTest.cpp b/test/iidm/converter/xml/NetworkXmlWriterContextTest.cpp index 558911866..1266a2c56 100644 --- a/test/iidm/converter/xml/NetworkXmlWriterContextTest.cpp +++ b/test/iidm/converter/xml/NetworkXmlWriterContextTest.cpp @@ -29,11 +29,10 @@ BOOST_AUTO_TEST_CASE(Constructor) { std::stringstream istream; powsybl::xml::XmlStreamWriter writer(istream, true); ExportOptions exportOptions; - FakeAnonymizer fakeAnonymizer; - stdcxx::reference_wrapper anonymizer(fakeAnonymizer); + std::unique_ptr anonymizer = stdcxx::make_unique(); Network network("id_network", "name_network"); const BusFilter& filter = BusFilter::create(network, exportOptions); - NetworkXmlWriterContext context(anonymizer, writer, exportOptions, filter, IidmXmlVersion::CURRENT_IIDM_XML_VERSION()); + NetworkXmlWriterContext context(std::move(anonymizer), writer, exportOptions, filter, IidmXmlVersion::CURRENT_IIDM_XML_VERSION()); BOOST_CHECK_EQUAL(static_cast(exportOptions.getTopologyLevel()), static_cast(context.getOptions().getTopologyLevel())); BOOST_CHECK_EQUAL(exportOptions.isAnonymized(), context.getOptions().isAnonymized()); BOOST_CHECK_EQUAL(exportOptions.isIndent(), context.getOptions().isIndent()); diff --git a/test/iidm/converter/xml/OptionalLoadTypeBugTest.cpp b/test/iidm/converter/xml/OptionalLoadTypeBugTest.cpp index 11fb8ce17..d31da2713 100644 --- a/test/iidm/converter/xml/OptionalLoadTypeBugTest.cpp +++ b/test/iidm/converter/xml/OptionalLoadTypeBugTest.cpp @@ -25,7 +25,7 @@ BOOST_AUTO_TEST_SUITE(OptionalLoadTypeTest) BOOST_AUTO_TEST_CASE(OptionalLoadTypeFromXml) { for (const auto& version : IidmXmlVersion::all()) { - Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetwork("optionalLoadTypeBug.xml", version.get())); + Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath("optionalLoadTypeBug.xml", version.get())); BOOST_CHECK_EQUAL(LoadType::UNDEFINED, network.getLoad("L").getLoadType()); } } diff --git a/test/iidm/converter/xml/ShuntCompensatorRoundTripTest.cpp b/test/iidm/converter/xml/ShuntCompensatorRoundTripTest.cpp index fad65ffa5..9f16c8423 100644 --- a/test/iidm/converter/xml/ShuntCompensatorRoundTripTest.cpp +++ b/test/iidm/converter/xml/ShuntCompensatorRoundTripTest.cpp @@ -42,7 +42,7 @@ Network createNonLinear() { .add(); VoltageLevel& vl1 = s1.newVoltageLevel() .setId("VL1") - .setNominalVoltage(380) + .setNominalV(380) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl1.getBusBreakerView().newBus() @@ -55,7 +55,7 @@ Network createNonLinear() { .add(); VoltageLevel& vl2 = s2.newVoltageLevel() .setId("VL2") - .setNominalVoltage(220) + .setNominalV(220) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl2.getBusBreakerView().newBus() @@ -115,15 +115,16 @@ BOOST_FIXTURE_TEST_CASE(ShuntNonLinearRoundTripTest, test::ResourceFixture) { // check that it fails for versions previous to 1.2 test::converter::RoundTrip::testForAllPreviousVersions(IidmXmlVersion::V1_3(), [&network](const iidm::converter::xml::IidmXmlVersion& version) { std::stringstream ss; + const std::string& filename = stdcxx::format("%1%.xiidm", network.getId()); ExportOptions options = ExportOptions().setVersion(version.toString(".")); - POWSYBL_ASSERT_THROW(Network::writeXml(ss, network, options), PowsyblException, stdcxx::format("shunt.shuntNonLinearModel is not supported for IIDM-XML version %1%. IIDM-XML version should be >= 1.3", version.toString(".")).c_str()); + POWSYBL_ASSERT_THROW(Network::writeXml(filename, ss, network, options), PowsyblException, stdcxx::format("shunt.shuntNonLinearModel is not supported for IIDM-XML version %1%. IIDM-XML version should be >= 1.3", version.toString(".")).c_str()); }); // check that it doesn't fail for versions previous to 1.2 when log error is the IIDM version incompatibility behavior test::converter::RoundTrip::testForAllPreviousVersions(IidmXmlVersion::V1_3(), [&network](const iidm::converter::xml::IidmXmlVersion& version) { ExportOptions options = ExportOptions().setVersion(version.toString(".")).setIidmVersionIncompatibilityBehavior(ExportOptions::IidmVersionIncompatibilityBehavior::LOG_ERROR); const auto& writer = [&options](const iidm::Network& n, std::ostream& stream) { - iidm::Network::writeXml(stream, n, options); + iidm::Network::writeXml(stdcxx::format("%1%.xiidm", n.getId()), stream, n, options); }; test::converter::RoundTrip::writeXmlTest(network, writer, test::converter::RoundTrip::getVersionedNetwork("nonLinearShuntRoundTripRef.xml", version)); }); diff --git a/test/iidm/converter/xml/SkipExtensionTest.cpp b/test/iidm/converter/xml/SkipExtensionTest.cpp index e515eece5..60fd60bfb 100644 --- a/test/iidm/converter/xml/SkipExtensionTest.cpp +++ b/test/iidm/converter/xml/SkipExtensionTest.cpp @@ -34,7 +34,8 @@ namespace xml { BOOST_AUTO_TEST_SUITE(SkipExtensionTestSuite) BOOST_FIXTURE_TEST_CASE(SkipExtensionTest, test::ResourceFixture) { - Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetwork("multiple-extensions.xml", IidmXmlVersion::V1_0())); + const std::string& filename = "multiple-extensions.xml"; + Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath(filename, IidmXmlVersion::V1_0())); const std::string& refNetwork = test::converter::RoundTrip::getVersionedNetwork("noExtension.xml", IidmXmlVersion::V1_0()); stdcxx::Properties properties; @@ -42,47 +43,36 @@ BOOST_FIXTURE_TEST_CASE(SkipExtensionTest, test::ResourceFixture) { properties.set(ExportOptions::EXTENSIONS_LIST, ""); properties.set(ExportOptions::VERSION, "1.0"); - Network::writeXml(ostream, network, ExportOptions(properties)); + Network::writeXml(filename, ostream, network, ExportOptions(properties)); BOOST_CHECK_EQUAL(refNetwork, ostream.str()); } BOOST_FIXTURE_TEST_CASE(checkSomeFiltered, test::ResourceFixture) { - std::stringstream stream; - stream << test::converter::RoundTrip::getVersionedNetwork("multiple-extensions.xml", IidmXmlVersion::V1_0()); - FakeAnonymizer anonymizer; - + const std::string& filename = "multiple-extensions.xml"; stdcxx::Properties properties; properties.set(ImportOptions::EXTENSIONS_LIST, "loadFoo"); - Network network = Network::readXml(stream, ImportOptions(properties), anonymizer); + Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath(filename, IidmXmlVersion::V1_0()), ImportOptions(properties)); network.getLoad("LOAD").getExtension(); POWSYBL_ASSERT_THROW(network.getLoad("LOAD").getExtension(), PowsyblException, "Extension powsybl::network::LoadBarExt not found"); network.getLoad("LOAD2").getExtension(); } BOOST_FIXTURE_TEST_CASE(checkReadNoExtension, test::ResourceFixture) { - std::stringstream stream; - stream << test::converter::RoundTrip::getVersionedNetwork("multiple-extensions.xml", IidmXmlVersion::V1_0()); - FakeAnonymizer anonymizer; - stdcxx::Properties properties; properties.set(ImportOptions::EXTENSIONS_LIST, ""); - Network network = Network::readXml(stream, ImportOptions(properties), anonymizer); + Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath("multiple-extensions.xml", IidmXmlVersion::V1_0()), ImportOptions(properties)); POWSYBL_ASSERT_THROW(network.getLoad("LOAD").getExtension(), PowsyblException, "Extension powsybl::network::LoadFooExt not found"); POWSYBL_ASSERT_THROW(network.getLoad("LOAD").getExtension(), PowsyblException, "Extension powsybl::network::LoadBarExt not found"); POWSYBL_ASSERT_THROW(network.getLoad("LOAD2").getExtension(), PowsyblException, "Extension powsybl::network::LoadFooExt not found"); } BOOST_FIXTURE_TEST_CASE(checkReadAllExtensions, test::ResourceFixture) { - std::stringstream stream; - stream << test::converter::RoundTrip::getVersionedNetwork("multiple-extensions.xml", IidmXmlVersion::V1_0()); - FakeAnonymizer anonymizer; - stdcxx::Properties properties; properties.set(ImportOptions::EXTENSIONS_LIST, "loadFoo,loadBar"); - Network network = Network::readXml(stream, ImportOptions(properties), anonymizer); + Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath("multiple-extensions.xml", IidmXmlVersion::V1_0()), ImportOptions(properties)); network.getLoad("LOAD").getExtension(); network.getLoad("LOAD").getExtension(); network.getLoad("LOAD2").getExtension(); diff --git a/test/iidm/converter/xml/extensions/TerminalMockExt.hpp b/test/iidm/converter/xml/extensions/TerminalMockExt.hpp index 6cfbdfb59..c7ad9640b 100644 --- a/test/iidm/converter/xml/extensions/TerminalMockExt.hpp +++ b/test/iidm/converter/xml/extensions/TerminalMockExt.hpp @@ -9,7 +9,7 @@ #define POWSYBL_IIDM_CONVERTER_XML_EXTENSIONS_TERMINALMOCKEXT_HPP #include -#include +#include namespace powsybl { diff --git a/test/iidm/converter/xml/extensions/TerminalMockXmlSerializer.cpp b/test/iidm/converter/xml/extensions/TerminalMockXmlSerializer.cpp index 789d77fcc..b855ea12a 100644 --- a/test/iidm/converter/xml/extensions/TerminalMockXmlSerializer.cpp +++ b/test/iidm/converter/xml/extensions/TerminalMockXmlSerializer.cpp @@ -37,12 +37,14 @@ TerminalMockXmlSerializer::TerminalMockXmlSerializer() : .put(IidmXmlVersion::V1_1(), {"1.1"}) .put(IidmXmlVersion::V1_2(), {"1.2"}) .put(IidmXmlVersion::V1_3(), {"1.3"}) + .put(IidmXmlVersion::V1_4(), {"1.4"}) .build(), stdcxx::MapBuilder() .put("1.0", "http://www.itesla_project.eu/schema/iidm/ext/terminal_mock/1_0") .put("1.1", "http://www.powsybl.org/schema/iidm/ext/terminal_mock/1_1") .put("1.2", "http://www.powsybl.org/schema/iidm/ext/terminal_mock/1_2") .put("1.3", "http://www.powsybl.org/schema/iidm/ext/terminal_mock/1_3") + .put("1.4", "http://www.powsybl.org/schema/iidm/ext/terminal_mock/1_4") .build()) { } diff --git a/test/iidm/converter/xml/xiidm.cpp b/test/iidm/converter/xml/xiidm.cpp index 4e9244daa..c0a1746ed 100644 --- a/test/iidm/converter/xml/xiidm.cpp +++ b/test/iidm/converter/xml/xiidm.cpp @@ -8,14 +8,47 @@ #define BOOST_TEST_MODULE iidm-xml #include +#include "extensions/LoadBarXmlSerializer.hpp" +#include "extensions/LoadFooXmlSerializer.hpp" +#include "extensions/LoadMockExtXmlSerializer.hpp" +#include "extensions/LoadQuxXmlSerializer.hpp" +#include "extensions/TerminalMockXmlSerializer.hpp" +#include #include #include +namespace xml = powsybl::iidm::converter::xml; +namespace ext = powsybl::iidm::converter::xml::extensions; + namespace powsybl { namespace test { -BOOST_TEST_GLOBAL_FIXTURE(ExtensionFixture); +class ExtensionFixtureXiidm : public ResourceFixture { + public: + ExtensionFixtureXiidm(); + + ExtensionFixtureXiidm(const ExtensionFixtureXiidm&) = default; + + ExtensionFixtureXiidm(ExtensionFixtureXiidm&&) = default; + + ~ExtensionFixtureXiidm() = default; + + ExtensionFixtureXiidm& operator=(const ExtensionFixtureXiidm&) = default; + + ExtensionFixtureXiidm& operator=(ExtensionFixtureXiidm&&) = default; +}; + +ExtensionFixtureXiidm::ExtensionFixtureXiidm() { + auto& extProvider = powsybl::iidm::ExtensionProviders::getInstance(); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); + extProvider.registerExtension(stdcxx::make_unique()); +} + +BOOST_TEST_GLOBAL_FIXTURE(ExtensionFixtureXiidm); BOOST_TEST_GLOBAL_FIXTURE(XmlFixture); } // namespace test diff --git a/test/iidm/extensions/LoadDetailTest.cpp b/test/iidm/extensions/LoadDetailTest.cpp index e79d0479b..8bcd97a82 100644 --- a/test/iidm/extensions/LoadDetailTest.cpp +++ b/test/iidm/extensions/LoadDetailTest.cpp @@ -36,7 +36,7 @@ Network createNetwork() { .add(); VoltageLevel& vl = s.newVoltageLevel() .setId("VL") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl.getBusBreakerView().newBus() @@ -170,11 +170,12 @@ BOOST_FIXTURE_TEST_CASE(LoadDetailXmlSerializerTest, test::ResourceFixture) { } BOOST_FIXTURE_TEST_CASE(LoadDetailXmlSerializerOldRefTest, test::ResourceFixture) { - Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetwork("loadDetailOldRef.xml", converter::xml::IidmXmlVersion::V1_2())); + const std::string& filename = "loadDetailOldRef.xml"; + Network network = Network::readXml(test::converter::RoundTrip::getVersionedNetworkPath(filename, converter::xml::IidmXmlVersion::V1_2())); const std::string& refNetwork = test::converter::RoundTrip::getVersionedNetwork("loadDetailRef.xml", converter::xml::IidmXmlVersion::CURRENT_IIDM_XML_VERSION()); std::stringstream ostream; - Network::writeXml(ostream, network); + Network::writeXml(filename, ostream, network); BOOST_CHECK_EQUAL(refNetwork, ostream.str()); } diff --git a/test/iidm/extensions/SlackTerminalTest.cpp b/test/iidm/extensions/SlackTerminalTest.cpp index d0b7cabda..c8372eb9c 100644 --- a/test/iidm/extensions/SlackTerminalTest.cpp +++ b/test/iidm/extensions/SlackTerminalTest.cpp @@ -38,7 +38,7 @@ Network createBusBreakerNetwork() { .add(); VoltageLevel& vl = s.newVoltageLevel() .setId("VL") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl.getBusBreakerView().newBus() @@ -58,7 +58,7 @@ Network createBusBreakerNetwork() { .add(); VoltageLevel& vl1 = s.newVoltageLevel() .setId("VL1") - .setNominalVoltage(400) + .setNominalV(400) .setTopologyKind(TopologyKind::BUS_BREAKER) .add(); vl1.getBusBreakerView().newBus() diff --git a/test/iidm/util/TerminalFinderTest.cpp b/test/iidm/util/TerminalFinderTest.cpp index a643ccec9..1d6937dc1 100644 --- a/test/iidm/util/TerminalFinderTest.cpp +++ b/test/iidm/util/TerminalFinderTest.cpp @@ -19,8 +19,6 @@ namespace powsybl { namespace iidm { -namespace util { - BOOST_AUTO_TEST_SUITE(TerminalFinderTestSuite) BOOST_AUTO_TEST_CASE(testBbsTerminal) { @@ -30,7 +28,7 @@ BOOST_AUTO_TEST_CASE(testBbsTerminal) { BOOST_CHECK(static_cast(optTerminalN0)); const auto& terminalStream = optTerminalN0.get().getBusBreakerView().getBus().get().getConnectedTerminals(); - stdcxx::Reference bestOptTerminal = util::TerminalFinder::getDefault().find(terminalStream); + stdcxx::Reference bestOptTerminal = TerminalFinder::find(terminalStream); BOOST_CHECK(static_cast(bestOptTerminal)); Terminal& bestTerminal = bestOptTerminal.get(); @@ -43,12 +41,10 @@ BOOST_AUTO_TEST_CASE(testNoTerminal) { Network network = powsybl::network::FictitiousSwitchFactory::create(); VoltageLevel& vlN = network.getVoltageLevel("N"); - const util::TerminalFinder& slackTerminalFinder = util::TerminalFinder::getDefault(); - Bus& bus = vlN.getBusBreakerView().getBus("N_13"); const auto& terminalIter = bus.getConnectedTerminals(); - BOOST_CHECK(!static_cast(slackTerminalFinder.find(terminalIter))); + BOOST_CHECK(!static_cast(TerminalFinder::find(terminalIter))); } BOOST_AUTO_TEST_CASE(testLineTerminal1) { @@ -58,7 +54,7 @@ BOOST_AUTO_TEST_CASE(testLineTerminal1) { Bus& bus = vlhv2.getBusBreakerView().getBus("NHV1"); const auto& terminalStream = bus.getConnectedTerminals(); - stdcxx::Reference bestOptTerminal = util::TerminalFinder::getDefault().find(terminalStream); + stdcxx::Reference bestOptTerminal = TerminalFinder::find(terminalStream); BOOST_CHECK(static_cast(bestOptTerminal)); Terminal& bestTerminal = bestOptTerminal.get(); @@ -74,7 +70,7 @@ BOOST_AUTO_TEST_CASE(testLineTerminal2) { Bus& bus = vlhv2.getBusBreakerView().getBus("NHV2"); const auto& terminalStream = bus.getConnectedTerminals(); - stdcxx::Reference bestOptTerminal = util::TerminalFinder::getDefault().find(terminalStream); + stdcxx::Reference bestOptTerminal = TerminalFinder::find(terminalStream); BOOST_CHECK(static_cast(bestOptTerminal)); Terminal& bestTerminal = bestOptTerminal.get(); @@ -87,10 +83,14 @@ BOOST_AUTO_TEST_CASE(testGeneratorTerminal) { Network network = powsybl::network::EurostagFactory::createTutorial1Network(); VoltageLevel& vlgen = network.getVoltageLevel("VLGEN"); - Bus& bus = vlgen.getBusBreakerView().getBus("NGEN"); + const Bus& cBus = vlgen.getBusBreakerView().getBus("NGEN"); + const auto& cTerminalStream = cBus.getConnectedTerminals(); + stdcxx::CReference cBestOptTerminal = TerminalFinder::find(cTerminalStream); + BOOST_CHECK(static_cast(cBestOptTerminal)); + Bus& bus = vlgen.getBusBreakerView().getBus("NGEN"); const auto& terminalStream = bus.getConnectedTerminals(); - stdcxx::Reference bestOptTerminal = util::TerminalFinder::getDefault().find(terminalStream); + stdcxx::Reference bestOptTerminal = TerminalFinder::find(terminalStream); BOOST_CHECK(static_cast(bestOptTerminal)); Terminal& bestTerminal = bestOptTerminal.get(); @@ -102,29 +102,32 @@ BOOST_AUTO_TEST_CASE(testGeneratorTerminal) { BOOST_AUTO_TEST_CASE(testTerminalFromComparator) { Network network = powsybl::network::EurostagFactory::createTutorial1Network(); VoltageLevel& vlgen = network.getVoltageLevel("VLGEN"); + const Bus& cBus = vlgen.getBusBreakerView().getBus("NGEN"); Bus& bus = vlgen.getBusBreakerView().getBus("NGEN"); + const auto& cTerminalStream = cBus.getConnectedTerminals(); const auto& terminalStream = bus.getConnectedTerminals(); // sort by id alphabetically - util::TerminalFinder terminalFinderLess([](const Terminal& t1, const Terminal& t2) { + const TerminalFinder::Comparator& terminalFinderLess = [](const Terminal& t1, const Terminal& t2) { return t1.getConnectable().get().getId() < t2.getConnectable().get().getId(); - }); - Terminal& bestLessTerminal = terminalFinderLess.find(terminalStream).get(); + }; + const Terminal& cBestLessTerminal = TerminalFinder::find(terminalFinderLess, cTerminalStream).get(); + BOOST_CHECK_EQUAL("NGEN_NHV1", cBestLessTerminal.getConnectable().get().getNameOrId()); + + Terminal& bestLessTerminal = TerminalFinder::find(terminalFinderLess, terminalStream).get(); BOOST_CHECK_EQUAL("NGEN_NHV1", bestLessTerminal.getConnectable().get().getNameOrId()); // sort by id reverse alphabetically - util::TerminalFinder terminalFinderMore([](const Terminal& t1, const Terminal& t2) { + const TerminalFinder::Comparator& terminalFinderMore([](const Terminal& t1, const Terminal& t2) { return t1.getConnectable().get().getId() > t2.getConnectable().get().getId(); }); - Terminal& bestMoreTerminal = terminalFinderMore.find(terminalStream).get(); + Terminal& bestMoreTerminal = TerminalFinder::find(terminalFinderMore, terminalStream).get(); BOOST_CHECK_EQUAL("GEN", bestMoreTerminal.getConnectable().get().getNameOrId()); } BOOST_AUTO_TEST_SUITE_END() -} // namespace util - } // namespace iidm } // namespace powsybl diff --git a/test/logging/CMakeLists.txt b/test/logging/CMakeLists.txt index e28ade522..e65da4bb5 100644 --- a/test/logging/CMakeLists.txt +++ b/test/logging/CMakeLists.txt @@ -14,7 +14,9 @@ set(UNIT_TEST_SOURCES ) add_executable(unit-tests-logging ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-logging PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-logging PRIVATE iidm-tests) +if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-logging PRIVATE BOOST_TEST_DYN_LINK) +endif () +target_link_libraries(unit-tests-logging PRIVATE iidm-tests${TARGET_POSTFIX}) add_test(NAME logging COMMAND unit-tests-logging) diff --git a/test/math/CMakeLists.txt b/test/math/CMakeLists.txt index ef26708b5..445c11db7 100644 --- a/test/math/CMakeLists.txt +++ b/test/math/CMakeLists.txt @@ -11,7 +11,9 @@ set(UNIT_TEST_SOURCES ) add_executable(unit-tests-math ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-math PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-math PRIVATE iidm-tests) +if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-math PRIVATE BOOST_TEST_DYN_LINK) +endif () +target_link_libraries(unit-tests-math PRIVATE iidm-tests${TARGET_POSTFIX}) add_test(NAME math COMMAND unit-tests-math) diff --git a/test/network/CMakeLists.txt b/test/network/CMakeLists.txt index ed9250aa5..ff61ef6c3 100644 --- a/test/network/CMakeLists.txt +++ b/test/network/CMakeLists.txt @@ -10,7 +10,9 @@ set(UNIT_TEST_SOURCES network.cpp) add_executable(unit-tests-network ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-network PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-network PRIVATE iidm-tests) +if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-network PRIVATE BOOST_TEST_DYN_LINK) +endif () +target_link_libraries(unit-tests-network PRIVATE iidm-tests${TARGET_POSTFIX}) add_test(NAME network COMMAND unit-tests-network) diff --git a/test/network/EurostagFactoryTest.cpp b/test/network/EurostagFactoryTest.cpp index e9475fc28..362fb19e2 100644 --- a/test/network/EurostagFactoryTest.cpp +++ b/test/network/EurostagFactoryTest.cpp @@ -79,28 +79,28 @@ BOOST_AUTO_TEST_CASE(createTutorial1NetworkTest) { BOOST_CHECK_EQUAL_COLLECTIONS(expected2.cbegin(), expected2.cend(), actual2.cbegin(), actual2.cend()); const auto& vlGen = network.getVoltageLevel("VLGEN"); - BOOST_CHECK_CLOSE(24.0, vlGen.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(24.0, vlGen.getNominalV(), std::numeric_limits::epsilon()); BOOST_TEST(std::isnan(vlGen.getLowVoltageLimit())); BOOST_TEST(std::isnan(vlGen.getHighVoltageLimit())); BOOST_CHECK_EQUAL(iidm::TopologyKind::BUS_BREAKER, vlGen.getTopologyKind()); BOOST_CHECK_EQUAL(2UL, vlGen.getConnectableCount()); const auto& vlHv1 = network.getVoltageLevel("VLHV1"); - BOOST_CHECK_CLOSE(380.0, vlHv1.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(380.0, vlHv1.getNominalV(), std::numeric_limits::epsilon()); BOOST_TEST(std::isnan(vlHv1.getLowVoltageLimit())); BOOST_TEST(std::isnan(vlHv1.getHighVoltageLimit())); BOOST_CHECK_EQUAL(iidm::TopologyKind::BUS_BREAKER, vlHv1.getTopologyKind()); BOOST_CHECK_EQUAL(3UL, vlHv1.getConnectableCount()); const auto& vlHv2 = network.getVoltageLevel("VLHV2"); - BOOST_CHECK_CLOSE(380.0, vlHv2.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(380.0, vlHv2.getNominalV(), std::numeric_limits::epsilon()); BOOST_TEST(std::isnan(vlHv2.getLowVoltageLimit())); BOOST_TEST(std::isnan(vlHv2.getHighVoltageLimit())); BOOST_CHECK_EQUAL(iidm::TopologyKind::BUS_BREAKER, vlHv2.getTopologyKind()); BOOST_CHECK_EQUAL(3UL, vlHv2.getConnectableCount()); const auto& vlLoad = network.getVoltageLevel("VLLOAD"); - BOOST_CHECK_CLOSE(150.0, vlLoad.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(150.0, vlLoad.getNominalV(), std::numeric_limits::epsilon()); BOOST_TEST(std::isnan(vlLoad.getLowVoltageLimit())); BOOST_TEST(std::isnan(vlLoad.getHighVoltageLimit())); BOOST_CHECK_EQUAL(iidm::TopologyKind::BUS_BREAKER, vlLoad.getTopologyKind()); @@ -298,28 +298,28 @@ BOOST_AUTO_TEST_CASE(createWithCurrentLimitsTest) { BOOST_CHECK_EQUAL_COLLECTIONS(expected2.cbegin(), expected2.cend(), actual2.cbegin(), actual2.cend()); const auto& vlGen = network.getVoltageLevel("VLGEN"); - BOOST_CHECK_CLOSE(24.0, vlGen.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(24.0, vlGen.getNominalV(), std::numeric_limits::epsilon()); BOOST_TEST(std::isnan(vlGen.getLowVoltageLimit())); BOOST_TEST(std::isnan(vlGen.getHighVoltageLimit())); BOOST_CHECK_EQUAL(iidm::TopologyKind::BUS_BREAKER, vlGen.getTopologyKind()); BOOST_CHECK_EQUAL(3UL, vlGen.getConnectableCount()); const auto& vlHv1 = network.getVoltageLevel("VLHV1"); - BOOST_CHECK_CLOSE(380.0, vlHv1.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(380.0, vlHv1.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(400.0, vlHv1.getLowVoltageLimit(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(500.0, vlHv1.getHighVoltageLimit(), std::numeric_limits::epsilon()); BOOST_CHECK_EQUAL(iidm::TopologyKind::BUS_BREAKER, vlHv1.getTopologyKind()); BOOST_CHECK_EQUAL(3UL, vlHv1.getConnectableCount()); const auto& vlHv2 = network.getVoltageLevel("VLHV2"); - BOOST_CHECK_CLOSE(380.0, vlHv2.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(380.0, vlHv2.getNominalV(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(300.0, vlHv2.getLowVoltageLimit(), std::numeric_limits::epsilon()); BOOST_CHECK_CLOSE(500.0, vlHv2.getHighVoltageLimit(), std::numeric_limits::epsilon()); BOOST_CHECK_EQUAL(iidm::TopologyKind::BUS_BREAKER, vlHv2.getTopologyKind()); BOOST_CHECK_EQUAL(3UL, vlHv2.getConnectableCount()); const auto& vlLoad = network.getVoltageLevel("VLLOAD"); - BOOST_CHECK_CLOSE(150.0, vlLoad.getNominalVoltage(), std::numeric_limits::epsilon()); + BOOST_CHECK_CLOSE(150.0, vlLoad.getNominalV(), std::numeric_limits::epsilon()); BOOST_TEST(std::isnan(vlLoad.getLowVoltageLimit())); BOOST_TEST(std::isnan(vlLoad.getHighVoltageLimit())); BOOST_CHECK_EQUAL(iidm::TopologyKind::BUS_BREAKER, vlLoad.getTopologyKind()); diff --git a/test/resources/V1_4/LccRoundTripRef.xml b/test/resources/V1_4/LccRoundTripRef.xml new file mode 100644 index 000000000..20a69a36a --- /dev/null +++ b/test/resources/V1_4/LccRoundTripRef.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/VscRoundTripRef.xml b/test/resources/V1_4/VscRoundTripRef.xml new file mode 100644 index 000000000..a4965b49a --- /dev/null +++ b/test/resources/V1_4/VscRoundTripRef.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/batteryRoundTripRef.xml b/test/resources/V1_4/batteryRoundTripRef.xml new file mode 100644 index 000000000..8fb118128 --- /dev/null +++ b/test/resources/V1_4/batteryRoundTripRef.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/completeThreeWindingsTransformerRoundTripRef.xml b/test/resources/V1_4/completeThreeWindingsTransformerRoundTripRef.xml new file mode 100644 index 000000000..04f07209d --- /dev/null +++ b/test/resources/V1_4/completeThreeWindingsTransformerRoundTripRef.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/danglingLine.xml b/test/resources/V1_4/danglingLine.xml new file mode 100644 index 000000000..ce9edf8f4 --- /dev/null +++ b/test/resources/V1_4/danglingLine.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/danglingLineWithGeneration.xml b/test/resources/V1_4/danglingLineWithGeneration.xml new file mode 100644 index 000000000..28c42536a --- /dev/null +++ b/test/resources/V1_4/danglingLineWithGeneration.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1-properties.xml b/test/resources/V1_4/eurostag-tutorial-example1-properties.xml new file mode 100644 index 000000000..22d7c3928 --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1-properties.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1-terminalMock.xml b/test/resources/V1_4/eurostag-tutorial-example1-terminalMock.xml new file mode 100644 index 000000000..8d3470a10 --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1-terminalMock.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1-with-bad-loadMockExt.xml b/test/resources/V1_4/eurostag-tutorial-example1-with-bad-loadMockExt.xml new file mode 100644 index 000000000..b6596f039 --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1-with-bad-loadMockExt.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1-with-bad-loadQuxExt.xml b/test/resources/V1_4/eurostag-tutorial-example1-with-bad-loadQuxExt.xml new file mode 100644 index 000000000..5875de60f --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1-with-bad-loadQuxExt.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_1.xml b/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_1.xml new file mode 100644 index 000000000..71e724542 --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_1.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_2.xml b/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_2.xml new file mode 100644 index 000000000..cb46866b1 --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_2.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_3.xml b/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_3.xml new file mode 100644 index 000000000..59c9fd9c9 --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1-with-loadMockExt-1_3.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1-with-terminalMock-ext.xml b/test/resources/V1_4/eurostag-tutorial-example1-with-terminalMock-ext.xml new file mode 100644 index 000000000..1b598e819 --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1-with-terminalMock-ext.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial-example1.xml b/test/resources/V1_4/eurostag-tutorial-example1.xml new file mode 100644 index 000000000..1430ffe12 --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial-example1.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/eurostag-tutorial1-lf.xml b/test/resources/V1_4/eurostag-tutorial1-lf.xml new file mode 100644 index 000000000..f4f8841df --- /dev/null +++ b/test/resources/V1_4/eurostag-tutorial1-lf.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/fictitiousSwitchRef-bbk.xml b/test/resources/V1_4/fictitiousSwitchRef-bbk.xml new file mode 100644 index 000000000..8c3ac93a8 --- /dev/null +++ b/test/resources/V1_4/fictitiousSwitchRef-bbk.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/fictitiousSwitchRef-bbr.xml b/test/resources/V1_4/fictitiousSwitchRef-bbr.xml new file mode 100644 index 000000000..f1dc6a209 --- /dev/null +++ b/test/resources/V1_4/fictitiousSwitchRef-bbr.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/fictitiousSwitchRef.xml b/test/resources/V1_4/fictitiousSwitchRef.xml new file mode 100644 index 000000000..7a9ab15c9 --- /dev/null +++ b/test/resources/V1_4/fictitiousSwitchRef.xml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/fourSubstationsNbk.xml b/test/resources/V1_4/fourSubstationsNbk.xml new file mode 100644 index 000000000..450b7e6f1 --- /dev/null +++ b/test/resources/V1_4/fourSubstationsNbk.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/internalConnections.xml b/test/resources/V1_4/internalConnections.xml new file mode 100644 index 000000000..cc0edd406 --- /dev/null +++ b/test/resources/V1_4/internalConnections.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/loadDetailRef.xml b/test/resources/V1_4/loadDetailRef.xml new file mode 100644 index 000000000..862dc459a --- /dev/null +++ b/test/resources/V1_4/loadDetailRef.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/multiple-extensions.xml b/test/resources/V1_4/multiple-extensions.xml new file mode 100644 index 000000000..a98f1c12d --- /dev/null +++ b/test/resources/V1_4/multiple-extensions.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/nonLinearShuntRoundTripRef.xml b/test/resources/V1_4/nonLinearShuntRoundTripRef.xml new file mode 100644 index 000000000..2e257e2d8 --- /dev/null +++ b/test/resources/V1_4/nonLinearShuntRoundTripRef.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/optionalLoadTypeBug.xml b/test/resources/V1_4/optionalLoadTypeBug.xml new file mode 100644 index 000000000..db31dbbbf --- /dev/null +++ b/test/resources/V1_4/optionalLoadTypeBug.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/test/resources/V1_4/phaseShifterRoundTripRef.xml b/test/resources/V1_4/phaseShifterRoundTripRef.xml new file mode 100644 index 000000000..2d3197429 --- /dev/null +++ b/test/resources/V1_4/phaseShifterRoundTripRef.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/reactiveLimitsRoundTripRef.xml b/test/resources/V1_4/reactiveLimitsRoundTripRef.xml new file mode 100644 index 000000000..9e97c2b31 --- /dev/null +++ b/test/resources/V1_4/reactiveLimitsRoundTripRef.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/regulatingStaticVarCompensatorRoundTripRef.xml b/test/resources/V1_4/regulatingStaticVarCompensatorRoundTripRef.xml new file mode 100644 index 000000000..01f7838e7 --- /dev/null +++ b/test/resources/V1_4/regulatingStaticVarCompensatorRoundTripRef.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/regulatingTerminal.xml b/test/resources/V1_4/regulatingTerminal.xml new file mode 100644 index 000000000..ea43c1f8a --- /dev/null +++ b/test/resources/V1_4/regulatingTerminal.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/shuntRoundTripRef.xml b/test/resources/V1_4/shuntRoundTripRef.xml new file mode 100644 index 000000000..653371be3 --- /dev/null +++ b/test/resources/V1_4/shuntRoundTripRef.xml @@ -0,0 +1,24 @@ + + + + + + + + + Alias + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/staticVarCompensatorRoundTripRef.xml b/test/resources/V1_4/staticVarCompensatorRoundTripRef.xml new file mode 100644 index 000000000..2ed497f79 --- /dev/null +++ b/test/resources/V1_4/staticVarCompensatorRoundTripRef.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/terminalRef.xml b/test/resources/V1_4/terminalRef.xml new file mode 100644 index 000000000..302be340a --- /dev/null +++ b/test/resources/V1_4/terminalRef.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/threeWindingsTransformerRoundTripRef.xml b/test/resources/V1_4/threeWindingsTransformerRoundTripRef.xml new file mode 100644 index 000000000..1724628df --- /dev/null +++ b/test/resources/V1_4/threeWindingsTransformerRoundTripRef.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/tieline.xml b/test/resources/V1_4/tieline.xml new file mode 100644 index 000000000..8f963a697 --- /dev/null +++ b/test/resources/V1_4/tieline.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/tielineFictitious.xml b/test/resources/V1_4/tielineFictitious.xml new file mode 100644 index 000000000..e04ea41ca --- /dev/null +++ b/test/resources/V1_4/tielineFictitious.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/resources/V1_4/tielineWithAliases.xml b/test/resources/V1_4/tielineWithAliases.xml new file mode 100644 index 000000000..beb4ca27e --- /dev/null +++ b/test/resources/V1_4/tielineWithAliases.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Alias + Other alias + + + diff --git a/test/stdcxx/CMakeLists.txt b/test/stdcxx/CMakeLists.txt index 5d7def66e..fea9062c7 100644 --- a/test/stdcxx/CMakeLists.txt +++ b/test/stdcxx/CMakeLists.txt @@ -15,7 +15,9 @@ set(UNIT_TEST_SOURCES ) add_executable(unit-tests-stdcxx ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-stdcxx PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-stdcxx PRIVATE iidm-tests) +if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-stdcxx PRIVATE BOOST_TEST_DYN_LINK) +endif () +target_link_libraries(unit-tests-stdcxx PRIVATE iidm-tests${TARGET_POSTFIX}) add_test(NAME stdcxx COMMAND unit-tests-stdcxx) diff --git a/test/xml/CMakeLists.txt b/test/xml/CMakeLists.txt index 7c9cfa64e..f11cb7b2f 100644 --- a/test/xml/CMakeLists.txt +++ b/test/xml/CMakeLists.txt @@ -11,7 +11,9 @@ set(UNIT_TEST_SOURCES XmlStreamWriterTest.cpp) add_executable(unit-tests-xml ${UNIT_TEST_SOURCES}) -target_compile_definitions(unit-tests-xml PRIVATE BOOST_TEST_DYN_LINK) -target_link_libraries(unit-tests-xml PRIVATE iidm-tests) +if (BUILD_SHARED_LIBS) + target_compile_definitions(unit-tests-xml PRIVATE BOOST_TEST_DYN_LINK) +endif () +target_link_libraries(unit-tests-xml PRIVATE iidm-tests${TARGET_POSTFIX}) add_test(NAME xml COMMAND unit-tests-xml) diff --git a/tools/benchmark/Benchmark.cpp b/tools/benchmark/Benchmark.cpp index aa5bb224c..2af4826e2 100644 --- a/tools/benchmark/Benchmark.cpp +++ b/tools/benchmark/Benchmark.cpp @@ -109,25 +109,9 @@ int main(int argc, char** argv) { // Load the XIIDM extensions loadExtensions(vm[EXT_PATH].as()); - const auto& inputFile = vm[INPUT_FILE].as(); - std::ifstream inputStream(inputFile); - if (!inputStream.is_open()) { - std::cerr << stdcxx::format("Unable to open file '%1%' for reading", inputFile) << std::endl; - return EXIT_FAILURE; - } - - const auto& outputFile = vm[OUTPUT_FILE].as(); - std::ofstream outputStream(outputFile); - if (!outputStream.is_open()) { - std::cerr << stdcxx::format("Unable to open file '%1%' for writing", outputFile) << std::endl; - return EXIT_FAILURE; - } - - const powsybl::iidm::Network& network = powsybl::iidm::Network::readXml(inputStream, powsybl::iidm::converter::ImportOptions(options), powsybl::iidm::converter::FakeAnonymizer()); - powsybl::iidm::Network::writeXml(outputStream, network, powsybl::iidm::converter::ExportOptions(options)); + const powsybl::iidm::Network& network = powsybl::iidm::Network::readXml(vm[INPUT_FILE].as(), powsybl::iidm::converter::ImportOptions(options)); + powsybl::iidm::Network::writeXml(vm[OUTPUT_FILE].as(), network, powsybl::iidm::converter::ExportOptions(options)); - inputStream.close(); - outputStream.close(); } catch (const boost::program_options::error& e) { std::cerr << "ERROR: " << e.what() << std::endl << std::endl; std::cerr << desc << std::endl; diff --git a/tools/benchmark/CMakeLists.txt b/tools/benchmark/CMakeLists.txt index ab7fb7920..f27d0a016 100644 --- a/tools/benchmark/CMakeLists.txt +++ b/tools/benchmark/CMakeLists.txt @@ -10,7 +10,7 @@ set(IIDM_BENCHMARK_SOURCES ) add_executable(iidm-benchmark ${IIDM_BENCHMARK_SOURCES}) -target_link_libraries(iidm-benchmark PRIVATE iidm Boost::program_options) +target_link_libraries(iidm-benchmark PRIVATE iidm${TARGET_POSTFIX} Boost::program_options) # Installation install(TARGETS iidm-benchmark