From 53f8f90685bcf777f959048e396f8851c34b898a Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 14 Feb 2024 11:48:59 +0000 Subject: [PATCH 001/168] villas: Use Python dictionaries for defining VILLASconfig files Signed-off-by: Steffen Vogel --- examples/villas/dpsim-file.py | 20 +++++++------ .../villas/dpsim-mqtt-cigre-mv-pf-profiles.py | 19 +++++++------ .../villas/dpsim-mqtt-import-export-MIMO.py | 28 +++++++++---------- examples/villas/dpsim-mqtt-import-export.py | 16 +++++------ examples/villas/dpsim-mqtt.py | 28 ++++++++++--------- 5 files changed, 59 insertions(+), 52 deletions(-) diff --git a/examples/villas/dpsim-file.py b/examples/villas/dpsim-file.py index cf7b157d6e..dbab6bf162 100644 --- a/examples/villas/dpsim-file.py +++ b/examples/villas/dpsim-file.py @@ -1,5 +1,7 @@ # This example demonstrates the export of values calculated by dpsim to a file using the VILLASnode interface +import json + import dpsimpy import dpsimpyvillas @@ -39,16 +41,16 @@ sim.set_time_step(time_step) sim.set_final_time(final_time) -file_config = '''{ - "type": "file", - "format": "csv", - "uri": "logs/output.csv", - "out": { - "flush": true - } -}''' +intf_config = { + 'type': 'file', + 'format': 'csv', + 'uri': 'logs/output.csv', + 'out': { + 'flush': True + } +} -intf = dpsimpyvillas.InterfaceVillas(file_config, name='dpsim-file') +intf = dpsimpyvillas.InterfaceVillas(name='dpsim-file', config=json.dumps(intf_config)) intf.export_attribute(evs.attr('i_intf').derive_coeff(0, 0), 0) sim.add_interface(intf) diff --git a/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py b/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py index 8b5ef2c850..3bc4e531b3 100644 --- a/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py +++ b/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py @@ -4,6 +4,7 @@ import logging import os import sys +import json import dpsimpy import dpsimpyvillas @@ -55,16 +56,18 @@ logger = dpsimpy.Logger(name) # setup VILLASnode -intf_mqtt = dpsimpyvillas.InterfaceVillas(name='MQTT', config='''{ - "type": "mqtt", - "host": "mqtt", - "in": { - "subscribe": "mqtt-dpsim" +intf_mqtt_config = { + 'type': 'mqtt', + 'host': 'mqtt', + 'in': { + 'subscribe': 'mqtt-dpsim' }, - "out": { - "publish": "dpsim-mqtt" + 'out': { + 'publish': 'dpsim-mqtt' } -}''') +} + +intf_mqtt = dpsimpyvillas.InterfaceVillas(name='MQTT', config=json.dumps(intf_mqtt_config)) # setup simulation sim = dpsimpy.RealTimeSimulation(name) diff --git a/examples/villas/dpsim-mqtt-import-export-MIMO.py b/examples/villas/dpsim-mqtt-import-export-MIMO.py index 1e37e46b86..f11efa8606 100644 --- a/examples/villas/dpsim-mqtt-import-export-MIMO.py +++ b/examples/villas/dpsim-mqtt-import-export-MIMO.py @@ -155,31 +155,31 @@ def dpsim(): sim.log_attribute('n2.v', n1.attr('v')) intf_config = { - "type": "mqtt", - "format": "json", - "host": "mqtt", - "in": { - "subscribe": "/mqtt-dpsim" + 'type': 'mqtt', + 'format': 'json', + 'host': 'mqtt', + 'in': { + 'subscribe': '/mqtt-dpsim' }, - "out": { - "publish": "/dpsim-mqtt" + 'out': { + 'publish': '/dpsim-mqtt' } } intf_config_2 = { - "type": "shmem", - "in": { - "name": "/shmem-dpsim" + 'type': 'shmem', + 'in': { + 'name': '/shmem-dpsim' }, - "out": { - "name": "/dpsim-shmem" + 'out': { + 'name': '/dpsim-shmem' } } - intf = dpsimpyvillas.InterfaceVillas(name="dpsim-mqtt", config=intf_config) + intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) sim.add_interface(intf) - intf2 = dpsimpyvillas.InterfaceVillas(name="dpsim-shmem", config=intf_config_2) + intf2 = dpsimpyvillas.InterfaceVillas(name='dpsim-shmem', config=json.dumps(intf_config_2)) sim.add_interface(intf2) intf.import_attribute(load.attr('P'), 0) intf.export_attribute(n1.attr('v').derive_coeff(0,0), 0) diff --git a/examples/villas/dpsim-mqtt-import-export.py b/examples/villas/dpsim-mqtt-import-export.py index 8367852c33..9d30034666 100644 --- a/examples/villas/dpsim-mqtt-import-export.py +++ b/examples/villas/dpsim-mqtt-import-export.py @@ -125,18 +125,18 @@ def dpsim(): sim.log_attribute('n2.v', n2.attr('v')) intf_config = { - "type": "mqtt", - "format": "json", - "host": "mqtt", - "in": { - "subscribe": "/mqtt-dpsim" + 'type': 'mqtt', + 'format': 'json', + 'host': 'mqtt', + 'in': { + 'subscribe': '/mqtt-dpsim' }, - "out": { - "publish": "/dpsim-mqtt" + 'out': { + 'publish': '/dpsim-mqtt' } } - intf = dpsimpyvillas.InterfaceVillas(name="dpsim-mqtt", config=intf_config) + intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) intf.import_attribute(load.attr('P'), 0) intf.export_attribute(n1.attr('v').derive_coeff(0,0), 0) intf.export_attribute(n2.attr('v').derive_coeff(0,0).derive_mag(), 1) diff --git a/examples/villas/dpsim-mqtt.py b/examples/villas/dpsim-mqtt.py index f50007efe2..b318e1827f 100644 --- a/examples/villas/dpsim-mqtt.py +++ b/examples/villas/dpsim-mqtt.py @@ -1,6 +1,8 @@ # This example demonstrates the export of values calculated by dpsim to a MQTT broker using the VILLASnode interface # Note, that dpsim also expects to read a (complex) reference voltage from MQTT, so the simulation will block on every timestep until this value is provided +import json + import dpsimpy import dpsimpyvillas @@ -40,19 +42,19 @@ sim.set_time_step(time_step) sim.set_final_time(final_time) -mqtt_config = '''{ - "type": "mqtt", - "format": "json", - "host": "mqtt", - "in": { - "subscribe": "/mqtt-dpsim" - }, - "out": { - "publish": "/dpsim-mqtt" - } -}''' - -intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=mqtt_config) +intf_config = { + 'type': 'mqtt', + 'format': 'json', + 'host': 'mqtt', + 'in': { + 'subscribe': '/mqtt-dpsim' + }, + 'out': { + 'publish': '/dpsim-mqtt' + } +} + +intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) intf.import_attribute(evs.attr('V_ref'), 0, True) intf.export_attribute(r12.attr('i_intf').derive_coeff(0, 0), 0) From 5b8dd51967976ea6404b68115087743e39c4f901 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:19:31 +0100 Subject: [PATCH 002/168] fix: Cleanup code-style of setup.py Signed-off-by: Steffen Vogel --- python/README.md | 2 +- setup.py | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/python/README.md b/python/README.md index 299f2c31ac..de08399d41 100644 --- a/python/README.md +++ b/python/README.md @@ -1 +1 @@ -This python package wraps the C++ core package of DPsim and includes pure python code that is convenient to use in combination with the simulation core. \ No newline at end of file +This Python package wraps the C++ core package of DPsim and includes pure Python code that is convenient to use in combination with the simulation core. diff --git a/setup.py b/setup.py index c9b1ddecea..701ee0179a 100644 --- a/setup.py +++ b/setup.py @@ -1,24 +1,22 @@ import os -import re import sys import platform import subprocess from setuptools import setup, find_packages, Extension from setuptools.command.build_ext import build_ext -from distutils.version import LooseVersion class CMakeExtension(Extension): def __init__(self, name): Extension.__init__(self, name, sources=[]) + class CMakeBuild(build_ext): def build_extension(self, ext): extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) - debug = int(os.environ.get("DEBUG", 0)) if self.debug is None else self.debug cfg = 'Debug' if self.debug else 'Release' print('building CMake extension in %s configuration' % cfg) @@ -27,7 +25,7 @@ def build_extension(self, ext): f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG={extdir}", f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE={extdir}", f"-DPYTHON_EXECUTABLE={sys.executable}", - f"-DCMAKE_BUILD_TYPE={cfg}" # not used on MSVC, but no harm + f"-DCMAKE_BUILD_TYPE={cfg}" # not used on MSVC, but no harm ] if platform.system() == 'Windows': @@ -58,6 +56,7 @@ def build_extension(self, ext): ['cmake', '--build', '.', '--target', 'dpsimpy'] + build_args, cwd=self.build_temp ) + setup( packages=find_packages('python/src'), package_dir={"dpsim": "python/src/dpsim"}, From eb85b1b556048bbeb4587da4818d7a172ce273ce Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:36:39 +0100 Subject: [PATCH 003/168] fix(style): Remove duplicated typedef Signed-off-by: Steffen Vogel --- dpsim-models/include/dpsim-models/Definitions.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Definitions.h b/dpsim-models/include/dpsim-models/Definitions.h index 88eec7e6b8..cd1481334f 100644 --- a/dpsim-models/include/dpsim-models/Definitions.h +++ b/dpsim-models/include/dpsim-models/Definitions.h @@ -92,8 +92,6 @@ typedef Eigen::PartialPivLU LUFactorized; /// typedef Eigen::SparseLU LUFactorizedSparse; /// -typedef Eigen::Matrix Vector; -/// template using MatrixVar = Eigen::Matrix; From 700eaeaa848fafee580ac7b9648ac3ad7112bf3e Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:21:32 +0100 Subject: [PATCH 004/168] fix(docs): Fix typo and wrong diff Signed-off-by: Steffen Vogel --- docs/hugo/content/en/docs/Getting started/real-time.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/hugo/content/en/docs/Getting started/real-time.md b/docs/hugo/content/en/docs/Getting started/real-time.md index 03175856e0..b0e279e832 100644 --- a/docs/hugo/content/en/docs/Getting started/real-time.md +++ b/docs/hugo/content/en/docs/Getting started/real-time.md @@ -43,7 +43,7 @@ Note that this is not persistent when rebooting. ## Simulation Model Tuning Real time capable models cannot issue any system calls during simulation as the context switch to the kernel introduces unacceptable latencies. -This means models cannot allocate memory, use mutexes or other interupt-driven synchronization primitives, read or write data from files. +This means models cannot allocate memory, use mutexes or other interrupt-driven synchronization primitives, read or write data from files. You should turn off logging, when time steps in the low milliseconds are desired. There is a `RealTimeDataLogger` that can be used to output simulation results in these cases. Note however, that this logger pre-allocated the memory required for all of the logging required during simulations. @@ -59,8 +59,8 @@ index 8801cbe8d..4a2843269 100644 check_symbol_exists(timerfd_create sys/timerfd.h HAVE_TIMERFD) check_symbol_exists(getopt_long getopt.h HAVE_GETOPT) if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") -- add_compile_options(-flto -march=native -Ofast) -+ add_compile_options( -Ofast) +- add_compile_options(-Ofast) ++ add_compile_options(-Ofast -flto -march=native) endif() # Get version info and buildid from Git From a6dc445f2068fabbf0f4393d8010afd6c7b8a6a7 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:40:57 +0100 Subject: [PATCH 005/168] feat(cmake): Allow disable LTO builds Signed-off-by: Steffen Vogel --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8801cbe8d5..0b851c1e9d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,9 @@ set(PROJECT_DESCRIPTION "C++ Power System Simulation Library") set(PROJECT_HOMEPAGE_URL "https://dpsim.fein-aachen.org/") set(PROJECT_VCS_URL "https://github.com/sogno-platform/dpsim") +# Build options +option(WITH_LTO "Enable Link Time Optimization in Release builds" ON) + # Required for dpsim_python if(POLICY CMP0076) cmake_policy(SET CMP0076 NEW) @@ -79,7 +82,11 @@ include(CheckSymbolExists) check_symbol_exists(timerfd_create sys/timerfd.h HAVE_TIMERFD) check_symbol_exists(getopt_long getopt.h HAVE_GETOPT) if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - add_compile_options(-flto -march=native -Ofast) + add_compile_options(-march=native -Ofast) + + if(WITH_LTO) + add_compile_options(-flto) + endif() endif() # Get version info and buildid from Git From d68db551334b35bddbc31b3f68e5ff46978691d2 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 11:49:33 +0100 Subject: [PATCH 006/168] fix(cmake): Add WITH_MARCH_NATIVE option to enable native host arch builds Signed-off-by: Steffen Vogel --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b851c1e9d..04517fc215 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ set(PROJECT_VCS_URL "https://github.com/sogno-platform/dpsim") # Build options option(WITH_LTO "Enable Link Time Optimization in Release builds" ON) +option(WITH_MARCH_NATIVE "Optimize build for native host architecture" ON) # Required for dpsim_python if(POLICY CMP0076) @@ -82,7 +83,11 @@ include(CheckSymbolExists) check_symbol_exists(timerfd_create sys/timerfd.h HAVE_TIMERFD) check_symbol_exists(getopt_long getopt.h HAVE_GETOPT) if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - add_compile_options(-march=native -Ofast) + add_compile_options(-Ofast) + + if(WITH_MARCH_NATIVE) + add_compile_options(-march=native) + endif() if(WITH_LTO) add_compile_options(-flto) From 1f28c5753611e49738391fb09af9e57bec8802dd Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 11:50:08 +0100 Subject: [PATCH 007/168] fix(cmake): Disable WITH_LTO and WITH_MARCH_NATIVE options by default Signed-off-by: Steffen Vogel --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 04517fc215..9d683a0eba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,8 @@ set(PROJECT_HOMEPAGE_URL "https://dpsim.fein-aachen.org/") set(PROJECT_VCS_URL "https://github.com/sogno-platform/dpsim") # Build options -option(WITH_LTO "Enable Link Time Optimization in Release builds" ON) -option(WITH_MARCH_NATIVE "Optimize build for native host architecture" ON) +option(WITH_LTO "Enable Link Time Optimization in Release builds" OFF) +option(WITH_MARCH_NATIVE "Optimize build for native host architecture" OFF) # Required for dpsim_python if(POLICY CMP0076) From eaebca7c7d4125bc4b06c799db681807dd05c03c Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:22:06 +0100 Subject: [PATCH 008/168] fix(examples): Only build Fpga9BusHil example if build with CIMpp Signed-off-by: Steffen Vogel --- dpsim-villas/examples/cxx/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index 51c7ceed15..db5bb8bd58 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -20,7 +20,6 @@ set(SHMEM_SOURCES FpgaExample.cpp FpgaCosim3PhInfiniteBus.cpp FpgaCosimulation.cpp - Fpga9BusHil.cpp SharedMemExample.cpp #ShmemExample.cpp #ShmemDistributedReference.cpp @@ -33,6 +32,7 @@ set(SHMEM_SOURCES ) if(WITH_CIM) + list(APPEND SHMEM_SOURCES Fpga9BusHil.cpp) list(APPEND INCLUDE_DIRS ${CIMPP_INCLUDE_DIRS}) endif() From e632d7960058d1b07ebe58ae2d9096a415ac0275 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 11:44:53 +0100 Subject: [PATCH 009/168] fix(cmake): Renamed CMake variable Signed-off-by: Steffen Vogel --- dpsim-villas/examples/cxx/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index db5bb8bd58..a8fb2e8254 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -14,7 +14,7 @@ list(APPEND LIBRARIES "villas-fpga") list(APPEND LIBRARIES "xil") list(APPEND INCLUDE_DIRS ${VILLASNODE_INCLUDE_DIRS}) -set(SHMEM_SOURCES +set(DPSIM_VILLAS_EXAMPLE_SOURCES FileExample.cpp MqttExample.cpp FpgaExample.cpp @@ -32,11 +32,11 @@ set(SHMEM_SOURCES ) if(WITH_CIM) - list(APPEND SHMEM_SOURCES Fpga9BusHil.cpp) + list(APPEND DPSIM_VILLAS_EXAMPLE_SOURCES Fpga9BusHil.cpp) list(APPEND INCLUDE_DIRS ${CIMPP_INCLUDE_DIRS}) endif() -foreach(SOURCE ${SHMEM_SOURCES} ${CIM_SHMEM_SOURCES}) +foreach(SOURCE ${DPSIM_VILLAS_EXAMPLE_SOURCES} ${CIM_DPSIM_VILLAS_SOURCES}) get_filename_component(TARGET ${SOURCE} NAME_WE) add_executable(${TARGET} ${SOURCE}) From 369fb7edab72eed1d9726db76aff9c77ba6a8989 Mon Sep 17 00:00:00 2001 From: Felix Wege Date: Mon, 31 Mar 2025 11:40:10 +0200 Subject: [PATCH 010/168] fix(mnasolver): wrap extern c in preprocessor condition To allow C plugins to include MNASolverDynInterface, `extern "C"` needs to be wrapped in a preprocessor condition for C++ only. Signed-off-by: Felix Wege --- dpsim/include/dpsim/MNASolverDynInterface.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/dpsim/include/dpsim/MNASolverDynInterface.h b/dpsim/include/dpsim/MNASolverDynInterface.h index 8d311b3569..a629ffb274 100644 --- a/dpsim/include/dpsim/MNASolverDynInterface.h +++ b/dpsim/include/dpsim/MNASolverDynInterface.h @@ -25,6 +25,12 @@ struct dpsim_mna_plugin { void (*cleanup)(void); }; -extern "C" struct dpsim_mna_plugin *get_mna_plugin(const char *name); +#ifdef __cplusplus +extern "C" { +#endif +struct dpsim_mna_plugin *get_mna_plugin(const char *name); +#ifdef __cplusplus +} +#endif #endif From f4885c9a1ee3d74105381b7144f322a81c513bde Mon Sep 17 00:00:00 2001 From: Felix Wege Date: Mon, 31 Mar 2025 11:46:21 +0200 Subject: [PATCH 011/168] fix: include paths of MNASolverPlugin examples Signed-off-by: Felix Wege --- dpsim/src/SolverPlugins/example/Makefile | 2 +- dpsim/src/SolverPlugins/magma/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dpsim/src/SolverPlugins/example/Makefile b/dpsim/src/SolverPlugins/example/Makefile index ba63af42a9..c525cacb7f 100644 --- a/dpsim/src/SolverPlugins/example/Makefile +++ b/dpsim/src/SolverPlugins/example/Makefile @@ -6,7 +6,7 @@ CC = gcc all: plugin.so %.o : %.c - $(CC) $(CC_FLAGS) -I../../../Include -c -fpic -o $@ $< + $(CC) $(CC_FLAGS) -I../../../include -c -fpic -o $@ $< plugin.so: example.o $(CC) $(LD_FLAGS) -shared -o $@ $< diff --git a/dpsim/src/SolverPlugins/magma/Makefile b/dpsim/src/SolverPlugins/magma/Makefile index 17d61434ef..48bbe70cf5 100644 --- a/dpsim/src/SolverPlugins/magma/Makefile +++ b/dpsim/src/SolverPlugins/magma/Makefile @@ -9,7 +9,7 @@ LD_FLAGS += -g -lmagma -lmagma_sparse all: libdps_magma.so %.o : %.c - $(CC) $(CC_FLAGS) -I../../../Include -c -fpic -o $@ $< + $(CC) $(CC_FLAGS) -I../../../include -c -fpic -o $@ $< libdps_magma.so: magma.o $(CC) -shared -o $@ $< $(LD_FLAGS) From 2dee7a6257d2a9ddd07fce76b5788b18e75c964f Mon Sep 17 00:00:00 2001 From: Felix Wege Date: Mon, 31 Mar 2025 11:51:38 +0200 Subject: [PATCH 012/168] fix: library name of example plugin Signed-off-by: Felix Wege --- dpsim/src/SolverPlugins/example/example.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpsim/src/SolverPlugins/example/example.c b/dpsim/src/SolverPlugins/example/example.c index 4c82eff6e7..d8e06ec06c 100644 --- a/dpsim/src/SolverPlugins/example/example.c +++ b/dpsim/src/SolverPlugins/example/example.c @@ -9,7 +9,7 @@ int example_solve(double *rhs_values, double *lhs_values); void example_log(const char *str); void example_cleanup(void); -static const char *PLUGIN_NAME = "plugin.so"; +static const char *PLUGIN_NAME = "plugin"; static struct dpsim_mna_plugin example_plugin = { .log = example_log, //a properly working dpsim will override this with the spdlog logger From 909b39b7fd21a9c5a48d50a6575c110e7febe43b Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 07:48:38 +0200 Subject: [PATCH 013/168] fix(ci): Attempt to fix PyPi package publish Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 86c8fbf1f3..2066ce6313 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -50,12 +50,12 @@ jobs: # run: docker build . --file packaging/Docker/Dockerfile.manylinux -t sogno/dpsim:manylinux - name: Build dpsim wheels for all supported python versions - uses: pypa/cibuildwheel@v2.18.0 + uses: pypa/cibuildwheel@v2.23.2 with: output-dir: dist - name: Publish distribution to Test PyPI - uses: pypa/gh-action-pypi-publish@release/v1.8 + uses: pypa/gh-action-pypi-publish@release/v1.12.4 with: password: ${{ secrets.TEST_PYPI_API_TOKEN }} repository_url: https://test.pypi.org/legacy/ @@ -63,6 +63,6 @@ jobs: - name: Publish distribution to PyPI if: startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@release/v1.8 + uses: pypa/gh-action-pypi-publish@release/v1.12.4 with: password: ${{ secrets.PYPI_API_TOKEN }} \ No newline at end of file From 397acd992e7f147b6adf98c402db9060b41f8e28 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 11:02:30 +0200 Subject: [PATCH 014/168] fix(ci): Fix tag of pypa/gh-action-pypi-publish action Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 2066ce6313..8b5ef9cd91 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -23,7 +23,7 @@ jobs: run: python3 -m build --sdist --outdir dist/ - name: Publish distribution to Test PyPI - uses: pypa/gh-action-pypi-publish@release/v1.8 + uses: pypa/gh-action-pypi-publish@v1.12.4 with: password: ${{ secrets.TEST_PYPI_API_TOKEN }} repository_url: https://test.pypi.org/legacy/ @@ -31,7 +31,7 @@ jobs: - name: Publish distribution to PyPI if: startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@release/v1.8 + uses: pypa/gh-action-pypi-publish@v1.12.4 with: password: ${{ secrets.PYPI_API_TOKEN }} @@ -55,7 +55,7 @@ jobs: output-dir: dist - name: Publish distribution to Test PyPI - uses: pypa/gh-action-pypi-publish@release/v1.12.4 + uses: pypa/gh-action-pypi-publish@v1.12.4 with: password: ${{ secrets.TEST_PYPI_API_TOKEN }} repository_url: https://test.pypi.org/legacy/ @@ -63,6 +63,6 @@ jobs: - name: Publish distribution to PyPI if: startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@release/v1.12.4 + uses: pypa/gh-action-pypi-publish@v1.12.4 with: password: ${{ secrets.PYPI_API_TOKEN }} \ No newline at end of file From 5103091407474e356260c2d276e426490aa1fe83 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 11:10:29 +0200 Subject: [PATCH 015/168] fix(ci): Upgrade version of setuptools for publishing packages to PyPi Signed-off-by: Steffen Vogel --- packaging/Docker/Dockerfile.dev | 2 +- packaging/Docker/Dockerfile.dev-minimal | 2 +- packaging/Docker/Dockerfile.manylinux | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index c12d260950..efd9253a5f 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -72,7 +72,7 @@ RUN dnf -y install \ # Python dependencies ADD requirements.txt . -RUN pip3 install --upgrade wheel build +RUN pip3 install --upgrade wheel build setuptools RUN pip3 install -r requirements.txt # Install CIMpp from source diff --git a/packaging/Docker/Dockerfile.dev-minimal b/packaging/Docker/Dockerfile.dev-minimal index 1394c8efc6..c2551fd06f 100644 --- a/packaging/Docker/Dockerfile.dev-minimal +++ b/packaging/Docker/Dockerfile.dev-minimal @@ -23,7 +23,7 @@ RUN dnf --refresh -y install \ # Python dependencies ADD requirements.txt . -RUN pip3 install --upgrade wheel build +RUN pip3 install --upgrade wheel build setuptools RUN pip3 install -r requirements.txt EXPOSE 8888 diff --git a/packaging/Docker/Dockerfile.manylinux b/packaging/Docker/Dockerfile.manylinux index a27a4e53b8..35cc813abf 100644 --- a/packaging/Docker/Dockerfile.manylinux +++ b/packaging/Docker/Dockerfile.manylinux @@ -64,7 +64,7 @@ ENV LD_LIBRARY_PATH="/usr/local/lib64:${LD_LIBRARY_PATH}" # Python dependencies ADD requirements-manylinux.txt . -RUN pip3 install --upgrade wheel build +RUN pip3 install --upgrade wheel build setuptools RUN pip3 install -r requirements-manylinux.txt # Install CIMpp from source From 1110dc6078e59cdac2d22300fd27f58da0dee04d Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 28 Feb 2024 18:38:39 +0100 Subject: [PATCH 016/168] Fix some capitalization Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 8b5ef9cd91..75a140ff95 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -1,4 +1,4 @@ -name: Publish dpsim package to PyPi +name: Publish DPsim package to Python Package Index (PyPI) on: push: @@ -9,7 +9,7 @@ on: jobs: build-and-publish-sdist: - name: Build dpsim sdist and publish to PyPi + name: Build DPsim source distribution and publish to PyPi runs-on: ubuntu-latest container: sogno/dpsim:dev steps: @@ -18,7 +18,7 @@ jobs: with: submodules: recursive - - name: Build dpsim source dist + - name: Build DPsim source distribution shell: bash run: python3 -m build --sdist --outdir dist/ @@ -35,9 +35,8 @@ jobs: with: password: ${{ secrets.PYPI_API_TOKEN }} - build-and-publish-wheels: - name: Build dpsim wheels and publish to PyPi + name: Build DPsim wheels and publish to PyPI runs-on: ubuntu-20.04 steps: - name: Checkout @@ -45,11 +44,7 @@ jobs: with: submodules: recursive - # - name: Build manylinux docker image # Remove this step as soon as the image is published on docker hub - # shell: bash - # run: docker build . --file packaging/Docker/Dockerfile.manylinux -t sogno/dpsim:manylinux - - - name: Build dpsim wheels for all supported python versions + - name: Build DPsim wheels for all supported Python versions uses: pypa/cibuildwheel@v2.23.2 with: output-dir: dist From 4d81db10617cbff404bb9ce4d5de6f7a073b60f1 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 28 Feb 2024 17:20:35 +0100 Subject: [PATCH 017/168] Fixup whitespaces Remove trailing whitespaces Harmonize file endings to single empty line Signed-off-by: Steffen Vogel --- .github/workflows/container.yaml | 1 - .github/workflows/documentation-fein.yaml | 4 +- .github/workflows/publish_to_pypi.yaml | 2 +- .../workflows/run_and_profile_example.yaml | 6 +- LICENSE | 2 +- configs/realtime_tests/decoupled.sh | 2 +- configs/realtime_tests/diakoptics.sh | 2 +- configs/realtime_tests/inverter.sh | 2 +- configs/shmem_cosim/shmem_test.conf | 4 +- configs/start_ShmemDistributedDirect.sh | 4 +- docs/doxygen/DoxyMain.md | 2 - docs/hugo/.gitignore | 1 - docs/hugo/Dockerfile | 2 +- docs/hugo/config.toml | 14 ++--- docs/hugo/content/en/_index.html | 1 - .../content/en/docs/Concepts/dyn-phasors.md | 1 - .../content/en/docs/Concepts/powerflow.md | 6 +- .../en/docs/Contribution guidelines/index.md | 2 +- .../content/en/docs/Development/Debugging.md | 12 ++-- .../content/en/docs/Getting started/_index.md | 2 - .../content/en/docs/Getting started/build.md | 2 +- .../en/docs/Getting started/install.md | 2 +- .../en/docs/Models/RLC-Elements/index.md | 2 +- .../en/docs/Models/Transformer/index.md | 6 +- .../en/docs/Models/power-electronics.md | 2 +- .../en/docs/Overview/Attributes/index.md | 12 ++-- .../en/docs/Overview/Scheduling/index.md | 2 +- docs/hugo/content/en/docs/Overview/_index.md | 1 - .../content/en/docs/Overview/subcomponents.md | 8 +-- docs/hugo/content/en/docs/Reference/index.md | 2 +- docs/hugo/content/en/docs/Roadmap/index.md | 3 +- docs/hugo/content/en/docs/Tasks/_index.md | 1 - .../en/docs/Tasks/create-simulation.md | 2 +- docs/hugo/content/en/search.md | 1 - docs/hugo/docker-entrypoint.sh | 2 +- docs/past-commits.txt | 1 - docs/sphinx/Reference.rst | 2 +- dpsim-models/include/dpsim-models/Factory.h | 2 +- dpsim/examples/cxx/GeneratorFactory.h | 2 +- dpsim/examples/cxx/test_RealTime.yml | 2 +- dpsim/examples/cxx/test_Shmem.yml | 2 +- dpsim/include/dpsim/pybind/Attributes.h | 2 +- dpsim/src/SolverPlugins/magma/Makefile | 2 +- dpsim/src/pybind/CMakeLists.txt | 2 +- examples/Matlab/CalculateError.m | 56 +++++++++---------- examples/Matlab/CompareDPandEMT_DPsim.m | 3 +- examples/Matlab/CompareSynGenResults.m | 16 +++--- examples/Matlab/CompareVBRandDQ.m | 2 +- examples/Matlab/CompareVBRandDQ_DP.m | 10 ++-- examples/Matlab/DP_CompareSynGenResults.m | 17 +++--- examples/Matlab/ExciterTest.m | 2 +- examples/Matlab/FundamentalToStandard.m | 5 +- examples/Matlab/StandardToFundamental.m | 1 - examples/Matlab/TurbineTest.m | 4 +- examples/Matlab/compareDpAndEmt.m | 3 +- examples/Matlab/compareDpAndEmtInterp.m | 1 - examples/Matlab/compareDpResults.m | 2 +- examples/Matlab/mmi_ICCEP.m | 2 +- examples/Matlab/plotDpEmtVoltage.m | 2 +- .../docker-compose.yml | 2 +- scripts/start_jupyter.sh | 2 +- 61 files changed, 123 insertions(+), 144 deletions(-) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index befcd30a23..c38c36cc40 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -103,4 +103,3 @@ jobs: file: packaging/Docker/Dockerfile.manylinux push: true tags: sogno/dpsim:manylinux - diff --git a/.github/workflows/documentation-fein.yaml b/.github/workflows/documentation-fein.yaml index 414fd285c3..f3fdec69fd 100644 --- a/.github/workflows/documentation-fein.yaml +++ b/.github/workflows/documentation-fein.yaml @@ -5,7 +5,7 @@ on: branches: - master -jobs: +jobs: deploy: runs-on: ubuntu-latest steps: @@ -36,7 +36,7 @@ jobs: - name: Deploy dpsim-simulator / FEIN uses: peaceiris/actions-gh-pages@v4 with: - deploy_key: ${{ secrets.HUGO_ACTIONS_DEPLOY_KEY }} + deploy_key: ${{ secrets.HUGO_ACTIONS_DEPLOY_KEY }} external_repository: dpsim-simulator/dpsim-simulator.github.io publish_dir: ./docs/hugo/public # keep_files: true diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 75a140ff95..308f38c701 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -60,4 +60,4 @@ jobs: if: startsWith(github.ref, 'refs/tags') uses: pypa/gh-action-pypi-publish@v1.12.4 with: - password: ${{ secrets.PYPI_API_TOKEN }} \ No newline at end of file + password: ${{ secrets.PYPI_API_TOKEN }} diff --git a/.github/workflows/run_and_profile_example.yaml b/.github/workflows/run_and_profile_example.yaml index d4058ce444..7e92830322 100644 --- a/.github/workflows/run_and_profile_example.yaml +++ b/.github/workflows/run_and_profile_example.yaml @@ -27,7 +27,7 @@ jobs: - name: Run Binary run: ${{ inputs.path }} 2>&1 | tee output.log - + - name: Extract metrics shell: bash working-directory: ${{ github.workspace }} @@ -35,7 +35,7 @@ jobs: cat output.log | sed -n -E -e 's/^.*Average step time. ([0-9]+\.[0-9]+)$/step-time \1/p' | tee -a metrics.txt - + - name: Run Profiler run: gprof ${{ inputs.path }} | gprof2dot -s | dot -Tpng -o profiling.png || true @@ -45,4 +45,4 @@ jobs: name: profiler-output-${{ inputs.name }} path: | metrics.txt - profiling.png \ No newline at end of file + profiling.png diff --git a/LICENSE b/LICENSE index fa0086a952..a612ad9813 100644 --- a/LICENSE +++ b/LICENSE @@ -370,4 +370,4 @@ Exhibit B - "Incompatible With Secondary Licenses" Notice --------------------------------------------------------- This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. \ No newline at end of file + defined by the Mozilla Public License, v. 2.0. diff --git a/configs/realtime_tests/decoupled.sh b/configs/realtime_tests/decoupled.sh index fbbe08561a..f219c9dfba 100755 --- a/configs/realtime_tests/decoupled.sh +++ b/configs/realtime_tests/decoupled.sh @@ -8,4 +8,4 @@ do sudo taskset --all-tasks --cpu-list 12-23 chrt --fifo 99 build/dpsim/examples/cxx/WSCC_9bus_mult_decoupled -ocopies=$i -othreads=$j -oseq=$k done done -done \ No newline at end of file +done diff --git a/configs/realtime_tests/diakoptics.sh b/configs/realtime_tests/diakoptics.sh index cba6a91c3f..801f9b223d 100755 --- a/configs/realtime_tests/diakoptics.sh +++ b/configs/realtime_tests/diakoptics.sh @@ -11,4 +11,4 @@ do done done done -done \ No newline at end of file +done diff --git a/configs/realtime_tests/inverter.sh b/configs/realtime_tests/inverter.sh index 4c767366b5..5b9b7d1c3e 100755 --- a/configs/realtime_tests/inverter.sh +++ b/configs/realtime_tests/inverter.sh @@ -13,4 +13,4 @@ do do sudo taskset --all-tasks --cpu-list 12-23 chrt --fifo 99 build/dpsim/examples/cxx/DP_Inverter_Grid_Parallel -othreads=$j -oseq=$k done -done \ No newline at end of file +done diff --git a/configs/shmem_cosim/shmem_test.conf b/configs/shmem_cosim/shmem_test.conf index d744fd1f3c..6e0f623b37 100644 --- a/configs/shmem_cosim/shmem_test.conf +++ b/configs/shmem_cosim/shmem_test.conf @@ -19,7 +19,7 @@ "name": "sogno/dpsim:dev", "tag": "latest" }, - + "container_name": "shmem_tests" } }, @@ -28,4 +28,4 @@ "path": "dpsim/", "exec_command": "docker exec -w /dpsim shmem_tests ./build/dpsim/examples/cxx/ShmemDistributedVillas 0" } -} \ No newline at end of file +} diff --git a/configs/start_ShmemDistributedDirect.sh b/configs/start_ShmemDistributedDirect.sh index bfc1ae4ec8..911797037f 100644 --- a/configs/start_ShmemDistributedDirect.sh +++ b/configs/start_ShmemDistributedDirect.sh @@ -2,7 +2,7 @@ CPS_LOG_PREFIX="[Left ] " build/dpsim-villas/examples/cxx/ShmemDistributedDirect 0 & P1=$! CPS_LOG_PREFIX="[Right] " build/dpsim-villas/examples/cxx/ShmemDistributedDirect 1 & P2=$! - + for job in $P1 $P2; do wait $job || exit 1 -done \ No newline at end of file +done diff --git a/docs/doxygen/DoxyMain.md b/docs/doxygen/DoxyMain.md index d1a43c1ed5..7c2e670f24 100644 --- a/docs/doxygen/DoxyMain.md +++ b/docs/doxygen/DoxyMain.md @@ -3,5 +3,3 @@ DPsim is a solver library for dynamic power system simulation. The [main documentation](https://dpsim.fein-aachen.org/) has build / installation instructions, links to examples and explains the concepts implemented in DPsim as well as its architecture. - - diff --git a/docs/hugo/.gitignore b/docs/hugo/.gitignore index d55f5c85a2..46949d0d5c 100644 --- a/docs/hugo/.gitignore +++ b/docs/hugo/.gitignore @@ -2,4 +2,3 @@ public resources node_modules .hugo_build.lock - diff --git a/docs/hugo/Dockerfile b/docs/hugo/Dockerfile index ca0a7be64a..bd8799de55 100644 --- a/docs/hugo/Dockerfile +++ b/docs/hugo/Dockerfile @@ -20,4 +20,4 @@ WORKDIR /website ENTRYPOINT ["./docker-entrypoint.sh"] -EXPOSE 1313 \ No newline at end of file +EXPOSE 1313 diff --git a/docs/hugo/config.toml b/docs/hugo/config.toml index 3489d1fe08..284baa0b1d 100644 --- a/docs/hugo/config.toml +++ b/docs/hugo/config.toml @@ -23,13 +23,13 @@ category = "categories" [params.taxonomy] # set taxonomyCloud = [] to hide taxonomy clouds -taxonomyCloud = ["tags", "categories"] +taxonomyCloud = ["tags", "categories"] # If used, must have same length as taxonomyCloud -taxonomyCloudTitle = ["Tag Cloud", "Categories"] +taxonomyCloudTitle = ["Tag Cloud", "Categories"] # set taxonomyPageHeader = [] to hide taxonomies on the page headers -taxonomyPageHeader = ["tags", "categories"] +taxonomyPageHeader = ["tags", "categories"] # Highlighting config @@ -95,13 +95,13 @@ copyright = "The DPsim Authors" # This menu appears only if you have at least one [params.versions] set. version_menu = "Releases" -# Flag used in the "version-banner" partial to decide whether to display a +# Flag used in the "version-banner" partial to decide whether to display a # banner on every page indicating that this is an archived version of the docs. # Set this flag to "true" if you want to display the banner. archived_version = false # The version number for the version of the docs represented in this doc set. -# Used in the "version-banner" partial to display a version number for the +# Used in the "version-banner" partial to display a version number for the # current doc set. version = "0.0" @@ -159,7 +159,7 @@ yes = 'Glad to hear it! Please tell us how we can improve.' # Adds a reading time to the top of each doc. -# If you want this feature, but occasionally need to remove the Reading time from a single page, +# If you want this feature, but occasionally need to remove the Reading time from a single page, # add "hide_readingtime: true" to the page's front matter [params.ui.readingtime] enable = false @@ -222,4 +222,4 @@ enable = true disable = false [[module.imports]] path = "github.com/google/docsy/dependencies" - disable = false \ No newline at end of file + disable = false diff --git a/docs/hugo/content/en/_index.html b/docs/hugo/content/en/_index.html index aa7017f24a..7449de0362 100644 --- a/docs/hugo/content/en/_index.html +++ b/docs/hugo/content/en/_index.html @@ -19,4 +19,3 @@ Photo by NASA on Unsplash {{< /blocks/section >}} - diff --git a/docs/hugo/content/en/docs/Concepts/dyn-phasors.md b/docs/hugo/content/en/docs/Concepts/dyn-phasors.md index 9f6874800d..acd3663056 100644 --- a/docs/hugo/content/en/docs/Concepts/dyn-phasors.md +++ b/docs/hugo/content/en/docs/Concepts/dyn-phasors.md @@ -18,4 +18,3 @@ Another common term coming from power electrical engineering is shifted frequenc In the following, the general approach of dynamic phasors for power system simulation is explained starting from the idea of bandpass signals. This is because the 50 Hz or 60 Hz fundamental and small deviations from it can be seen as such a bandpass signal. Futhermore, higher frequencies, for example, generated by power electronics can be modelled in a similar way. - diff --git a/docs/hugo/content/en/docs/Concepts/powerflow.md b/docs/hugo/content/en/docs/Concepts/powerflow.md index 6caefc9c50..9b4c1455ab 100644 --- a/docs/hugo/content/en/docs/Concepts/powerflow.md +++ b/docs/hugo/content/en/docs/Concepts/powerflow.md @@ -103,7 +103,7 @@ If we now perform the algebraic multiplication of the two terms inside the paren ```math \begin{align} {P}_{k} = \sum_{j=1}^{N} \vert V_{k} \vert \vert V_{j} \vert \left ( G_{kj}cos(\theta_{k} - \theta_{j}) + B_{kj} sin(\theta_{k} - \theta_{j}) \right ) \\ -{Q}_{k} = \sum_{j=1}^{N} \vert V_{k} \vert \vert V_{j} \vert \left ( G_{kj}sin(\theta_{k} - \theta_{j}) - B_{kj} cos(\theta_{k} - \theta_{j}) \right ) +{Q}_{k} = \sum_{j=1}^{N} \vert V_{k} \vert \vert V_{j} \vert \left ( G_{kj}sin(\theta_{k} - \theta_{j}) - B_{kj} cos(\theta_{k} - \theta_{j}) \right ) \end{align} ``` @@ -160,7 +160,7 @@ J_{jj}^{QV} &= \frac{\partial Q_{j}(\vec{x})}{\partial \vert V_{j} \vert } = \fr The linear system of equations that is solved in every Newton iteration can be written in matrix form as follows: ```math \begin{align} --\left [ \begin{array}{cccccc} +-\left [ \begin{array}{cccccc} \frac{\partial \Delta P_{2} }{\partial \theta_{2}} & \cdots & \frac{\partial \Delta P_{2} }{\partial \theta_{N}} & \frac{\partial \Delta P_{2} }{\partial \vert V_{N_{G+1}} \vert} & \cdots & \frac{\partial \Delta P_{2} }{\partial \vert V_{N} \vert} \\ \vdots & \ddots & \vdots & \vdots & \ddots & \vdots \\ @@ -197,4 +197,4 @@ To sum up, the NR algorithm, for application to the power flow problem is: * Otherwise, go to step 4. 4. Evaluate the Jacobian matrix $\textbf{J}^{(i)}$ and compute $\Delta \vec{x}^{(i)}$. 5. Compute the update solution vector $\vec{x}^{(i+1)}$. Return to step 3. -6. Stop. \ No newline at end of file +6. Stop. diff --git a/docs/hugo/content/en/docs/Contribution guidelines/index.md b/docs/hugo/content/en/docs/Contribution guidelines/index.md index e0960c292a..151aca3c9a 100644 --- a/docs/hugo/content/en/docs/Contribution guidelines/index.md +++ b/docs/hugo/content/en/docs/Contribution guidelines/index.md @@ -7,5 +7,5 @@ description: > How to contribute to DPsim. --- -We'd love to accept your patches and contributions to this project. +We'd love to accept your patches and contributions to this project. Please send us a [pull request](https://github.com/sogno-platform/dpsim/pulls) or get in touch with us via mail or [slack](https://lfenergy.slack.com/archives/C054GB551TL) if you would like to contribute. diff --git a/docs/hugo/content/en/docs/Development/Debugging.md b/docs/hugo/content/en/docs/Development/Debugging.md index f313f9fcd6..6d75ec5c48 100644 --- a/docs/hugo/content/en/docs/Development/Debugging.md +++ b/docs/hugo/content/en/docs/Development/Debugging.md @@ -5,7 +5,7 @@ linkTitle: "Debugging" ## Mixed Python C++ Debugging -### Prerequisites +### Prerequisites Your vscode launch.json should have two configurations, one to launch the python process and one to attach gdb: @@ -35,7 +35,7 @@ Your vscode launch.json should have two configurations, one to launch the python "ignoreFailures": true } ] - } + } ] } @@ -44,7 +44,7 @@ Make sure to adapt your PYTHONPATH variable if necessary. The C++ code has to be build in debug mode - cmake .. -DCMAKE_BUILD_TYPE=Debug + cmake .. -DCMAKE_BUILD_TYPE=Debug ### Attaching C++ Debugger @@ -58,7 +58,7 @@ The C++ code has to be build in debug mode - press play to continue Python debugging… the c++ debugger will stop at the next breakpoint You can automate this by using the vscode extension “Python C++ Debugger” and by adding this configuration to the launch.json above: - + { "name": "Python C++ Debugger", "type": "pythoncpp", @@ -84,7 +84,7 @@ Use the following launch.json for vscode and set the program path: "name": "(gdb) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/dpsim/build/Examples/Cxx/example", + "program": "${workspaceFolder}/dpsim/build/Examples/Cxx/example", "args": [], "stopAtEntry": true, "cwd": "${workspaceFolder}", @@ -100,4 +100,4 @@ Use the following launch.json for vscode and set the program path: ] } ] - } \ No newline at end of file + } diff --git a/docs/hugo/content/en/docs/Getting started/_index.md b/docs/hugo/content/en/docs/Getting started/_index.md index 6a62fa6b16..8c0ab9de09 100644 --- a/docs/hugo/content/en/docs/Getting started/_index.md +++ b/docs/hugo/content/en/docs/Getting started/_index.md @@ -5,5 +5,3 @@ weight: 2 description: > How to install, build and run the DPsim project. --- - - diff --git a/docs/hugo/content/en/docs/Getting started/build.md b/docs/hugo/content/en/docs/Getting started/build.md index 03872b61b0..7542bb9ea7 100644 --- a/docs/hugo/content/en/docs/Getting started/build.md +++ b/docs/hugo/content/en/docs/Getting started/build.md @@ -54,7 +54,7 @@ To build everything run $ cmake --build . To use other libraries that are installed, use the relevant option defined in the CMakeList.txt files, for example for GSL below, and then build as usual: - + $ cmake .. -DWITH_GSL=ON If you would like to use the Python package, it has to be added to the path. diff --git a/docs/hugo/content/en/docs/Getting started/install.md b/docs/hugo/content/en/docs/Getting started/install.md index 404fa91c3e..0724b13614 100644 --- a/docs/hugo/content/en/docs/Getting started/install.md +++ b/docs/hugo/content/en/docs/Getting started/install.md @@ -49,4 +49,4 @@ Then, DPsim can be installed as a Python module: ## From Source -To build and install DPsim from the source files, please refer to the build section. \ No newline at end of file +To build and install DPsim from the source files, please refer to the build section. diff --git a/docs/hugo/content/en/docs/Models/RLC-Elements/index.md b/docs/hugo/content/en/docs/Models/RLC-Elements/index.md index e9bfbc8ea8..939f1a7439 100644 --- a/docs/hugo/content/en/docs/Models/RLC-Elements/index.md +++ b/docs/hugo/content/en/docs/Models/RLC-Elements/index.md @@ -170,4 +170,4 @@ $$ $$ $$ \langle i_{equiv} \rangle(k-1) = \frac{1 - b^2 - j2b + 2Ra + (Ra)^2 - j2Rab}{(1+Ra^2) + b^2} \langle i \rangle(k-1) + \frac{a + Ra^2 - jab}{(1+Ra)^2 + b^2} \langle v \rangle(k-1) -$$ \ No newline at end of file +$$ diff --git a/docs/hugo/content/en/docs/Models/Transformer/index.md b/docs/hugo/content/en/docs/Models/Transformer/index.md index 4414883c63..8762084cd4 100644 --- a/docs/hugo/content/en/docs/Models/Transformer/index.md +++ b/docs/hugo/content/en/docs/Models/Transformer/index.md @@ -13,7 +13,7 @@ The single line diagram is depicted in the figure below. If node reduction is not applied, two virtual nodes are created to stamp this model into the system matrix. Furthermore, the ideal transformer has an additional equation, which requires an extension of the system matrix. -The complete matrix stamp for the ideal transformer is +The complete matrix stamp for the ideal transformer is ```math \begin{array}{c|c c c} @@ -33,10 +33,10 @@ i_{l} \cr \cr \cr 0\cr -\end{pmatrix} +\end{pmatrix} ``` The variable $j$ denotes the high voltage node while $k$ is the low voltage node. $l$ indicates the inserted row and column to accommodate the relation between the two voltages at the ends of the transformer. The transformer ratio is defined as $T = V_{j} / V_{k}$. -A phase shift can be introduced if $T$ is considered as a complex number. \ No newline at end of file +A phase shift can be introduced if $T$ is considered as a complex number. diff --git a/docs/hugo/content/en/docs/Models/power-electronics.md b/docs/hugo/content/en/docs/Models/power-electronics.md index 4318ad91f8..14fa055ddd 100644 --- a/docs/hugo/content/en/docs/Models/power-electronics.md +++ b/docs/hugo/content/en/docs/Models/power-electronics.md @@ -2,4 +2,4 @@ title: "VS-Inverter" linkTitle: "VS-Inverter" date: 2020-03-18 ---- \ No newline at end of file +--- diff --git a/docs/hugo/content/en/docs/Overview/Attributes/index.md b/docs/hugo/content/en/docs/Overview/Attributes/index.md index cf36222e54..70c58aa223 100644 --- a/docs/hugo/content/en/docs/Overview/Attributes/index.md +++ b/docs/hugo/content/en/docs/Overview/Attributes/index.md @@ -12,11 +12,11 @@ In general, attributes are instances of the `Attribute` class, but they are u Through the template parameter `T` of the `Attribute` class, attributes can have different value types, most commonly `Real`, `Complex`, `Matrix`, or `MatrixComp`. Additionally, attributes can fall into one of two categories: **Static** attributes have a fixed value which can only be changed explicitly through the attribute's `set`-method or through a mutable reference obtained through `get`. -**Dynamic** attributes on the other hand can dynamically re-compute their value from other attributes every time they are read. This can for example be used to create a scalar attribute of type `Real` whose value always contains the magnitude of another, different attribute of type `Complex`. +**Dynamic** attributes on the other hand can dynamically re-compute their value from other attributes every time they are read. This can for example be used to create a scalar attribute of type `Real` whose value always contains the magnitude of another, different attribute of type `Complex`. Any simulation component or class which inherits from `IdentifiedObject` contains an instance of an `AttributeList`. This list can be used to store all the attributes present in this component and later access them via a `String` instead of having to use the member variable directly. -For reasons of code clarity and runtime safety, the member variables should still be used whenever possible. +For reasons of code clarity and runtime safety, the member variables should still be used whenever possible. ## Creating and Storing Attributes Normally, a new attribute is created by using the `create` or `createDynamic` method of an `AttributeList` object. @@ -24,7 +24,7 @@ These two methods will create a new attribute of the given type and insert it in Afterwards, a pointer to the attribute is returned which can then be stored in a component's member variable. Usually this is done in the component's constructor in an initialization list: -```cpp +```cpp /// Component class Base::Ph1::PiLine public: @@ -53,7 +53,7 @@ Simulation::Simulation(String name, Logger::Level logLevel) : mTimeStep(AttributeStatic::make(0.001)), mSplitSubnets(AttributeStatic::make(true)), mSteadyStateInit(AttributeStatic::make(false)), - //... + //... { // ... } @@ -83,7 +83,7 @@ Real read3 = **attr; //read3 = 0.003 ``` ## Working with Dynamic Attributes -In general, dynamic attributes can be accessed via the same `get` and `set`-methods described above for static attributes. However, +In general, dynamic attributes can be accessed via the same `get` and `set`-methods described above for static attributes. However, dynamic attributes can additionally have **dependencies** on other attributes which affect the behavior of these methods. Usually, this is used to dynamically compute the attribute's value from the value of another attribute. In the simplest case, a dynamic attribute can be set to **reference** another (static or dynamic) attribute using the `setReference`-method. After this method has been called, @@ -187,4 +187,4 @@ void DP::Ph1::Inductor::mnaAddPostStepDependencies( } ``` Here, the MNA post step depends on the solution vector of the system, `leftVector`, and modifies `mIntfVoltage` and `mIntfCurrent`. -Therefore, this task needs to be scheduled after the system solution that computes `leftVector` and before tasks that require the voltage and current interface vectors of the inductance, e.g. the task logging these values. \ No newline at end of file +Therefore, this task needs to be scheduled after the system solution that computes `leftVector` and before tasks that require the voltage and current interface vectors of the inductance, e.g. the task logging these values. diff --git a/docs/hugo/content/en/docs/Overview/Scheduling/index.md b/docs/hugo/content/en/docs/Overview/Scheduling/index.md index 2214830e87..3ecd7840d7 100644 --- a/docs/hugo/content/en/docs/Overview/Scheduling/index.md +++ b/docs/hugo/content/en/docs/Overview/Scheduling/index.md @@ -12,4 +12,4 @@ In the simplest case, all tasks of a level have to be finished before tasks of t ![image](task_graph_levels.svg) The dependencies of tasks on data are determined by referencing the attributes that are read or modified by the task. -The scheduler computes the schedule prior to the simulation from the task dependency graph resulting from the tasks' data dependencies. \ No newline at end of file +The scheduler computes the schedule prior to the simulation from the task dependency graph resulting from the tasks' data dependencies. diff --git a/docs/hugo/content/en/docs/Overview/_index.md b/docs/hugo/content/en/docs/Overview/_index.md index 6638d4666d..06e49d65bb 100644 --- a/docs/hugo/content/en/docs/Overview/_index.md +++ b/docs/hugo/content/en/docs/Overview/_index.md @@ -20,4 +20,3 @@ The project is released under the terms of the [MPL 2.0](https://mozilla.org/MPL * [Getting Started]({{< ref "/docs/Getting Started/" >}} "Getting Started"): Get started with DPsim * [Examples]({{< ref "/docs/Examples/" >}} "Examples"): Check out some example code! - diff --git a/docs/hugo/content/en/docs/Overview/subcomponents.md b/docs/hugo/content/en/docs/Overview/subcomponents.md index 437ae1af89..600cc1e532 100644 --- a/docs/hugo/content/en/docs/Overview/subcomponents.md +++ b/docs/hugo/content/en/docs/Overview/subcomponents.md @@ -22,7 +22,7 @@ should be stamped into the system `rightVector`: DP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) : Base::Ph1::PiLine(mAttributes), // Call the constructor of CompositePowerComp and enable automatic pre- and post-step creation - CompositePowerComp(uid, name, true, true, logLevel) + CompositePowerComp(uid, name, true, true, logLevel) { //... } @@ -31,7 +31,7 @@ void DP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { //... // Create series sub components mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); - + // Setup mSubSeriesResistor... // Register the resistor as a subcomponent. The resistor's pre- and post-step will be called before the pre- and post-step of the parent, @@ -39,7 +39,7 @@ void DP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); - + // Setup mSubSeriesInductor... // Register the inductor as a subcomponent. The inductor's pre- and post-step will be called before the pre- and post-step of the parent, @@ -80,4 +80,4 @@ void DP::Ph1::PiLine::mnaCompAddPreStepDependencies(AttributeBase::List &prevSte prevStepDependencies.push_back(mIntfVoltage); modifiedAttributes.push_back(mRightVector); } -``` \ No newline at end of file +``` diff --git a/docs/hugo/content/en/docs/Reference/index.md b/docs/hugo/content/en/docs/Reference/index.md index 835a7cc76a..3cd4ba5d72 100644 --- a/docs/hugo/content/en/docs/Reference/index.md +++ b/docs/hugo/content/en/docs/Reference/index.md @@ -10,4 +10,4 @@ description: > The [Sphinx documentation](https://sogno-platform.github.io/dpsim/sphinx/about.html) describes the Python API. The [Doxygen documentation](https://sogno-platform.github.io/dpsim/doxygen/index.html) is automatically generated from the C++ code using Doxygen. -It is helpful to understand the general structure of the C++ DPsim core components. \ No newline at end of file +It is helpful to understand the general structure of the C++ DPsim core components. diff --git a/docs/hugo/content/en/docs/Roadmap/index.md b/docs/hugo/content/en/docs/Roadmap/index.md index 532236367f..221130655e 100644 --- a/docs/hugo/content/en/docs/Roadmap/index.md +++ b/docs/hugo/content/en/docs/Roadmap/index.md @@ -4,7 +4,7 @@ linkTitle: "Roadmap" weight: 8 --- -Short-term planning for new features is done on the GitHub [Project board](https://github.com/orgs/sogno-platform/projects/1). +Short-term planning for new features is done on the GitHub [Project board](https://github.com/orgs/sogno-platform/projects/1). You can also check the [Issues List](https://github.com/sogno-platform/dpsim/issues) or the [Pull Requests](https://github.com/sogno-platform/dpsim/pulls) on GitHub. @@ -33,4 +33,3 @@ You can also check the [Issues List](https://github.com/sogno-platform/dpsim/iss - [ ] improve integration of diakoptics solver - Interfaces - [ ] implement CIM reader in Python using new pybind interface and cimpy library - diff --git a/docs/hugo/content/en/docs/Tasks/_index.md b/docs/hugo/content/en/docs/Tasks/_index.md index 9902a7449c..a10e29e70e 100644 --- a/docs/hugo/content/en/docs/Tasks/_index.md +++ b/docs/hugo/content/en/docs/Tasks/_index.md @@ -14,4 +14,3 @@ Each task should give the user * What this task accomplishes. * Instructions for the task. If it involves editing a file, running a command, or writing code, provide code-formatted example snippets to show the user what to do! If there are multiple steps, provide them as a numbered list. * If appropriate, links to related concept, tutorial, or example pages. - diff --git a/docs/hugo/content/en/docs/Tasks/create-simulation.md b/docs/hugo/content/en/docs/Tasks/create-simulation.md index 1c3d85335e..5e1a1a7c75 100644 --- a/docs/hugo/content/en/docs/Tasks/create-simulation.md +++ b/docs/hugo/content/en/docs/Tasks/create-simulation.md @@ -37,4 +37,4 @@ The build process is similar to the one of DPsim: $ cd my-project $ mkdir build && cd build $ cmake .. - $ make my-scenario \ No newline at end of file + $ make my-scenario diff --git a/docs/hugo/content/en/search.md b/docs/hugo/content/en/search.md index e3690fd5a8..db621987e5 100644 --- a/docs/hugo/content/en/search.md +++ b/docs/hugo/content/en/search.md @@ -3,4 +3,3 @@ title: Search Results layout: search --- - diff --git a/docs/hugo/docker-entrypoint.sh b/docs/hugo/docker-entrypoint.sh index 0e3a231af2..240fb43fb5 100755 --- a/docs/hugo/docker-entrypoint.sh +++ b/docs/hugo/docker-entrypoint.sh @@ -4,4 +4,4 @@ npm install -D --save autoprefixer npm install -D --save postcss-cli hugo --minify -hugo server --bind 0.0.0.0 -D \ No newline at end of file +hugo server --bind 0.0.0.0 -D diff --git a/docs/past-commits.txt b/docs/past-commits.txt index 0f7ff36085..da07a355ce 100644 --- a/docs/past-commits.txt +++ b/docs/past-commits.txt @@ -5321,4 +5321,3 @@ de4a03b811dae2d7441302a446c25b755680a022 search in standard location for Eigen Former-commit-id: c9310bac6e209da1b93386e119e21f011f92cc3c b3397eaff3d785202d6d1333400b66891454ca9b compile examples to avoid undefined references Former-commit-id: 095db5bbf729884810ff9d3b4cdb805557d92e04 - diff --git a/docs/sphinx/Reference.rst b/docs/sphinx/Reference.rst index b0d53f53dd..68ba21db04 100644 --- a/docs/sphinx/Reference.rst +++ b/docs/sphinx/Reference.rst @@ -50,4 +50,4 @@ Electromagnetic Transient Models .. automodule:: dpsimpy.sp.ph1 :members: - :undoc-members: \ No newline at end of file + :undoc-members: diff --git a/dpsim-models/include/dpsim-models/Factory.h b/dpsim-models/include/dpsim-models/Factory.h index 703b7ca0ec..273928d164 100644 --- a/dpsim-models/include/dpsim-models/Factory.h +++ b/dpsim-models/include/dpsim-models/Factory.h @@ -132,4 +132,4 @@ void registerSynchronGenerators() { } } // namespace Ph1 } // namespace DP -} // namespace SynchronGeneratorFactory \ No newline at end of file +} // namespace SynchronGeneratorFactory diff --git a/dpsim/examples/cxx/GeneratorFactory.h b/dpsim/examples/cxx/GeneratorFactory.h index dfd1c67c43..c98ef7bb2a 100644 --- a/dpsim/examples/cxx/GeneratorFactory.h +++ b/dpsim/examples/cxx/GeneratorFactory.h @@ -59,4 +59,4 @@ createGenEMT(const String &SGModel, const String &name, return genEMT; } -} // namespace GeneratorFactory \ No newline at end of file +} // namespace GeneratorFactory diff --git a/dpsim/examples/cxx/test_RealTime.yml b/dpsim/examples/cxx/test_RealTime.yml index 7466ecdad4..d1f5a90c13 100644 --- a/dpsim/examples/cxx/test_RealTime.yml +++ b/dpsim/examples/cxx/test_RealTime.yml @@ -1,2 +1,2 @@ RT_DP_ResVS_RL1: - cmd: build/dpsim/examples/cxx/RT_DP_VS_RL2 \ No newline at end of file + cmd: build/dpsim/examples/cxx/RT_DP_VS_RL2 diff --git a/dpsim/examples/cxx/test_Shmem.yml b/dpsim/examples/cxx/test_Shmem.yml index 552ca0ad69..67f2a53bd8 100644 --- a/dpsim/examples/cxx/test_Shmem.yml +++ b/dpsim/examples/cxx/test_Shmem.yml @@ -7,4 +7,4 @@ Shmem_WSCC_9bus_Ctrl: ShmemDistributedDirect: skip: true shell: True - cmd: configs/start_ShmemDistributedDirect.sh \ No newline at end of file + cmd: configs/start_ShmemDistributedDirect.sh diff --git a/dpsim/include/dpsim/pybind/Attributes.h b/dpsim/include/dpsim/pybind/Attributes.h index 542538e526..bb9eb6881b 100644 --- a/dpsim/include/dpsim/pybind/Attributes.h +++ b/dpsim/include/dpsim/pybind/Attributes.h @@ -16,4 +16,4 @@ namespace py = pybind11; using namespace pybind11::literals; -void addAttributes(py::module_ m); \ No newline at end of file +void addAttributes(py::module_ m); diff --git a/dpsim/src/SolverPlugins/magma/Makefile b/dpsim/src/SolverPlugins/magma/Makefile index 48bbe70cf5..a42f69875e 100644 --- a/dpsim/src/SolverPlugins/magma/Makefile +++ b/dpsim/src/SolverPlugins/magma/Makefile @@ -12,4 +12,4 @@ all: libdps_magma.so $(CC) $(CC_FLAGS) -I../../../include -c -fpic -o $@ $< libdps_magma.so: magma.o - $(CC) -shared -o $@ $< $(LD_FLAGS) + $(CC) -shared -o $@ $< $(LD_FLAGS) diff --git a/dpsim/src/pybind/CMakeLists.txt b/dpsim/src/pybind/CMakeLists.txt index 6788950dc2..07b5a88111 100644 --- a/dpsim/src/pybind/CMakeLists.txt +++ b/dpsim/src/pybind/CMakeLists.txt @@ -15,4 +15,4 @@ set_target_properties(dpsimpy LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) target_link_libraries(dpsimpy PRIVATE dpsim) -target_include_directories(dpsimpy PUBLIC ${DPSIMPY_INCLUDE_DIRS}) \ No newline at end of file +target_include_directories(dpsimpy PUBLIC ${DPSIMPY_INCLUDE_DIRS}) diff --git a/examples/Matlab/CalculateError.m b/examples/Matlab/CalculateError.m index c2bc39d53d..41847c03a9 100644 --- a/examples/Matlab/CalculateError.m +++ b/examples/Matlab/CalculateError.m @@ -41,12 +41,12 @@ dt = 0.000050; %% read results from c++ simulation while dt <= 0.011000 - + FileName = FileNameVector(i,1:27); Path = strcat('../../../vsa/Results/LoadChange/DPsim/EMT/VBR/', FileName); Log_SynGen = csvread(Path,1); CurrentVector = Log_SynGen(:,1:4); - + %% Calculate and display error %Cut Current and Voltage vector to get steady state results l=length(CurrentVector); @@ -56,7 +56,7 @@ CurrentVector_LC = -CurrentVector(l_new:2*l_new,2); CurrentReference_reduced = zeros(l,2); - + if l == l_Ref CurrentReference_reduced(:,1) = Results_Reference(:,1); CurrentReference_reduced(:,2) = Results_Reference(:,5); @@ -68,8 +68,8 @@ CurrentReference_reduced(n,2) = Results_Reference(m,5); n = n+1; end -end - +end + %Reference current in Steady state and after load change Reference_SS = CurrentReference_reduced(1:l_new,2); Reference_LC = CurrentReference_reduced(l_new:2*l_new,2); @@ -100,7 +100,7 @@ ErrorVector_VBR(i) = 100*err_LC/Peak_Ref_LC; dtVectorVBR(i) = dt; i = i + 1; - + if dt >= 0.001 dt = dt + 0.001; elseif dt >= 0.0001 @@ -109,9 +109,9 @@ dt = dt + 0.000050; end end - - + + %% Dq Model i = 1; @@ -128,12 +128,12 @@ dt = 0.000050; while dt <= 0.000800 - + FileName = FileNameVector(i,1:26); Path = strcat('../../../vsa/Results/LoadChange/DPsim/EMT/Dq/', FileName); Log_SynGen = csvread(Path,1); CurrentVector = Log_SynGen(:,1:4); - + l=length(CurrentVector); l_new=round(1/3*l); @@ -141,7 +141,7 @@ CurrentVector_LC = CurrentVector(l_new:2*l_new,2); CurrentReference_reduced = zeros(l,2); - + if l == l_Ref CurrentReference_reduced(:,1) = Results_Reference(:,1); CurrentReference_reduced(:,2) = Results_Reference(:,5); @@ -153,8 +153,8 @@ CurrentReference_reduced(n,2) = Results_Reference(m,5); n = n+1; end - end - + end + %Reference current in Steady state and after load change Reference_SS = CurrentReference_reduced(1:l_new,2); Reference_LC = CurrentReference_reduced(l_new:2*l_new,2); @@ -183,7 +183,7 @@ ErrorVector_dq(i) = 100*err_LC/Peak_Ref_LC; dtVectordq(i) = dt; i = i + 1; - + if dt >= 0.0001 dt = dt + 0.0001; else @@ -232,7 +232,7 @@ currentDP(row,col+compOffsetDP)*sin(2*pi*60*currentDP(row,1)); end - + l_DP=length(currentShiftDP); l_new_DP=round(1/3*l_DP); @@ -240,7 +240,7 @@ CurrentVector_LC_DP = -currentShiftDP(l_new_DP:2*l_new_DP,2); CurrentReference_reduced = zeros(l_DP,2); - + if l_DP == l_Ref CurrentReference_reduced(:,1) = Results_Reference(:,1); CurrentReference_reduced(:,2) = Results_Reference(:,5); @@ -252,8 +252,8 @@ CurrentReference_reduced(n,2) = Results_Reference(m,5); n = n+1; end - end - + end + %Reference current in Steady state and after load change Reference_SS = CurrentReference_reduced(1:l_new_DP,2); Reference_LC = CurrentReference_reduced(l_new_DP:2*l_new_DP,2); @@ -282,7 +282,7 @@ ErrorVector_VBRDP(i) = 100*err_LC_DP/Peak_Ref_LC; dtVectorVBRDP(i) = dt; i = i + 1; - + if dt >= 0.001 dt = dt + 0.001; elseif dt >= 0.0001 @@ -315,7 +315,7 @@ Log_SynGen = csvread(Path,1); currentDP = Log_SynGen(:,1:7); compOffsetDP = (size(currentDP,2) - 1) / 2; - + currentShiftDP = currentDP(:,1); col = 2; for row = 1:size(currentDP,1) @@ -323,7 +323,7 @@ currentDP(row,col+compOffsetDP)*sin(2*pi*60*currentDP(row,1)); end - + l_DP=length(currentShiftDP); l_new_DP=round(1/3*l_DP); @@ -331,7 +331,7 @@ CurrentVector_LC_DP = currentShiftDP(l_new_DP:2*l_new_DP,2); CurrentReference_reduced = zeros(l_DP,2); - + if l_DP == l_Ref CurrentReference_reduced(:,1) = Results_Reference(:,1); CurrentReference_reduced(:,2) = Results_Reference(:,5); @@ -343,8 +343,8 @@ CurrentReference_reduced(n,2) = Results_Reference(m,5); n = n+1; end - end - + end + %Reference current in Steady state and after load change Reference_SS = CurrentReference_reduced(1:l_new_DP,2); Reference_LC = CurrentReference_reduced(l_new_DP:2*l_new_DP,2); @@ -372,7 +372,7 @@ ErrorVector_dqDP(i) = 100*err_LC_DP/Peak_Ref_LC; dtVectordqDP(i) = dt; i = i + 1; - + if dt >= 0.0001 dt = dt + 0.0001; else @@ -393,7 +393,7 @@ legend({'EMT VBR','DP VBR'},'FontSize',12) ylabel('Error [%]','FontSize',12); xlabel('Time Step [s]','FontSize',12); - + set(plot1,'LineWidth',2); set(plot2,'LineWidth',2); set(plotp,'LineWidth',2); @@ -413,7 +413,7 @@ ylabel('Error [%]','FontSize',12); xlabel('Time Step [s]','FontSize',12); ylim([0 16]); - + set(plot3,'LineWidth',2); set(plot4,'LineWidth',2); @@ -432,7 +432,7 @@ ylabel('Error [%]','FontSize',12); xlabel('Time Step [s]','FontSize',12); ylim([0 2]); - + set(plot3,'LineWidth',2); set(plot4,'LineWidth',2); diff --git a/examples/Matlab/CompareDPandEMT_DPsim.m b/examples/Matlab/CompareDPandEMT_DPsim.m index b9a4927d56..ddb9b1eb74 100644 --- a/examples/Matlab/CompareDPandEMT_DPsim.m +++ b/examples/Matlab/CompareDPandEMT_DPsim.m @@ -2,7 +2,7 @@ clear %% read PLECS results -Results_PLECSV = csvread('../../vsa/Results/SynGenVBREmt_ABCFault_DPSim/data_synGenVBR_v.csv'); +Results_PLECSV = csvread('../../vsa/Results/SynGenVBREmt_ABCFault_DPSim/data_synGenVBR_v.csv'); Results_PLECSI = csvread('../../vsa/Results/SynGenVBREmt_ABCFault_DPSim/data_synGenVBR_i.csv'); %% Read data from DP simulation and calculate absolute value and phase @@ -125,4 +125,3 @@ legend('Current Phase c PLECS', 'DP shift c', 'DP abs c') xlabel('time [s]') ylabel('current [A]') - diff --git a/examples/Matlab/CompareSynGenResults.m b/examples/Matlab/CompareSynGenResults.m index fc487d4557..aac358ead3 100644 --- a/examples/Matlab/CompareSynGenResults.m +++ b/examples/Matlab/CompareSynGenResults.m @@ -21,8 +21,8 @@ Peak_Ref_SS = max(Results_Reference(1:l_Ref/3,5)); Peak_Ref_LC = max(Results_Reference(l_Ref/3:2*l_Ref/3,5)); if strcmp(TestName,'TestExciterAndTurbine') == 1 -omega_Reference = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/omega.csv'); -vt_Reference = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/vt.csv'); +omega_Reference = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/omega.csv'); +vt_Reference = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/vt.csv'); end %% read results from c++ simulation Path = ['../../../vsa/Results/',TestName,'/DPsim/',SimulationType,'/',GeneratorType,'/']; @@ -112,7 +112,7 @@ title('Current phase c'); legend('ic DPSim','ic Simulink'); -if strcmp(TestName,'TestExciterAndTurbine') == 1 +if strcmp(TestName,'TestExciterAndTurbine') == 1 h7=figure(7) hold off plotomega1 = plot(Log_SynGen(:,1),Log_SynGen(:,6)); @@ -167,10 +167,10 @@ CurrentVector_SS = CurrentVector(1:l_new,2); CurrentVector_LC = CurrentVector(l_new:2*l_new,2); end - + CurrentReference_reduced = zeros(l,2); - + if l == l_Ref CurrentReference_reduced(:,1) = Results_Reference(:,1); CurrentReference_reduced(:,2) = Results_Reference(:,5); @@ -182,8 +182,8 @@ CurrentReference_reduced(n,2) = Results_Reference(m,5); n = n+1; end -end - +end + %Reference current in Steady state and after load change Reference_SS = CurrentReference_reduced(1:l_new,2); Reference_LC = CurrentReference_reduced(l_new:2*l_new,2); @@ -214,4 +214,4 @@ %% Calculate avarage step time StepTimeVector = Log_SynGen(:,7); -disp(['Avarage step time for generator: ', num2str(mean(StepTimeVector)*1000), ' ms']); \ No newline at end of file +disp(['Avarage step time for generator: ', num2str(mean(StepTimeVector)*1000), ' ms']); diff --git a/examples/Matlab/CompareVBRandDQ.m b/examples/Matlab/CompareVBRandDQ.m index bfc3ee02e8..38edff1399 100644 --- a/examples/Matlab/CompareVBRandDQ.m +++ b/examples/Matlab/CompareVBRandDQ.m @@ -59,4 +59,4 @@ xlabel('time [s]','FontSize',12) ylabel('current [A]','FontSize',12) -legend({'Reference','EMT Classical','EMT VBR'},'FontSize',12); \ No newline at end of file +legend({'Reference','EMT Classical','EMT VBR'},'FontSize',12); diff --git a/examples/Matlab/CompareVBRandDQ_DP.m b/examples/Matlab/CompareVBRandDQ_DP.m index c2980f98dc..a29c71c565 100644 --- a/examples/Matlab/CompareVBRandDQ_DP.m +++ b/examples/Matlab/CompareVBRandDQ_DP.m @@ -99,9 +99,9 @@ if abs_on == 1 && shift_on == 1 legend({'Reference', 'DP shift VBR', 'DP abs VBR', 'DP shift Classical', 'DP abs Classical'},'FontSize',12) -elseif abs_on == 1 && shift_on == 0 +elseif abs_on == 1 && shift_on == 0 legend({'Reference', 'DP abs VBR', 'DP abs Classical'},'FontSize',12) -elseif abs_on == 0 && shift_on == 1 +elseif abs_on == 0 && shift_on == 1 legend({'Reference', 'DP shift VBR', 'DP shift Classical'},'FontSize',12) end @@ -197,13 +197,11 @@ if abs_on == 1 && shift_on == 1 legend({'Reference', 'DP shift VBR', 'DP abs VBR', 'DP shift Classical', 'DP abs Classical'},'FontSize',12) -elseif abs_on == 1 && shift_on == 0 +elseif abs_on == 1 && shift_on == 0 legend({'Reference', 'DP abs VBR', 'DP abs Classical'},'FontSize',12) -elseif abs_on == 0 && shift_on == 1 +elseif abs_on == 0 && shift_on == 1 legend({'Reference', 'DP shift VBR', 'DP shift Classical'},'FontSize',12) end xlabel('time [s]','FontSize',12) ylabel('current [A]','FontSize',12) - - diff --git a/examples/Matlab/DP_CompareSynGenResults.m b/examples/Matlab/DP_CompareSynGenResults.m index 8c8baa2e4c..ac96a986fe 100644 --- a/examples/Matlab/DP_CompareSynGenResults.m +++ b/examples/Matlab/DP_CompareSynGenResults.m @@ -17,8 +17,8 @@ Results_Reference= csvread(['../../../vsa/Results/',TestName,'/Simulink/Voltages_and_currents.csv']); if strcmp(TestName,'TestExciterAndTurbine') == 1 -omega_Reference = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/omega.csv'); -vt_Reference = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/vt.csv'); +omega_Reference = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/omega.csv'); +vt_Reference = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/vt.csv'); end l_Ref = length(Results_Reference); @@ -138,7 +138,7 @@ if strcmp(GeneratorType,'VBR') == 1 legend({'Reference', 'DP VBR abs'},'FontSize',12) else - legend({'Reference', 'DP Classical abs'},'FontSize',12) + legend({'Reference', 'DP Classical abs'},'FontSize',12) end xlabel('Time [s]','FontSize',12); ylabel('Current [A]','FontSize',12); @@ -199,7 +199,7 @@ set(h7,'pos',[5 5 24 13]) pos = get(h7,'Position'); set(h7,'PaperPositionMode','Auto','PaperUnits','centimeters','PaperSize',[pos(3), pos(4)]) -% +% h8 = figure(8) hold off plotvt1 = plot(Log_SynGen(:,1),Log_SynGen(:,11)); @@ -227,10 +227,10 @@ CurrentVector_LC_DP = -currentShiftDP(l_new_DP:2*l_new_DP,2); else CurrentVector_SS_DP = currentShiftDP(1:l_new_DP,2); - CurrentVector_LC_DP = currentShiftDP(l_new_DP:2*l_new_DP,2); + CurrentVector_LC_DP = currentShiftDP(l_new_DP:2*l_new_DP,2); end CurrentReference_reduced = zeros(l_DP,2); - + if l_DP == l_Ref CurrentReference_reduced(:,1) = Results_Reference(:,1); CurrentReference_reduced(:,2) = Results_Reference(:,5); @@ -242,8 +242,8 @@ CurrentReference_reduced(n,2) = Results_Reference(m,5); n = n+1; end - end - + end + %Reference current in Steady state and after load change Reference_SS = CurrentReference_reduced(1:l_new_DP,2); Reference_LC = CurrentReference_reduced(l_new_DP:2*l_new_DP,2); @@ -269,4 +269,3 @@ disp(['Root Mean-squared error ia ',TestName,': ', num2str(100*err_LC_DP/Peak_Ref_LC), ' %']); disp(' '); disp(' '); - diff --git a/examples/Matlab/ExciterTest.m b/examples/Matlab/ExciterTest.m index 016a2e497f..428e4e8719 100644 --- a/examples/Matlab/ExciterTest.m +++ b/examples/Matlab/ExciterTest.m @@ -2,7 +2,7 @@ %% read Simulink results -Results_Simulink = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/ExciterOutput_Simulink.csv'); +Results_Simulink = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/ExciterOutput_Simulink.csv'); %% read results from c++ simulation Results_DPsim = csvread('../../../vsa/Results/TestExciterAndTurbine/DPsim/EMT/VBR/ExciterOutput_DPSim.csv'); diff --git a/examples/Matlab/FundamentalToStandard.m b/examples/Matlab/FundamentalToStandard.m index 6256d9c221..ccc6022a8f 100644 --- a/examples/Matlab/FundamentalToStandard.m +++ b/examples/Matlab/FundamentalToStandard.m @@ -4,11 +4,11 @@ Laq, L1q, L2q, R1q, R2q) %FundamentalToStandard Transform fundamental machine parameters to standard %parameters -% The calculations are based on the classical definition. +% The calculations are based on the classical definition. % Equations used are from Kundur p. 144 - 147 % ---- Relationship between parameters used in DPSim and parameters -% defined in Kundur: +% defined in Kundur: % Lad = Lmd % L1d = Llkd % Lfd = Llfd @@ -52,4 +52,3 @@ Lq_t = Ll + Laq*L1q/(Laq+L1q); end - diff --git a/examples/Matlab/StandardToFundamental.m b/examples/Matlab/StandardToFundamental.m index 13ef7751c2..fd44adcea9 100644 --- a/examples/Matlab/StandardToFundamental.m +++ b/examples/Matlab/StandardToFundamental.m @@ -18,4 +18,3 @@ R1q = (Laq + L1q)/(Tq0_t*377); R2q = (1/(Tq0_s*377))*(L2q + Laq*L1q/(Laq+L1q)); end - diff --git a/examples/Matlab/TurbineTest.m b/examples/Matlab/TurbineTest.m index 8ca69bb85c..d10e7cc8a9 100644 --- a/examples/Matlab/TurbineTest.m +++ b/examples/Matlab/TurbineTest.m @@ -2,8 +2,8 @@ %% read Simulink results -Results_Simulink = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/TurbineOutput.csv'); -Omega_Simulink = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/omega.csv'); +Results_Simulink = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/TurbineOutput.csv'); +Omega_Simulink = csvread('../../../vsa/Results/TestExciterAndTurbine/Simulink/omega.csv'); %% read results from c++ simulation Results_DPsim = csvread('../../../vsa/Results/TestExciterAndTurbine/DPsim/EMT/VBR/TurbineOutput_DPsim.csv'); diff --git a/examples/Matlab/compareDpAndEmt.m b/examples/Matlab/compareDpAndEmt.m index 0f51bf706b..d4ba286db1 100644 --- a/examples/Matlab/compareDpAndEmt.m +++ b/examples/Matlab/compareDpAndEmt.m @@ -30,7 +30,7 @@ % Downsampling of reference voltage for row = 1:size(voltageShiftDP,1) if voltageRef(size(voltageRef,1),1) >= voltageShiftDP(row,1) - indices(row) = find(voltageRef(:,1) == voltageShiftDP(row,1),1); + indices(row) = find(voltageRef(:,1) == voltageShiftDP(row,1),1); end end for i = 1:size(indices,2) @@ -61,4 +61,3 @@ ylabel('voltage [V]') end - diff --git a/examples/Matlab/compareDpAndEmtInterp.m b/examples/Matlab/compareDpAndEmtInterp.m index afb3177f53..faff0f9648 100644 --- a/examples/Matlab/compareDpAndEmtInterp.m +++ b/examples/Matlab/compareDpAndEmtInterp.m @@ -60,4 +60,3 @@ ylabel('voltage [V]') end - diff --git a/examples/Matlab/compareDpResults.m b/examples/Matlab/compareDpResults.m index 5f182231d0..664597fdbd 100644 --- a/examples/Matlab/compareDpResults.m +++ b/examples/Matlab/compareDpResults.m @@ -59,4 +59,4 @@ xlabel('time [s]') ylabel('voltage [V]') -end \ No newline at end of file +end diff --git a/examples/Matlab/mmi_ICCEP.m b/examples/Matlab/mmi_ICCEP.m index 677af4b5f9..6b3d56573d 100644 --- a/examples/Matlab/mmi_ICCEP.m +++ b/examples/Matlab/mmi_ICCEP.m @@ -97,4 +97,4 @@ [mseDPInterp, mseEMTInterp] = compareDpAndEmtInterp(filenameRef, filenameVoltageDP, filenameVoltageEMT, 3); comparison(10,:) = [40 mseEMT(4) mseEMTInterp(4) mseDP(4) mseDPInterp(4)] -dlmwrite('comparison_table.csv',comparison,';') \ No newline at end of file +dlmwrite('comparison_table.csv',comparison,';') diff --git a/examples/Matlab/plotDpEmtVoltage.m b/examples/Matlab/plotDpEmtVoltage.m index 3760f2bea1..d5e08ecddc 100644 --- a/examples/Matlab/plotDpEmtVoltage.m +++ b/examples/Matlab/plotDpEmtVoltage.m @@ -42,4 +42,4 @@ xlabel('time [s]') ylabel('voltage [V]') -end \ No newline at end of file +end diff --git a/examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml b/examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml index fab32160f2..a8406e553d 100644 --- a/examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml +++ b/examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml @@ -4,7 +4,7 @@ services: context: ../../../../ #dpsim top-level folder dockerfile: packaging/Docker/Dockerfile.dev environment: - PYTHONPATH: /dpsim/build:/dpsim/build/Source/Python:/dpsim/Source/Python + PYTHONPATH: /dpsim/build:/dpsim/build/Source/Python:/dpsim/Source/Python ports: - "8888:8888" volumes: diff --git a/scripts/start_jupyter.sh b/scripts/start_jupyter.sh index 81dfdb1b4c..c5998cfb62 100644 --- a/scripts/start_jupyter.sh +++ b/scripts/start_jupyter.sh @@ -3,4 +3,4 @@ cd /dpsim-dev/dpsim/build export PYTHONPATH="$(pwd)/Source/Python:$(pwd)/../Source/Python" cd /dpsim-dev/dpsim -jupyter lab --ip="0.0.0.0" --allow-root --no-browser \ No newline at end of file +jupyter lab --ip="0.0.0.0" --allow-root --no-browser From 073c1e8b55e2c1acf1bf82adcbbf0751d54104f1 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 20:16:27 +0200 Subject: [PATCH 018/168] fix(ci): Fix Windows builds with newer CMake versions Signed-off-by: Steffen Vogel --- .github/workflows/build_test_windows.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build_test_windows.yaml b/.github/workflows/build_test_windows.yaml index 6414822163..7d41234a49 100644 --- a/.github/workflows/build_test_windows.yaml +++ b/.github/workflows/build_test_windows.yaml @@ -31,5 +31,6 @@ jobs: cd ${{ github.workspace }} cd build git describe --tags --abbrev=0 --match "v*" - cmake -DWITH_PYBIND=OFF .. + # TODO: Remove '-DCMAKE_POLICY_VERSION_MINIMUM=3.5' once spdlog version has been bumped + cmake -DWITH_PYBIND=OFF -DCMAKE_POLICY_VERSION_MINIMUM="3.5" .. cmake --build . --target dpsim --parallel From f0d08926ae52e453eb7cbeae3bf2ba473dce9f3b Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 20:10:41 +0200 Subject: [PATCH 019/168] fix: Builds on Clang due to -Wnan-infinity-disabled and -ffast-math Signed-off-by: Steffen Vogel --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9d683a0eba..8cba36dfb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,6 +85,16 @@ check_symbol_exists(getopt_long getopt.h HAVE_GETOPT) if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") add_compile_options(-Ofast) + # On Clang -Ofast enables -ffast-math which in turn enables -ffinite-math-only. + # This option causes all calls to functions checking for infinity or NaN to raise + # a warning (e.g. std::isnan). + # As we also set -Werror, these warnings are causing the build to fail. + # With this compiler option, we excplicity silence this warning. + check_cxx_compiler_flag("-Wno-nan-infinity-disabled" CXX_SUPPORTS_WNAN_INFINITY_DISABLED) + if(CXX_SUPPORTS_WNAN_INFINITY_DISABLED) + add_compile_options(-Wno-nan-infinity-disabled) + endif() + if(WITH_MARCH_NATIVE) add_compile_options(-march=native) endif() From f9a9188604a553f440af298eb9cab7dd70dd6791 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 07:21:38 +0200 Subject: [PATCH 020/168] Move pytest.ini to pyproject.toml Signed-off-by: Steffen Vogel --- pyproject.toml | 5 ++++- pytest.ini | 2 -- 2 files changed, 4 insertions(+), 3 deletions(-) delete mode 100644 pytest.ini diff --git a/pyproject.toml b/pyproject.toml index f23ef37807..138608a45a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,6 +4,9 @@ build-backend = "setuptools.build_meta" [tool.cibuildwheel] build-verbosity = "3" -build="[cp]p3{8,9,10,11}-manylinux_x86_64" +build = "[cp]p3{8,9,10,11}-manylinux_x86_64" manylinux-x86_64-image = "sogno/dpsim:manylinux" manylinux-pypy_x86_64-image = "sogno/dpsim:manylinux" + +[tool.pytest.ini_options] +filterwarnings = ["ignore::DeprecationWarning"] diff --git a/pytest.ini b/pytest.ini deleted file mode 100644 index 7d448c5c6c..0000000000 --- a/pytest.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pytest] -filterwarnings = ignore::DeprecationWarning \ No newline at end of file From 7afceba5af6c838d872b9861654a8196ca079561 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:36:12 +0100 Subject: [PATCH 021/168] fix(deps): Add support for newer Spdlog versions Signed-off-by: Steffen Vogel --- CMakeLists.txt | 4 +- cmake/FetchSpdlog.cmake | 2 +- .../include/dpsim-models/Filesystem.h | 8 +++ dpsim-models/include/dpsim-models/Logger.h | 59 +++++++++++++++++++ dpsim/src/RealTimeSimulation.cpp | 9 +-- 5 files changed, 73 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8cba36dfb6..048856bca0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,8 +167,8 @@ endif() if(FETCH_SPDLOG OR WIN32) include(FetchSpdlog) else() - find_package(spdlog 1.5.0 REQUIRED) - find_package(fmt 6.1.2 REQUIRED) + find_package(spdlog 1.10.0 REQUIRED) + find_package(fmt 8.1.1 REQUIRED) endif() if(FETCH_CIMPP OR WIN32) diff --git a/cmake/FetchSpdlog.cmake b/cmake/FetchSpdlog.cmake index dd661f3c81..037f5075ff 100644 --- a/cmake/FetchSpdlog.cmake +++ b/cmake/FetchSpdlog.cmake @@ -5,7 +5,7 @@ option(SPDLOG_BUILD_EXAMPLES "Build spdlog examples" OFF) include(FetchContent) FetchContent_Declare(spdlog-module GIT_REPOSITORY https://github.com/gabime/spdlog.git - GIT_TAG v1.5.0 + GIT_TAG v1.15.0 GIT_SHALLOW TRUE GIT_PROGRESS TRUE ) diff --git a/dpsim-models/include/dpsim-models/Filesystem.h b/dpsim-models/include/dpsim-models/Filesystem.h index df13e828aa..4c7ef862a3 100644 --- a/dpsim-models/include/dpsim-models/Filesystem.h +++ b/dpsim-models/include/dpsim-models/Filesystem.h @@ -13,3 +13,11 @@ namespace fs = std::experimental::filesystem; #include namespace fs = ghc::filesystem; #endif + +#include + +#if FMT_VERSION >= 90000 +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +#endif diff --git a/dpsim-models/include/dpsim-models/Logger.h b/dpsim-models/include/dpsim-models/Logger.h index ac42949ee3..d68f13b5d4 100644 --- a/dpsim-models/include/dpsim-models/Logger.h +++ b/dpsim-models/include/dpsim-models/Logger.h @@ -69,3 +69,62 @@ class Logger { static String getCSVLineFromData(Real time, const MatrixComp &data); }; } // namespace CPS + + +#if FMT_VERSION >= 90000 +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter + : public fmt::ostream_formatter {}; +template +class fmt::formatter> + : public fmt::ostream_formatter {}; +template +class fmt::formatter> + : public fmt::ostream_formatter {}; +template +class fmt::formatter> + : public fmt::ostream_formatter {}; + +template <> +class fmt::formatter> + : public fmt::ostream_formatter {}; +template <> +class fmt::formatter> + : public fmt::ostream_formatter {}; +#endif diff --git a/dpsim/src/RealTimeSimulation.cpp b/dpsim/src/RealTimeSimulation.cpp index 1d64f54a69..089477878b 100644 --- a/dpsim/src/RealTimeSimulation.cpp +++ b/dpsim/src/RealTimeSimulation.cpp @@ -10,6 +10,7 @@ #include #include #include +#include using namespace CPS; using namespace DPsim; @@ -42,12 +43,8 @@ void RealTimeSimulation::run(const Timer::StartClock::time_point &startAt) { sync(); - auto now_time = std::chrono::system_clock::to_time_t(startAt); - SPDLOG_LOGGER_INFO(mLog, "Starting simulation at {} (delta_T = {} seconds)", - std::put_time(std::localtime(&now_time), "%F %T"), - std::chrono::duration_cast( - startAt - Timer::StartClock::now()) - .count()); + SPDLOG_LOGGER_INFO(mLog, "Starting simulation at {:%Y-%m-%d %H:%M:%S} (delta_T = {} seconds)", + startAt, startAt - Timer::StartClock::now()); mTimer.setStartTime(startAt); mTimer.setInterval(**mTimeStep); From 7dd5da6a709a448625b94a27b94206e2ab478922 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 14:51:55 +0200 Subject: [PATCH 022/168] fix: Add missing #pragma once Signed-off-by: Steffen Vogel --- dpsim-models/include/dpsim-models/Filesystem.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dpsim-models/include/dpsim-models/Filesystem.h b/dpsim-models/include/dpsim-models/Filesystem.h index 4c7ef862a3..85eeb1a1d0 100644 --- a/dpsim-models/include/dpsim-models/Filesystem.h +++ b/dpsim-models/include/dpsim-models/Filesystem.h @@ -6,6 +6,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. *********************************************************************************/ +#pragma once + #ifndef USE_GHC_FS #include namespace fs = std::experimental::filesystem; From d5f33cafba47928b6778b268f5f80ff89c122211 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 17:31:16 +0200 Subject: [PATCH 023/168] fix: Use correct include for bundled fmt headers Signed-off-by: Steffen Vogel --- dpsim/src/RealTimeSimulation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpsim/src/RealTimeSimulation.cpp b/dpsim/src/RealTimeSimulation.cpp index 089477878b..2c4095e782 100644 --- a/dpsim/src/RealTimeSimulation.cpp +++ b/dpsim/src/RealTimeSimulation.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include using namespace CPS; using namespace DPsim; From 2646867439ff54f9dfbdb60bc50f585b725d8275 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:38:41 +0100 Subject: [PATCH 024/168] fix(cmake): Fix code-style Signed-off-by: Steffen Vogel --- cmake/FindGSL.cmake | 2 +- cmake/FindSundials.cmake | 2 +- dpsim-models/src/CMakeLists.txt | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake/FindGSL.cmake b/cmake/FindGSL.cmake index 90ae8c8f1c..c39567c7b7 100644 --- a/cmake/FindGSL.cmake +++ b/cmake/FindGSL.cmake @@ -1,4 +1,4 @@ -if (WIN32) +if(WIN32) # GSL is currently not supported for Windows else() find_path(GSL_INCLUDE_DIR diff --git a/cmake/FindSundials.cmake b/cmake/FindSundials.cmake index 5203badaf0..59cc023e0d 100644 --- a/cmake/FindSundials.cmake +++ b/cmake/FindSundials.cmake @@ -1,4 +1,4 @@ -if (WIN32) +if(WIN32) message(STATUS "Sundials is currently not supported in Windows") else() find_path(SUNDIALS_INCLUDE_DIR diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index ff0b7ddd75..5ff995162f 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -158,13 +158,11 @@ list(APPEND MODELS_SOURCES if(WITH_CIM) list(APPEND MODELS_SOURCES CIM/Reader.cpp) - list(APPEND MODELS_LIBRARIES libcimpp) endif() if(WITH_GRAPHVIZ) list(APPEND MODELS_SOURCES Graph.cpp) - list(APPEND MODELS_INCLUDE_DIRS ${GRAPHVIZ_INCLUDE_DIRS}) list(APPEND MODELS_LIBRARIES ${GRAPHVIZ_LIBRARIES}) endif() From f0d35a357d420441960201fb8bc7433e560dab04 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 14 Feb 2024 14:49:44 +0000 Subject: [PATCH 025/168] python: Harmonize comment style Signed-off-by: Steffen Vogel Signed-off-by: Steffen Vogel --- examples/Python/Base/test_async.py | 2 +- examples/Python/Circuits/test_circuit.py | 8 ++-- .../RuntimeMeas/decoupling_9bus_comp.py | 3 +- .../RuntimeMeas/decoupling_9bus_existing.py | 2 +- .../Python/RuntimeMeas/decoupling_sched.py | 2 +- .../RuntimeMeas/diakoptics_splitsize.py | 2 +- examples/Python/RuntimeMeas/sched_nthreads.py | 4 +- examples/conftest.py | 6 +-- .../test_shmem_cigre_mv_pf_profiles.py | 12 +++-- examples/villas/dpsim-file.py | 2 +- .../villas/dpsim-mqtt-cigre-mv-pf-profiles.py | 20 ++++---- .../villas/dpsim-mqtt-import-export-MIMO.py | 4 +- examples/villas/dpsim-mqtt-import-export.py | 2 +- python/src/dpsim/matpower.py | 47 ++++++++++--------- setup.py | 2 +- 15 files changed, 62 insertions(+), 56 deletions(-) diff --git a/examples/Python/Base/test_async.py b/examples/Python/Base/test_async.py index 5c96b22524..80488d233b 100644 --- a/examples/Python/Base/test_async.py +++ b/examples/Python/Base/test_async.py @@ -30,7 +30,7 @@ def test_async(): start = dt.datetime.now() + dt.timedelta(seconds=4) - sim = dpsim.RealTimeSimulation(__name__, system, duration=10, timestep=0.0005)#, start_time=start) + sim = dpsim.RealTimeSimulation(__name__, system, duration=10, timestep=0.0005) # , start_time=start) # Start in two seconds! sim.start() diff --git a/examples/Python/Circuits/test_circuit.py b/examples/Python/Circuits/test_circuit.py index 0533d57db4..ee990fa278 100644 --- a/examples/Python/Circuits/test_circuit.py +++ b/examples/Python/Circuits/test_circuit.py @@ -30,12 +30,12 @@ def test_circuit(): sim = dpsim.Simulation(__name__, system, duration=0.2, timestep=0.0005) sim.run() - #results = rt.read_timeseries_dpsim_cmpl('Logs/' + sim.name + '_LeftVector.csv') - #expected = rt.read_timeseries_dpsim_real('examples/Results/Simulink/Circuits/SL_' + sim.name() + '.csv') + # results = rt.read_timeseries_dpsim_cmpl('Logs/' + sim.name + '_LeftVector.csv') + # expected = rt.read_timeseries_dpsim_real('examples/Results/Simulink/Circuits/SL_' + sim.name() + '.csv') err = 0 - #err += ts.TimeSeries.rmse(expected[0], results[0].dynphasor_shift_to_emt('n1_emt', 50)) - #err += ts.TimeSeries.rmse(expected[1], results[1].dynphasor_shift_to_emt('n2_emt', 50)) + # err += ts.TimeSeries.rmse(expected[0], results[0].dynphasor_shift_to_emt('n1_emt', 50)) + # err += ts.TimeSeries.rmse(expected[1], results[1].dynphasor_shift_to_emt('n2_emt', 50)) print('Total RMSE: %g' % (err)) diff --git a/examples/Python/RuntimeMeas/decoupling_9bus_comp.py b/examples/Python/RuntimeMeas/decoupling_9bus_comp.py index 12865cecd8..d3da2a9677 100644 --- a/examples/Python/RuntimeMeas/decoupling_9bus_comp.py +++ b/examples/Python/RuntimeMeas/decoupling_9bus_comp.py @@ -90,8 +90,7 @@ def do_sim(name, system): for i in range(0, 6): varname = 'BUS' + str(i+4) + '.v' -#varname = 'BUS4.v' -#i = 0 + pt.set_timeseries_labels(normal_emt[varname], varname + ' normal') pt.set_timeseries_labels(coupled_emt[varname], varname + ' coupled') pt.set_timeseries_labels(decoupled_emt[varname], varname + ' decoupled') diff --git a/examples/Python/RuntimeMeas/decoupling_9bus_existing.py b/examples/Python/RuntimeMeas/decoupling_9bus_existing.py index fa7b6636a7..2f96356c2c 100644 --- a/examples/Python/RuntimeMeas/decoupling_9bus_existing.py +++ b/examples/Python/RuntimeMeas/decoupling_9bus_existing.py @@ -58,7 +58,7 @@ def do_sim(name, system): reader_decoupled = dpsimpy.CIMReader(name) system = reader_decoupled.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.IdealVoltageSource) decouple_line(system, 'LINE75', 'BUS5', 'BUS7') -#decouple_line(system, 'LINE78', 'BUS7', 'BUS8') +# decouple_line(system, 'LINE78', 'BUS7', 'BUS8') decouple_line(system, 'LINE64', 'BUS6', 'BUS4') decouple_line(system, 'LINE89', 'BUS8', 'BUS9') do_sim('decoupled', system) diff --git a/examples/Python/RuntimeMeas/decoupling_sched.py b/examples/Python/RuntimeMeas/decoupling_sched.py index 89a3d5fcbf..fd5f19eb4a 100644 --- a/examples/Python/RuntimeMeas/decoupling_sched.py +++ b/examples/Python/RuntimeMeas/decoupling_sched.py @@ -36,7 +36,7 @@ def decoupling_sched(instance, sizes, schedulers): } instance.copy_settings = { 'decouple': True, - #'decouple': 'diakoptics', + # 'decouple': 'diakoptics', 'nodes': ['BUS5', 'BUS6', 'BUS8'], 'resistance': 100, 'inductance': 0.16, diff --git a/examples/Python/RuntimeMeas/diakoptics_splitsize.py b/examples/Python/RuntimeMeas/diakoptics_splitsize.py index 0e61bb39ac..70b244b5d6 100644 --- a/examples/Python/RuntimeMeas/diakoptics_splitsize.py +++ b/examples/Python/RuntimeMeas/diakoptics_splitsize.py @@ -36,7 +36,7 @@ def diakoptics_splitsize(instance, size, splits, scheduler): 'log_level': 0, } instance.copy_settings = { - #'decouple': True, + # 'decouple': True, 'decouple': 'diakoptics', 'nodes': ['BUS5', 'BUS6', 'BUS8'], 'resistance': 100, diff --git a/examples/Python/RuntimeMeas/sched_nthreads.py b/examples/Python/RuntimeMeas/sched_nthreads.py index 339eb72b8e..eb73ae0b9f 100644 --- a/examples/Python/RuntimeMeas/sched_nthreads.py +++ b/examples/Python/RuntimeMeas/sched_nthreads.py @@ -24,7 +24,7 @@ def sched_nthreads(instance, threads, schedulers, size): if __name__ == '__main__': threads = range(1, 11) schedulers = [ -# 'sequential', + # 'sequential', 'omp_level', 'thread_level', 'thread_level meas', @@ -32,7 +32,7 @@ def sched_nthreads(instance, threads, schedulers, size): 'thread_list meas', ] size = 1 - #size = 20 + # size = 20 name = 'sched_nthreads' if len(sys.argv) > 1: diff --git a/examples/conftest.py b/examples/conftest.py index edae686aa9..d6337b59f9 100644 --- a/examples/conftest.py +++ b/examples/conftest.py @@ -17,7 +17,7 @@ def parse_test_params(item, spec): class YamlFile(pytest.File): def collect(self): - # we need a yaml parser, e.g. PyYAML + # We need a yaml parser, e.g. PyYAML import yaml raw = yaml.safe_load(self.fspath.open()) @@ -105,7 +105,7 @@ def __init__(self, name, parent, spec, nb): def runtest(self): from traitlets.config import Config - #from nbconvert import HTMLExporter + # from nbconvert import HTMLExporter from nbconvert import MarkdownExporter from nbconvert.writers import FilesWriter @@ -119,7 +119,7 @@ def runtest(self): 'nbconvert.preprocessors.ExecutePreprocessor', 'nbconvert.preprocessors.ExtractOutputPreprocessor' ] - #exporter = HTMLExporter(config=c) + # exporter = HTMLExporter(config=c) exporter = MarkdownExporter(config=c) os.makedirs(c.FilesWriter.build_directory, exist_ok=True) diff --git a/examples/villas-deprecated/test_shmem_cigre_mv_pf_profiles.py b/examples/villas-deprecated/test_shmem_cigre_mv_pf_profiles.py index 78f95728e9..e28b372aa4 100644 --- a/examples/villas-deprecated/test_shmem_cigre_mv_pf_profiles.py +++ b/examples/villas-deprecated/test_shmem_cigre_mv_pf_profiles.py @@ -1,7 +1,13 @@ # To run this example, an MQTT broker is required -# docker run -it -p 1883:1883 -p 9001:9001 eclipse-mosquitto -# test message: mosquitto_pub -t 'test/topic' -m "test" -# get messages: mosquitto_sub -v -t '#' +# +# Start container: +# docker run -it -p 1883:1883 -p 9001:9001 eclipse-mosquitto +# +# Send message: +# mosquitto_pub -t 'test/topic' -m "test" +# +# Get messages: +# mosquitto_sub -v -t '#' import glob import sys diff --git a/examples/villas/dpsim-file.py b/examples/villas/dpsim-file.py index dbab6bf162..5c1398140b 100644 --- a/examples/villas/dpsim-file.py +++ b/examples/villas/dpsim-file.py @@ -54,7 +54,7 @@ intf.export_attribute(evs.attr('i_intf').derive_coeff(0, 0), 0) sim.add_interface(intf) -#sim.import_attribute('v_intf', 'V_ref', 0) +# sim.import_attribute('v_intf', 'V_ref', 0) sim.add_logger(logger) diff --git a/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py b/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py index 3bc4e531b3..ed7dded177 100644 --- a/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py +++ b/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py @@ -9,22 +9,22 @@ import dpsimpy import dpsimpyvillas -# setup +# Setup name = 'CIGRE-MV-Profiles' time_step = 1 final_time = 30 -# setup stdout logger +# Setup stdout logger base = os.path.splitext(os.path.basename(sys.argv[0]))[0] log = logging.getLogger(base) -# read topology from CIM -files = glob.glob('build/_deps/cim-data-src/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/*.xml') # downloaded by CMake +# Read topology from CIM +files = glob.glob('build/_deps/cim-data-src/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/*.xml') # Downloaded by CMake log.info('CIM files: %s', files) reader = dpsimpy.CIMReader(name) system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode) -# map from CSV to simulation names +# Map from CSV to simulation names assignList = { 'LOAD-H-1': 'Load_H_1', 'LOAD-H-3': 'Load_H_3', @@ -46,13 +46,13 @@ 'LOAD-I-14': 'Load_I_14' } -# read profiles from CSV +# Read profiles from CSV csv_files = 'build/_deps/profile-data-src/CIGRE_MV_NoTap/load_profiles/' log.info('CSV files: %s', csv_files) csvreader = dpsimpy.CSVReader(name, csv_files, assignList, dpsimpy.LogLevel.info) csvreader.assignLoadProfile(system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS) -# instantiate logger +# Instantiate logger logger = dpsimpy.Logger(name) # setup VILLASnode @@ -69,7 +69,7 @@ intf_mqtt = dpsimpyvillas.InterfaceVillas(name='MQTT', config=json.dumps(intf_mqtt_config)) -# setup simulation +# Setup simulation sim = dpsimpy.RealTimeSimulation(name) sim.set_system(system) sim.set_domain(dpsimpy.Domain.SP) @@ -79,7 +79,7 @@ sim.add_logger(logger) sim.add_interface(intf_mqtt) -# setup exports +# Setup exports for i in range(15): objname = 'N'+str(i) intf_mqtt.export_attribute(sim \ @@ -91,7 +91,7 @@ .derive_coeff(0,0) \ .derive_phase(), 2*i+1) -# log exports +# Log exports for node in system.nodes: sim.log_idobj_attribute(node.name(), 'v') diff --git a/examples/villas/dpsim-mqtt-import-export-MIMO.py b/examples/villas/dpsim-mqtt-import-export-MIMO.py index f11efa8606..5de738bf40 100644 --- a/examples/villas/dpsim-mqtt-import-export-MIMO.py +++ b/examples/villas/dpsim-mqtt-import-export-MIMO.py @@ -1,5 +1,5 @@ # This example attempts to read a sine signal generated by VILLASnode via a MQTT connection as well as a shared memory connection. -# dpsim then exports several values over these connections which should be read by VILLASnode and written to a file. +# DPsim then exports several values over these connections which should be read by VILLASnode and written to a file. # Due to problems with the shared memory node in VILLAS, this example currently does not run correctly! @@ -193,7 +193,7 @@ def dpsim(): def test_shmem_import_export(): logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.INFO) - sim, intf, intf2 = dpsim() #intf needs to be extracted from the dpsim-function since the interface object gets deleted otherwise leading to SegFault when starting the simulation + sim, intf, intf2 = dpsim() # intf needs to be extracted from the dpsim-function since the interface object gets deleted otherwise leading to SegFault when starting the simulation node = villas() node.start() diff --git a/examples/villas/dpsim-mqtt-import-export.py b/examples/villas/dpsim-mqtt-import-export.py index 9d30034666..87ca9cf879 100644 --- a/examples/villas/dpsim-mqtt-import-export.py +++ b/examples/villas/dpsim-mqtt-import-export.py @@ -147,7 +147,7 @@ def dpsim(): def test_shmem_import_export(): logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.INFO) - sim, intf = dpsim() #intf needs to be extracted from the dpsim-function since the interface object gets deleted otherwise leading to SegFault when starting the simulation + sim, intf = dpsim() # intf needs to be extracted from the dpsim-function since the interface object gets deleted otherwise leading to SegFault when starting the simulation node = villas() node.start() diff --git a/python/src/dpsim/matpower.py b/python/src/dpsim/matpower.py index 7914cd13c3..3c53040559 100644 --- a/python/src/dpsim/matpower.py +++ b/python/src/dpsim/matpower.py @@ -7,7 +7,7 @@ class Reader: def __init__(self, mpc_file_path, mpc_name = 'mpc'): - # read input file (returns multidimensional dict) + # Read input file (returns multidimensional dict) self.mpc_raw = scipy.io.loadmat(mpc_file_path) self.mpc_name = mpc_name @@ -58,7 +58,7 @@ def process_mpc(self): self.mpc_gen_data['status'] = self.mpc_gen_data['status'].astype(int) #### Branches - # extract only first 13 columns since following columns include results + # Extract only first 13 columns since following columns include results mpc_branch_raw = self.mpc_raw[self.mpc_name][0][0][branch_data_idx][:, :13] branch_data_header = ["fbus", "tbus", "r", "x", "b", "rateA", "rateB", @@ -76,11 +76,11 @@ def create_dpsim_objects(self): self.process_mpc() - # return values: nodes and components + # Return values: nodes and components dpsimpy_busses_dict = {} dpsimpy_comp_dict = {} - # default multiplier for matpower data + # Default multiplier for matpower data mw_w = 1e6 kv_v = 1e3 @@ -91,13 +91,13 @@ def create_dpsim_objects(self): inj = 0 for index, bus in self.mpc_bus_data.iterrows(): - # create dpsimpy busses + # Create dpsimpy busses bus = bus + 1 bus_index = str(self.mpc_bus_data.at[index,'bus_i']) bus_name = bus_index dpsimpy_busses_dict[bus_name] = dpsimpy.sp.SimNode(bus_name, dpsimpy.PhaseType.Single) - # for each bus type create corresponding dpsimpy component + # For each bus type create corresponding dpsimpy component # 1 = PQ, 2 = PV, 3 = ref, 4 = isolated bus_type = self.mpc_bus_data.at[index,'type'] @@ -113,7 +113,7 @@ def create_dpsim_objects(self): dpsimpy_comp_dict[load_name][0].set_parameters(load_p, load_q, load_baseV) dpsimpy_comp_dict[load_name][0].modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PQ) - # add connections + # Add connections dpsimpy_comp_dict[load_name].append([dpsimpy_busses_dict[bus_index]]) # [to bus] # Generators @@ -121,21 +121,21 @@ def create_dpsim_objects(self): generator = generator + 1 gen_name = "gen%s" %generator - # relevant data from self.mpc_gen_data. Identification with bus number available in mpc_bus_data and mpc_gen_data + # Relevant data from self.mpc_gen_data. Identification with bus number available in mpc_bus_data and mpc_gen_data gen = self.mpc_gen_data.loc[self.mpc_gen_data['bus'] == self.mpc_bus_data.at[index,'bus_i']] - gen_baseS = gen['mBase']*mw_w # gen base MVA default is mpc.baseMVA - gen_baseV = self.mpc_bus_data.at[index,'baseKV']*kv_v # gen base kV - gen_v = gen['Vg']*gen_baseV # gen set point voltage (gen['Vg'] in p.u.) - gen_p = gen['Pg']*mw_w # gen ini. active power (gen['Pg'] in MVA) - # gen_q = gen['Qg']*mw_w # gen ini. reactive power (gen['Qg'] in MVAr) - gen_nom_s = abs(complex(gen['Pmax'], gen['Qmax'])) # gen nominal power (set default to mpc.baseMVA ? ) + gen_baseS = gen['mBase']*mw_w # Generator base MVA default is mpc.baseMVA + gen_baseV = self.mpc_bus_data.at[index,'baseKV']*kv_v # Generator base kV + gen_v = gen['Vg']*gen_baseV # Generator set point voltage (gen['Vg'] in p.u.) + gen_p = gen['Pg']*mw_w # Generator ini. active power (gen['Pg'] in MVA) + # gen_q = gen['Qg']*mw_w # Generator ini. reactive power (gen['Qg'] in MVAr) + gen_nom_s = abs(complex(gen['Pmax'], gen['Qmax'])) # Generator nominal power (set default to mpc.baseMVA ?) dpsimpy_comp_dict[gen_name] = [dpsimpy.sp.ph1.SynchronGenerator(gen_name, dpsimpy.LogLevel.info)] dpsimpy_comp_dict[gen_name][0].set_parameters(gen_nom_s, gen_baseV, gen_p, gen_v, dpsimpy.PowerflowBusType.PV) dpsimpy_comp_dict[gen_name][0].set_base_voltage(gen_baseV) - # add connections + # Add connections dpsimpy_comp_dict[gen_name].append([dpsimpy_busses_dict[bus_index]]) # [to bus] # Network injection (slack bus) @@ -143,10 +143,10 @@ def create_dpsim_objects(self): inj = inj + 1 extnet_name = "extnet%s" %inj - # relevant data from self.mpc_gen_data. Identification with bus number available in mpc_bus_data and mpc_gen_data + # Relevant data from self.mpc_gen_data. Identification with bus number available in mpc_bus_data and mpc_gen_data extnet = self.mpc_gen_data.loc[self.mpc_gen_data['bus'] == self.mpc_bus_data.at[index,'bus_i']] - # extnet_baseS= extnet['mBase']*mw_w # default is mpc.baseMVA + # extnet_baseS = extnet['mBase']*mw_w # Default is mpc.baseMVA extnet_baseV = self.mpc_bus_data.at[index,'baseKV']*kv_v extnet_v = extnet['Vg']*extnet_baseV @@ -155,16 +155,16 @@ def create_dpsim_objects(self): dpsimpy_comp_dict[extnet_name][0].set_base_voltage(extnet_baseV) dpsimpy_comp_dict[extnet_name][0].modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD) - # add connections + # Add connections dpsimpy_comp_dict[extnet_name].append([dpsimpy_busses_dict[bus_index]]) # [to bus] - #isolated + # Isolated elif bus_type == 4: print("isolated bus type") else: print("bus type error") - ### branches #### + ### Branches line = 0 trafo = 0 for index, branch in self.mpc_branch_data.iterrows(): @@ -191,12 +191,13 @@ def create_dpsim_objects(self): line_b = self.mpc_branch_data.at[index,'b'] / line_baseZ line_l = line_x / self.mpc_omega line_c = line_b / self.mpc_omega - line_g = 0 # line conductance is not included in mpc + line_g = 0 # Line conductance is not included in mpc dpsimpy_comp_dict[line_name] = [dpsimpy.sp.ph1.PiLine(line_name, dpsimpy.LogLevel.info)] dpsimpy_comp_dict[line_name][0].set_parameters(line_r, line_l, line_c, line_g) dpsimpy_comp_dict[line_name][0].set_base_voltage(line_tbus_baseV) - # add connections + + # Add connections dpsimpy_comp_dict[line_name].append([dpsimpy_busses_dict[str(line_fbus)], dpsimpy_busses_dict[str(line_tbus)]]) # Transformers @@ -235,7 +236,7 @@ def create_dpsim_objects(self): print(transf_primary_v, transf_secondary_v, np.abs(transf_ratio), np.angle(transf_ratio), transf_r, transf_l) print(transf_tbus_baseV) - # add connections + # Add connections dpsimpy_comp_dict[transf_name].append([dpsimpy_busses_dict[str(transf_fbus)], dpsimpy_busses_dict[str(transf_tbus)]]) return dpsimpy_busses_dict, dpsimpy_comp_dict diff --git a/setup.py b/setup.py index 701ee0179a..3b4e06ca0c 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ def build_extension(self, ext): f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG={extdir}", f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE={extdir}", f"-DPYTHON_EXECUTABLE={sys.executable}", - f"-DCMAKE_BUILD_TYPE={cfg}" # not used on MSVC, but no harm + f"-DCMAKE_BUILD_TYPE={cfg}" # Not used on MSVC, but no harm ] if platform.system() == 'Windows': From fbeac106d6e710fa688366da38216c028ccad585 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 07:18:39 +0200 Subject: [PATCH 026/168] Remove outdated and broken GitLab CI pipeline Signed-off-by: Steffen Vogel --- .gitlab-ci.yml | 559 ------------------------------------------------- 1 file changed, 559 deletions(-) delete mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 54e4a431c0..0000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,559 +0,0 @@ -variables: - GIT_STRATEGY: fetch - GIT_SUBMODULE_STRATEGY: recursive - - RSYNC_OPTS: --recursive --ignore-missing-args --chown ${DEPLOY_USER}:${DEPLOY_USER} - - DOCKER_IMAGE: sogno/dpsim - DOCKER_IMAGE_DEV: sogno/dpsim-dev - DOCKER_IMAGE_DEV_ROCKY: sogno/dpsim-dev-rocky - - MAKE_OPTS: -j16 # for HYPER buildbots - -stages: - - prepare - - build - - test - - generate -# - deploy - -# moved to github actions -#.docker-fedora-template: &docker-fedora-template -# stage: prepare -# image: docker:20.10 -# needs: [] -# script: -# - docker build -# --build-arg MAKE_OPTS=${MAKE_OPTS} -# --file packaging/Docker/Dockerfile.dev -# ${TAGS} -# ${BUILD_ARGS} . -# tags: -# - docker -# -#docker:fedora-cgmes: -# <<: *docker-fedora-template -# variables: -# TAGS: --tag ${DOCKER_IMAGE_DEV}:${CI_COMMIT_REF_NAME}-cgmes --tag ${DOCKER_IMAGE_DEV}:latest -# BUILD_ARGS: --build-arg CIM_VERSION=CGMES_2.4.15_16FEB2016 - -# CGMES is the preferred CIM flavor -#docker:fedora-cim: -# <<: *docker-fedora-template -# variables: -# TAGS: --tag ${DOCKER_IMAGE_DEV}:${CI_COMMIT_REF_NAME}-cim -# BUILD_ARGS: --build-arg CIM_VERSION=IEC61970_16v29a - -docker:rocky: - stage: prepare - needs: [] - script: - - docker build . - --build-arg MAKE_OPTS=${MAKE_OPTS} - --file packaging/Docker/Dockerfile.dev-rocky - --tag ${DOCKER_IMAGE_DEV_ROCKY}:${CI_COMMIT_REF_NAME} - tags: - - docker - -# moved to github actions -#build:linux-cgmes: -# stage: build -# needs: ["docker:fedora-cgmes"] -# script: -# - mkdir -p build -# - cd build -# - cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 .. -# - make -j 32 -# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}-cgmes -# cache: -# artifacts: -# paths: -# - build -# tags: -# - docker - -# CGMES is the preferred CIM flavor -#build:linux-cim: -# stage: build -# needs: ["docker:fedora-cim"] -# script: -# - mkdir -p build -# - cd build -# - cmake -DCIM_VERSION=IEC61970_16v29a .. -# - make -j 32 -# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}-cim -# cache: -# paths: -# - build -# key: build-linux -# tags: -# - docker - -# moved to github actions -#build:linux-profiling: -# stage: build -# needs: ["docker:centos"] -# script: -# - mkdir -p build -# - cd build -# - cmake -DWITH_PROFILING=ON -DWITH_ASAN=ON -DWITH_CUDA=OFF -DFETCH_SPDLOG=ON .. -# - make -j 32 -# image: ${DOCKER_IMAGE_DEV}-centos:${DOCKER_TAG} -# cache: -# artifacts: -# paths: -# - build -# tags: -# - docker - -build:linux-cuda: - stage: build - needs: ["docker:rocky"] - image: ${DOCKER_IMAGE_DEV_ROCKY}:${CI_COMMIT_REF_NAME} - artifacts: - paths: - - build - tags: - - docker - script: - - mkdir -p build - - cd build - - cmake -DWITH_CUDA=ON -DWITH_SPARSE=ON -DFETCH_SPDLOG=ON -DWITH_MAGMA=ON .. - - make ${MAKE_OPTS} - cache: - -# moved to GitHub actions -#build:windows: -# stage: build -# needs: [] -# script: -# - New-Item -ItemType Directory -Force -Path build -# - Set-Location -Path build -# - cmake .. -# - cmake --build . -j 24 - -# moved to GitHub actions -#build:docker: -# stage: build -# needs: [] -# script: -# - docker build -# --file packaging/Docker/Dockerfile -# --build-arg DOCKER_TAG=${DOCKER_TAG} -# --build-arg MAKE_OPTS=${MAKE_OPTS} -# --tag ${DOCKER_IMAGE}:${DOCKER_TAG} -# --tag ${DOCKER_IMAGE}:latest . -# tags: -# - docker -# only: -# - tags - -#build:macos: -# stage: build -# script: -# - mkdir -p build -# - cd build -# - cmake -DCMAKE_C_COMPILER=/usr/local/bin/gcc-9 -# -DCMAKE_CXX_COMPILER=/usr/local/bin/g++-9 -# -DFETCH_CIMPP=ON -# -DWITH_SUNDIALS=OFF .. -# - make -j $(sysctl -n hw.ncpu) -# cache: -# paths: -# - build -# key: build-macos -# artifacts: -# paths: -# - build -# tags: -# - mac - -#test:pytest: -# stage: test -# variables: -# PYTHONPATH: "build/Source/Python:Source/Python" -# script: -# - pytest -v examples/CIM/test_CIM.yml -# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG} -# dependencies: -# - build:linux -# tags: -# - docker - -############################################################################## -# Stage test -############################################################################## - -# moved to GitHub actions -#test:jupyter-cgmes: -# stage: test -# needs: ["build:linux-cgmes"] -# variables: -# PYTHONPATH: "build:build/Source/Python:Source/Python" -# script: -# - pytest -v examples/Notebooks -# dependencies: -# - build:linux-cgmes -# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}-cgmes -# tags: -# - docker -# artifacts: -# paths: -# - outputs/examples/Notebooks/ -# -#test:cppcheck 1/2: -# stage: test -# needs: ["docker:centos"] -# script: -# - set -o pipefail -# - cppcheck --max-configs=32 -j 32 --error-exitcode=1 -q --std=c++11 -I Include/ -I models/Include/ Source/ examples/ models/Source/ | tee cppcheck-error.log -# image: ${DOCKER_IMAGE_DEV}-centos:${DOCKER_TAG} -# dependencies: -# - docker:centos -# tags: -# - docker -# artifacts: -# when: on_failure -# paths: -# - cppcheck-error.log -# expose_as: 'cppcheck-error' -# -#test:cppcheck 2/2: -# stage: test -# needs: ["docker:centos"] -# allow_failure: true -# script: -# - set -o pipefail -# - cppcheck --max-configs=32 -j 32 --error-exitcode=1 -q --enable=warning,performance,portability,information,missingInclude --std=c++11 -I Include/ -I models/Include/ Source/ examples/ models/Source/ | tee cppcheck-warn.log -# image: ${DOCKER_IMAGE_DEV}-centos:${DOCKER_TAG} -# dependencies: -# - docker:centos -# tags: -# - docker -# artifacts: -# when: on_failure -# paths: -# - cppcheck-warn.log -# expose_as: 'cppcheck-warn' -# -#.test-examples: -# stage: test -# needs: ["build:linux-profiling"] -# script: -# - $TEST_BINARY_PATH/$TEST_BINARY $TEST_PARAM 2>&1 | tee output.log -# - cat output.log | -# sed -n -E -e 's/^.*Average step time. ([0-9]+\.[0-9]+)$/step-time \1/p' | -# tee -a metrics.txt -# - gprof $TEST_BINARY_PATH/$TEST_BINARY | gprof2dot -s | dot -Tpng -o profiling.png || true -# image: ${DOCKER_IMAGE_DEV}-centos:${DOCKER_TAG} -# dependencies: -# - build:linux-profiling -# tags: -# - docker -# artifacts: -# reports: -# metrics: metrics.txt -# paths: -# - profiling.png -# expose_as: 'test-examples' -# -#test:examples 1/2: -# extends: .test-examples -# variables: -## Name of the test binary -# TEST_BINARY: 'WSCC_9bus_mult_decoupled' -## Path where the test binary is located -# TEST_BINARY_PATH: 'build/dpsim/examples/cxx' -## Command line parameters for the test binary -# TEST_PARAM: '' -# -#test:examples 2/2: -# extends: .test-examples -# variables: -## Name of the test binary -# TEST_BINARY: 'WSCC_9bus_mult_coupled' -## Path where the test binary is located -# TEST_BINARY_PATH: 'build/dpsim/examples/cxx' -## Command line parameters for the test binary -# TEST_PARAM: '' - - -.benchmark-script: &benchmark-script | - for ((copies=0;copies<=$TEST_NUM_COPIES;copies++)) - do - echo "Running with $copies copies" - $TEST_BINARY_PATH/$TEST_BINARY $TEST_PARAM -o copies=$copies 2>&1 | tee output.log - cat output.log | - sed -n -E -e 's/^.*Average step time. ([0-9]+\.[0-9]+)$/\1/p' | - tee -a ${METRICS_ID}-metrics.txt - done - -.benchmark-step-times: - stage: test - script: - - *benchmark-script - image: ${DOCKER_IMAGE_DEV_ROCKY}:${CI_COMMIT_REF_NAME} - tags: - - docker - -test:solver-benchmark 1/2: - extends: .benchmark-step-times - needs: ["build:linux-cuda"] - dependencies: - - build:linux-cuda - variables: -# Metrics-filename - METRICS_ID: 'cpu-dense' -# Name of the test binary - TEST_BINARY: 'WSCC_9bus_mult_coupled' -# Path where the test binary is located - TEST_BINARY_PATH: 'build/dpsim/examples/cxx' -# Up to how many copies should be benchmarked (WSCC_9bus - Example) - TEST_NUM_COPIES: 6 - TEST_PARAM: "-U EigenDense" - artifacts: - reports: - metrics: cpu-dense-metrics.txt - paths: - - cpu-dense-metrics.txt - expose_as: 'step-times-benchmark' - - -test:solver-benchmark 2/2: - extends: .benchmark-step-times - needs: ["build:linux-cuda"] - dependencies: - - build:linux-cuda - variables: -# Metrics-filename - METRICS_ID: 'cpu-sparse' -# Name of the test binary - TEST_BINARY: 'WSCC_9bus_mult_coupled' -# Path where the test binary is located - TEST_BINARY_PATH: 'build/dpsim/examples/cxx' -# Up to how many copies should be benchmarked (WSCC_9bus - Example) - TEST_NUM_COPIES: 6 - TEST_PARAM: "-U EigenSparse" - artifacts: - reports: - metrics: cpu-sparse-metrics.txt - paths: - - cpu-sparse-metrics.txt - expose_as: 'step-times-benchmark' - - -.gpu-init-script: &gpu-init-script | - mkdir ~/.ssh && - echo "-----BEGIN OPENSSH PRIVATE KEY-----" > ~/.ssh/id_rsa && - echo $SSH_PRIVATE | sed "s/\S\{64\}/&\n/g" >> ~/.ssh/id_rsa && - echo "-----END OPENSSH PRIVATE KEY-----" >> ~/.ssh/id_rsa && - echo $SSH_PUBLIC > ~/.ssh/id_rsa.pub && - echo $KNOWN_HOSTS > ~/.ssh/known_hosts && chmod 600 ~/.ssh/id_rsa - echo "$TEST_BINARY_PATH/$TEST_BINARY $TEST_FILES" | tr -d '\n' | xargs -r -d " " -I % cp % $LDIR - ldd $LDIR/$TEST_BINARY | - sed -n -E -e 's/^\s+\S+ => (\S+) \S+$/\1/p' | - grep -Ev "$(echo $REMOTE_LIBS | tr ' ' '|')|not" | - xargs -I % cp % $LDIR/ - ssh $GPU_TARGET mkdir -p $RDIR - scp -r $LDIR/* $GPU_TARGET:$RDIR/ - -.gpu-run-script: &gpu-run-script | - ssh $GPU_TARGET "LD_LIBRARY_PATH=$RDIR:${LD_LIBRARY_PATH} LD_PRELOAD=$RDIR/cricket-server.so $RDIR/$TEST_BINARY" & - sleep 2 - PATH=$LDIR:${PATH} REMOTE_GPU_ADDRESS=ghost.acs-lab.eonerc.rwth-aachen.de LD_PRELOAD=$LDIR/cricket-client.so $TEST_BINARY_PATH/$TEST_BINARY $TEST_PARAM 2>&1 | tee output.log - cat output.log | - sed -n -E -e 's/^.*Average step time. ([0-9]+\.[0-9]+)$/\1/p' | - tee -a ${METRICS_ID}-metrics.txt - -.remote-gpu: - stage: test - variables: - GPU_TARGET: 'gitlab-runner@ghost' - RDIR: '/tmp/gitlab-jobs/$CI_PROJECT_NAME/$CI_JOB_ID' - CI_DIR: '$CI_BUILDS_DIR/$CI_PROJECT_PATH' - LDIR: '/cricket/bin' - TEST_FILES: '' - TEST_PARAM: '' - REMOTE_LIBS: 'linux-vdso.so.1 - librt.so.1 - libdl.so.2 - libcudart.so.10.2 - libcusolver.so.10 - libstdc\+\+.so.6 - libm.so.6 - libgcc_s.so.1 - libc.so.6 - /lib64/ld-linux-x86-64.so.2 - libutil.so.1 - libpthread.so.0' - script: - - *gpu-init-script - - *gpu-run-script - after_script: - - ssh $GPU_TARGET rm -rf $RDIR - - ssh $GPU_TARGET pkill -fe -2 $RDIR/$TEST_BINARY - image: ${DOCKER_IMAGE_DEV_ROCKY}:${CI_COMMIT_REF_NAME} - tags: - - docker - -test:cuda 1/3: - extends: .remote-gpu - needs: ["build:linux-cuda"] - dependencies: - - build:linux-cuda - variables: -# Metrics-filename - METRICS_ID: 'cuda' -# Name of the test binary - TEST_BINARY: 'WSCC_9bus_mult_coupled' -# Path where the test binary is located - TEST_BINARY_PATH: 'build/dpsim/examples/cxx' -# Additional files that are necessary to run the application on the GPU node - TEST_FILE: '' -# Command line parameters for the test binary - TEST_PARAM: "-U CUDADense" - artifacts: - reports: - metrics: cuda-metrics.txt - paths: - - cuda-metrics.txt - expose_as: 'step-times-benchmark' - -test:cuda 2/3: - extends: .remote-gpu - needs: ["build:linux-cuda"] - dependencies: - - build:linux-cuda - allow_failure: true - variables: -# Metrics-filename - METRICS_ID: 'cuda' -# Name of the test binary - TEST_BINARY: 'WSCC_9bus_mult_coupled' -# Path where the test binary is located - TEST_BINARY_PATH: 'build/dpsim/examples/cxx' -# Additional files that are necessary to run the application on the GPU node - TEST_FILE: '' -# Command line parameters for the test binary - TEST_PARAM: '-U CUDASparse' - artifacts: - reports: - metrics: cuda-metrics.txt - paths: - - cuda-metrics.txt - expose_as: 'step-times-benchmark' - -test:cuda 3/3: - extends: .remote-gpu - needs: ["build:linux-cuda"] - allow_failure: true - dependencies: - - build:linux-cuda - variables: -# Metrics-filename - METRICS_ID: 'cuda' -# Name of the test binary - TEST_BINARY: 'WSCC_9bus_mult_coupled' -# Path where the test binary is located - TEST_BINARY_PATH: 'build/dpsim/examples/cxx' -# Additional files that are necessary to run the application on the GPU node - TEST_FILE: '' -# Command line parameters for the test binary - TEST_PARAM: '-U CUDAMagma' - artifacts: - reports: - metrics: cuda-metrics.txt - paths: - - cuda-metrics.txt - expose_as: 'step-times-benchmark' - - -############################################################################## -# Stage generate -############################################################################## - -# moved to GitHub actions -#generate:docs: -# stage: generate -# needs: ["build:linux-cgmes"] -# script: -# - make ${MAKE_OPTS} -C build docs -# - make ${MAKE_OPTS} -C build docs_cxx -# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}-cgmes -# dependencies: -# - build:linux-cgmes -# artifacts: -# paths: -# - build/docs/sphinx/html -# - build/docs/doxygen/html -# tags: -# - docker -# -#generate:packages: -# stage: generate -# needs: ["build:linux-cgmes"] -# script: -# - make ${MAKE_OPTS} -C build package -# only: -# - tags -# tags: -# - docker -# image: ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}-cgmes -# dependencies: -# - build:linux-cgmes -# artifacts: -# paths: -# - build/*.rpm -# - build/*.tar.gz - -generate:metrics: - stage: generate - needs: ["test:solver-benchmark 1/2", "test:solver-benchmark 2/2"] - script: - - echo "set terminal svg size 800, 500; set output 'metrics.svg'; set title 'Speed of different Solver-Configurations'; set style data lines; set key outside; set xlabel \"Copies (WSCC-9bus Example)\"; set ylabel \"Average steptime (µs)\"; set xtics 1; set xtics nomirror; set ytics nomirror; set grid; plot \"cpu-dense-metrics.txt\" using (\$1 * 1000000) title \"Solving with CPU and dense matrices\", \"gpu-dense-metrics.txt\" using (\$1 * 1000000) title \"Solving with GPU and dense matrices\", \"cpu-sparse-metrics.txt\" using (\$1 * 1000000) title \"Solving with CPU and sparse matrices\"" > script.p - - gnuplot script.p - image: ${DOCKER_IMAGE_DEV_ROCKY}:${CI_COMMIT_REF_NAME} - artifacts: - reports: - metrics: metrics.svg - paths: - - metrics.svg - expose_as: 'WSCC-9bus-benchmark' - tags: - - docker - - -############################################################################## -# Stage deploy -############################################################################## - -# moved to GitHub actions -#pages: -# stage: deploy -# needs: ["generate:docs"] -# script: -# - cp -r build/docs/sphinx/html/. public/sphinx -# - cp -r build/docs/doxygen/html/. public/doxygen -# artifacts: -# paths: -# - public -# dependencies: -# - generate:docs -# only: -# - deploy -# tags: -# - docker -# -#deploy:docker: -# stage: deploy -# script: -# - docker push ${DOCKER_IMAGE_DEV}:${DOCKER_TAG}-cgmes -# - docker push ${DOCKER_IMAGE_DEV}:latest -# - docker push ${DOCKER_IMAGE}:${DOCKER_TAG}-cgmes -# - docker push ${DOCKER_IMAGE}:latest -# dependencies: -# - build:docker -# tags: -# - docker -# only: -# - tags From 40df72178b5501e4c85d503c0d72a1ec3c045755 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 14 Feb 2024 17:56:07 +0000 Subject: [PATCH 027/168] Add minimal pre-commit Signed-off-by: Steffen Vogel --- .github/workflows/pre_commit.yaml | 14 +++++++++++ .pre-commit-config.yaml | 41 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 .github/workflows/pre_commit.yaml create mode 100644 .pre-commit-config.yaml diff --git a/.github/workflows/pre_commit.yaml b/.github/workflows/pre_commit.yaml new file mode 100644 index 0000000000..a5a8222c80 --- /dev/null +++ b/.github/workflows/pre_commit.yaml @@ -0,0 +1,14 @@ +name: Run pre-commit + +on: + pull_request: + push: + branches: [main] + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000..4198718ae0 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,41 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + # - id: end-of-file-fixer + # exclude: \.svg$ + # - id: check-ast + # - id: check-xml + # - id: check-yaml + # - id: check-json + # # devcontainer.json contains comments + # exclude: .devcontainer/devcontainer\.json + # - id: check-toml + # - id: check-added-large-files + # - id: pretty-format-json + # # black has its own mind of formatting Jupyter notebooks + # exclude: \.ipynb$|^.devcontainer/devcontainer\.json$|package-lock\.json$ + # args: + # - --no-sort-keys + # - --autofix + + # - repo: https://github.com/pre-commit/mirrors-clang-format + # rev: "v17.0.6" + # hooks: + # - id: clang-format + + # - repo: https://github.com/editorconfig-checker/editorconfig-checker.python + # rev: "2.7.3" + # hooks: + # - id: editorconfig-checker + # alias: ec + + # Using this mirror lets us use mypyc-compiled black, which is about 2x faster + # - repo: https://github.com/psf/black-pre-commit-mirror + # rev: "23.3.0" + # hooks: + # - id: black + # - id: black-jupyter From e78bf0d41e77be0d3b2eae3e6f9a7283365f0c79 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 2 Apr 2025 17:02:03 +0200 Subject: [PATCH 028/168] fix(style): Remove trailing whitespaces Signed-off-by: Steffen Vogel --- examples/Python/RuntimeMeas/meas_utils.py | 4 ++-- examples/villas/dpsim-mqtt-import-export-MIMO.py | 6 +++--- examples/villas/dpsim-mqtt.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/Python/RuntimeMeas/meas_utils.py b/examples/Python/RuntimeMeas/meas_utils.py index 9bf58f6ec9..3c18497e7f 100644 --- a/examples/Python/RuntimeMeas/meas_utils.py +++ b/examples/Python/RuntimeMeas/meas_utils.py @@ -202,7 +202,7 @@ def read_csv(filename): else: data[k].append(float(v)) return Measurement(None, xaxis, xlabel, data, filename.rstrip('.csv'), sigma) - + def speedup(self, old, name): if self.xaxis != old.xaxis: raise ValueError("x axis mismatch") @@ -229,7 +229,7 @@ def write_csv(self, filename): for k in self.sigma.keys(): row['sigma ' + k] = self.sigma[k][i] writer.writerow(row) - + def write_settings(self, filename): with open(filename, 'w') as f: json.dump(self.instance.__dict__, f, indent=4) diff --git a/examples/villas/dpsim-mqtt-import-export-MIMO.py b/examples/villas/dpsim-mqtt-import-export-MIMO.py index 5de738bf40..424181e9db 100644 --- a/examples/villas/dpsim-mqtt-import-export-MIMO.py +++ b/examples/villas/dpsim-mqtt-import-export-MIMO.py @@ -76,7 +76,7 @@ def villas(): 'signal': 'sine', 'rate': 10, 'frequency': 0.1, - 'amplitude': 50000, + 'amplitude': 50000, 'offset': 100000 }, } @@ -148,7 +148,7 @@ def dpsim(): sim.set_time_step(0.1) sim.set_final_time(10) sim.do_init_from_nodes_and_terminals(False) - + logger = dpsimpy.Logger(name) sim.add_logger(logger) sim.log_attribute('n1.v', n1.attr('v')) @@ -187,7 +187,7 @@ def dpsim(): intf2.import_attribute(load.attr('Q'), 0) intf2.export_attribute(n1.attr('v').derive_coeff(0,0), 0) intf2.export_attribute(n2.attr('v').derive_coeff(0,0).derive_mag(), 1) - + return sim, intf, intf2 def test_shmem_import_export(): diff --git a/examples/villas/dpsim-mqtt.py b/examples/villas/dpsim-mqtt.py index b318e1827f..9c82e3e14e 100644 --- a/examples/villas/dpsim-mqtt.py +++ b/examples/villas/dpsim-mqtt.py @@ -1,5 +1,5 @@ # This example demonstrates the export of values calculated by dpsim to a MQTT broker using the VILLASnode interface -# Note, that dpsim also expects to read a (complex) reference voltage from MQTT, so the simulation will block on every timestep until this value is provided +# Note, that dpsim also expects to read a (complex) reference voltage from MQTT, so the simulation will block on every timestep until this value is provided import json From 50ad24c908c00625de8c10c254a1efdc5971cf82 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 2 Apr 2025 21:28:42 +0200 Subject: [PATCH 029/168] feat(pre-commit): Enable end-of-file-fixer Signed-off-by: Steffen Vogel --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4198718ae0..560eba5c0e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,8 +5,8 @@ repos: rev: v5.0.0 hooks: - id: trailing-whitespace - # - id: end-of-file-fixer - # exclude: \.svg$ + - id: end-of-file-fixer + exclude: \.svg$ # - id: check-ast # - id: check-xml # - id: check-yaml From a50b8b38dad8558b81d73cf62a1297f8805e85ec Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 2 Apr 2025 21:29:19 +0200 Subject: [PATCH 030/168] fix(style): Fix end of files to contain a single new line Signed-off-by: Steffen Vogel --- .clang-format | 1 - .github/workflows/build_test_linux_rocky.yaml | 2 +- docs/sphinx/conf.py.in | 2 +- .../include/dpsim-models/EMT/EMT_Ph3_SSN_Full_Serial_RLC.h | 2 +- dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Inductor.h | 2 +- dpsim-models/include/dpsim-models/MNAStampUtils.h | 2 +- dpsim-models/src/EMT/EMT_Ph1_Switch.cpp | 2 +- dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp | 2 +- dpsim-models/src/EMT/EMT_Ph3_SSN_Full_Serial_RLC.cpp | 2 +- examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb | 2 +- examples/Notebooks/Components/SynGenDq7od_ParameterStudy.ipynb | 2 +- examples/test_example.yml | 2 +- examples/villas/dpsim-file.py | 2 +- examples/villas/dpsim-mqtt-import-export-MIMO.py | 2 +- examples/villas/dpsim-mqtt-producer.py | 2 +- examples/villas/dpsim-mqtt.py | 2 +- python/src/dpsim/matpower.py | 1 - 17 files changed, 15 insertions(+), 17 deletions(-) diff --git a/.clang-format b/.clang-format index 5bf551f4dd..ce2f4e39f6 100644 --- a/.clang-format +++ b/.clang-format @@ -6,4 +6,3 @@ BasedOnStyle: LLVM # Increase ColumnLimit to avoid breaking SPDX headers ColumnLimit: 200 - diff --git a/.github/workflows/build_test_linux_rocky.yaml b/.github/workflows/build_test_linux_rocky.yaml index a2bd68c134..28bf13f77d 100644 --- a/.github/workflows/build_test_linux_rocky.yaml +++ b/.github/workflows/build_test_linux_rocky.yaml @@ -64,4 +64,4 @@ jobs: - name: Build every target shell: bash working-directory: ${{ github.workspace }}/build - run: cmake --build . --parallel $(nproc) \ No newline at end of file + run: cmake --build . --parallel $(nproc) diff --git a/docs/sphinx/conf.py.in b/docs/sphinx/conf.py.in index 52c0e4ddcf..5b8cc1c977 100755 --- a/docs/sphinx/conf.py.in +++ b/docs/sphinx/conf.py.in @@ -73,4 +73,4 @@ html_static_path = [ ] html_context = { 'source_url_prefix': "@PROJECT_VCS_URL@/docs/", -} \ No newline at end of file +} diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Full_Serial_RLC.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Full_Serial_RLC.h index 145109cbe0..3b9eb3a2ec 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Full_Serial_RLC.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Full_Serial_RLC.h @@ -94,4 +94,4 @@ class Full_Serial_RLC final : public MNASimPowerComp, } // namespace SSN } // namespace Ph3 } // namespace EMT -} // namespace CPS \ No newline at end of file +} // namespace CPS diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Inductor.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Inductor.h index a1e1871496..400b8857f4 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Inductor.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Inductor.h @@ -83,4 +83,4 @@ class Inductor final : public MNASimPowerComp, } // namespace SSN } // namespace Ph3 } // namespace EMT -} // namespace CPS \ No newline at end of file +} // namespace CPS diff --git a/dpsim-models/include/dpsim-models/MNAStampUtils.h b/dpsim-models/include/dpsim-models/MNAStampUtils.h index d3372bf41b..38e7bdfb2f 100644 --- a/dpsim-models/include/dpsim-models/MNAStampUtils.h +++ b/dpsim-models/include/dpsim-models/MNAStampUtils.h @@ -101,4 +101,4 @@ class MNAStampUtils { Int maxFreq, Int freqIdx, const Logger::Log &mSLog); }; -} // namespace CPS \ No newline at end of file +} // namespace CPS diff --git a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp index 67221aa6bc..2632bf9454 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp @@ -113,4 +113,4 @@ void EMT::Ph1::Switch::mnaCompUpdateCurrent(const Matrix &leftVector) { (**mIntfCurrent)(0, 0) = (**mIsClosed) ? (**mIntfVoltage)(0, 0) / (**mClosedResistance) : (**mIntfVoltage)(0, 0) / (**mOpenResistance); -} \ No newline at end of file +} diff --git a/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp b/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp index a2aab0319a..dc63f3c9b1 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp @@ -184,4 +184,4 @@ void EMT::Ph3::CurrentSource::mnaCompUpdateVoltage(const Matrix &leftVector) { (**mIntfVoltage)(2, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); } -} \ No newline at end of file +} diff --git a/dpsim-models/src/EMT/EMT_Ph3_SSN_Full_Serial_RLC.cpp b/dpsim-models/src/EMT/EMT_Ph3_SSN_Full_Serial_RLC.cpp index 1b53bb2a77..52440aadef 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_SSN_Full_Serial_RLC.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_SSN_Full_Serial_RLC.cpp @@ -359,4 +359,4 @@ void EMT::Ph3::SSN::Full_Serial_RLC::setParameters(Matrix resistance, void EMT::Ph3::SSN::Full_Serial_RLC::ssnUpdateState() { mState = mDufourAKHat * mState + mDufourBKHat * mDufourUNT + mDufourBKNHat * **mIntfVoltage; -} \ No newline at end of file +} diff --git a/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb b/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb index 7727043782..d7ee214c4b 100644 --- a/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb +++ b/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb @@ -288,4 +288,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/examples/Notebooks/Components/SynGenDq7od_ParameterStudy.ipynb b/examples/Notebooks/Components/SynGenDq7od_ParameterStudy.ipynb index 5253b860cd..677e70fb45 100644 --- a/examples/Notebooks/Components/SynGenDq7od_ParameterStudy.ipynb +++ b/examples/Notebooks/Components/SynGenDq7od_ParameterStudy.ipynb @@ -904,4 +904,4 @@ }, "nbformat": 4, "nbformat_minor": 4 -} \ No newline at end of file +} diff --git a/examples/test_example.yml b/examples/test_example.yml index 561cfe3020..919ac193ed 100644 --- a/examples/test_example.yml +++ b/examples/test_example.yml @@ -14,4 +14,4 @@ example_test3: description: Returns non-zero return code cmd: exit 1 shell: True - xfail: True \ No newline at end of file + xfail: True diff --git a/examples/villas/dpsim-file.py b/examples/villas/dpsim-file.py index 5c1398140b..d7cdf73c56 100644 --- a/examples/villas/dpsim-file.py +++ b/examples/villas/dpsim-file.py @@ -60,4 +60,4 @@ evs.set_intf_current([[complex(5, 0)]]) -sim.run(1) \ No newline at end of file +sim.run(1) diff --git a/examples/villas/dpsim-mqtt-import-export-MIMO.py b/examples/villas/dpsim-mqtt-import-export-MIMO.py index 424181e9db..6e58c5a062 100644 --- a/examples/villas/dpsim-mqtt-import-export-MIMO.py +++ b/examples/villas/dpsim-mqtt-import-export-MIMO.py @@ -201,4 +201,4 @@ def test_shmem_import_export(): node.stop() if __name__ == '__main__': - test_shmem_import_export() \ No newline at end of file + test_shmem_import_export() diff --git a/examples/villas/dpsim-mqtt-producer.py b/examples/villas/dpsim-mqtt-producer.py index 4cd44d7a6b..b5376982bc 100644 --- a/examples/villas/dpsim-mqtt-producer.py +++ b/examples/villas/dpsim-mqtt-producer.py @@ -24,4 +24,4 @@ def build_message(sequence, v_ref): print(m_message) publish.single(topic="/mqtt-dpsim", payload=m_message, hostname="mqtt") seq += 1 - time.sleep(T_s) \ No newline at end of file + time.sleep(T_s) diff --git a/examples/villas/dpsim-mqtt.py b/examples/villas/dpsim-mqtt.py index 9c82e3e14e..f6337f3986 100644 --- a/examples/villas/dpsim-mqtt.py +++ b/examples/villas/dpsim-mqtt.py @@ -62,4 +62,4 @@ sim.add_logger(logger) -sim.run(1) \ No newline at end of file +sim.run(1) diff --git a/python/src/dpsim/matpower.py b/python/src/dpsim/matpower.py index 3c53040559..4824023779 100644 --- a/python/src/dpsim/matpower.py +++ b/python/src/dpsim/matpower.py @@ -264,4 +264,3 @@ def load_mpc(self): system = dpsimpy.SystemTopology(self.mpc_freq, system_nodes, system_comp) return system - From 56b6fd6c9b1d0bcb99a6ad39b89b0d8627ef6267 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 14:30:53 +0200 Subject: [PATCH 031/168] fix(python): Fix build of manylinux Docker image with newer CMake versions Signed-off-by: Steffen Vogel --- packaging/Docker/Dockerfile.manylinux | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packaging/Docker/Dockerfile.manylinux b/packaging/Docker/Dockerfile.manylinux index 35cc813abf..444ed45ad3 100644 --- a/packaging/Docker/Dockerfile.manylinux +++ b/packaging/Docker/Dockerfile.manylinux @@ -56,7 +56,8 @@ RUN cd /tmp && \ git clone --branch v3.2.1 --recurse-submodules https://github.com/LLNL/sundials.git && \ mkdir -p sundials/build && cd sundials/build && \ cmake ${CMAKE_OPTS} .. \ - -DCMAKE_BUILD_TYPE=Release && \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 && \ make ${MAKE_OPTS} install # CIMpp and VILLASnode are installed here @@ -100,7 +101,8 @@ RUN cd /tmp && \ mkdir -p spdlog/build && cd spdlog/build && \ cmake ${CMAKE_OPTS} .. \ -DCMAKE_POSITION_INDEPENDENT_CODE=True \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 && \ + -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/spdlog @@ -113,7 +115,7 @@ RUN cd /tmp && \ -DCMAKE_C_COMPILER:FILEPATH=/opt/rh/gcc-toolset-11/root/usr/bin/gcc \ -DCMAKE_CXX_COMPILER:FILEPATH=/opt/rh/gcc-toolset-11/root/usr/bin/g++ \ -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ - -DDOWNLOAD_GO=OFF && \ + -DCMAKE_POLICY_VERSION_MINIMUM=3.5 && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node From 7e2a004a0f821624562e01982af0d532ecb4138f Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 15:52:57 +0200 Subject: [PATCH 032/168] fix(ci): Do not use deprecated option names for pypa/gh-action-pypi-publish action Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 308f38c701..8ba2fc628b 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -53,8 +53,8 @@ jobs: uses: pypa/gh-action-pypi-publish@v1.12.4 with: password: ${{ secrets.TEST_PYPI_API_TOKEN }} - repository_url: https://test.pypi.org/legacy/ - skip_existing: true + repository-url: https://test.pypi.org/legacy/ + skip-existing: true - name: Publish distribution to PyPI if: startsWith(github.ref, 'refs/tags') From 7158b6f8a88eb0174ceb660c052f239ce068b518 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 16:15:10 +0200 Subject: [PATCH 033/168] fix(ci): Update phased-out ubuntu-20.04 runners by ubuntu-24.04 Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 8ba2fc628b..8ee7ef20d3 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -10,7 +10,7 @@ on: jobs: build-and-publish-sdist: name: Build DPsim source distribution and publish to PyPi - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 container: sogno/dpsim:dev steps: - name: Checkout @@ -37,7 +37,7 @@ jobs: build-and-publish-wheels: name: Build DPsim wheels and publish to PyPI - runs-on: ubuntu-20.04 + runs-on: ubuntu-24.04 steps: - name: Checkout uses: actions/checkout@v4 From 67250545a522599f453edfd6d2304cbd89e3f098 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 16:17:22 +0200 Subject: [PATCH 034/168] fix(ci): Run PyPi packaging workflows also on pull requests Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 8ee7ef20d3..729f3e17bd 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -1,9 +1,8 @@ name: Publish DPsim package to Python Package Index (PyPI) on: + pull_request: push: - branches: - - master tags: - '*' From 2c5d8e648e6a949c8bb20410492d1ab239badd06 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 18:00:00 +0200 Subject: [PATCH 035/168] fix(ci): Also upgrade Python packaging package to resolve build errors Signed-off-by: Steffen Vogel --- packaging/Docker/Dockerfile.dev | 2 +- packaging/Docker/Dockerfile.dev-minimal | 2 +- packaging/Docker/Dockerfile.dev-rocky | 3 +-- packaging/Docker/Dockerfile.manylinux | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index efd9253a5f..770742d020 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -72,7 +72,7 @@ RUN dnf -y install \ # Python dependencies ADD requirements.txt . -RUN pip3 install --upgrade wheel build setuptools +RUN pip3 install --upgrade wheel build setuptools packaging RUN pip3 install -r requirements.txt # Install CIMpp from source diff --git a/packaging/Docker/Dockerfile.dev-minimal b/packaging/Docker/Dockerfile.dev-minimal index c2551fd06f..08c6bd01e0 100644 --- a/packaging/Docker/Dockerfile.dev-minimal +++ b/packaging/Docker/Dockerfile.dev-minimal @@ -23,7 +23,7 @@ RUN dnf --refresh -y install \ # Python dependencies ADD requirements.txt . -RUN pip3 install --upgrade wheel build setuptools +RUN pip3 install --upgrade wheel build setuptools packaging RUN pip3 install -r requirements.txt EXPOSE 8888 diff --git a/packaging/Docker/Dockerfile.dev-rocky b/packaging/Docker/Dockerfile.dev-rocky index 236d6b9d84..6de7efc427 100644 --- a/packaging/Docker/Dockerfile.dev-rocky +++ b/packaging/Docker/Dockerfile.dev-rocky @@ -121,8 +121,7 @@ ENV LD_LIBRARY_PATH="/usr/local/lib64:${LD_LIBRARY_PATH}" # # Python dependencies # ADD requirements.txt . -# RUN pip3 install -U setuptools -# RUN pip3 install -U wheel +# RUN pip3 install --upgrade wheel build setuptools packaging # RUN pip3 install -r requirements.txt # # Remove this part in the future and use dedicated Jupyter Dockerfile diff --git a/packaging/Docker/Dockerfile.manylinux b/packaging/Docker/Dockerfile.manylinux index 444ed45ad3..d804809703 100644 --- a/packaging/Docker/Dockerfile.manylinux +++ b/packaging/Docker/Dockerfile.manylinux @@ -65,7 +65,7 @@ ENV LD_LIBRARY_PATH="/usr/local/lib64:${LD_LIBRARY_PATH}" # Python dependencies ADD requirements-manylinux.txt . -RUN pip3 install --upgrade wheel build setuptools +RUN pip3 install --upgrade wheel build setuptools packaging RUN pip3 install -r requirements-manylinux.txt # Install CIMpp from source From 515baa6139fabd7aa5daf11b70620d72467f01c3 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 20:53:51 +0200 Subject: [PATCH 036/168] fix(ci): Move upload to PyPi into separate job Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 44 +++++++++++++++++--------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 729f3e17bd..c0a5208377 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -7,8 +7,8 @@ on: - '*' jobs: - build-and-publish-sdist: - name: Build DPsim source distribution and publish to PyPi + build-sdist: + name: Build DPsim source distribution runs-on: ubuntu-24.04 container: sogno/dpsim:dev steps: @@ -21,21 +21,14 @@ jobs: shell: bash run: python3 -m build --sdist --outdir dist/ - - name: Publish distribution to Test PyPI - uses: pypa/gh-action-pypi-publish@v1.12.4 - with: - password: ${{ secrets.TEST_PYPI_API_TOKEN }} - repository_url: https://test.pypi.org/legacy/ - skip_existing: true - - - name: Publish distribution to PyPI - if: startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@v1.12.4 + - name: Archive Python source distribution + uses: actions/upload-artifact@v4 with: - password: ${{ secrets.PYPI_API_TOKEN }} + name: dist-source + path: dist/ - build-and-publish-wheels: - name: Build DPsim wheels and publish to PyPI + build-wheels: + name: Build DPsim wheels runs-on: ubuntu-24.04 steps: - name: Checkout @@ -48,6 +41,27 @@ jobs: with: output-dir: dist + - name: Archive Python wheels + uses: actions/upload-artifact@v4 + with: + name: dist-wheels + path: dist/ + + publish: + name: Publish wheels and source distribution to PyPI + runs-on: ubuntu-24.04 + needs: + - build-wheels + - build-sdist + + steps: + - name: Download artifacts from build jobs + uses: actions/download-artifact@v4 + with: + pattern: dist-* + merge-multiple: true + path: dist/ + - name: Publish distribution to Test PyPI uses: pypa/gh-action-pypi-publish@v1.12.4 with: From 5fbaba0e57ce515a98f449ab123dff7951820dd9 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 20:54:44 +0200 Subject: [PATCH 037/168] fix(ci): Simplify triggers for workflows Signed-off-by: Steffen Vogel --- .github/workflows/build_test_linux_fedora.yaml | 3 ++- .github/workflows/build_test_linux_fedora_minimal.yaml | 3 ++- .github/workflows/build_test_linux_rocky.yaml | 3 ++- .github/workflows/build_test_windows.yaml | 3 ++- .github/workflows/publish_to_pypi.yaml | 2 ++ .github/workflows/sonar_cloud.yaml | 3 --- 6 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build_test_linux_fedora.yaml b/.github/workflows/build_test_linux_fedora.yaml index 0aa745bd1f..a0ee5f3818 100644 --- a/.github/workflows/build_test_linux_fedora.yaml +++ b/.github/workflows/build_test_linux_fedora.yaml @@ -2,8 +2,9 @@ name: Build & Test Fedora on: push: + branches: + - master pull_request: - types: [opened, synchronize, reopened] ## Build ## diff --git a/.github/workflows/build_test_linux_fedora_minimal.yaml b/.github/workflows/build_test_linux_fedora_minimal.yaml index ed7bf5bc44..45ab47f097 100644 --- a/.github/workflows/build_test_linux_fedora_minimal.yaml +++ b/.github/workflows/build_test_linux_fedora_minimal.yaml @@ -2,8 +2,9 @@ name: Build & Test Fedora Minimal on: push: + branches: + - master pull_request: - types: [opened, synchronize, reopened] ## Build ## diff --git a/.github/workflows/build_test_linux_rocky.yaml b/.github/workflows/build_test_linux_rocky.yaml index 28bf13f77d..7bf8ce1777 100644 --- a/.github/workflows/build_test_linux_rocky.yaml +++ b/.github/workflows/build_test_linux_rocky.yaml @@ -2,8 +2,9 @@ name: Build & Test RockyLinux on: push: + branches: + - master pull_request: - types: [opened, synchronize, reopened] ## Build ## diff --git a/.github/workflows/build_test_windows.yaml b/.github/workflows/build_test_windows.yaml index 7d41234a49..8771e82386 100644 --- a/.github/workflows/build_test_windows.yaml +++ b/.github/workflows/build_test_windows.yaml @@ -2,8 +2,9 @@ name: Build & Test Windows on: push: + branches: + - master pull_request: - types: [opened, synchronize, reopened] ## Build ## diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index c0a5208377..43a9c77f76 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -3,6 +3,8 @@ name: Publish DPsim package to Python Package Index (PyPI) on: pull_request: push: + branches: + - master tags: - '*' diff --git a/.github/workflows/sonar_cloud.yaml b/.github/workflows/sonar_cloud.yaml index 2e2fdfeafd..3976490cb4 100644 --- a/.github/workflows/sonar_cloud.yaml +++ b/.github/workflows/sonar_cloud.yaml @@ -1,12 +1,9 @@ name: Sonar Cloud Analysis on: - # Trigger analysis when pushing in master or pull requests, and when creating - # a pull request. push: branches: - master pull_request: - types: [opened, synchronize, reopened] jobs: sonarcloud: From d0f4bc292b1b1b5fcd423968f7676e1539d115b1 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 1 Apr 2025 20:58:05 +0200 Subject: [PATCH 038/168] fix(python): Build with newer CMake versions Signed-off-by: Steffen Vogel --- setup.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 3b4e06ca0c..bf2cabb62f 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,8 @@ def build_extension(self, ext): f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_DEBUG={extdir}", f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE={extdir}", f"-DPYTHON_EXECUTABLE={sys.executable}", - f"-DCMAKE_BUILD_TYPE={cfg}" # Not used on MSVC, but no harm + f"-DCMAKE_BUILD_TYPE={cfg}", # Not used on MSVC, but no harm + "-DCMAKE_POLICY_VERSION_MINIMUM=3.5" ] if platform.system() == 'Windows': From 31b29a0aec185bddf632e1a1cb49d6bafd3e4af8 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 2 Apr 2025 22:29:10 +0200 Subject: [PATCH 039/168] fix(ci): Update manylinux Docker image Signed-off-by: Steffen Vogel --- packaging/Docker/Dockerfile.manylinux | 70 +++++++++++++-------------- 1 file changed, 34 insertions(+), 36 deletions(-) diff --git a/packaging/Docker/Dockerfile.manylinux b/packaging/Docker/Dockerfile.manylinux index d804809703..ba3706ba72 100644 --- a/packaging/Docker/Dockerfile.manylinux +++ b/packaging/Docker/Dockerfile.manylinux @@ -21,18 +21,19 @@ LABEL \ org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" RUN dnf -y update -RUN yum install -y epel-release +RUN dnf install -y epel-release # Toolchain -RUN yum install -y \ - gcc-toolset-11 clang \ - git \ +RUN dnf install -y \ + gcc-toolset-14 \ + git wget \ rpmdevtools rpm-build \ - make cmake pkgconfig \ + make cmake pkgconfig libtool \ + autoconf automake autogen libtool flex bison \ python3-pip \ cppcheck -# Tools needed for developement +# Tools needed for development RUN dnf -y install \ doxygen graphviz \ gdb \ @@ -45,8 +46,6 @@ RUN dnf --refresh -y install \ libxml2-devel \ graphviz-devel -RUN yum install -y fmt-devel - # Install some debuginfos RUN dnf -y debuginfo-install \ python3 @@ -56,13 +55,11 @@ RUN cd /tmp && \ git clone --branch v3.2.1 --recurse-submodules https://github.com/LLNL/sundials.git && \ mkdir -p sundials/build && cd sundials/build && \ cmake ${CMAKE_OPTS} .. \ + -DBUILD_SHARED_LIBS=ON \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 && \ make ${MAKE_OPTS} install -# CIMpp and VILLASnode are installed here -ENV LD_LIBRARY_PATH="/usr/local/lib64:${LD_LIBRARY_PATH}" - # Python dependencies ADD requirements-manylinux.txt . RUN pip3 install --upgrade wheel build setuptools packaging @@ -75,7 +72,6 @@ RUN cd /tmp && \ git checkout ${CIMPP_COMMIT} && \ git submodule update --init && \ cmake ${CMAKE_OPTS} .. \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ -DUSE_CIM_VERSION=${CIM_VERSION} \ -DBUILD_SHARED_LIBS=ON \ -DBUILD_ARABICA_EXAMPLES=OFF && \ @@ -83,40 +79,42 @@ RUN cd /tmp && \ rm -rf /tmp/libcimpp # Install VILLASnode dependencies -RUN yum install -y \ - openssl-devel \ - libuuid-devel \ - libcurl-devel \ +RUN dnf install -y \ + hiredis-devel \ jansson-devel \ - libwebsockets-devel \ - mosquitto-devel \ libconfig-devel \ + libcurl-devel \ + libibverbs-devel \ + libmodbus-devel \ + libnice-devel \ libnl3-devel \ + librdkafka-devel \ + librdmacm-devel \ + libusb-devel \ + libuuid-devel \ + libwebsockets-devel \ + lua-devel \ + mosquitto-devel \ + openssl-devel \ + protobuf-c-devel \ protobuf-devel \ - protobuf-c-devel - -# Install spdlog from source -RUN cd /tmp && \ - git clone --branch v1.6.1 --recurse-submodules --depth 1 https://github.com/gabime/spdlog.git && \ - mkdir -p spdlog/build && cd spdlog/build && \ - cmake ${CMAKE_OPTS} .. \ - -DCMAKE_POSITION_INDEPENDENT_CODE=True \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ - -DCMAKE_POLICY_VERSION_MINIMUM=3.5 && \ - make ${MAKE_OPTS} install && \ - rm -rf /tmp/spdlog + nanomsg-devel \ + zeromq-devel \ + graphviz-devel # Install VILLASnode from source RUN cd /tmp && \ git clone --recurse-submodules https://github.com/VILLASframework/node.git villas-node && \ - mkdir -p villas-node/build && cd villas-node/build && \ + cd villas-node && \ git checkout ${VILLAS_VERSION} && \ + sed -i 's/v0.18.4/v0.22.6/g' packaging/deps.sh && \ + sed -i 's/1.3.7/1.3.14/g' packaging/deps.sh && \ + DEPS_SKIP=criterion,ethercat \ + MAKE_OPTS="" \ + CMAKE_OPTS=-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ + bash -x packaging/deps.sh && \ + mkdir -p build && cd build && \ cmake ${CMAKE_OPTS} .. \ - -DCMAKE_C_COMPILER:FILEPATH=/opt/rh/gcc-toolset-11/root/usr/bin/gcc \ - -DCMAKE_CXX_COMPILER:FILEPATH=/opt/rh/gcc-toolset-11/root/usr/bin/g++ \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node - -ENV CMAKE_OPTS="-DCMAKE_C_COMPILER:FILEPATH=/opt/rh/gcc-toolset-11/root/usr/bin/gcc -DCMAKE_CXX_COMPILER:FILEPATH=/opt/rh/gcc-toolset-11/root/usr/bin/g++" From ebf6e335e4d0183b44e28b73cd9225d9a8f6459d Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 3 Apr 2025 05:00:10 +0200 Subject: [PATCH 040/168] chore: Update VILLASnode version Signed-off-by: Steffen Vogel --- packaging/Docker/Dockerfile.manylinux | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packaging/Docker/Dockerfile.manylinux b/packaging/Docker/Dockerfile.manylinux index ba3706ba72..9279240c82 100644 --- a/packaging/Docker/Dockerfile.manylinux +++ b/packaging/Docker/Dockerfile.manylinux @@ -7,7 +7,7 @@ FROM quay.io/pypa/manylinux_2_28_x86_64 ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 ARG CIMPP_COMMIT=1b11d5c17bedf0ae042628b42ecb4e49df70b2f6 -ARG VILLAS_VERSION=18cdd2a6364d05fbf413ca699616cd324abfcb54 +ARG VILLAS_VERSION=84df28645077e05e5115f92ef328d688400b35b9 ARG CMAKE_OPTS ARG MAKE_OPTS=-j4 @@ -80,7 +80,6 @@ RUN cd /tmp && \ # Install VILLASnode dependencies RUN dnf install -y \ - hiredis-devel \ jansson-devel \ libconfig-devel \ libcurl-devel \ @@ -92,7 +91,6 @@ RUN dnf install -y \ librdmacm-devel \ libusb-devel \ libuuid-devel \ - libwebsockets-devel \ lua-devel \ mosquitto-devel \ openssl-devel \ @@ -107,12 +105,10 @@ RUN cd /tmp && \ git clone --recurse-submodules https://github.com/VILLASframework/node.git villas-node && \ cd villas-node && \ git checkout ${VILLAS_VERSION} && \ - sed -i 's/v0.18.4/v0.22.6/g' packaging/deps.sh && \ - sed -i 's/1.3.7/1.3.14/g' packaging/deps.sh && \ DEPS_SKIP=criterion,ethercat \ MAKE_OPTS="" \ CMAKE_OPTS=-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ - bash -x packaging/deps.sh && \ + bash packaging/deps.sh && \ mkdir -p build && cd build && \ cmake ${CMAKE_OPTS} .. \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 && \ From 472a30318cb2b58c9885f6ca027c48ab10a141aa Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 3 Apr 2025 13:10:06 +0200 Subject: [PATCH 041/168] feat(ci): Use trusted / OIDC publishing to PyPi.org Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 43a9c77f76..abb5361a94 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -52,6 +52,8 @@ jobs: publish: name: Publish wheels and source distribution to PyPI runs-on: ubuntu-24.04 + permissions: + id-token: write needs: - build-wheels - build-sdist @@ -67,12 +69,9 @@ jobs: - name: Publish distribution to Test PyPI uses: pypa/gh-action-pypi-publish@v1.12.4 with: - password: ${{ secrets.TEST_PYPI_API_TOKEN }} repository-url: https://test.pypi.org/legacy/ skip-existing: true - name: Publish distribution to PyPI if: startsWith(github.ref, 'refs/tags') uses: pypa/gh-action-pypi-publish@v1.12.4 - with: - password: ${{ secrets.PYPI_API_TOKEN }} From 4f9536a0ed7bf6a522e5358d43beef0dd674a1ad Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 3 Apr 2025 13:20:04 +0200 Subject: [PATCH 042/168] fix(ci): Only attempt to upload to PyPi for pushes to master and or tags Doing uploads to PyPi.org does not work for PRs due to missing permissions. Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index abb5361a94..29dd644641 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -52,6 +52,7 @@ jobs: publish: name: Publish wheels and source distribution to PyPI runs-on: ubuntu-24.04 + if: github.event_name == 'push' permissions: id-token: write needs: From fc549b6653896b3de4eae77066d1b34dc587e46f Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Thu, 3 Apr 2025 13:29:20 +0200 Subject: [PATCH 043/168] feat(ci): Use matrix build strategy for build Python wheels Signed-off-by: Steffen Vogel --- .github/workflows/publish_to_pypi.yaml | 16 +++++++++++----- pyproject.toml | 5 ++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 29dd644641..e029c723c3 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -30,23 +30,29 @@ jobs: path: dist/ build-wheels: - name: Build DPsim wheels + name: Build DPsim Python wheel runs-on: ubuntu-24.04 + strategy: + matrix: + platform: [manylinux_x86_64] + python: [cp39, cp310, cp311, cp312, cp313] steps: - name: Checkout uses: actions/checkout@v4 with: submodules: recursive - - name: Build DPsim wheels for all supported Python versions + - name: Build wheel uses: pypa/cibuildwheel@v2.23.2 + env: + CIBW_BUILD: "${{ matrix.python }}-${{ matrix.platform }}" with: output-dir: dist - - name: Archive Python wheels + - name: Upload wheel as artifact uses: actions/upload-artifact@v4 with: - name: dist-wheels + name: dist-wheels-${{ matrix.python }}-${{ matrix.platform }} path: dist/ publish: @@ -60,7 +66,7 @@ jobs: - build-sdist steps: - - name: Download artifacts from build jobs + - name: Download wheels from build jobs uses: actions/download-artifact@v4 with: pattern: dist-* diff --git a/pyproject.toml b/pyproject.toml index 138608a45a..3053afeea9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,10 +3,9 @@ requires = ["setuptools>=42"] build-backend = "setuptools.build_meta" [tool.cibuildwheel] -build-verbosity = "3" -build = "[cp]p3{8,9,10,11}-manylinux_x86_64" +build-verbosity = 3 +build = "cp3{9,10,11,12,13}-manylinux_x86_64" manylinux-x86_64-image = "sogno/dpsim:manylinux" -manylinux-pypy_x86_64-image = "sogno/dpsim:manylinux" [tool.pytest.ini_options] filterwarnings = ["ignore::DeprecationWarning"] From d21c7c358c59d9a491cd86a08974b93bfa5a74a8 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 2 Apr 2025 22:22:10 +0200 Subject: [PATCH 044/168] feat(pre-commit): Enable AST, XML, YAML, JSON and TOML checks Signed-off-by: Steffen Vogel --- .pre-commit-config.yaml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 560eba5c0e..0a669bf609 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,14 +7,14 @@ repos: - id: trailing-whitespace - id: end-of-file-fixer exclude: \.svg$ - # - id: check-ast - # - id: check-xml - # - id: check-yaml - # - id: check-json - # # devcontainer.json contains comments - # exclude: .devcontainer/devcontainer\.json - # - id: check-toml - # - id: check-added-large-files + - id: check-ast + - id: check-xml + - id: check-yaml + - id: check-json + # devcontainer.json contains comments + exclude: .devcontainer/devcontainer\.json + - id: check-toml + - id: check-added-large-files # - id: pretty-format-json # # black has its own mind of formatting Jupyter notebooks # exclude: \.ipynb$|^.devcontainer/devcontainer\.json$|package-lock\.json$ From 566862d36e48237c7d6d5328147814cc91828eb2 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:54:27 +0100 Subject: [PATCH 045/168] chore(cmake): Remove deprecated options Signed-off-by: Steffen Vogel --- CMakeLists.txt | 58 ++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 048856bca0..5df8818ae4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,8 +13,28 @@ set(PROJECT_HOMEPAGE_URL "https://dpsim.fein-aachen.org/") set(PROJECT_VCS_URL "https://github.com/sogno-platform/dpsim") # Build options -option(WITH_LTO "Enable Link Time Optimization in Release builds" OFF) -option(WITH_MARCH_NATIVE "Optimize build for native host architecture" OFF) +option(FETCH_EIGEN "Fetch Eigen3 as module" OFF) +option(FETCH_KLU "Fetch KLU as module" ON) +option(FETCH_SPDLOG "Fetch spdlog as module" OFF) +option(FETCH_CIMPP "Fetch CIMpp as module" OFF) +option(FETCH_PYBIND "Fetch pybind11 as module" OFF) +option(FETCH_GRID_DATA "Fetch grid data" ON) +option(FETCH_FILESYSTEM "Fetch standalone implementation of std::filesystem" OFF) +option(FETCH_JSON "Fetch json library as module" ON) + +option(WITH_LTO "Enable Link Time Optimization in Release builds" OFF) +option(WITH_MARCH_NATIVE "Optimize build for native host architecture" OFF) +option(WITH_PROFILING "Add `-pg` profiling flag to compilation" OFF) +option(WITH_ASAN "Adds compiler flags to use the address sanitizer" OFF) +option(WITH_TSAN "Adds compiler flags to use the thread sanitizer" OFF) +option(WITH_SPARSE "Use sparse matrices in MNA-Solver" ON) + +option(BUILD_SHARED_LIBS "Build shared library" OFF) +option(DPSIM_BUILD_EXAMPLES "Build C++ examples" ON) +option(DPSIM_BUILD_DOC "Build documentation" ON) + +option(CGMES_BUILD "Build with CGMES instead of CIMpp" OFF) + # Required for dpsim_python if(POLICY CMP0076) @@ -108,36 +128,6 @@ endif() include(GetVersion) GetVersion(${PROJECT_SOURCE_DIR} "DPSIM") -# Deprecated build options -# TODO: Remove deprecated options in future release -option(WITH_EIGEN_MODULE "Fetch Eigen3 as module (deprecated option)" OFF) -option(WITH_KLU "Build with KLU as module (deprecated option)" ON) -option(WITH_SPDLOG_SUBMODULE "Fetch spdlog as module (deprecated option)" OFF) -option(WITH_CIM_SUBMODULE "Fetch CIMpp as module (deprecated option)" OFF) -option(WITH_PYBIND_MODULE "Fetch pybind11 as module (deprecated option)" OFF) -option(GET_GRID_DATA "Fetch grid data (deprecated option)" ON) - -# Build options -option(FETCH_EIGEN "Fetch Eigen3 as module" ${WITH_EIGEN_MODULE}) -option(FETCH_KLU "Fetch KLU as module" ${WITH_KLU}) -option(FETCH_SPDLOG "Fetch spdlog as module" ${WITH_SPDLOG_SUBMODULE}) -option(FETCH_CIMPP "Fetch CIMpp as module" ${WITH_CIM_SUBMODULE}) -option(FETCH_PYBIND "Fetch pybind11 as module" ${WITH_PYBIND_MODULE}) -option(FETCH_GRID_DATA "Fetch grid data" ${GET_GRID_DATA}) -option(FETCH_FILESYSTEM "Fetch standalone implememtation of std::filesystem" OFF) - -option(WITH_JSON "Include json library" ON) -option(WITH_PROFILING "Add `-pg` profiling flag to compiliation" OFF) -option(WITH_ASAN "Adds compiler flags to use the address sanitizer" OFF) -option(WITH_TSAN "Adds compiler flags to use the thread sanitizer" OFF) -option(WITH_SPARSE "Use sparse matrices in MNA-Solver" ON) - -option(BUILD_SHARED_LIBS "Build shared library" OFF) -option(DPSIM_BUILD_EXAMPLES "Build C++ examples" ON) -option(DPSIM_BUILD_DOC "Build documentation" ON) - -option(CGMES_BUILD "Build with CGMES instead of CIMpp" OFF) - find_package(Threads REQUIRED) find_package(Sundials) find_package(OpenMP) @@ -187,7 +177,7 @@ if(FETCH_GRID_DATA) include(FetchGridData) endif() -if(WITH_JSON) +if(FETCH_JSON) include(FetchJsonLibrary) endif() @@ -226,9 +216,11 @@ cmake_dependent_option(WITH_VILLAS "Enable VILLASnode interface" cmake_dependent_option(WITH_RT "Enable real-time features" ON "Linux_FOUND" OFF) cmake_dependent_option(WITH_CIM "Enable support for parsing CIM" ON "CIMpp_FOUND" OFF) cmake_dependent_option(WITH_OPENMP "Enable OpenMP-based parallelisation" ON "OPENMP_FOUND" OFF) +cmake_dependent_option(WITH_KLU "Enable KLU factorization" ON "FETCH_KLU" OFF) cmake_dependent_option(WITH_CUDA "Enable CUDA-based parallelisation" OFF "CUDA_FOUND" OFF) cmake_dependent_option(WITH_GRAPHVIZ "Enable Graphviz Graphs" ON "GRAPHVIZ_FOUND" OFF) cmake_dependent_option(WITH_PYBIND "Enable PYBIND support" ON "pybind11_FOUND" OFF) +cmake_dependent_option(WITH_JSON "Enable JSON library support" ON "FETCH_JSON" OFF) cmake_dependent_option(WITH_MAGMA "Enable MAGMA features" ON "MAGMA_FOUND" OFF) cmake_dependent_option(WITH_MNASOLVERPLUGIN "Enable MNASolver Plugins" ON "NOT WIN32" OFF) From a6ea39ea29020ac199e375359b421c19fdeca50b Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 2 Apr 2025 22:01:54 +0200 Subject: [PATCH 046/168] fix(cmake): Allow building without JSON library Signed-off-by: Steffen Vogel --- dpsim/examples/cxx/CMakeLists.txt | 7 ++++++- dpsim/include/dpsim/Config.h.in | 1 + dpsim/include/dpsim/Simulation.h | 3 --- dpsim/include/dpsim/Utils.h | 6 +++++- dpsim/src/Utils.cpp | 2 ++ dpsim/src/pybind/EMTComponents.cpp | 9 +++++++++ 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index 11c797f280..e4dd0a00a6 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -64,7 +64,6 @@ set(CIRCUIT_SOURCES Circuits/DP_SynGenTrStab_SMIB_Fault.cpp Circuits/EMT_SynGenDQ7odTrapez_SMIB_Fault.cpp Circuits/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault.cpp - Circuits/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault_JsonSyngenParams.cpp Circuits/EMT_SynGenDQ7odTrapez_DP_SynGenTrStab_SMIB_Fault.cpp Circuits/EMT_SynGenTrStab_SMIB_Fault.cpp Circuits/SP_SynGenTrStab_SMIB_Fault_KundurExample1.cpp @@ -93,6 +92,12 @@ set(CIRCUIT_SOURCES ) +if(WITH_JSON) + list(APPEND CIRCUIT_SOURCES + Circuits/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault_JsonSyngenParams.cpp + ) +endif() + set(SYNCGEN_SOURCES Components/DP_SynGenDq7odTrapez_SteadyState.cpp Components/DP_SynGenDq7odTrapez_ThreePhFault.cpp diff --git a/dpsim/include/dpsim/Config.h.in b/dpsim/include/dpsim/Config.h.in index 33f2e14b6a..48e34b967e 100644 --- a/dpsim/include/dpsim/Config.h.in +++ b/dpsim/include/dpsim/Config.h.in @@ -29,6 +29,7 @@ #cmakedefine WITH_MAGMA #cmakedefine WITH_KLU #cmakedefine WITH_MNASOLVERPLUGIN +#cmakedefine WITH_JSON #cmakedefine CGMES_BUILD #cmakedefine HAVE_GETOPT diff --git a/dpsim/include/dpsim/Simulation.h b/dpsim/include/dpsim/Simulation.h index a44bf7d3c2..4d568c6a8f 100644 --- a/dpsim/include/dpsim/Simulation.h +++ b/dpsim/include/dpsim/Simulation.h @@ -16,14 +16,11 @@ #include #include #include -#include #ifdef WITH_GRAPHVIZ #include #endif -using json = nlohmann::json; - namespace DPsim { /// Forward declaration of CommandLineArgs from Utils class CommandLineArgs; diff --git a/dpsim/include/dpsim/Utils.h b/dpsim/include/dpsim/Utils.h index 4388422582..808e68d212 100644 --- a/dpsim/include/dpsim/Utils.h +++ b/dpsim/include/dpsim/Utils.h @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -28,7 +27,10 @@ #include #include +#ifdef WITH_JSON +#include using json = nlohmann::json; +#endif namespace DPsim { @@ -133,10 +135,12 @@ class CommandLineArgs { namespace Utils { +#ifdef WITH_JSON void applySimulationParametersFromJson(const json config, Simulation &sim); void applySynchronousGeneratorParametersFromJson( const json config, std::shared_ptr syngen); +#endif String encodeXml(String &data); diff --git a/dpsim/src/Utils.cpp b/dpsim/src/Utils.cpp index c3a04701fb..1619d1c411 100644 --- a/dpsim/src/Utils.cpp +++ b/dpsim/src/Utils.cpp @@ -427,6 +427,7 @@ std::list DPsim::Utils::findFiles(std::list filennames, return foundnames; } +#ifdef WITH_JSON void DPsim::Utils::applySimulationParametersFromJson(const json config, Simulation &sim) { if (config.contains("timestep")) @@ -451,3 +452,4 @@ void DPsim::Utils::applySynchronousGeneratorParametersFromJson( syngen->applyParametersOperationalPerUnit(); } } +#endif diff --git a/dpsim/src/pybind/EMTComponents.cpp b/dpsim/src/pybind/EMTComponents.cpp index 52a1b7bbda..d4441ae927 100644 --- a/dpsim/src/pybind/EMTComponents.cpp +++ b/dpsim/src/pybind/EMTComponents.cpp @@ -14,6 +14,11 @@ #include #include +#ifdef WITH_JSON +#include +using json = nlohmann::json; +#endif + namespace py = pybind11; using namespace pybind11::literals; @@ -253,12 +258,14 @@ void addEMTPh3Components(py::module_ mEMTPh3) { "Llkq2"_a, "inertia"_a, "init_active_power"_a, "init_reactive_power"_a, "init_terminal_volt"_a, "init_volt_angle"_a, "init_mech_power"_a) +#ifdef WITH_JSON .def("apply_parameters_from_json", [](std::shared_ptr syngen, const CPS::String json) { DPsim::Utils::applySynchronousGeneratorParametersFromJson( json::parse(json), syngen); }) +#endif .def("set_initial_values", &CPS::EMT::Ph3::SynchronGeneratorDQTrapez::setInitialValues, "init_active_power"_a, "init_reactive_power"_a, @@ -379,12 +386,14 @@ void addEMTPh3Components(py::module_ mEMTPh3) { "Llkq2"_a, "inertia"_a, "init_active_power"_a, "init_reactive_power"_a, "init_terminal_volt"_a, "init_volt_angle"_a, "init_mech_power"_a) +#ifdef WITH_JSON .def("apply_parameters_from_json", [](std::shared_ptr syngen, const CPS::String json) { DPsim::Utils::applySynchronousGeneratorParametersFromJson( json::parse(json), syngen); }) +#endif .def("set_initial_values", &CPS::EMT::Ph3::SynchronGeneratorDQODE::setInitialValues, "init_active_power"_a, "init_reactive_power"_a, From e04be4394c1c3dc9379c2fcc915b25d087c097d9 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 4 Apr 2025 07:47:14 +0200 Subject: [PATCH 047/168] feat(pre-commit): Enable clang-format check Signed-off-by: Steffen Vogel --- .clang-format | 3 +-- .pre-commit-config.yaml | 10 ++++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.clang-format b/.clang-format index ce2f4e39f6..3d43be1f73 100644 --- a/.clang-format +++ b/.clang-format @@ -4,5 +4,4 @@ --- BasedOnStyle: LLVM -# Increase ColumnLimit to avoid breaking SPDX headers -ColumnLimit: 200 +ReflowComments: false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0a669bf609..6d679c16d9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -22,10 +22,12 @@ repos: # - --no-sort-keys # - --autofix - # - repo: https://github.com/pre-commit/mirrors-clang-format - # rev: "v17.0.6" - # hooks: - # - id: clang-format + - repo: https://github.com/pre-commit/mirrors-clang-format + rev: "v17.0.6" + hooks: + - id: clang-format + files: \.(c|cpp|h|hpp)(\.in)?$ + args: [] # - repo: https://github.com/editorconfig-checker/editorconfig-checker.python # rev: "2.7.3" From 3ea97f5c39e4515a033feb3ad5f20efafd69b0a0 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 4 Apr 2025 07:47:40 +0200 Subject: [PATCH 048/168] fix(style): Reformat code-base using clang-format Signed-off-by: Steffen Vogel --- .../include/dpsim-models/Components.h | 2 +- .../DP/DP_Ph1_ProfileVoltageSource.h | 50 +++-- .../EMT/EMT_Ph3_ControlledCurrentSource.h | 28 ++- .../EMT/EMT_Ph3_ControlledVoltageSource.h | 28 ++- .../include/dpsim-models/EMT/EMT_Ph3_RXLoad.h | 9 +- .../include/dpsim-models/Filesystem.h | 4 +- dpsim-models/include/dpsim-models/Logger.h | 46 ++--- .../include/dpsim-models/MNAStampUtils.h | 8 +- dpsim-models/src/CIM/Reader.cpp | 3 +- .../src/DP/DP_Ph1_ProfileVoltageSource.cpp | 189 +++++++++++++----- dpsim-models/src/EMT/EMT_Ph1_Switch.cpp | 9 +- .../src/EMT/EMT_Ph1_VoltageSource.cpp | 2 +- .../EMT/EMT_Ph3_ControlledCurrentSource.cpp | 106 +++++++--- .../EMT/EMT_Ph3_ControlledVoltageSource.cpp | 137 +++++++++---- dpsim-models/src/EMT/EMT_Ph3_RXLoad.cpp | 39 ++-- dpsim-models/src/SimPowerComp.cpp | 3 +- dpsim-models/src/SystemTopology.cpp | 6 +- dpsim-villas/examples/cxx/Fpga9BusHil.cpp | 155 +++++++++----- .../examples/cxx/FpgaCosim3PhInfiniteBus.cpp | 56 ++++-- .../examples/cxx/FpgaCosimulation.cpp | 44 ++-- dpsim-villas/examples/cxx/FpgaExample.cpp | 39 ++-- .../cxx/CIM/DP_WSCC_9bus_split_decoupled.cpp | 37 ++-- .../cxx/CIM/EMT_WSCC-9bus_FullOrderSG.cpp | 6 +- .../cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp | 50 ++--- .../cxx/CIM/WSCC_9bus_mult_coupled.cpp | 19 +- .../cxx/CIM/WSCC_9bus_mult_decoupled.cpp | 19 +- .../cxx/CIM/WSCC_9bus_mult_diakoptics.cpp | 19 +- dpsim/include/dpsim/DataLogger.h | 3 +- dpsim/include/dpsim/DataLoggerInterface.h | 67 +++++-- dpsim/include/dpsim/InterfaceQueued.h | 56 ++++-- dpsim/include/dpsim/RealTimeDataLogger.h | 9 +- dpsim/include/dpsim/Simulation.h | 4 +- dpsim/src/DataLogger.cpp | 13 +- dpsim/src/InterfaceQueued.cpp | 59 ++++-- dpsim/src/MNASolverPlugin.cpp | 3 +- dpsim/src/RealTimeDataLogger.cpp | 52 +++-- dpsim/src/RealTimeSimulation.cpp | 6 +- dpsim/src/pybind/DPComponents.cpp | 13 +- dpsim/src/pybind/EMTComponents.cpp | 10 +- dpsim/src/pybind/SPComponents.cpp | 6 +- dpsim/src/pybind/main.cpp | 15 +- 41 files changed, 952 insertions(+), 477 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index 0c53e76fc9..8b73d3ca32 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -84,10 +84,10 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_ProfileVoltageSource.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_ProfileVoltageSource.h index a058929fa3..6fd09d6e13 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_ProfileVoltageSource.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_ProfileVoltageSource.h @@ -22,7 +22,9 @@ namespace CPS { namespace DP { namespace Ph1 { -class ProfileVoltageSource : public MNASimPowerComp, public DAEInterface, public SharedFactory { +class ProfileVoltageSource : public MNASimPowerComp, + public DAEInterface, + public SharedFactory { private: /// void updateVoltage(Real time); @@ -38,9 +40,13 @@ class ProfileVoltageSource : public MNASimPowerComp, public DAEInterfac const CPS::Attribute::Ptr mVoltage; /// Defines UID, name, component parameters and logging level - ProfileVoltageSource(String uid, String name, std::filesystem::path sourceFile, Logger::Level loglevel = Logger::Level::off); + ProfileVoltageSource(String uid, String name, + std::filesystem::path sourceFile, + Logger::Level loglevel = Logger::Level::off); /// Defines UID, name, component parameters and logging level - ProfileVoltageSource(String name, std::filesystem::path sourceFile, Logger::Level logLevel = Logger::Level::off) : ProfileVoltageSource(name, name, sourceFile, logLevel) {} + ProfileVoltageSource(String name, std::filesystem::path sourceFile, + Logger::Level logLevel = Logger::Level::off) + : ProfileVoltageSource(name, name, sourceFile, logLevel) {} /// SimPowerComp::Ptr clone(String name) override; @@ -52,11 +58,15 @@ class ProfileVoltageSource : public MNASimPowerComp, public DAEInterfac // #### MNA Section #### /// Initializes internal variables of the component - void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; - void mnaCompInitializeHarm(Real omega, Real timeStep, std::vector::Ptr> leftVectors) override; + void mnaCompInitialize(Real omega, Real timeStep, + Attribute::Ptr leftVector) override; + void mnaCompInitializeHarm( + Real omega, Real timeStep, + std::vector::Ptr> leftVectors) override; /// Stamps system matrix void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override; - void mnaCompApplySystemMatrixStampHarm(SparseMatrixRow &systemMatrix, Int freqIdx) override; + void mnaCompApplySystemMatrixStampHarm(SparseMatrixRow &systemMatrix, + Int freqIdx) override; /// Stamps right side (source) vector void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override; void mnaCompApplyRightSideVectorStampHarm(Matrix &rightVector) override; @@ -65,16 +75,25 @@ class ProfileVoltageSource : public MNASimPowerComp, public DAEInterfac /// MNA pre step operations void mnaCompPreStep(Real time, Int timeStepCount) override; /// MNA post step operations - void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + void mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; /// Add MNA pre step dependencies - void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + void mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) override; /// Add MNA post step dependencies - void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, - Attribute::Ptr &leftVector) override; + void + mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; class MnaPreStepHarm : public CPS::Task { public: - MnaPreStepHarm(ProfileVoltageSource &voltageSource) : Task(**voltageSource.mName + ".MnaPreStepHarm"), mVoltageSource(voltageSource) { + MnaPreStepHarm(ProfileVoltageSource &voltageSource) + : Task(**voltageSource.mName + ".MnaPreStepHarm"), + mVoltageSource(voltageSource) { mAttributeDependencies.push_back(mVoltageSource.mVoltage); mModifiedAttributes.push_back(mVoltageSource.mRightVector); mModifiedAttributes.push_back(mVoltageSource.mIntfVoltage); @@ -87,8 +106,10 @@ class ProfileVoltageSource : public MNASimPowerComp, public DAEInterfac class MnaPostStepHarm : public CPS::Task { public: - MnaPostStepHarm(ProfileVoltageSource &voltageSource, const std::vector::Ptr> &leftVectors) - : Task(**voltageSource.mName + ".MnaPostStepHarm"), mVoltageSource(voltageSource), mLeftVectors(leftVectors) { + MnaPostStepHarm(ProfileVoltageSource &voltageSource, + const std::vector::Ptr> &leftVectors) + : Task(**voltageSource.mName + ".MnaPostStepHarm"), + mVoltageSource(voltageSource), mLeftVectors(leftVectors) { for (UInt i = 0; i < mLeftVectors.size(); i++) mAttributeDependencies.push_back(mLeftVectors[i]); mModifiedAttributes.push_back(mVoltageSource.mIntfCurrent); @@ -102,7 +123,8 @@ class ProfileVoltageSource : public MNASimPowerComp, public DAEInterfac // #### DAE Section #### /// Residual function for DAE Solver - void daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) override; + void daeResidual(double ttime, const double state[], const double dstate_dt[], + double resid[], std::vector &off) override; /// Voltage Getter Complex daeInitialize() override; }; diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ControlledCurrentSource.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ControlledCurrentSource.h index de9f59839c..03189ce68e 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ControlledCurrentSource.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ControlledCurrentSource.h @@ -21,7 +21,8 @@ namespace Ph3 { /// /// This model uses modified nodal analysis to represent an ideal current source. /// This involves the stamping of the current to the right side vector. -class ControlledCurrentSource : public MNASimPowerComp, public SharedFactory { +class ControlledCurrentSource : public MNASimPowerComp, + public SharedFactory { protected: // Updates current according to reference phasor and frequency void updateCurrent(Real time); @@ -30,9 +31,12 @@ class ControlledCurrentSource : public MNASimPowerComp, public SharedFacto const Attribute::Ptr mCurrentRef; /// Defines UID, name and logging level - ControlledCurrentSource(String uid, String name, Logger::Level logLevel = Logger::Level::off); + ControlledCurrentSource(String uid, String name, + Logger::Level logLevel = Logger::Level::off); /// - ControlledCurrentSource(String name, Logger::Level logLevel = Logger::Level::off) : ControlledCurrentSource(name, name, logLevel) {} + ControlledCurrentSource(String name, + Logger::Level logLevel = Logger::Level::off) + : ControlledCurrentSource(name, name, logLevel) {} SimPowerComp::Ptr clone(String name) override; // #### General #### @@ -42,7 +46,8 @@ class ControlledCurrentSource : public MNASimPowerComp, public SharedFacto void setParameters(Matrix currentRef); // #### MNA section #### /// Initializes internal variables of the component - void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + void mnaCompInitialize(Real omega, Real timeStep, + Attribute::Ptr leftVector) override; /// Stamps right side (source) vector void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override; /// Returns voltage through the component @@ -50,12 +55,19 @@ class ControlledCurrentSource : public MNASimPowerComp, public SharedFacto /// MNA pre step operations void mnaCompPreStep(Real time, Int timeStepCount) override; /// MNA post step operations - void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + void mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; /// Add MNA pre step dependencies - void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + void mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) override; /// Add MNA post step dependencies - void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, - Attribute::Ptr &leftVector) override; + void + mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ControlledVoltageSource.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ControlledVoltageSource.h index fbd45334b8..32b7bd8fa8 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ControlledVoltageSource.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ControlledVoltageSource.h @@ -21,7 +21,8 @@ namespace Ph3 { /// /// This model uses modified nodal analysis to represent an ideal voltage source. /// This voltage source derives it's output purely from attributes rather than an internal signal generator. -class ControlledVoltageSource : public MNASimPowerComp, public SharedFactory { +class ControlledVoltageSource : public MNASimPowerComp, + public SharedFactory { protected: // Updates voltage according to reference phasor and frequency void updateVoltage(Real time); @@ -30,9 +31,12 @@ class ControlledVoltageSource : public MNASimPowerComp, public SharedFacto const CPS::Attribute::Ptr mVoltageRef; /// Defines UID, name and logging level - ControlledVoltageSource(String uid, String name, Logger::Level logLevel = Logger::Level::off); + ControlledVoltageSource(String uid, String name, + Logger::Level logLevel = Logger::Level::off); /// - ControlledVoltageSource(String name, Logger::Level logLevel = Logger::Level::off) : ControlledVoltageSource(name, name, logLevel) {} + ControlledVoltageSource(String name, + Logger::Level logLevel = Logger::Level::off) + : ControlledVoltageSource(name, name, logLevel) {} SimPowerComp::Ptr clone(String name) override; // #### General #### @@ -45,7 +49,8 @@ class ControlledVoltageSource : public MNASimPowerComp, public SharedFacto // #### MNA section #### /// Initializes internal variables of the component - void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + void mnaCompInitialize(Real omega, Real timeStep, + Attribute::Ptr leftVector) override; /// Stamps system matrix void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override; /// Stamps right side (source) vector @@ -55,12 +60,19 @@ class ControlledVoltageSource : public MNASimPowerComp, public SharedFacto /// MNA pre step operations void mnaCompPreStep(Real time, Int timeStepCount) override; /// MNA post step operations - void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + void mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; /// Add MNA pre step dependencies - void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + void mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) override; /// Add MNA post step dependencies - void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, - Attribute::Ptr &leftVector) override; + void + mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_RXLoad.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_RXLoad.h index 1fbdf00bcc..febf754aaf 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_RXLoad.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_RXLoad.h @@ -59,9 +59,14 @@ class RXLoad : public CompositePowerComp, public SharedFactory { Logger::Level logLevel = Logger::Level::off); // #### General #### - virtual String description() override { return fmt::format("Active: {}MW, Reactive: {}MVAr, Voltage: {}kV", (**mActivePower)(0, 0) / 1e6, (**mReactivePower)(0, 0) / 1e6, (**mNomVoltage) / 1e3); }; + virtual String description() override { + return fmt::format("Active: {}MW, Reactive: {}MVAr, Voltage: {}kV", + (**mActivePower)(0, 0) / 1e6, + (**mReactivePower)(0, 0) / 1e6, (**mNomVoltage) / 1e3); + }; /// - void setParameters(Matrix activePower, Matrix reactivePower, Real volt, bool reactanceInSeries = false); + void setParameters(Matrix activePower, Matrix reactivePower, Real volt, + bool reactanceInSeries = false); /// Initializes component from power flow data void initializeFromNodesAndTerminals(Real frequency) override; diff --git a/dpsim-models/include/dpsim-models/Filesystem.h b/dpsim-models/include/dpsim-models/Filesystem.h index 85eeb1a1d0..43eef985e5 100644 --- a/dpsim-models/include/dpsim-models/Filesystem.h +++ b/dpsim-models/include/dpsim-models/Filesystem.h @@ -19,7 +19,5 @@ namespace fs = ghc::filesystem; #include #if FMT_VERSION >= 90000 -template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +template <> class fmt::formatter : public fmt::ostream_formatter {}; #endif diff --git a/dpsim-models/include/dpsim-models/Logger.h b/dpsim-models/include/dpsim-models/Logger.h index d68f13b5d4..421ac22a66 100644 --- a/dpsim-models/include/dpsim-models/Logger.h +++ b/dpsim-models/include/dpsim-models/Logger.h @@ -70,50 +70,38 @@ class Logger { }; } // namespace CPS - #if FMT_VERSION >= 90000 template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter { +}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter {}; template <> -class fmt::formatter - : public fmt::ostream_formatter {}; +class fmt::formatter : public fmt::ostream_formatter { +}; template -class fmt::formatter> - : public fmt::ostream_formatter {}; +class fmt::formatter> : public fmt::ostream_formatter { +}; template class fmt::formatter> : public fmt::ostream_formatter {}; diff --git a/dpsim-models/include/dpsim-models/MNAStampUtils.h b/dpsim-models/include/dpsim-models/MNAStampUtils.h index 38e7bdfb2f..ccb065fe51 100644 --- a/dpsim-models/include/dpsim-models/MNAStampUtils.h +++ b/dpsim-models/include/dpsim-models/MNAStampUtils.h @@ -30,10 +30,10 @@ class MNAStampUtils { const Matrix &conductanceMat, SparseMatrixRow &mat, UInt node1Index, UInt node2Index, const Logger::Log &mSLog); - static void stamp3x3ConductanceMatrixNodeToGround(const Matrix &conductanceMat, - SparseMatrixRow &mat, - UInt nodeIndex, - const Logger::Log &mSLog); + static void + stamp3x3ConductanceMatrixNodeToGround(const Matrix &conductanceMat, + SparseMatrixRow &mat, UInt nodeIndex, + const Logger::Log &mSLog); static void stampAdmittanceMatrix( const MatrixComp &admittanceMat, SparseMatrixRow &mat, UInt node1Index, diff --git a/dpsim-models/src/CIM/Reader.cpp b/dpsim-models/src/CIM/Reader.cpp index 427d1f9a55..2d1dda5789 100644 --- a/dpsim-models/src/CIM/Reader.cpp +++ b/dpsim-models/src/CIM/Reader.cpp @@ -1190,7 +1190,8 @@ void Reader::processTopologicalNode(CIMPP::TopologicalNode *topNode) { auto pfEquipment = mPowerflowEquipment.at(equipment->mRID); if (pfEquipment == nullptr) { - SPDLOG_LOGGER_ERROR(mSLog, "Equipment {} is null in equipment list", equipment->mRID); + SPDLOG_LOGGER_ERROR(mSLog, "Equipment {} is null in equipment list", + equipment->mRID); throw SystemError("Equipment is null in equipment list."); } std::dynamic_pointer_cast>(pfEquipment) diff --git a/dpsim-models/src/DP/DP_Ph1_ProfileVoltageSource.cpp b/dpsim-models/src/DP/DP_Ph1_ProfileVoltageSource.cpp index 458105656c..8d36e4c56f 100644 --- a/dpsim-models/src/DP/DP_Ph1_ProfileVoltageSource.cpp +++ b/dpsim-models/src/DP/DP_Ph1_ProfileVoltageSource.cpp @@ -17,8 +17,12 @@ using namespace CPS; -DP::Ph1::ProfileVoltageSource::ProfileVoltageSource(String uid, String name, std::filesystem::path sourceFile, Logger::Level logLevel) - : MNASimPowerComp(uid, name, true, true, logLevel), mVoltage(mAttributes->createDynamic("V")), mSourceFile(sourceFile), mSourceIndex(0), mSamples() { +DP::Ph1::ProfileVoltageSource::ProfileVoltageSource( + String uid, String name, std::filesystem::path sourceFile, + Logger::Level logLevel) + : MNASimPowerComp(uid, name, true, true, logLevel), + mVoltage(mAttributes->createDynamic("V")), + mSourceFile(sourceFile), mSourceIndex(0), mSamples() { setVirtualNodeNumber(1); setTerminalNumber(2); **mIntfVoltage = MatrixComp::Zero(1, 1); @@ -32,53 +36,65 @@ void DP::Ph1::ProfileVoltageSource::readFromFile() { std::ifstream file(mSourceFile, std::ios::binary | std::ios::ate); if (!file.is_open()) { - throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not open file " + mSourceFile.string()); + throw SystemError( + "ProfileVoltageSource::ProfileVoltageSource could not open file " + + mSourceFile.string()); } std::streamsize size = file.tellg(); file.seekg(0, std::ios::beg); - size_t sample_num = size / (sizeof(struct villas::node::Sample) + SAMPLE_DATA_LENGTH(1)); + size_t sample_num = + size / (sizeof(struct villas::node::Sample) + SAMPLE_DATA_LENGTH(1)); std::vector buffer(size); if (!file.read(buffer.data(), size)) { - throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not read file " + mSourceFile.string()); + throw SystemError( + "ProfileVoltageSource::ProfileVoltageSource could not read file " + + mSourceFile.string()); } unsigned i, j; Villas__Node__Message *pb_msg; - pb_msg = villas__node__message__unpack(nullptr, size, (uint8_t *)buffer.data()); + pb_msg = + villas__node__message__unpack(nullptr, size, (uint8_t *)buffer.data()); if (!pb_msg) - throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not unpack Protobuf message"); + throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not " + "unpack Protobuf message"); for (i = 0; i < pb_msg->n_samples; i++) { Villas__Node__Sample *pb_smp = pb_msg->samples[i]; if (pb_smp->type != VILLAS__NODE__SAMPLE__TYPE__DATA) - throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not unpack Protobuf message"); + throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not " + "unpack Protobuf message"); if (pb_smp->n_values != 1) { - throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not unpack Protobuf message"); + throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not " + "unpack Protobuf message"); } for (j = 0; j < pb_smp->n_values; j++) { Villas__Node__Value *pb_val = pb_smp->values[j]; if (pb_val->value_case != VILLAS__NODE__VALUE__VALUE_F) - throw SystemError("ProfileVoltageSource::ProfileVoltageSource could not unpack Protobuf message"); + throw SystemError("ProfileVoltageSource::ProfileVoltageSource could " + "not unpack Protobuf message"); mSamples.push_back(pb_val->f); } } villas__node__message__free_unpacked(pb_msg, nullptr); - std::cout << "Read " << mSamples.size() << " samples from file " << mSourceFile << std::endl; + std::cout << "Read " << mSamples.size() << " samples from file " + << mSourceFile << std::endl; for (double sample : mSamples) { std::cout << sample << std::endl; } } -void DP::Ph1::ProfileVoltageSource::setSourceFile(std::filesystem::path file, size_t index) { +void DP::Ph1::ProfileVoltageSource::setSourceFile(std::filesystem::path file, + size_t index) { mSourceFile = file; mSourceIndex = index; readFromFile(); @@ -90,7 +106,8 @@ SimPowerComp::Ptr DP::Ph1::ProfileVoltageSource::clone(String name) { return copy; } -void DP::Ph1::ProfileVoltageSource::initializeFromNodesAndTerminals(Real frequency) { +void DP::Ph1::ProfileVoltageSource::initializeFromNodesAndTerminals( + Real frequency) { /// CHECK: The frequency parameter is unused if (**mVoltage == Complex(0, 0)) **mVoltage = initialSingleVoltage(1) - initialSingleVoltage(0); @@ -98,19 +115,26 @@ void DP::Ph1::ProfileVoltageSource::initializeFromNodesAndTerminals(Real frequen // #### MNA functions #### -void DP::Ph1::ProfileVoltageSource::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { +void DP::Ph1::ProfileVoltageSource::mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) { attributeDependencies.push_back(mVoltage); modifiedAttributes.push_back(mRightVector); modifiedAttributes.push_back(mIntfVoltage); } -void DP::Ph1::ProfileVoltageSource::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, - Attribute::Ptr &leftVector) { +void DP::Ph1::ProfileVoltageSource::mnaCompAddPostStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { attributeDependencies.push_back(leftVector); modifiedAttributes.push_back(mIntfCurrent); }; -void DP::Ph1::ProfileVoltageSource::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { +void DP::Ph1::ProfileVoltageSource::mnaCompInitialize( + Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); (**mIntfVoltage)(0, 0) = *mVoltage; @@ -120,10 +144,13 @@ void DP::Ph1::ProfileVoltageSource::mnaCompInitialize(Real omega, Real timeStep, "\nInitial voltage {:s}" "\nInitial current {:s}" "\n--- MNA initialization finished ---", - Logger::phasorToString((**mIntfVoltage)(0, 0)), Logger::phasorToString((**mIntfCurrent)(0, 0))); + Logger::phasorToString((**mIntfVoltage)(0, 0)), + Logger::phasorToString((**mIntfCurrent)(0, 0))); } -void DP::Ph1::ProfileVoltageSource::mnaCompInitializeHarm(Real omega, Real timeStep, std::vector::Ptr> leftVectors) { +void DP::Ph1::ProfileVoltageSource::mnaCompInitializeHarm( + Real omega, Real timeStep, + std::vector::Ptr> leftVectors) { updateMatrixNodeIndices(); (**mIntfVoltage)(0, 0) = *mVoltage; @@ -133,61 +160,95 @@ void DP::Ph1::ProfileVoltageSource::mnaCompInitializeHarm(Real omega, Real timeS **mRightVector = Matrix::Zero(leftVectors[0]->get().rows(), mNumFreqs); } -void DP::Ph1::ProfileVoltageSource::mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) { +void DP::Ph1::ProfileVoltageSource::mnaCompApplySystemMatrixStamp( + SparseMatrixRow &systemMatrix) { for (UInt freq = 0; freq < mNumFreqs; freq++) { if (terminalNotGrounded(0)) { - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0), Complex(-1, 0), mNumFreqs, freq); - Math::setMatrixElement(systemMatrix, matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex(), Complex(-1, 0), mNumFreqs, freq); + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), + matrixNodeIndex(0), Complex(-1, 0), mNumFreqs, + freq); + Math::setMatrixElement(systemMatrix, matrixNodeIndex(0), + mVirtualNodes[0]->matrixNodeIndex(), + Complex(-1, 0), mNumFreqs, freq); } if (terminalNotGrounded(1)) { - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(1), Complex(1, 0), mNumFreqs, freq); - Math::setMatrixElement(systemMatrix, matrixNodeIndex(1), mVirtualNodes[0]->matrixNodeIndex(), Complex(1, 0), mNumFreqs, freq); + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), + matrixNodeIndex(1), Complex(1, 0), mNumFreqs, + freq); + Math::setMatrixElement(systemMatrix, matrixNodeIndex(1), + mVirtualNodes[0]->matrixNodeIndex(), Complex(1, 0), + mNumFreqs, freq); } SPDLOG_LOGGER_INFO(mSLog, "-- Stamp frequency {:d} ---", freq); if (terminalNotGrounded(0)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", -1., matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex()); - SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", -1., mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", -1., + matrixNodeIndex(0), + mVirtualNodes[0]->matrixNodeIndex()); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", -1., + mVirtualNodes[0]->matrixNodeIndex(), + matrixNodeIndex(0)); } if (terminalNotGrounded(1)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1., mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(1)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1., matrixNodeIndex(1), mVirtualNodes[0]->matrixNodeIndex()); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1., + mVirtualNodes[0]->matrixNodeIndex(), + matrixNodeIndex(1)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1., + matrixNodeIndex(1), + mVirtualNodes[0]->matrixNodeIndex()); } } } -void DP::Ph1::ProfileVoltageSource::mnaCompApplySystemMatrixStampHarm(SparseMatrixRow &systemMatrix, Int freqIdx) { +void DP::Ph1::ProfileVoltageSource::mnaCompApplySystemMatrixStampHarm( + SparseMatrixRow &systemMatrix, Int freqIdx) { if (terminalNotGrounded(0)) { - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0), Complex(-1, 0)); - Math::setMatrixElement(systemMatrix, matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex(), Complex(-1, 0)); + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), + matrixNodeIndex(0), Complex(-1, 0)); + Math::setMatrixElement(systemMatrix, matrixNodeIndex(0), + mVirtualNodes[0]->matrixNodeIndex(), Complex(-1, 0)); } if (terminalNotGrounded(1)) { - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(1), Complex(1, 0)); - Math::setMatrixElement(systemMatrix, matrixNodeIndex(1), mVirtualNodes[0]->matrixNodeIndex(), Complex(1, 0)); + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), + matrixNodeIndex(1), Complex(1, 0)); + Math::setMatrixElement(systemMatrix, matrixNodeIndex(1), + mVirtualNodes[0]->matrixNodeIndex(), Complex(1, 0)); } SPDLOG_LOGGER_INFO(mSLog, "-- Stamp frequency {:d} ---", freqIdx); if (terminalNotGrounded(0)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", -1., matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex()); - SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", -1., mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", -1., + matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex()); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", -1., + mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0)); } if (terminalNotGrounded(1)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1., mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(1)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1., matrixNodeIndex(1), mVirtualNodes[0]->matrixNodeIndex()); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1., + mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(1)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f} to system at ({:d},{:d})", 1., + matrixNodeIndex(1), mVirtualNodes[0]->matrixNodeIndex()); } } -void DP::Ph1::ProfileVoltageSource::mnaCompApplyRightSideVectorStamp(Matrix &rightVector) { +void DP::Ph1::ProfileVoltageSource::mnaCompApplyRightSideVectorStamp( + Matrix &rightVector) { // TODO: Is this correct with two nodes not gnd? - Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(), (**mIntfVoltage)(0, 0), mNumFreqs); - SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}", Logger::complexToString((**mIntfVoltage)(0, 0)), mVirtualNodes[0]->matrixNodeIndex()); + Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(), + (**mIntfVoltage)(0, 0), mNumFreqs); + SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}", + Logger::complexToString((**mIntfVoltage)(0, 0)), + mVirtualNodes[0]->matrixNodeIndex()); } -void DP::Ph1::ProfileVoltageSource::mnaCompApplyRightSideVectorStampHarm(Matrix &rightVector) { +void DP::Ph1::ProfileVoltageSource::mnaCompApplyRightSideVectorStampHarm( + Matrix &rightVector) { for (UInt freq = 0; freq < mNumFreqs; freq++) { // TODO: Is this correct with two nodes not gnd? - Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(), (**mIntfVoltage)(0, freq), 1, 0, freq); - SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}", Logger::complexToString((**mIntfVoltage)(0, freq)), mVirtualNodes[0]->matrixNodeIndex()); + Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(), + (**mIntfVoltage)(0, freq), 1, 0, freq); + SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}", + Logger::complexToString((**mIntfVoltage)(0, freq)), + mVirtualNodes[0]->matrixNodeIndex()); } } @@ -197,27 +258,42 @@ void DP::Ph1::ProfileVoltageSource::updateVoltage(Real time) { // std::cout << "Update voltage to " << (**mIntfVoltage)(0, 0) << " at " << time << std::endl; } -void DP::Ph1::ProfileVoltageSource::mnaCompPreStep(Real time, Int timeStepCount) { +void DP::Ph1::ProfileVoltageSource::mnaCompPreStep(Real time, + Int timeStepCount) { updateVoltage(time); mnaCompApplyRightSideVectorStamp(**mRightVector); } -void DP::Ph1::ProfileVoltageSource::MnaPreStepHarm::execute(Real time, Int timeStepCount) { +void DP::Ph1::ProfileVoltageSource::MnaPreStepHarm::execute(Real time, + Int timeStepCount) { mVoltageSource.updateVoltage(time); - mVoltageSource.mnaCompApplyRightSideVectorStampHarm(**mVoltageSource.mRightVector); + mVoltageSource.mnaCompApplyRightSideVectorStampHarm( + **mVoltageSource.mRightVector); } -void DP::Ph1::ProfileVoltageSource::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { mnaCompUpdateCurrent(**leftVector); } +void DP::Ph1::ProfileVoltageSource::mnaCompPostStep( + Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateCurrent(**leftVector); +} -void DP::Ph1::ProfileVoltageSource::MnaPostStepHarm::execute(Real time, Int timeStepCount) { mVoltageSource.mnaCompUpdateCurrent(**mLeftVectors[0]); } +void DP::Ph1::ProfileVoltageSource::MnaPostStepHarm::execute( + Real time, Int timeStepCount) { + mVoltageSource.mnaCompUpdateCurrent(**mLeftVectors[0]); +} -void DP::Ph1::ProfileVoltageSource::mnaCompUpdateCurrent(const Matrix &leftVector) { +void DP::Ph1::ProfileVoltageSource::mnaCompUpdateCurrent( + const Matrix &leftVector) { for (UInt freq = 0; freq < mNumFreqs; freq++) { - (**mIntfCurrent)(0, freq) = Math::complexFromVectorElement(leftVector, mVirtualNodes[0]->matrixNodeIndex(), mNumFreqs, freq); + (**mIntfCurrent)(0, freq) = Math::complexFromVectorElement( + leftVector, mVirtualNodes[0]->matrixNodeIndex(), mNumFreqs, freq); } } -void DP::Ph1::ProfileVoltageSource::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { +void DP::Ph1::ProfileVoltageSource::daeResidual(double ttime, + const double state[], + const double dstate_dt[], + double resid[], + std::vector &off) { /* new state vector definintion: state[0]=node0_voltage state[1]=node1_voltage @@ -232,10 +308,13 @@ void DP::Ph1::ProfileVoltageSource::daeResidual(double ttime, const double state int Pos1 = matrixNodeIndex(0); int Pos2 = matrixNodeIndex(1); - int c_offset = off[0] + off[1]; // current offset for component - int n_offset_1 = c_offset + Pos1 + 1; // current offset for first nodal equation - int n_offset_2 = c_offset + Pos2 + 1; // current offset for second nodal equation - resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor + int c_offset = off[0] + off[1]; // current offset for component + int n_offset_1 = + c_offset + Pos1 + 1; // current offset for first nodal equation + int n_offset_2 = + c_offset + Pos2 + 1; // current offset for second nodal equation + resid[c_offset] = (state[Pos2] - state[Pos1]) - + state[c_offset]; // Voltage equation for Resistor // resid[++c_offset] = ; //TODO : add inductance equation resid[n_offset_1] += (**mIntfCurrent)(0, 0).real(); resid[n_offset_2] += (**mIntfCurrent)(0, 0).real(); diff --git a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp index 2632bf9454..cc3f84005a 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp @@ -29,7 +29,8 @@ void EMT::Ph1::Switch::initializeFromNodesAndTerminals(Real frequency) { Real resistance = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; (**mIntfVoltage)(0, 0) = - RMS3PH_TO_PEAK1PH * (initialSingleVoltage(1) - initialSingleVoltage(0)).real(); + RMS3PH_TO_PEAK1PH * + (initialSingleVoltage(1) - initialSingleVoltage(0)).real(); (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / resistance; SPDLOG_LOGGER_INFO(mSLog, @@ -41,8 +42,10 @@ void EMT::Ph1::Switch::initializeFromNodesAndTerminals(Real frequency) { "\n--- Initialization from powerflow finished ---", Logger::matrixToString(**mIntfVoltage), Logger::matrixToString(**mIntfCurrent), - Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0).real()), - Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1).real())); + Logger::phasorToString(RMS3PH_TO_PEAK1PH * + initialSingleVoltage(0).real()), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * + initialSingleVoltage(1).real())); } void EMT::Ph1::Switch::mnaCompInitialize(Real omega, Real timeStep, diff --git a/dpsim-models/src/EMT/EMT_Ph1_VoltageSource.cpp b/dpsim-models/src/EMT/EMT_Ph1_VoltageSource.cpp index 41688a8137..bc546b2a85 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_VoltageSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_VoltageSource.cpp @@ -84,7 +84,7 @@ void EMT::Ph1::VoltageSource::updateVoltage(Real time) { if (srcFreq > 0) (**mIntfVoltage)(0, 0) = Math::abs(voltageRef) * - cos((time)*2. * PI * srcFreq + Math::phase(voltageRef)); + cos((time) * 2. * PI * srcFreq + Math::phase(voltageRef)); else (**mIntfVoltage)(0, 0) = voltageRef.real(); } diff --git a/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp b/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp index 35e7fa66ca..ec410b520f 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp @@ -10,8 +10,10 @@ using namespace CPS; -EMT::Ph3::ControlledCurrentSource::ControlledCurrentSource(String uid, String name, Logger::Level logLevel) - : MNASimPowerComp(uid, name, true, true, logLevel), mCurrentRef(mAttributes->create("I_ref")) { +EMT::Ph3::ControlledCurrentSource::ControlledCurrentSource( + String uid, String name, Logger::Level logLevel) + : MNASimPowerComp(uid, name, true, true, logLevel), + mCurrentRef(mAttributes->create("I_ref")) { mPhaseType = PhaseType::ABC; setVirtualNodeNumber(0); setTerminalNumber(2); @@ -27,13 +29,16 @@ SimPowerComp::Ptr EMT::Ph3::ControlledCurrentSource::clone(String name) { void EMT::Ph3::ControlledCurrentSource::setParameters(Matrix currentRef) { **mCurrentRef = currentRef; - mSLog->info("\nCurrent reference phasor [I]: {:s}", Logger::matrixCompToString(currentRef)); + mSLog->info("\nCurrent reference phasor [I]: {:s}", + Logger::matrixCompToString(currentRef)); mParametersSet = true; } -void EMT::Ph3::ControlledCurrentSource::initializeFromNodesAndTerminals(Real frequency) { - SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization from node voltages and terminal ---"); +void EMT::Ph3::ControlledCurrentSource::initializeFromNodesAndTerminals( + Real frequency) { + SPDLOG_LOGGER_INFO( + mSLog, "\n--- Initialization from node voltages and terminal ---"); if (!mParametersSet) { **mCurrentRef = Matrix::Zero(3, 1); @@ -42,70 +47,105 @@ void EMT::Ph3::ControlledCurrentSource::initializeFromNodesAndTerminals(Real fre "\nTerminal 1 voltage: {:s}" "\nTerminal 0 power: {:s}" "\nTerminal 1 power: {:s}", - Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1)), Logger::complexToString(terminal(0)->singlePower()), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1)), + Logger::complexToString(terminal(0)->singlePower()), Logger::complexToString(terminal(1)->singlePower())); } else { - SPDLOG_LOGGER_INFO(mSLog, - "\nInitialization from node voltages and terminal omitted (parameter " - "already set)." - "\nReference voltage: {:s}", - Logger::matrixToString(attributeTyped("I_ref")->get())); + SPDLOG_LOGGER_INFO( + mSLog, + "\nInitialization from node voltages and terminal omitted (parameter " + "already set)." + "\nReference voltage: {:s}", + Logger::matrixToString(attributeTyped("I_ref")->get())); } - SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization from node voltages and terminal ---"); + SPDLOG_LOGGER_INFO( + mSLog, "\n--- Initialization from node voltages and terminal ---"); mSLog->flush(); } -void EMT::Ph3::ControlledCurrentSource::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); } +void EMT::Ph3::ControlledCurrentSource::mnaCompInitialize( + Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); +} -void EMT::Ph3::ControlledCurrentSource::mnaCompApplyRightSideVectorStamp(Matrix &rightVector) { +void EMT::Ph3::ControlledCurrentSource::mnaCompApplyRightSideVectorStamp( + Matrix &rightVector) { if (terminalNotGrounded(1)) { - Math::setVectorElement(rightVector, matrixNodeIndex(1, 0), -(**mIntfCurrent)(0, 0)); - Math::setVectorElement(rightVector, matrixNodeIndex(1, 1), -(**mIntfCurrent)(1, 0)); - Math::setVectorElement(rightVector, matrixNodeIndex(1, 2), -(**mIntfCurrent)(2, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(1, 0), + -(**mIntfCurrent)(0, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(1, 1), + -(**mIntfCurrent)(1, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(1, 2), + -(**mIntfCurrent)(2, 0)); } if (terminalNotGrounded(0)) { - Math::setVectorElement(rightVector, matrixNodeIndex(0, 0), (**mIntfCurrent)(0, 0)); - Math::setVectorElement(rightVector, matrixNodeIndex(0, 1), (**mIntfCurrent)(1, 0)); - Math::setVectorElement(rightVector, matrixNodeIndex(0, 2), (**mIntfCurrent)(2, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(0, 0), + (**mIntfCurrent)(0, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(0, 1), + (**mIntfCurrent)(1, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(0, 2), + (**mIntfCurrent)(2, 0)); } } void EMT::Ph3::ControlledCurrentSource::updateCurrent(Real time) { **mIntfCurrent = **mCurrentRef; - SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate current: {:s}", Logger::matrixToString(**mIntfCurrent)); + SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate current: {:s}", + Logger::matrixToString(**mIntfCurrent)); } -void EMT::Ph3::ControlledCurrentSource::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { +void EMT::Ph3::ControlledCurrentSource::mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) { attributeDependencies.push_back(mCurrentRef); modifiedAttributes.push_back(mRightVector); modifiedAttributes.push_back(mIntfVoltage); } -void EMT::Ph3::ControlledCurrentSource::mnaCompPreStep(Real time, Int timeStepCount) { +void EMT::Ph3::ControlledCurrentSource::mnaCompPreStep(Real time, + Int timeStepCount) { updateCurrent(time); mnaCompApplyRightSideVectorStamp(**mRightVector); } -void EMT::Ph3::ControlledCurrentSource::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, - Attribute::Ptr &leftVector) { +void EMT::Ph3::ControlledCurrentSource::mnaCompAddPostStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { attributeDependencies.push_back(leftVector); modifiedAttributes.push_back(mIntfVoltage); }; -void EMT::Ph3::ControlledCurrentSource::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { mnaCompUpdateVoltage(**leftVector); } +void EMT::Ph3::ControlledCurrentSource::mnaCompPostStep( + Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); +} -void EMT::Ph3::ControlledCurrentSource::mnaCompUpdateVoltage(const Matrix &leftVector) { +void EMT::Ph3::ControlledCurrentSource::mnaCompUpdateVoltage( + const Matrix &leftVector) { // v1 - v0 **mIntfVoltage = Matrix::Zero(3, 1); if (terminalNotGrounded(1)) { - (**mIntfVoltage)(0, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); - (**mIntfVoltage)(1, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)); - (**mIntfVoltage)(2, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)); + (**mIntfVoltage)(0, 0) = + Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); + (**mIntfVoltage)(1, 0) = + Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)); + (**mIntfVoltage)(2, 0) = + Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)); } if (terminalNotGrounded(0)) { - (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); - (**mIntfVoltage)(1, 0) = (**mIntfVoltage)(1, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); - (**mIntfVoltage)(2, 0) = (**mIntfVoltage)(2, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); + (**mIntfVoltage)(0, 0) = + (**mIntfVoltage)(0, 0) - + Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); + (**mIntfVoltage)(1, 0) = + (**mIntfVoltage)(1, 0) - + Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); + (**mIntfVoltage)(2, 0) = + (**mIntfVoltage)(2, 0) - + Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); } } diff --git a/dpsim-models/src/EMT/EMT_Ph3_ControlledVoltageSource.cpp b/dpsim-models/src/EMT/EMT_Ph3_ControlledVoltageSource.cpp index c93620a3b5..0dd96f9970 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_ControlledVoltageSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_ControlledVoltageSource.cpp @@ -10,8 +10,11 @@ using namespace CPS; -EMT::Ph3::ControlledVoltageSource::ControlledVoltageSource(String uid, String name, Logger::Level logLevel) - : MNASimPowerComp(uid, name, true, true, logLevel), mVoltageRef(mAttributes->createDynamic("V_ref")) // rms-value, phase-to-phase +EMT::Ph3::ControlledVoltageSource::ControlledVoltageSource( + String uid, String name, Logger::Level logLevel) + : MNASimPowerComp(uid, name, true, true, logLevel), + mVoltageRef(mAttributes->createDynamic( + "V_ref")) // rms-value, phase-to-phase { mPhaseType = PhaseType::ABC; setVirtualNodeNumber(1); @@ -26,7 +29,8 @@ void EMT::Ph3::ControlledVoltageSource::setParameters(Matrix voltageRef) { mParametersSet = true; } -void EMT::Ph3::ControlledVoltageSource::initializeFromNodesAndTerminals(Real frequency) { +void EMT::Ph3::ControlledVoltageSource::initializeFromNodesAndTerminals( + Real frequency) { SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization from node voltages ---"); // TODO: this approach currently overwrites voltage reference set from outside, when not using setParameters if (!mParametersSet) { @@ -35,12 +39,15 @@ void EMT::Ph3::ControlledVoltageSource::initializeFromNodesAndTerminals(Real fre "\nReference voltage: {:s}" "\nTerminal 0 voltage: {:s}" "\nTerminal 1 voltage: {:s}", - Logger::matrixCompToString(**mVoltageRef), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + Logger::matrixCompToString(**mVoltageRef), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1))); } else { - SPDLOG_LOGGER_INFO(mSLog, - "\nInitialization from node voltages omitted (parameter already set)." - "\nReference voltage: {:s}", - Logger::matrixCompToString(**mVoltageRef)); + SPDLOG_LOGGER_INFO( + mSLog, + "\nInitialization from node voltages omitted (parameter already set)." + "\nReference voltage: {:s}", + Logger::matrixCompToString(**mVoltageRef)); } SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization from node voltages ---"); mSLog->flush(); @@ -52,64 +59,114 @@ SimPowerComp::Ptr EMT::Ph3::ControlledVoltageSource::clone(String name) { return copy; } -void EMT::Ph3::ControlledVoltageSource::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); } +void EMT::Ph3::ControlledVoltageSource::mnaCompInitialize( + Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); +} -void EMT::Ph3::ControlledVoltageSource::mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) { +void EMT::Ph3::ControlledVoltageSource::mnaCompApplySystemMatrixStamp( + SparseMatrixRow &systemMatrix) { if (terminalNotGrounded(0)) { - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), -1); - Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), matrixNodeIndex(0, 0), -1); - - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 1), mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), -1); - Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), matrixNodeIndex(0, 1), -1); - - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2), mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), -1); - Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), matrixNodeIndex(0, 2), -1); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), + -1); + Math::addToMatrixElement(systemMatrix, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), + matrixNodeIndex(0, 0), -1); + + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 1), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), + -1); + Math::addToMatrixElement(systemMatrix, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), + matrixNodeIndex(0, 1), -1); + + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), + -1); + Math::addToMatrixElement(systemMatrix, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), + matrixNodeIndex(0, 2), -1); } if (terminalNotGrounded(1)) { - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), 1); - Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), matrixNodeIndex(1, 0), 1); - - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 1), mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), 1); - Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), matrixNodeIndex(1, 1), 1); - - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 2), mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), 1); - Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), matrixNodeIndex(1, 2), 1); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), + 1); + Math::addToMatrixElement(systemMatrix, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), + matrixNodeIndex(1, 0), 1); + + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 1), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), + 1); + Math::addToMatrixElement(systemMatrix, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), + matrixNodeIndex(1, 1), 1); + + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 2), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), + 1); + Math::addToMatrixElement(systemMatrix, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), + matrixNodeIndex(1, 2), 1); } } -void EMT::Ph3::ControlledVoltageSource::mnaCompApplyRightSideVectorStamp(Matrix &rightVector) { - Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), (**mIntfVoltage)(0, 0)); - Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), (**mIntfVoltage)(1, 0)); - Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), (**mIntfVoltage)(2, 0)); +void EMT::Ph3::ControlledVoltageSource::mnaCompApplyRightSideVectorStamp( + Matrix &rightVector) { + Math::setVectorElement(rightVector, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), + (**mIntfVoltage)(0, 0)); + Math::setVectorElement(rightVector, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), + (**mIntfVoltage)(1, 0)); + Math::setVectorElement(rightVector, + mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), + (**mIntfVoltage)(2, 0)); } void EMT::Ph3::ControlledVoltageSource::updateVoltage(Real time) { **mIntfVoltage = **mVoltageRef; - SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate Voltage: {:s}", Logger::matrixToString(**mIntfVoltage)); + SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate Voltage: {:s}", + Logger::matrixToString(**mIntfVoltage)); } -void EMT::Ph3::ControlledVoltageSource::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { +void EMT::Ph3::ControlledVoltageSource::mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) { attributeDependencies.push_back(mVoltageRef); modifiedAttributes.push_back(mRightVector); modifiedAttributes.push_back(mIntfVoltage); } -void EMT::Ph3::ControlledVoltageSource::mnaCompPreStep(Real time, Int timeStepCount) { +void EMT::Ph3::ControlledVoltageSource::mnaCompPreStep(Real time, + Int timeStepCount) { updateVoltage(time); mnaCompApplyRightSideVectorStamp(**mRightVector); } -void EMT::Ph3::ControlledVoltageSource::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, - Attribute::Ptr &leftVector) { +void EMT::Ph3::ControlledVoltageSource::mnaCompAddPostStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { attributeDependencies.push_back(leftVector); modifiedAttributes.push_back(mIntfCurrent); }; -void EMT::Ph3::ControlledVoltageSource::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { mnaCompUpdateCurrent(**leftVector); } +void EMT::Ph3::ControlledVoltageSource::mnaCompPostStep( + Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateCurrent(**leftVector); +} -void EMT::Ph3::ControlledVoltageSource::mnaCompUpdateCurrent(const Matrix &leftVector) { - (**mIntfCurrent)(0, 0) = Math::realFromVectorElement(leftVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::A)); - (**mIntfCurrent)(1, 0) = Math::realFromVectorElement(leftVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::B)); - (**mIntfCurrent)(2, 0) = Math::realFromVectorElement(leftVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C)); +void EMT::Ph3::ControlledVoltageSource::mnaCompUpdateCurrent( + const Matrix &leftVector) { + (**mIntfCurrent)(0, 0) = Math::realFromVectorElement( + leftVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::A)); + (**mIntfCurrent)(1, 0) = Math::realFromVectorElement( + leftVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::B)); + (**mIntfCurrent)(2, 0) = Math::realFromVectorElement( + leftVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C)); } diff --git a/dpsim-models/src/EMT/EMT_Ph3_RXLoad.cpp b/dpsim-models/src/EMT/EMT_Ph3_RXLoad.cpp index c412e7f3f5..56dc11431b 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_RXLoad.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_RXLoad.cpp @@ -11,8 +11,11 @@ using namespace CPS; EMT::Ph3::RXLoad::RXLoad(String uid, String name, Logger::Level logLevel) - : CompositePowerComp(uid, name, true, true, Logger::Level::trace), mActivePower(mAttributes->create("P")), mReactivePower(mAttributes->create("Q")), - mNomVoltage(mAttributes->create("V_nom")), mReactanceInSeries(false) { + : CompositePowerComp(uid, name, true, true, Logger::Level::trace), + mActivePower(mAttributes->create("P")), + mReactivePower(mAttributes->create("Q")), + mNomVoltage(mAttributes->create("V_nom")), + mReactanceInSeries(false) { mPhaseType = PhaseType::ABC; setTerminalNumber(1); @@ -45,7 +48,8 @@ EMT::Ph3::RXLoad::RXLoad(String name, Matrix activePower, Matrix reactivePower, initPowerFromTerminal = false; } -void EMT::Ph3::RXLoad::setParameters(Matrix activePower, Matrix reactivePower, Real volt, bool reactanceInSeries) { +void EMT::Ph3::RXLoad::setParameters(Matrix activePower, Matrix reactivePower, + Real volt, bool reactanceInSeries) { **mActivePower = activePower; **mReactivePower = reactivePower; mReactanceInSeries = reactanceInSeries; @@ -107,18 +111,26 @@ void EMT::Ph3::RXLoad::initializeFromNodesAndTerminals(Real frequency) { **mIntfVoltage = vInitABC.real(); if ((**mActivePower)(0, 0) != 0) { - mResistance = std::pow(**mNomVoltage / sqrt(3), 2) * (**mActivePower).inverse(); + mResistance = + std::pow(**mNomVoltage / sqrt(3), 2) * (**mActivePower).inverse(); } if ((**mReactivePower)(0, 0) != 0) - mReactance = std::pow(**mNomVoltage / sqrt(3), 2) * (**mReactivePower).inverse(); + mReactance = + std::pow(**mNomVoltage / sqrt(3), 2) * (**mReactivePower).inverse(); else mReactance = Matrix::Zero(1, 1); if (mReactanceInSeries) { MatrixComp impedance = MatrixComp::Zero(3, 3); - impedance << Complex(mResistance(0, 0), mReactance(0, 0)), Complex(mResistance(0, 1), mReactance(0, 1)), Complex(mResistance(0, 2), mReactance(0, 2)), Complex(mResistance(1, 0), mReactance(1, 0)), - Complex(mResistance(1, 1), mReactance(1, 1)), Complex(mResistance(1, 2), mReactance(1, 2)), Complex(mResistance(2, 0), mReactance(2, 0)), Complex(mResistance(2, 1), mReactance(2, 1)), + impedance << Complex(mResistance(0, 0), mReactance(0, 0)), + Complex(mResistance(0, 1), mReactance(0, 1)), + Complex(mResistance(0, 2), mReactance(0, 2)), + Complex(mResistance(1, 0), mReactance(1, 0)), + Complex(mResistance(1, 1), mReactance(1, 1)), + Complex(mResistance(1, 2), mReactance(1, 2)), + Complex(mResistance(2, 0), mReactance(2, 0)), + Complex(mResistance(2, 1), mReactance(2, 1)), Complex(mResistance(2, 2), mReactance(2, 2)); **mIntfCurrent = (impedance.inverse() * vInitABC).real(); @@ -128,11 +140,13 @@ void EMT::Ph3::RXLoad::initializeFromNodesAndTerminals(Real frequency) { vInitTerm0(0, 0) = initialSingleVoltage(0); vInitTerm0(1, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_B; vInitTerm0(2, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_C; - mVirtualNodes[0]->setInitialVoltage(vInitTerm0 + mResistance * **mIntfCurrent); + mVirtualNodes[0]->setInitialVoltage(vInitTerm0 + + mResistance * **mIntfCurrent); } if ((**mActivePower)(0, 0) != 0) { - mSubResistor = std::make_shared(**mName + "_res", mLogLevel); + mSubResistor = + std::make_shared(**mName + "_res", mLogLevel); mSubResistor->setParameters(mResistance); if (mReactanceInSeries) { mSubResistor->connect({mTerminals[0]->node(), mVirtualNodes[0]}); @@ -141,7 +155,8 @@ void EMT::Ph3::RXLoad::initializeFromNodesAndTerminals(Real frequency) { } mSubResistor->initialize(mFrequencies); mSubResistor->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); if (!mReactanceInSeries) { **mIntfCurrent += mSubResistor->intfCurrent(); @@ -155,9 +170,9 @@ void EMT::Ph3::RXLoad::initializeFromNodesAndTerminals(Real frequency) { std::make_shared(**mName + "_ind", mLogLevel); mSubInductor->setParameters(mInductance); if (mReactanceInSeries) { - mSubInductor->connect({SimNode::GND, mVirtualNodes[0]}); + mSubInductor->connect({SimNode::GND, mVirtualNodes[0]}); } else { - mSubInductor->connect({SimNode::GND, mTerminals[0]->node()}); + mSubInductor->connect({SimNode::GND, mTerminals[0]->node()}); } mSubInductor->initialize(mFrequencies); mSubInductor->initializeFromNodesAndTerminals(frequency); diff --git a/dpsim-models/src/SimPowerComp.cpp b/dpsim-models/src/SimPowerComp.cpp index 0456e7e9f9..ffdb7a93e6 100644 --- a/dpsim-models/src/SimPowerComp.cpp +++ b/dpsim-models/src/SimPowerComp.cpp @@ -271,7 +271,8 @@ void SimPowerComp::connect(typename SimNode::List nodes) { } for (UInt i = 0; i < nodes.size(); i++) { if (nodes[i] == nullptr) { - throw SystemError(fmt::format("Node is nullptr for Component {}", **mName)); + throw SystemError( + fmt::format("Node is nullptr for Component {}", **mName)); } String name = **mName + "_T" + std::to_string(i); typename SimTerminal::Ptr terminal = diff --git a/dpsim-models/src/SystemTopology.cpp b/dpsim-models/src/SystemTopology.cpp index 5330f7b334..b62ffa1835 100644 --- a/dpsim-models/src/SystemTopology.cpp +++ b/dpsim-models/src/SystemTopology.cpp @@ -422,9 +422,11 @@ Graph::Graph SystemTopology::topologyGraph() { std::stringstream label, tooltip; label << "" << name << "
"; - label << "" << type << "
"; + label << "" << type + << "
"; if (topoComp->description() != "") { - label << "" << topoComp->description() << ""; + label << "" + << topoComp->description() << ""; } tooltip << "Attributes:"; diff --git a/dpsim-villas/examples/cxx/Fpga9BusHil.cpp b/dpsim-villas/examples/cxx/Fpga9BusHil.cpp index cbefd327a8..0961f31540 100644 --- a/dpsim-villas/examples/cxx/Fpga9BusHil.cpp +++ b/dpsim-villas/examples/cxx/Fpga9BusHil.cpp @@ -27,11 +27,13 @@ using namespace CPS::EMT; using namespace CPS::EMT::Ph1; const CPS::CIM::Examples::Components::GovernorKundur::Parameters govKundur; -const CPS::CIM::Examples::Components::ExcitationSystemEremia::Parameters excEremia; +const CPS::CIM::Examples::Components::ExcitationSystemEremia::Parameters + excEremia; const std::string buildFpgaConfig(CommandLineArgs &args) { - std::filesystem::path fpgaIpPath = "/usr/local/etc/villas/node/etc/fpga/vc707-xbar-pcie/" - "vc707-xbar-pcie.json"; + std::filesystem::path fpgaIpPath = + "/usr/local/etc/villas/node/etc/fpga/vc707-xbar-pcie/" + "vc707-xbar-pcie.json"; if (args.options.find("ips") != args.options.end()) { fpgaIpPath = std::filesystem::path(args.getOptionString("ips")); @@ -87,18 +89,24 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { return config; } -std::pair>> hilTopology(CommandLineArgs &args, std::shared_ptr intf, std::shared_ptr logger) { +std::pair>> +hilTopology(CommandLineArgs &args, std::shared_ptr intf, + std::shared_ptr logger) { std::string simName = "Fpga9BusHil"; auto events = std::make_shared>(); - std::list filenames = - Utils::findFiles({"WSCC-09_Dyn_Full_DI.xml", "WSCC-09_Dyn_Full_EQ.xml", "WSCC-09_Dyn_Full_SV.xml", "WSCC-09_Dyn_Full_TP.xml"}, "build/_deps/cim-data-src/WSCC-09/WSCC-09_Dyn_Full", "CIMPATH"); + std::list filenames = Utils::findFiles( + {"WSCC-09_Dyn_Full_DI.xml", "WSCC-09_Dyn_Full_EQ.xml", + "WSCC-09_Dyn_Full_SV.xml", "WSCC-09_Dyn_Full_TP.xml"}, + "build/_deps/cim-data-src/WSCC-09/WSCC-09_Dyn_Full", "CIMPATH"); // ----- POWERFLOW FOR INITIALIZATION ----- // read original network topology String simNamePF = simName + "_PF"; CPS::CIM::Reader reader(simNamePF); - SystemTopology systemPF = reader.loadCIM(60, filenames, Domain::SP, PhaseType::Single, CPS::GeneratorType::PVNode); - systemPF.component("GEN1")->modifyPowerFlowBusType(CPS::PowerflowBusType::VD); + SystemTopology systemPF = reader.loadCIM( + 60, filenames, Domain::SP, PhaseType::Single, CPS::GeneratorType::PVNode); + systemPF.component("GEN1") + ->modifyPowerFlowBusType(CPS::PowerflowBusType::VD); // define logging auto loggerPF = DPsim::DataLogger::make(simNamePF); @@ -120,25 +128,42 @@ std::pair>> hilTopology( // ----- DYNAMIC SIMULATION ----- CPS::CIM::Reader reader2(simName); - SystemTopology sys = reader2.loadCIM(60, filenames, Domain::EMT, PhaseType::ABC, CPS::GeneratorType::FullOrderVBR); + SystemTopology sys = + reader2.loadCIM(60, filenames, Domain::EMT, PhaseType::ABC, + CPS::GeneratorType::FullOrderVBR); sys.initWithPowerflow(systemPF, CPS::Domain::EMT); - sys.component("LOAD5")->setParameters(Matrix({{125e6, 0, 0}, {0, 125e6, 0}, {0, 0, 125e6}}), Matrix({{90e6, 0, 0}, {0, 90e6, 0}, {0, 0, 90e6}}), 230e3, true); + sys.component("LOAD5")->setParameters( + Matrix({{125e6, 0, 0}, {0, 125e6, 0}, {0, 0, 125e6}}), + Matrix({{90e6, 0, 0}, {0, 90e6, 0}, {0, 0, 90e6}}), 230e3, true); - sys.component("LOAD8")->setParameters(Matrix({{100e6, 0, 0}, {0, 100e6, 0}, {0, 0, 100e6}}), Matrix({{30e6, 0, 0}, {0, 30e6, 0}, {0, 0, 30e6}}), 230e3, true); + sys.component("LOAD8")->setParameters( + Matrix({{100e6, 0, 0}, {0, 100e6, 0}, {0, 0, 100e6}}), + Matrix({{30e6, 0, 0}, {0, 30e6, 0}, {0, 0, 30e6}}), 230e3, true); - sys.component("LOAD6")->setParameters(Matrix({{90e6, 0, 0}, {0, 90e6, 0}, {0, 0, 90e6}}), Matrix({{30e6, 0, 0}, {0, 30e6, 0}, {0, 0, 30e6}}), 230e3, true); + sys.component("LOAD6")->setParameters( + Matrix({{90e6, 0, 0}, {0, 90e6, 0}, {0, 0, 90e6}}), + Matrix({{30e6, 0, 0}, {0, 30e6, 0}, {0, 0, 30e6}}), 230e3, true); auto gen1 = sys.component("GEN1"); - gen1->addGovernor(govKundur.Ta_t, govKundur.Tb, govKundur.Tc, govKundur.Fa, govKundur.Fb, govKundur.Fc, govKundur.Kg, govKundur.Tsr, govKundur.Tsm, 1, 1); - gen1->addExciter(excEremia.Ta, excEremia.Ka, excEremia.Te, excEremia.Ke, excEremia.Tf, excEremia.Kf, excEremia.Tr); + gen1->addGovernor(govKundur.Ta_t, govKundur.Tb, govKundur.Tc, govKundur.Fa, + govKundur.Fb, govKundur.Fc, govKundur.Kg, govKundur.Tsr, + govKundur.Tsm, 1, 1); + gen1->addExciter(excEremia.Ta, excEremia.Ka, excEremia.Te, excEremia.Ke, + excEremia.Tf, excEremia.Kf, excEremia.Tr); auto gen2 = sys.component("GEN2"); - gen2->addGovernor(govKundur.Ta_t, govKundur.Tb, govKundur.Tc, govKundur.Fa, govKundur.Fb, govKundur.Fc, govKundur.Kg, govKundur.Tsr, govKundur.Tsm, 1, 1); - gen2->addExciter(excEremia.Ta, excEremia.Ka, excEremia.Te, excEremia.Ke, excEremia.Tf, excEremia.Kf, excEremia.Tr); + gen2->addGovernor(govKundur.Ta_t, govKundur.Tb, govKundur.Tc, govKundur.Fa, + govKundur.Fb, govKundur.Fc, govKundur.Kg, govKundur.Tsr, + govKundur.Tsm, 1, 1); + gen2->addExciter(excEremia.Ta, excEremia.Ka, excEremia.Te, excEremia.Ke, + excEremia.Tf, excEremia.Kf, excEremia.Tr); auto gen3 = sys.component("GEN3"); - gen3->addGovernor(govKundur.Ta_t, govKundur.Tb, govKundur.Tc, govKundur.Fa, govKundur.Fb, govKundur.Fc, govKundur.Kg, govKundur.Tsr, govKundur.Tsm, 1, 1); - gen3->addExciter(excEremia.Ta, excEremia.Ka, excEremia.Te, excEremia.Ke, excEremia.Tf, excEremia.Kf, excEremia.Tr); + gen3->addGovernor(govKundur.Ta_t, govKundur.Tb, govKundur.Tc, govKundur.Fa, + govKundur.Fb, govKundur.Fc, govKundur.Kg, govKundur.Tsr, + govKundur.Tsm, 1, 1); + gen3->addExciter(excEremia.Ta, excEremia.Ka, excEremia.Te, excEremia.Ke, + excEremia.Tf, excEremia.Kf, excEremia.Tr); auto cs = Ph1::CurrentSource::make("cs"); cs->setParameters(Complex(0, 0)); @@ -154,25 +179,37 @@ std::pair>> hilTopology( // We scale the voltage so we map the nominal voltage in the simulation (230kV) to a nominal real peak voltage // of 15V. The amplifier has a gain of 20, so the voltage before the amplifier is 1/20 of the voltage at the load. constexpr double voltage_scale = 15. * 1.414 / (230e3 * 20.); - auto updateFn = std::make_shared::Actor>([](std::shared_ptr &dependent, typename CPS::Attribute::Ptr dependency) { - *dependent = *dependency * voltage_scale; - if (*dependent > 1.) { - *dependent = 1.; - } else if (*dependent < -1.) { - *dependent = -1.; - } - }); - scaledOutputVoltage->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, - CPS::AttributeUpdateTask::make(CPS::UpdateTaskKind::UPDATE_ON_GET, *updateFn, sys.node("BUS6")->mVoltage->deriveCoeff(0, 0))); + auto updateFn = std::make_shared::Actor>( + [](std::shared_ptr &dependent, + typename CPS::Attribute::Ptr dependency) { + *dependent = *dependency * voltage_scale; + if (*dependent > 1.) { + *dependent = 1.; + } else if (*dependent < -1.) { + *dependent = -1.; + } + }); + scaledOutputVoltage->addTask( + CPS::UpdateTaskKind::UPDATE_ON_GET, + CPS::AttributeUpdateTask::make( + CPS::UpdateTaskKind::UPDATE_ON_GET, *updateFn, + sys.node("BUS6")->mVoltage->deriveCoeff(0, 0))); auto voltageInterfaceActive = CPS::AttributeStatic::make(false); - auto voltageActiveFn = std::make_shared::Actor>([](std::shared_ptr &dependent, typename CPS::Attribute::Ptr dependency) { - if (!*dependency) { - *dependent = 0.; - } - }); - scaledOutputVoltage->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, CPS::AttributeUpdateTask::make(CPS::UpdateTaskKind::UPDATE_ON_GET, *voltageActiveFn, voltageInterfaceActive)); + auto voltageActiveFn = + std::make_shared::Actor>( + [](std::shared_ptr &dependent, + typename CPS::Attribute::Ptr dependency) { + if (!*dependency) { + *dependent = 0.; + } + }); + scaledOutputVoltage->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, + CPS::AttributeUpdateTask::make( + CPS::UpdateTaskKind::UPDATE_ON_GET, + *voltageActiveFn, voltageInterfaceActive)); // We activate the voltage interface after 2 seconds to allow the current sensors to stabilize. - auto activeVoltageEvent = AttributeEvent::make(2., voltageInterfaceActive, true); + auto activeVoltageEvent = + AttributeEvent::make(2., voltageInterfaceActive, true); events->push_back(activeVoltageEvent); // We scale the current using a gain so that we get a load in the simulation in the MVA range. @@ -182,20 +219,33 @@ std::pair>> hilTopology( constexpr double current_offset = -2.483036; auto scaledCurrent = CPS::AttributeDynamic::make(0); auto closedLoop = CPS::AttributeStatic::make(false); - auto currentScaleFn = std::make_shared::Actor>([](std::shared_ptr &dependent, typename CPS::Attribute::Ptr dependency) { - if (!*dependency) { - *dependent = 0.; - } else { - *dependent = (*dependent + current_offset) * current_scale; - } - }); - scaledCurrent->addTask(CPS::UpdateTaskKind::UPDATE_ON_SET, CPS::AttributeUpdateTask::make(CPS::UpdateTaskKind::UPDATE_ON_SET, *currentScaleFn, closedLoop)); + auto currentScaleFn = + std::make_shared::Actor>( + [](std::shared_ptr &dependent, + typename CPS::Attribute::Ptr dependency) { + if (!*dependency) { + *dependent = 0.; + } else { + *dependent = (*dependent + current_offset) * current_scale; + } + }); + scaledCurrent->addTask( + CPS::UpdateTaskKind::UPDATE_ON_SET, + CPS::AttributeUpdateTask::make( + CPS::UpdateTaskKind::UPDATE_ON_SET, *currentScaleFn, closedLoop)); auto closeLoopEvent = AttributeEvent::make(2., closedLoop, true); events->push_back(closeLoopEvent); - auto currentCopyFn = std::make_shared::Actor>( - [](std::shared_ptr &dependent, typename CPS::Attribute::Ptr dependency) { dependency->set(Complex(*dependent, 0)); }); - scaledCurrent->addTask(CPS::UpdateTaskKind::UPDATE_ON_SET, CPS::AttributeUpdateTask::make(CPS::UpdateTaskKind::UPDATE_ON_SET, *currentCopyFn, cs->mCurrentRef)); + auto currentCopyFn = + std::make_shared::Actor>( + [](std::shared_ptr &dependent, + typename CPS::Attribute::Ptr dependency) { + dependency->set(Complex(*dependent, 0)); + }); + scaledCurrent->addTask( + CPS::UpdateTaskKind::UPDATE_ON_SET, + CPS::AttributeUpdateTask::make( + CPS::UpdateTaskKind::UPDATE_ON_SET, *currentCopyFn, cs->mCurrentRef)); intf->addImport(seqnumAttribute, true, true); intf->addImport(scaledCurrent, true, true); @@ -219,15 +269,20 @@ std::pair>> hilTopology( } int main(int argc, char *argv[]) { - CommandLineArgs args(argc, argv, "Fpga9BusHil", 0.01, 10 * 60, 60., -1, CPS::Logger::Level::info, CPS::Logger::Level::off, false, false, false, CPS::Domain::EMT); + CommandLineArgs args(argc, argv, "Fpga9BusHil", 0.01, 10 * 60, 60., -1, + CPS::Logger::Level::info, CPS::Logger::Level::off, false, + false, false, CPS::Domain::EMT); CPS::Logger::setLogDir("logs/" + args.name); - bool log = args.options.find("log") != args.options.end() && args.getOptionBool("log"); + bool log = args.options.find("log") != args.options.end() && + args.getOptionBool("log"); - auto intf = std::make_shared(buildFpgaConfig(args), "Fpga9BusHil", spdlog::level::off); + auto intf = std::make_shared( + buildFpgaConfig(args), "Fpga9BusHil", spdlog::level::off); std::filesystem::path logFilename = "logs/" + args.name + "/Fpga9BusHil.csv"; std::shared_ptr logger = nullptr; if (log) { - logger = RealTimeDataLogger::make(logFilename, args.duration, args.timeStep); + logger = + RealTimeDataLogger::make(logFilename, args.duration, args.timeStep); } auto topo = hilTopology(args, intf, logger); diff --git a/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp b/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp index 4e03d89b72..cc1c36d554 100644 --- a/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp +++ b/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp @@ -29,8 +29,9 @@ using namespace DPsim; using namespace CPS::EMT; const std::string buildFpgaConfig(CommandLineArgs &args) { - std::filesystem::path fpgaIpPath = "/usr/local/etc/villas/node/etc/fpga/vc707-xbar-pcie/" - "vc707-xbar-pcie.json"; + std::filesystem::path fpgaIpPath = + "/usr/local/etc/villas/node/etc/fpga/vc707-xbar-pcie/" + "vc707-xbar-pcie.json"; ; if (args.options.find("ips") != args.options.end()) { @@ -132,11 +133,14 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - DPsim::Logger::get("FpgaCosim3PhInfiniteBus")->debug("Config for Node:\n{}", config); + DPsim::Logger::get("FpgaCosim3PhInfiniteBus") + ->debug("Config for Node:\n{}", config); return config; } -SystemTopology buildTopology(CommandLineArgs &args, std::shared_ptr intfFpga, std::shared_ptr logger) { +SystemTopology buildTopology(CommandLineArgs &args, + std::shared_ptr intfFpga, + std::shared_ptr logger) { // Nodes auto bus1 = SimNode::make("bus1", PhaseType::ABC); auto bus2 = SimNode::make("bus2", PhaseType::ABC); @@ -144,13 +148,16 @@ SystemTopology buildTopology(CommandLineArgs &args, std::shared_ptr i // Components auto vs = Ph3::VoltageSource::make("vs"); - vs->setParameters(CPS::Math::singlePhaseVariableToThreePhase(CPS::Math::polar(230e3, 0)), 50); + vs->setParameters( + CPS::Math::singlePhaseVariableToThreePhase(CPS::Math::polar(230e3, 0)), + 50); auto r = Ph3::Resistor::make("R"); r->setParameters(Matrix{{10.4275, 0, 0}, {0, 10.4275, 0}, {0, 0, 10.4275}}); auto l = Ph3::Inductor::make("L"); - l->setParameters(Matrix{{0.325101, 0, 0}, {0, 0.325101, 0}, {0, 0, 0.325101}}); + l->setParameters( + Matrix{{0.325101, 0, 0}, {0, 0.325101, 0}, {0, 0, 0.325101}}); auto r2 = Ph3::Resistor::make("R2"); r2->setParameters(Matrix{{5.29e6, 0, 0}, {0, 5.29e6, 0}, {0, 0, 5.29e6}}); @@ -168,10 +175,20 @@ SystemTopology buildTopology(CommandLineArgs &args, std::shared_ptr i auto seqFromRTDSAttribute = CPS::AttributeStatic::make(0); auto seqFromDPsimAttribute = CPS::AttributeStatic::make(0); auto seqToDPsimAttribute = CPS::AttributeDynamic::make(0); - auto updateFn = std::make_shared::Actor>([](std::shared_ptr &dependent, typename CPS::Attribute::Ptr dependency) { *dependent = *dependent + 1; }); - seqToDPsimAttribute->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, CPS::AttributeUpdateTask::make(CPS::UpdateTaskKind::UPDATE_ON_GET, *updateFn, seqFromDPsimAttribute)); + auto updateFn = std::make_shared::Actor>( + [](std::shared_ptr &dependent, + typename CPS::Attribute::Ptr dependency) { + *dependent = *dependent + 1; + }); + seqToDPsimAttribute->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, + CPS::AttributeUpdateTask::make( + CPS::UpdateTaskKind::UPDATE_ON_GET, + *updateFn, seqFromDPsimAttribute)); auto seqNumForRTDS = CPS::AttributeDynamic::make(0); - seqNumForRTDS->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, CPS::AttributeUpdateTask::make(CPS::UpdateTaskKind::UPDATE_ON_GET, *updateFn, seqFromDPsimAttribute)); + seqNumForRTDS->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, + CPS::AttributeUpdateTask::make( + CPS::UpdateTaskKind::UPDATE_ON_GET, *updateFn, + seqFromDPsimAttribute)); intfFpga->addImport(seqFromRTDSAttribute, true, true); intfFpga->addImport(seqFromDPsimAttribute, true, true); @@ -196,20 +213,29 @@ SystemTopology buildTopology(CommandLineArgs &args, std::shared_ptr i logger->logAttribute("c_i", cs->mIntfCurrent->deriveCoeff(2, 0)); } - return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, bus1, bus2, bus3}, SystemComponentList{vs, cs, r, l, r2}); + return SystemTopology(args.sysFreq, + SystemNodeList{SimNode::GND, bus1, bus2, bus3}, + SystemComponentList{vs, cs, r, l, r2}); } int main(int argc, char *argv[]) { - CommandLineArgs args(argc, argv, "FpgaCosim3PhInfiniteBus", 0.01, 10 * 60, 50., -1, CPS::Logger::Level::info, CPS::Logger::Level::off, false, false, false, CPS::Domain::EMT); + CommandLineArgs args(argc, argv, "FpgaCosim3PhInfiniteBus", 0.01, 10 * 60, + 50., -1, CPS::Logger::Level::info, + CPS::Logger::Level::off, false, false, false, + CPS::Domain::EMT); CPS::Logger::setLogDir("logs/" + args.name); - bool log = args.options.find("log") != args.options.end() && args.getOptionBool("log"); + bool log = args.options.find("log") != args.options.end() && + args.getOptionBool("log"); - auto intfFpga = std::make_shared(buildFpgaConfig(args), "FpgaInterface", spdlog::level::off); + auto intfFpga = std::make_shared( + buildFpgaConfig(args), "FpgaInterface", spdlog::level::off); - std::filesystem::path logFilename = "logs/" + args.name + "/FpgaCosim3PhInfiniteBus.csv"; + std::filesystem::path logFilename = + "logs/" + args.name + "/FpgaCosim3PhInfiniteBus.csv"; std::shared_ptr logger = nullptr; if (log) { - logger = RealTimeDataLogger::make(logFilename, args.duration, args.timeStep); + logger = + RealTimeDataLogger::make(logFilename, args.duration, args.timeStep); } auto sys = buildTopology(args, intfFpga, logger); diff --git a/dpsim-villas/examples/cxx/FpgaCosimulation.cpp b/dpsim-villas/examples/cxx/FpgaCosimulation.cpp index 077fab07b4..79bea5b4d2 100644 --- a/dpsim-villas/examples/cxx/FpgaCosimulation.cpp +++ b/dpsim-villas/examples/cxx/FpgaCosimulation.cpp @@ -25,8 +25,9 @@ using namespace DPsim; using namespace CPS::EMT; const std::string buildFpgaConfig(CommandLineArgs &args) { - std::filesystem::path fpgaIpPath = "/usr/local/etc/villas/node/etc/fpga/vc707-xbar-pcie-dino/" - "vc707-xbar-pcie-dino-v2.json"; + std::filesystem::path fpgaIpPath = + "/usr/local/etc/villas/node/etc/fpga/vc707-xbar-pcie-dino/" + "vc707-xbar-pcie-dino-v2.json"; ; if (args.options.find("ips") != args.options.end()) { @@ -132,7 +133,9 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { return config; } -SystemTopology buildTopology(CommandLineArgs &args, std::shared_ptr intfFpga, std::shared_ptr logger) { +SystemTopology buildTopology(CommandLineArgs &args, + std::shared_ptr intfFpga, + std::shared_ptr logger) { // Nodes auto bus = SimNode::make("bus", PhaseType::ABC); @@ -155,10 +158,20 @@ SystemTopology buildTopology(CommandLineArgs &args, std::shared_ptr i auto seqFromRTDSAttribute = CPS::AttributeStatic::make(0); auto seqFromDPsimAttribute = CPS::AttributeStatic::make(0); auto seqToDPsimAttribute = CPS::AttributeDynamic::make(0); - auto updateFn = std::make_shared::Actor>([](std::shared_ptr &dependent, typename CPS::Attribute::Ptr dependency) { *dependent = *dependent + 1; }); - seqToDPsimAttribute->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, CPS::AttributeUpdateTask::make(CPS::UpdateTaskKind::UPDATE_ON_GET, *updateFn, seqFromDPsimAttribute)); + auto updateFn = std::make_shared::Actor>( + [](std::shared_ptr &dependent, + typename CPS::Attribute::Ptr dependency) { + *dependent = *dependent + 1; + }); + seqToDPsimAttribute->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, + CPS::AttributeUpdateTask::make( + CPS::UpdateTaskKind::UPDATE_ON_GET, + *updateFn, seqFromDPsimAttribute)); auto seqNumForRTDS = CPS::AttributeDynamic::make(0); - seqNumForRTDS->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, CPS::AttributeUpdateTask::make(CPS::UpdateTaskKind::UPDATE_ON_GET, *updateFn, seqFromDPsimAttribute)); + seqNumForRTDS->addTask(CPS::UpdateTaskKind::UPDATE_ON_GET, + CPS::AttributeUpdateTask::make( + CPS::UpdateTaskKind::UPDATE_ON_GET, *updateFn, + seqFromDPsimAttribute)); intfFpga->addImport(seqFromRTDSAttribute, true, true); intfFpga->addImport(seqFromDPsimAttribute, true, true); @@ -183,20 +196,27 @@ SystemTopology buildTopology(CommandLineArgs &args, std::shared_ptr i logger->logAttribute("c_i", load->mIntfCurrent->deriveCoeff(2, 0)); } - return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, bus}, SystemComponentList{vs, load}); + return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, bus}, + SystemComponentList{vs, load}); } int main(int argc, char *argv[]) { - CommandLineArgs args(argc, argv, "FpgaCosimulation", 0.01, 10 * 60, 60., -1, CPS::Logger::Level::info, CPS::Logger::Level::off, false, false, false, CPS::Domain::EMT); + CommandLineArgs args(argc, argv, "FpgaCosimulation", 0.01, 10 * 60, 60., -1, + CPS::Logger::Level::info, CPS::Logger::Level::off, false, + false, false, CPS::Domain::EMT); CPS::Logger::setLogDir("logs/" + args.name); - bool log = args.options.find("log") != args.options.end() && args.getOptionBool("log"); + bool log = args.options.find("log") != args.options.end() && + args.getOptionBool("log"); - auto intfFpga = std::make_shared(buildFpgaConfig(args), "FpgaInterface", spdlog::level::off); + auto intfFpga = std::make_shared( + buildFpgaConfig(args), "FpgaInterface", spdlog::level::off); - std::filesystem::path logFilename = "logs/" + args.name + "/FpgaCosimulation.csv"; + std::filesystem::path logFilename = + "logs/" + args.name + "/FpgaCosimulation.csv"; std::shared_ptr logger = nullptr; if (log) { - logger = RealTimeDataLogger::make(logFilename, args.duration, args.timeStep); + logger = + RealTimeDataLogger::make(logFilename, args.duration, args.timeStep); } auto sys = buildTopology(args, intfFpga, logger); diff --git a/dpsim-villas/examples/cxx/FpgaExample.cpp b/dpsim-villas/examples/cxx/FpgaExample.cpp index 24d90ba042..9abbf1b621 100644 --- a/dpsim-villas/examples/cxx/FpgaExample.cpp +++ b/dpsim-villas/examples/cxx/FpgaExample.cpp @@ -26,8 +26,9 @@ using namespace CPS::DP; using namespace CPS::DP::Ph1; const std::string buildFpgaConfig(CommandLineArgs &args) { - std::filesystem::path fpgaIpPath = "/usr/local/etc/villas/node/etc/fpga/vc707-xbar-pcie-dino/" - "vc707-xbar-pcie-dino.json"; + std::filesystem::path fpgaIpPath = + "/usr/local/etc/villas/node/etc/fpga/vc707-xbar-pcie-dino/" + "vc707-xbar-pcie-dino.json"; if (args.options.find("ips") != args.options.end()) { fpgaIpPath = std::filesystem::path(args.getOptionString("ips")); @@ -95,7 +96,9 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { return config; } -SystemTopology loopbackTopology(CommandLineArgs &args, std::shared_ptr intf, std::shared_ptr logger) { +SystemTopology loopbackTopology(CommandLineArgs &args, + std::shared_ptr intf, + std::shared_ptr logger) { // Nodes auto n1 = SimNode::make("n1"); @@ -125,7 +128,9 @@ SystemTopology loopbackTopology(CommandLineArgs &args, std::shared_ptr intf, std::shared_ptr logger) { +SystemTopology hilTopology(CommandLineArgs &args, + std::shared_ptr intf, + std::shared_ptr logger) { // Nodes auto n1 = SimNode::make("n1"); auto n2 = SimNode::make("n2"); @@ -157,10 +162,13 @@ SystemTopology hilTopology(CommandLineArgs &args, std::shared_ptr int logger->logAttribute("cs_i", cs->mIntfCurrent); } - return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, n1, n2}, SystemComponentList{vs, rs, cs}); + return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, n1, n2}, + SystemComponentList{vs, rs, cs}); } -SystemTopology profileTopology(CommandLineArgs &args, std::shared_ptr intf, std::shared_ptr logger) { +SystemTopology profileTopology(CommandLineArgs &args, + std::shared_ptr intf, + std::shared_ptr logger) { // Nodes auto n1 = SimNode::make("n1"); auto n2 = SimNode::make("n2"); @@ -191,10 +199,13 @@ SystemTopology profileTopology(CommandLineArgs &args, std::shared_ptr logger->logAttribute("cs_i", cs->mIntfCurrent); } - return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, n1, n2}, SystemComponentList{vs, rs, cs}); + return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, n1, n2}, + SystemComponentList{vs, rs, cs}); } -SystemTopology getTopology(CommandLineArgs &args, std::shared_ptr intf, std::shared_ptr logger) { +SystemTopology getTopology(CommandLineArgs &args, + std::shared_ptr intf, + std::shared_ptr logger) { if (args.options.find("topology") != args.options.end()) { std::string topology = args.getOptionString("topology"); if (topology == "hil") { @@ -217,14 +228,16 @@ std::shared_ptr getEvent(CommandLineArgs &args, SystemTopology &sys) { std::string event = args.getOptionString("event"); if (event == "frequencyDrop") { if (topology != "hil") { - throw std::runtime_error("frequencyDrop event only supported for topology \"hil\"."); + throw std::runtime_error( + "frequencyDrop event only supported for topology \"hil\"."); } auto vs = std::dynamic_pointer_cast(sys.mComponents[0]); return AttributeEvent::make(3, vs->mSrcFreq, 45.); } if (event == "voltageDrop") { if (topology != "hil") { - throw std::runtime_error("voltageDrop event only supported for topology \"hil\"."); + throw std::runtime_error( + "voltageDrop event only supported for topology \"hil\"."); } auto vs = std::dynamic_pointer_cast(sys.mComponents[0]); return AttributeEvent::make(3, vs->mVoltageRef->deriveReal(), 0.7); @@ -236,14 +249,16 @@ std::shared_ptr getEvent(CommandLineArgs &args, SystemTopology &sys) { int main(int argc, char *argv[]) { CommandLineArgs args(argc, argv, "FpgaExample", 0.01, 10 * 60, 5.); CPS::Logger::setLogDir("logs/" + args.name); - bool log = args.options.find("log") != args.options.end() && args.getOptionBool("log"); + bool log = args.options.find("log") != args.options.end() && + args.getOptionBool("log"); auto intf = std::make_shared( buildFpgaConfig(args), "FpgaExample", spdlog::level::off); std::filesystem::path logFilename = "logs/" + args.name + "/FpgaExample.csv"; std::shared_ptr logger = nullptr; if (log) { - logger = RealTimeDataLogger::make(logFilename, args.duration, args.timeStep); + logger = + RealTimeDataLogger::make(logFilename, args.duration, args.timeStep); } auto sys = getTopology(args, intf, logger); diff --git a/dpsim/examples/cxx/CIM/DP_WSCC_9bus_split_decoupled.cpp b/dpsim/examples/cxx/CIM/DP_WSCC_9bus_split_decoupled.cpp index 60c4a5702f..9fc0101a64 100644 --- a/dpsim/examples/cxx/CIM/DP_WSCC_9bus_split_decoupled.cpp +++ b/dpsim/examples/cxx/CIM/DP_WSCC_9bus_split_decoupled.cpp @@ -16,7 +16,8 @@ using namespace DPsim; using namespace CPS; -String decoupleLine(SystemTopology &sys, const String &lineName, const String &node1, const String node2) { +String decoupleLine(SystemTopology &sys, const String &lineName, + const String &node1, const String node2) { auto origLine = sys.component(lineName); Real Rline = origLine->attributeTyped("R_series")->get(); Real Lline = origLine->attributeTyped("L_series")->get(); @@ -27,9 +28,8 @@ String decoupleLine(SystemTopology &sys, const String &lineName, const String &n String dline_name = "dline_" + node1 + "_" + node2; auto line = Signal::DecouplingLine::make( - "dline_" + node1 + "_" + node2, sys.node(node1), - sys.node(node2), Rline, Lline, Cline, Logger::Level::debug - ); + "dline_" + node1 + "_" + node2, sys.node(node1), + sys.node(node2), Rline, Lline, Cline, Logger::Level::debug); sys.addComponent(line); sys.addComponents(line->getLineComponents()); @@ -43,10 +43,11 @@ void doSim(String &name, SystemTopology &sys, Int threads) { // logger->logAttribute("BUS5.v", sys.node("BUS5")->attribute("v")); // logger->logAttribute("BUS6.v", sys.node("BUS6")->attribute("v")); // logger->logAttribute("BUS8.v", sys.node("BUS8")->attribute("v")); - for (Int bus = 1; bus <= 9; bus++) { + for (Int bus = 1; bus <= 9; bus++) { String attrName = "v" + std::to_string(bus); String nodeName = "BUS" + std::to_string(bus); - logger->logAttribute(attrName, sys.node(nodeName)->attribute("v")); + logger->logAttribute(attrName, + sys.node(nodeName)->attribute("v")); } Simulation sim(name, Logger::Level::debug); @@ -72,8 +73,7 @@ int main(int argc, char *argv[]) { std::list filenames; filenames = DPsim::Utils::findFiles( - {"WSCC-09_DI.xml", "WSCC-09_EQ.xml", "WSCC-09_SV.xml", - "WSCC-09_TP.xml"}, + {"WSCC-09_DI.xml", "WSCC-09_EQ.xml", "WSCC-09_SV.xml", "WSCC-09_TP.xml"}, "build/_deps/cim-data-src/WSCC-09/WSCC-09", "CIMPATH"); Int numThreads = 0; @@ -84,25 +84,30 @@ int main(int argc, char *argv[]) { if (args.options.find("seq") != args.options.end()) numSeq = args.getOptionInt("seq"); - std::cout << "Simulate with " << numThreads - << " threads, sequence number " << numSeq << std::endl; + std::cout << "Simulate with " << numThreads << " threads, sequence number " + << numSeq << std::endl; // Monolithic Simulation String simNameMonolithic = "WSCC-9bus_monolithic_DP"; Logger::setLogDir("logs/" + simNameMonolithic); - CIM::Reader readerMonolithic(simNameMonolithic, Logger::Level::debug, Logger::Level::debug); + CIM::Reader readerMonolithic(simNameMonolithic, Logger::Level::debug, + Logger::Level::debug); SystemTopology systemMonolithic = readerMonolithic.loadCIM(60, filenames, Domain::DP, PhaseType::Single, - CPS::GeneratorType::IdealVoltageSource); + CPS::GeneratorType::IdealVoltageSource); doSim(simNameMonolithic, systemMonolithic, 0); // Decoupled Simulation - String simNameDecoupled = "WSCC_9bus_split_decoupled_DP_" + std::to_string(numThreads) + "_" + std::to_string(numSeq); + String simNameDecoupled = "WSCC_9bus_split_decoupled_DP_" + + std::to_string(numThreads) + "_" + + std::to_string(numSeq); Logger::setLogDir("logs/" + simNameDecoupled); - CIM::Reader readerDecoupled(simNameDecoupled, Logger::Level::debug, Logger::Level::debug); - SystemTopology systemDecoupled = readerDecoupled.loadCIM(60, filenames, Domain::DP, PhaseType::Single, - CPS::GeneratorType::IdealVoltageSource); + CIM::Reader readerDecoupled(simNameDecoupled, Logger::Level::debug, + Logger::Level::debug); + SystemTopology systemDecoupled = + readerDecoupled.loadCIM(60, filenames, Domain::DP, PhaseType::Single, + CPS::GeneratorType::IdealVoltageSource); String dline_75 = decoupleLine(systemDecoupled, "LINE75", "BUS5", "BUS7"); // decouple_line(system, "LINE78", "BUS7", "BUS8"); diff --git a/dpsim/examples/cxx/CIM/EMT_WSCC-9bus_FullOrderSG.cpp b/dpsim/examples/cxx/CIM/EMT_WSCC-9bus_FullOrderSG.cpp index d7a3fd0ae1..b4522e8605 100644 --- a/dpsim/examples/cxx/CIM/EMT_WSCC-9bus_FullOrderSG.cpp +++ b/dpsim/examples/cxx/CIM/EMT_WSCC-9bus_FullOrderSG.cpp @@ -25,8 +25,10 @@ int main(int argc, char *argv[]) { std::list filenames; CommandLineArgs args(argc, argv); if (argc <= 1) { - filenames = - Utils::findFiles({"WSCC-09_Dyn_Full_DI.xml", "WSCC-09_Dyn_Full_EQ.xml", "WSCC-09_Dyn_Full_SV.xml", "WSCC-09_Dyn_Full_TP.xml"}, "build/_deps/cim-data-src/WSCC-09/WSCC-09_Dyn_Full", "CIMPATH"); + filenames = Utils::findFiles( + {"WSCC-09_Dyn_Full_DI.xml", "WSCC-09_Dyn_Full_EQ.xml", + "WSCC-09_Dyn_Full_SV.xml", "WSCC-09_Dyn_Full_TP.xml"}, + "build/_deps/cim-data-src/WSCC-09/WSCC-09_Dyn_Full", "CIMPATH"); timeStep = 10e-6; finalTime = 0.1; } else { diff --git a/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp b/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp index 2b39f66ce2..6d8cbcbe55 100644 --- a/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp +++ b/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp @@ -16,7 +16,8 @@ using namespace DPsim; using namespace CPS; -String decoupleLine(SystemTopology &sys, const String &lineName, const String &node1, const String node2) { +String decoupleLine(SystemTopology &sys, const String &lineName, + const String &node1, const String node2) { auto origLine = sys.component(lineName); Matrix Rline = origLine->attributeTyped("R_series")->get(); Matrix Lline = origLine->attributeTyped("L_series")->get(); @@ -26,18 +27,16 @@ String decoupleLine(SystemTopology &sys, const String &lineName, const String &n String dline_name = "dline_" + node1 + "_" + node2; - auto line = Signal::DecouplingLineEMT::make( - "dline_" + node1 + "_" + node2, - Logger::Level::debug - ); + auto line = Signal::DecouplingLineEMT::make("dline_" + node1 + "_" + node2, + Logger::Level::debug); - Real Rline_scalar = Rline(0,0); - Real Lline_scalar = Lline(0,0); - Real Cline_scalar = Cline(0,0); + Real Rline_scalar = Rline(0, 0); + Real Lline_scalar = Lline(0, 0); + Real Cline_scalar = Cline(0, 0); - line->setParameters( - sys.node(node1), sys.node(node2), - Rline_scalar, Lline_scalar, Cline_scalar); + line->setParameters(sys.node(node1), + sys.node(node2), Rline_scalar, Lline_scalar, + Cline_scalar); sys.addComponent(line); sys.addComponents(line->getLineComponents()); @@ -51,10 +50,11 @@ void doSim(String &name, SystemTopology &sys, Int threads) { // logger->logAttribute("BUS5.v", sys.node("BUS5")->attribute("v")); // logger->logAttribute("BUS6.v", sys.node("BUS6")->attribute("v")); // logger->logAttribute("BUS8.v", sys.node("BUS8")->attribute("v")); - for (Int bus = 1; bus <= 9; bus++) { + for (Int bus = 1; bus <= 9; bus++) { String attrName = "v" + std::to_string(bus); String nodeName = "BUS" + std::to_string(bus); - logger->logAttribute(attrName, sys.node(nodeName)->attribute("v")); + logger->logAttribute(attrName, + sys.node(nodeName)->attribute("v")); } Simulation sim(name, Logger::Level::debug); @@ -80,8 +80,7 @@ int main(int argc, char *argv[]) { std::list filenames; filenames = DPsim::Utils::findFiles( - {"WSCC-09_DI.xml", "WSCC-09_EQ.xml", "WSCC-09_SV.xml", - "WSCC-09_TP.xml"}, + {"WSCC-09_DI.xml", "WSCC-09_EQ.xml", "WSCC-09_SV.xml", "WSCC-09_TP.xml"}, "build/_deps/cim-data-src/WSCC-09/WSCC-09", "CIMPATH"); Int numThreads = 0; @@ -92,25 +91,30 @@ int main(int argc, char *argv[]) { if (args.options.find("seq") != args.options.end()) numSeq = args.getOptionInt("seq"); - std::cout << "Simulate with " << numThreads - << " threads, sequence number " << numSeq << std::endl; + std::cout << "Simulate with " << numThreads << " threads, sequence number " + << numSeq << std::endl; // Monolithic Simulation String simNameMonolithic = "WSCC-9bus_monolithic_EMT"; Logger::setLogDir("logs/" + simNameMonolithic); - CIM::Reader readerMonolithic(simNameMonolithic, Logger::Level::debug, Logger::Level::debug); + CIM::Reader readerMonolithic(simNameMonolithic, Logger::Level::debug, + Logger::Level::debug); SystemTopology systemMonolithic = readerMonolithic.loadCIM(60, filenames, Domain::EMT, PhaseType::ABC, - CPS::GeneratorType::IdealVoltageSource); + CPS::GeneratorType::IdealVoltageSource); doSim(simNameMonolithic, systemMonolithic, 0); // Decoupled Simulation - String simNameDecoupled = "WSCC_9bus_split_decoupled_EMT_" + std::to_string(numThreads) + "_" + std::to_string(numSeq); + String simNameDecoupled = "WSCC_9bus_split_decoupled_EMT_" + + std::to_string(numThreads) + "_" + + std::to_string(numSeq); Logger::setLogDir("logs/" + simNameDecoupled); - CIM::Reader readerDecoupled(simNameDecoupled, Logger::Level::debug, Logger::Level::debug); - SystemTopology systemDecoupled = readerDecoupled.loadCIM(60, filenames, Domain::EMT, PhaseType::ABC, - CPS::GeneratorType::IdealVoltageSource); + CIM::Reader readerDecoupled(simNameDecoupled, Logger::Level::debug, + Logger::Level::debug); + SystemTopology systemDecoupled = + readerDecoupled.loadCIM(60, filenames, Domain::EMT, PhaseType::ABC, + CPS::GeneratorType::IdealVoltageSource); String dline_75 = decoupleLine(systemDecoupled, "LINE75", "BUS5", "BUS7"); // decouple_line(system, "LINE78", "BUS7", "BUS8"); diff --git a/dpsim/examples/cxx/CIM/WSCC_9bus_mult_coupled.cpp b/dpsim/examples/cxx/CIM/WSCC_9bus_mult_coupled.cpp index fc42ddca98..d3d31597dc 100644 --- a/dpsim/examples/cxx/CIM/WSCC_9bus_mult_coupled.cpp +++ b/dpsim/examples/cxx/CIM/WSCC_9bus_mult_coupled.cpp @@ -89,15 +89,16 @@ void simulateCoupled(std::list filenames, CommandLineArgs &args, // Logging auto logger = DataLogger::make(simName); for (Int cop = 1; cop <= copies; cop++) { - for (Int bus = 1; bus <= 9; bus++) { - String attrName = "v" + std::to_string(bus) + "_" + std::to_string(cop); - String nodeName = "BUS" + std::to_string(bus) + "_" + std::to_string(cop); - if (cop == 1) { - attrName = "v" + std::to_string(bus); - nodeName = "BUS" + std::to_string(bus); - } - logger->logAttribute(attrName, sys.node(nodeName)->attribute("v")); - } + for (Int bus = 1; bus <= 9; bus++) { + String attrName = "v" + std::to_string(bus) + "_" + std::to_string(cop); + String nodeName = "BUS" + std::to_string(bus) + "_" + std::to_string(cop); + if (cop == 1) { + attrName = "v" + std::to_string(bus); + nodeName = "BUS" + std::to_string(bus); + } + logger->logAttribute(attrName, + sys.node(nodeName)->attribute("v")); + } } sim.addLogger(logger); diff --git a/dpsim/examples/cxx/CIM/WSCC_9bus_mult_decoupled.cpp b/dpsim/examples/cxx/CIM/WSCC_9bus_mult_decoupled.cpp index 427981cc5b..2f61d77855 100644 --- a/dpsim/examples/cxx/CIM/WSCC_9bus_mult_decoupled.cpp +++ b/dpsim/examples/cxx/CIM/WSCC_9bus_mult_decoupled.cpp @@ -69,15 +69,16 @@ void simulateDecoupled(std::list filenames, Int copies, Int threads, // Logging auto logger = DataLogger::make(simName); for (Int cop = 1; cop <= copies; cop++) { - for (Int bus = 1; bus <= 9; bus++) { - String attrName = "v" + std::to_string(bus) + "_" + std::to_string(cop); - String nodeName = "BUS" + std::to_string(bus) + "_" + std::to_string(cop); - if (cop == 1) { - attrName = "v" + std::to_string(bus); - nodeName = "BUS" + std::to_string(bus); - } - logger->logAttribute(attrName, sys.node(nodeName)->attribute("v")); - } + for (Int bus = 1; bus <= 9; bus++) { + String attrName = "v" + std::to_string(bus) + "_" + std::to_string(cop); + String nodeName = "BUS" + std::to_string(bus) + "_" + std::to_string(cop); + if (cop == 1) { + attrName = "v" + std::to_string(bus); + nodeName = "BUS" + std::to_string(bus); + } + logger->logAttribute(attrName, + sys.node(nodeName)->attribute("v")); + } } sim.addLogger(logger); diff --git a/dpsim/examples/cxx/CIM/WSCC_9bus_mult_diakoptics.cpp b/dpsim/examples/cxx/CIM/WSCC_9bus_mult_diakoptics.cpp index d89a1fe95f..01e86196a5 100644 --- a/dpsim/examples/cxx/CIM/WSCC_9bus_mult_diakoptics.cpp +++ b/dpsim/examples/cxx/CIM/WSCC_9bus_mult_diakoptics.cpp @@ -90,15 +90,16 @@ void simulateDiakoptics(std::list filenames, Int copies, Int threads, // Logging auto logger = DataLogger::make(simName); for (Int cop = 1; cop <= copies; cop++) { - for (Int bus = 1; bus <= 9; bus++) { - String attrName = "v" + std::to_string(bus) + "_" + std::to_string(cop); - String nodeName = "BUS" + std::to_string(bus) + "_" + std::to_string(cop); - if (cop == 1) { - attrName = "v" + std::to_string(bus); - nodeName = "BUS" + std::to_string(bus); - } - logger->logAttribute(attrName, sys.node(nodeName)->attribute("v")); - } + for (Int bus = 1; bus <= 9; bus++) { + String attrName = "v" + std::to_string(bus) + "_" + std::to_string(cop); + String nodeName = "BUS" + std::to_string(bus) + "_" + std::to_string(cop); + if (cop == 1) { + attrName = "v" + std::to_string(bus); + nodeName = "BUS" + std::to_string(bus); + } + logger->logAttribute(attrName, + sys.node(nodeName)->attribute("v")); + } } sim.addLogger(logger); diff --git a/dpsim/include/dpsim/DataLogger.h b/dpsim/include/dpsim/DataLogger.h index 1654585558..7f478b7524 100644 --- a/dpsim/include/dpsim/DataLogger.h +++ b/dpsim/include/dpsim/DataLogger.h @@ -23,7 +23,8 @@ namespace DPsim { -class DataLogger : public DataLoggerInterface, public SharedFactory { +class DataLogger : public DataLoggerInterface, + public SharedFactory { protected: std::ofstream mLogFile; diff --git a/dpsim/include/dpsim/DataLoggerInterface.h b/dpsim/include/dpsim/DataLoggerInterface.h index 157cf53241..393f77a53a 100644 --- a/dpsim/include/dpsim/DataLoggerInterface.h +++ b/dpsim/include/dpsim/DataLoggerInterface.h @@ -33,15 +33,22 @@ class DataLoggerInterface { // Stops the logger. Afterwards it should not be used anymore. virtual void stop() = 0; - virtual void logAttribute(const String &name, CPS::AttributeBase::Ptr attr, UInt rowsMax = 0, UInt colsMax = 0) { - if (auto attrReal = std::dynamic_pointer_cast>(attr.getPtr())) { + virtual void logAttribute(const String &name, CPS::AttributeBase::Ptr attr, + UInt rowsMax = 0, UInt colsMax = 0) { + if (auto attrReal = + std::dynamic_pointer_cast>(attr.getPtr())) { mAttributes[name] = attrReal; - } else if (auto attrComp = std::dynamic_pointer_cast>(attr.getPtr())) { + } else if (auto attrComp = + std::dynamic_pointer_cast>( + attr.getPtr())) { mAttributes[name + ".re"] = attrComp->deriveReal(); mAttributes[name + ".im"] = attrComp->deriveImag(); - } else if (auto attrInt = std::dynamic_pointer_cast>(attr.getPtr())) { + } else if (auto attrInt = std::dynamic_pointer_cast>( + attr.getPtr())) { mAttributes[name] = attrInt; - } else if (auto attrMatrix = std::dynamic_pointer_cast>(attr.getPtr())) { + } else if (auto attrMatrix = + std::dynamic_pointer_cast>( + attr.getPtr())) { UInt rows = static_cast((**attrMatrix).rows()); UInt cols = static_cast((**attrMatrix).cols()); if (rowsMax == 0 || rowsMax > rows) @@ -52,16 +59,21 @@ class DataLoggerInterface { mAttributes[name] = attrMatrix->deriveCoeff(0, 0); } else if (cols == 1) { for (UInt k = 0; k < rowsMax; ++k) { - mAttributes[name + "_" + std::to_string(k)] = attrMatrix->deriveCoeff(k, 0); + mAttributes[name + "_" + std::to_string(k)] = + attrMatrix->deriveCoeff(k, 0); } } else { for (UInt k = 0; k < rowsMax; ++k) { for (UInt l = 0; l < colsMax; ++l) { - mAttributes[name + "_" + std::to_string(k) + "_" + std::to_string(l)] = attrMatrix->deriveCoeff(k, l); + mAttributes[name + "_" + std::to_string(k) + "_" + + std::to_string(l)] = + attrMatrix->deriveCoeff(k, l); } } } - } else if (auto attrMatrix = std::dynamic_pointer_cast>(attr.getPtr())) { + } else if (auto attrMatrix = + std::dynamic_pointer_cast>( + attr.getPtr())) { UInt rows = static_cast((**attrMatrix).rows()); UInt cols = static_cast((**attrMatrix).cols()); if (rowsMax == 0 || rowsMax > rows) @@ -69,30 +81,41 @@ class DataLoggerInterface { if (colsMax == 0 || colsMax > cols) colsMax = cols; if (rows == 1 && cols == 1) { - mAttributes[name + ".re"] = attrMatrix->deriveCoeff(0, 0)->deriveReal(); - mAttributes[name + ".im"] = attrMatrix->deriveCoeff(0, 0)->deriveImag(); + mAttributes[name + ".re"] = + attrMatrix->deriveCoeff(0, 0)->deriveReal(); + mAttributes[name + ".im"] = + attrMatrix->deriveCoeff(0, 0)->deriveImag(); } else if (cols == 1) { for (UInt k = 0; k < rowsMax; ++k) { - mAttributes[name + "_" + std::to_string(k) + ".re"] = attrMatrix->deriveCoeff(k, 0)->deriveReal(); - mAttributes[name + "_" + std::to_string(k) + ".im"] = attrMatrix->deriveCoeff(k, 0)->deriveImag(); + mAttributes[name + "_" + std::to_string(k) + ".re"] = + attrMatrix->deriveCoeff(k, 0)->deriveReal(); + mAttributes[name + "_" + std::to_string(k) + ".im"] = + attrMatrix->deriveCoeff(k, 0)->deriveImag(); } } else { for (UInt k = 0; k < rowsMax; ++k) { for (UInt l = 0; l < colsMax; ++l) { - mAttributes[name + "_" + std::to_string(k) + "_" + std::to_string(l) + ".re"] = attrMatrix->deriveCoeff(k, l)->deriveReal(); - mAttributes[name + "_" + std::to_string(k) + "_" + std::to_string(l) + ".im"] = attrMatrix->deriveCoeff(k, l)->deriveImag(); + mAttributes[name + "_" + std::to_string(k) + "_" + + std::to_string(l) + ".re"] = + attrMatrix->deriveCoeff(k, l)->deriveReal(); + mAttributes[name + "_" + std::to_string(k) + "_" + + std::to_string(l) + ".im"] = + attrMatrix->deriveCoeff(k, l)->deriveImag(); } } } } else { - throw std::runtime_error("DataLoggerInterface: Unknown attribute type for attribute " + name); + throw std::runtime_error( + "DataLoggerInterface: Unknown attribute type for attribute " + name); } } /// DEPRECATED: Only use for compatiblity, otherwise this just adds extra overhead to the logger. Instead just call logAttribute multiple times for every coefficient using /// `attr->deriveCoeff<>(a,b)`. - void logAttribute(const std::vector &name, CPS::AttributeBase::Ptr attr) { - if (auto attrMatrix = std::dynamic_pointer_cast>(attr.getPtr())) { + void logAttribute(const std::vector &name, + CPS::AttributeBase::Ptr attr) { + if (auto attrMatrix = + std::dynamic_pointer_cast>(attr.getPtr())) { if ((**attrMatrix).rows() == 1 && (**attrMatrix).cols() == 1) { logAttribute(name[0], attrMatrix->deriveCoeff(0, 0)); } else if ((**attrMatrix).cols() == 1) { @@ -102,11 +125,14 @@ class DataLoggerInterface { } else { for (UInt k = 0; k < (**attrMatrix).rows(); ++k) { for (UInt l = 0; l < (**attrMatrix).cols(); ++l) { - logAttribute(name[k * (**attrMatrix).cols() + l], attrMatrix->deriveCoeff(k, l)); + logAttribute(name[k * (**attrMatrix).cols() + l], + attrMatrix->deriveCoeff(k, l)); } } } - } else if (auto attrMatrix = std::dynamic_pointer_cast>(attr.getPtr())) { + } else if (auto attrMatrix = + std::dynamic_pointer_cast>( + attr.getPtr())) { if ((**attrMatrix).rows() == 1 && (**attrMatrix).cols() == 1) { logAttribute(name[0], attrMatrix->deriveCoeff(0, 0)); } else if ((**attrMatrix).cols() == 1) { @@ -116,7 +142,8 @@ class DataLoggerInterface { } else { for (UInt k = 0; k < (**attrMatrix).rows(); ++k) { for (UInt l = 0; l < (**attrMatrix).cols(); ++l) { - logAttribute(name[k * (**attrMatrix).cols() + l], attrMatrix->deriveCoeff(k, l)); + logAttribute(name[k * (**attrMatrix).cols() + l], + attrMatrix->deriveCoeff(k, l)); } } } diff --git a/dpsim/include/dpsim/InterfaceQueued.h b/dpsim/include/dpsim/InterfaceQueued.h index 6e206d3465..e03bd9eecd 100644 --- a/dpsim/include/dpsim/InterfaceQueued.h +++ b/dpsim/include/dpsim/InterfaceQueued.h @@ -21,15 +21,18 @@ namespace DPsim { class InterfaceWorker; -class InterfaceQueued : public Interface, public SharedFactory { +class InterfaceQueued : public Interface, + public SharedFactory { public: typedef std::shared_ptr Ptr; using AttributePacket = struct AttributePacket { CPS::AttributeBase::Ptr value; - UInt attributeId; // Used to identify the attribute. Defined by the position in the `mExportAttrsDpsim` and `mImportAttrsDpsim` lists - UInt sequenceId; // Increasing ID used to discern multiple consecutive updates of a single attribute + UInt + attributeId; // Used to identify the attribute. Defined by the position in the `mExportAttrsDpsim` and `mImportAttrsDpsim` lists + UInt + sequenceId; // Increasing ID used to discern multiple consecutive updates of a single attribute unsigned char flags; // Bit 0 set: Close interface }; @@ -38,9 +41,13 @@ class InterfaceQueued : public Interface, public SharedFactory PACKET_CLOSE_INTERFACE = 1, }; - InterfaceQueued(std::shared_ptr intf, const String &name = "", UInt downsampling = 1) : Interface(name), mInterfaceWorker(intf), mDownsampling(downsampling) { - mQueueDpsimToInterface = std::make_shared>(); - mQueueInterfaceToDpsim = std::make_shared>(); + InterfaceQueued(std::shared_ptr intf, + const String &name = "", UInt downsampling = 1) + : Interface(name), mInterfaceWorker(intf), mDownsampling(downsampling) { + mQueueDpsimToInterface = std::make_shared< + moodycamel::BlockingReaderWriterQueue>(); + mQueueInterfaceToDpsim = std::make_shared< + moodycamel::BlockingReaderWriterQueue>(); }; virtual void open() override; @@ -73,37 +80,51 @@ class InterfaceQueued : public Interface, public SharedFactory std::thread mInterfaceWriterThread; std::thread mInterfaceReaderThread; - std::shared_ptr> mQueueDpsimToInterface; - std::shared_ptr> mQueueInterfaceToDpsim; + std::shared_ptr> + mQueueDpsimToInterface; + std::shared_ptr> + mQueueInterfaceToDpsim; public: class WriterThread { private: - std::shared_ptr> mQueueDpsimToInterface; + std::shared_ptr> + mQueueDpsimToInterface; std::shared_ptr mInterfaceWorker; public: - WriterThread(std::shared_ptr> queueDpsimToInterface, std::shared_ptr intf) - : mQueueDpsimToInterface(queueDpsimToInterface), mInterfaceWorker(intf){}; + WriterThread( + std::shared_ptr> + queueDpsimToInterface, + std::shared_ptr intf) + : mQueueDpsimToInterface(queueDpsimToInterface), + mInterfaceWorker(intf){}; void operator()() const; }; class ReaderThread { private: - std::shared_ptr> mQueueInterfaceToDpsim; + std::shared_ptr> + mQueueInterfaceToDpsim; std::shared_ptr mInterfaceWorker; std::atomic &mOpened; public: - ReaderThread(std::shared_ptr> queueInterfaceToDpsim, std::shared_ptr intf, std::atomic &opened) - : mQueueInterfaceToDpsim(queueInterfaceToDpsim), mInterfaceWorker(intf), mOpened(opened){}; + ReaderThread( + std::shared_ptr> + queueInterfaceToDpsim, + std::shared_ptr intf, std::atomic &opened) + : mQueueInterfaceToDpsim(queueInterfaceToDpsim), mInterfaceWorker(intf), + mOpened(opened){}; void operator()() const; }; class PreStep : public CPS::Task { public: - explicit PreStep(InterfaceQueued &intf) : Task(intf.getName() + ".Read"), mIntf(intf) { - for (const auto &[attr, _seqId, _blockOnRead, _syncOnStart] : intf.mImportAttrsDpsim) { + explicit PreStep(InterfaceQueued &intf) + : Task(intf.getName() + ".Read"), mIntf(intf) { + for (const auto &[attr, _seqId, _blockOnRead, _syncOnStart] : + intf.mImportAttrsDpsim) { mModifiedAttributes.push_back(attr); } } @@ -116,7 +137,8 @@ class InterfaceQueued : public Interface, public SharedFactory class PostStep : public CPS::Task { public: - explicit PostStep(InterfaceQueued &intf) : Task(intf.getName() + ".Write"), mIntf(intf) { + explicit PostStep(InterfaceQueued &intf) + : Task(intf.getName() + ".Write"), mIntf(intf) { for (const auto &[attr, _seqId] : intf.mExportAttrsDpsim) { mAttributeDependencies.push_back(attr); } diff --git a/dpsim/include/dpsim/RealTimeDataLogger.h b/dpsim/include/dpsim/RealTimeDataLogger.h index ea2c8323dd..3b9bf77107 100644 --- a/dpsim/include/dpsim/RealTimeDataLogger.h +++ b/dpsim/include/dpsim/RealTimeDataLogger.h @@ -21,7 +21,8 @@ namespace DPsim { -class RealTimeDataLogger : public DataLoggerInterface, public SharedFactory { +class RealTimeDataLogger : public DataLoggerInterface, + public SharedFactory { protected: std::filesystem::path mFilename; @@ -34,7 +35,8 @@ class RealTimeDataLogger : public DataLoggerInterface, public SharedFactory Ptr; - RealTimeDataLogger(std::filesystem::path &filename, Real finalTime, Real timeStep); + RealTimeDataLogger(std::filesystem::path &filename, Real finalTime, + Real timeStep); RealTimeDataLogger(std::filesystem::path &filename, size_t rowNumber); virtual void start() override; @@ -46,7 +48,8 @@ class RealTimeDataLogger : public DataLoggerInterface, public SharedFactory(*this); diff --git a/dpsim/src/InterfaceQueued.cpp b/dpsim/src/InterfaceQueued.cpp index e94e84724e..a820c04082 100644 --- a/dpsim/src/InterfaceQueued.cpp +++ b/dpsim/src/InterfaceQueued.cpp @@ -15,16 +15,19 @@ void InterfaceQueued::open() { mOpened = true; if (!mImportAttrsDpsim.empty()) { - mInterfaceReaderThread = std::thread(InterfaceQueued::ReaderThread(mQueueInterfaceToDpsim, mInterfaceWorker, mOpened)); + mInterfaceReaderThread = std::thread(InterfaceQueued::ReaderThread( + mQueueInterfaceToDpsim, mInterfaceWorker, mOpened)); } if (!mExportAttrsDpsim.empty()) { - mInterfaceWriterThread = std::thread(InterfaceQueued::WriterThread(mQueueDpsimToInterface, mInterfaceWorker)); + mInterfaceWriterThread = std::thread(InterfaceQueued::WriterThread( + mQueueDpsimToInterface, mInterfaceWorker)); } } void InterfaceQueued::close() { mOpened = false; - mQueueDpsimToInterface->emplace(AttributePacket{nullptr, 0, 0, AttributePacketFlags::PACKET_CLOSE_INTERFACE}); + mQueueDpsimToInterface->emplace(AttributePacket{ + nullptr, 0, 0, AttributePacketFlags::PACKET_CLOSE_INTERFACE}); if (!mExportAttrsDpsim.empty()) { mInterfaceWriterThread.join(); @@ -75,48 +78,61 @@ void InterfaceQueued::syncExports() { } void InterfaceQueued::popDpsimAttrsFromQueue(bool isSync) { - AttributePacket receivedPacket = {nullptr, 0, 0, AttributePacketFlags::PACKET_NO_FLAGS}; + AttributePacket receivedPacket = {nullptr, 0, 0, + AttributePacketFlags::PACKET_NO_FLAGS}; UInt currentSequenceId = mNextSequenceInterfaceToDpsim; // Wait for and dequeue all attributes that read should block on // The std::find_if will look for all attributes that have not been updated in the current while loop (i. e. whose sequence ID is lower than the next expected sequence ID) - while (std::find_if(mImportAttrsDpsim.cbegin(), mImportAttrsDpsim.cend(), [currentSequenceId, isSync](auto attrTuple) { - auto &[_attr, seqId, blockOnRead, syncOnStart] = attrTuple; - if (isSync) { - return syncOnStart && seqId < currentSequenceId; - } else { - return blockOnRead && seqId < currentSequenceId; - } - }) != mImportAttrsDpsim.cend()) { + while (std::find_if(mImportAttrsDpsim.cbegin(), mImportAttrsDpsim.cend(), + [currentSequenceId, isSync](auto attrTuple) { + auto &[_attr, seqId, blockOnRead, syncOnStart] = + attrTuple; + if (isSync) { + return syncOnStart && seqId < currentSequenceId; + } else { + return blockOnRead && seqId < currentSequenceId; + } + }) != mImportAttrsDpsim.cend()) { if (mQueueInterfaceToDpsim->try_dequeue(receivedPacket) != false) { int i = 0; while (mQueueInterfaceToDpsim->try_dequeue(receivedPacket)) { i++; } - SPDLOG_LOGGER_WARN(mLog, "Overrun detected! Discarding {} overrun packets!", i); + SPDLOG_LOGGER_WARN(mLog, + "Overrun detected! Discarding {} overrun packets!", i); } else { mQueueInterfaceToDpsim->wait_dequeue(receivedPacket); } - if (!std::get<0>(mImportAttrsDpsim[receivedPacket.attributeId])->copyValue(receivedPacket.value)) { - SPDLOG_LOGGER_WARN(mLog, "Failed to copy received value onto attribute in Interface!"); + if (!std::get<0>(mImportAttrsDpsim[receivedPacket.attributeId]) + ->copyValue(receivedPacket.value)) { + SPDLOG_LOGGER_WARN( + mLog, "Failed to copy received value onto attribute in Interface!"); } - std::get<1>(mImportAttrsDpsim[receivedPacket.attributeId]) = receivedPacket.sequenceId; + std::get<1>(mImportAttrsDpsim[receivedPacket.attributeId]) = + receivedPacket.sequenceId; mNextSequenceInterfaceToDpsim = receivedPacket.sequenceId + 1; } // Fetch all remaining queue packets while (mQueueInterfaceToDpsim->try_dequeue(receivedPacket)) { - if (!std::get<0>(mImportAttrsDpsim[receivedPacket.attributeId])->copyValue(receivedPacket.value)) { - SPDLOG_LOGGER_WARN(mLog, "Failed to copy received value onto attribute in Interface!"); + if (!std::get<0>(mImportAttrsDpsim[receivedPacket.attributeId]) + ->copyValue(receivedPacket.value)) { + SPDLOG_LOGGER_WARN( + mLog, "Failed to copy received value onto attribute in Interface!"); } - std::get<1>(mImportAttrsDpsim[receivedPacket.attributeId]) = receivedPacket.sequenceId; + std::get<1>(mImportAttrsDpsim[receivedPacket.attributeId]) = + receivedPacket.sequenceId; mNextSequenceInterfaceToDpsim = receivedPacket.sequenceId + 1; } } void InterfaceQueued::pushDpsimAttrsToQueue() { for (UInt i = 0; i < mExportAttrsDpsim.size(); i++) { - mQueueDpsimToInterface->emplace(AttributePacket{std::get<0>(mExportAttrsDpsim[i])->cloneValueOntoNewAttribute(), i, std::get<1>(mExportAttrsDpsim[i]), AttributePacketFlags::PACKET_NO_FLAGS}); + mQueueDpsimToInterface->emplace(AttributePacket{ + std::get<0>(mExportAttrsDpsim[i])->cloneValueOntoNewAttribute(), i, + std::get<1>(mExportAttrsDpsim[i]), + AttributePacketFlags::PACKET_NO_FLAGS}); std::get<1>(mExportAttrsDpsim[i]) = mCurrentSequenceDpsimToInterface; mCurrentSequenceDpsimToInterface++; } @@ -126,7 +142,8 @@ void InterfaceQueued::WriterThread::operator()() const { bool interfaceClosed = false; std::vector attrsToWrite; while (!interfaceClosed) { - AttributePacket nextPacket = {nullptr, 0, 0, AttributePacketFlags::PACKET_NO_FLAGS}; + AttributePacket nextPacket = {nullptr, 0, 0, + AttributePacketFlags::PACKET_NO_FLAGS}; // Wait for at least one packet mQueueDpsimToInterface->wait_dequeue(nextPacket); diff --git a/dpsim/src/MNASolverPlugin.cpp b/dpsim/src/MNASolverPlugin.cpp index e23cf9ce58..f25135b0a2 100644 --- a/dpsim/src/MNASolverPlugin.cpp +++ b/dpsim/src/MNASolverPlugin.cpp @@ -75,7 +75,8 @@ template void MnaSolverPlugin::initialize() { std::vector hMat; int nnz = 0; if (this->mSystemMatrixRecomputation) { - SPDLOG_LOGGER_ERROR(this->mSLog, "System matrix recomputation not supported"); + SPDLOG_LOGGER_ERROR(this->mSLog, + "System matrix recomputation not supported"); return; } else { hMat = this->mSwitchedMatrices[std::bitset(0)]; diff --git a/dpsim/src/RealTimeDataLogger.cpp b/dpsim/src/RealTimeDataLogger.cpp index a071d19c57..797c6fca1a 100644 --- a/dpsim/src/RealTimeDataLogger.cpp +++ b/dpsim/src/RealTimeDataLogger.cpp @@ -13,16 +13,25 @@ using namespace DPsim; -RealTimeDataLogger::RealTimeDataLogger(std::filesystem::path &filename, size_t rowNumber) - : DataLoggerInterface(), mFilename(filename), mRowNumber(rowNumber), mCurrentRow(0), mCurrentAttribute(0), mAttributeData() {} +RealTimeDataLogger::RealTimeDataLogger(std::filesystem::path &filename, + size_t rowNumber) + : DataLoggerInterface(), mFilename(filename), mRowNumber(rowNumber), + mCurrentRow(0), mCurrentAttribute(0), mAttributeData() {} -RealTimeDataLogger::RealTimeDataLogger(std::filesystem::path &filename, Real finalTime, Real timeStep) - : DataLoggerInterface(), mFilename(filename), mRowNumber((finalTime / timeStep + 0.5)), mCurrentRow(0), mCurrentAttribute(0), mAttributeData() {} +RealTimeDataLogger::RealTimeDataLogger(std::filesystem::path &filename, + Real finalTime, Real timeStep) + : DataLoggerInterface(), mFilename(filename), + mRowNumber((finalTime / timeStep + 0.5)), mCurrentRow(0), + mCurrentAttribute(0), mAttributeData() {} void RealTimeDataLogger::start() { - double mb_size = static_cast(mRowNumber) * (mAttributes.size() + 1) * sizeof(Real); - auto log = CPS::Logger::get("RealTimeDataLogger", CPS::Logger::Level::off, CPS::Logger::Level::info); - log->info("Preallocating memory for real-time data logger: {} rows for {} attributes ({} MB)", mRowNumber, mAttributes.size(), mb_size / (1024 * 1024)); + double mb_size = + static_cast(mRowNumber) * (mAttributes.size() + 1) * sizeof(Real); + auto log = CPS::Logger::get("RealTimeDataLogger", CPS::Logger::Level::off, + CPS::Logger::Level::info); + log->info("Preallocating memory for real-time data logger: {} rows for {} " + "attributes ({} MB)", + mRowNumber, mAttributes.size(), mb_size / (1024 * 1024)); // We are doing real time so preallocate everything mAttributeData.resize(mRowNumber); for (auto &it : mAttributeData) { @@ -32,7 +41,8 @@ void RealTimeDataLogger::start() { } void RealTimeDataLogger::stop() { - auto mLogFile = std::ofstream(mFilename, std::ios_base::out | std::ios_base::trunc); + auto mLogFile = + std::ofstream(mFilename, std::ios_base::out | std::ios_base::trunc); if (!mLogFile.is_open()) { throw std::runtime_error("Cannot open log file " + mFilename.string()); } @@ -54,23 +64,35 @@ void RealTimeDataLogger::stop() { void RealTimeDataLogger::log(Real time, Int timeStepCount) { mCurrentRow = timeStepCount; if (timeStepCount < 0 || static_cast(timeStepCount) >= mRowNumber) { - throw std::runtime_error("RealTimeDataLogger: timeStepCount out of bounds. Please verify the logger was initialized correctly."); + throw std::runtime_error( + "RealTimeDataLogger: timeStepCount out of bounds. Please verify the " + "logger was initialized correctly."); } - if (mAttributeData.size() != mRowNumber || mAttributeData[mCurrentRow].size() != mAttributes.size() + 1) { - throw std::runtime_error("RealTimeDataLogger: Attribute data size mismatch"); + if (mAttributeData.size() != mRowNumber || + mAttributeData[mCurrentRow].size() != mAttributes.size() + 1) { + throw std::runtime_error( + "RealTimeDataLogger: Attribute data size mismatch"); } mAttributeData[mCurrentRow][0] = time; mCurrentAttribute = 1; for (auto it : mAttributes) { if (it.second->getType() == typeid(Real)) { - mAttributeData[mCurrentRow][mCurrentAttribute++] = **std::dynamic_pointer_cast>>(it.second.getPtr()); + mAttributeData[mCurrentRow][mCurrentAttribute++] = + **std::dynamic_pointer_cast>>( + it.second.getPtr()); } else if (it.second->getType() == typeid(Int)) { - mAttributeData[mCurrentRow][mCurrentAttribute++] = **std::dynamic_pointer_cast>>(it.second.getPtr()); + mAttributeData[mCurrentRow][mCurrentAttribute++] = + **std::dynamic_pointer_cast>>( + it.second.getPtr()); } } } -void RealTimeDataLogger::Step::execute(Real time, Int timeStepCount) { mLogger.log(time, timeStepCount); } +void RealTimeDataLogger::Step::execute(Real time, Int timeStepCount) { + mLogger.log(time, timeStepCount); +} -CPS::Task::Ptr RealTimeDataLogger::getTask() { return std::make_shared(*this); } +CPS::Task::Ptr RealTimeDataLogger::getTask() { + return std::make_shared(*this); +} diff --git a/dpsim/src/RealTimeSimulation.cpp b/dpsim/src/RealTimeSimulation.cpp index 2c4095e782..8b979f1c1d 100644 --- a/dpsim/src/RealTimeSimulation.cpp +++ b/dpsim/src/RealTimeSimulation.cpp @@ -43,8 +43,10 @@ void RealTimeSimulation::run(const Timer::StartClock::time_point &startAt) { sync(); - SPDLOG_LOGGER_INFO(mLog, "Starting simulation at {:%Y-%m-%d %H:%M:%S} (delta_T = {} seconds)", - startAt, startAt - Timer::StartClock::now()); + SPDLOG_LOGGER_INFO( + mLog, + "Starting simulation at {:%Y-%m-%d %H:%M:%S} (delta_T = {} seconds)", + startAt, startAt - Timer::StartClock::now()); mTimer.setStartTime(startAt); mTimer.setInterval(**mTimeStep); diff --git a/dpsim/src/pybind/DPComponents.cpp b/dpsim/src/pybind/DPComponents.cpp index 316a91a856..e74ddfabb3 100644 --- a/dpsim/src/pybind/DPComponents.cpp +++ b/dpsim/src/pybind/DPComponents.cpp @@ -155,7 +155,7 @@ void addDPPh1Components(py::module_ mDPPh1) { "loglevel"_a = CPS::Logger::Level::off) .def("set_parameters", &CPS::DP::Ph1::Switch::setParameters, "open_resistance"_a, "closed_resistance"_a, - // cppcheck-suppress assignBoolToPointer + // cppcheck-suppress assignBoolToPointer "closed"_a = false) .def("open", &CPS::DP::Ph1::Switch::open) .def("close", &CPS::DP::Ph1::Switch::close) @@ -169,7 +169,7 @@ void addDPPh1Components(py::module_ mDPPh1) { "loglevel"_a = CPS::Logger::Level::off) .def("set_parameters", &CPS::DP::Ph1::varResSwitch::setParameters, "open_resistance"_a, "closed_resistance"_a, - // cppcheck-suppress assignBoolToPointer + // cppcheck-suppress assignBoolToPointer "closed"_a = false) .def("open", &CPS::DP::Ph1::varResSwitch::open) .def("close", &CPS::DP::Ph1::varResSwitch::close) @@ -363,7 +363,7 @@ void addDPPh1Components(py::module_ mDPPh1) { "loglevel"_a = CPS::Logger::Level::off) .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off, - // cppcheck-suppress assignBoolToPointer + // cppcheck-suppress assignBoolToPointer "with_trafo"_a = false) .def("set_parameters", &CPS::DP::Ph1::AvVoltageSourceInverterDQ::setParameters, @@ -405,9 +405,8 @@ void addDPPh1Components(py::module_ mDPPh1) { "loglevel"_a = CPS::Logger::Level::off) .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off, - // cppcheck-suppress assignBoolToPointer - "with_resistive_losses"_a = - false) + // cppcheck-suppress assignBoolToPointer + "with_resistive_losses"_a = false) .def("set_parameters", py::overload_cast( @@ -481,7 +480,7 @@ void addDPPh3Components(py::module_ mDPPh3) { "loglevel"_a = CPS::Logger::Level::off) .def("set_parameters", &CPS::DP::Ph3::SeriesSwitch::setParameters, "open_resistance"_a, "closed_resistance"_a, - // cppcheck-suppress assignBoolToPointer + // cppcheck-suppress assignBoolToPointer "closed"_a = false) .def("open", &CPS::DP::Ph3::SeriesSwitch::open) .def("close", &CPS::DP::Ph3::SeriesSwitch::close) diff --git a/dpsim/src/pybind/EMTComponents.cpp b/dpsim/src/pybind/EMTComponents.cpp index d4441ae927..9d0a2d4ac5 100644 --- a/dpsim/src/pybind/EMTComponents.cpp +++ b/dpsim/src/pybind/EMTComponents.cpp @@ -216,9 +216,13 @@ void addEMTPh3Components(py::module_ mEMTPh3) { "parallel_conductance"_a = zeroMatrix(3)) .def("connect", &CPS::EMT::Ph3::PiLine::connect); - py::class_, CPS::SimPowerComp>(mEMTPh3, "RXLoad", py::multiple_inheritance()) - .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) - .def("set_parameters", &CPS::EMT::Ph3::RXLoad::setParameters, "active_power"_a, "reactive_power"_a, "volt"_a, + py::class_, + CPS::SimPowerComp>(mEMTPh3, "RXLoad", + py::multiple_inheritance()) + .def(py::init(), "name"_a, + "loglevel"_a = CPS::Logger::Level::off) + .def("set_parameters", &CPS::EMT::Ph3::RXLoad::setParameters, + "active_power"_a, "reactive_power"_a, "volt"_a, // cppcheck-suppress assignBoolToPointer "reactance_in_series"_a = false) .def("connect", &CPS::EMT::Ph3::RXLoad::connect); diff --git a/dpsim/src/pybind/SPComponents.cpp b/dpsim/src/pybind/SPComponents.cpp index 3b833c1de3..44dd0422c7 100644 --- a/dpsim/src/pybind/SPComponents.cpp +++ b/dpsim/src/pybind/SPComponents.cpp @@ -134,7 +134,7 @@ void addSPPh1Components(py::module_ mSPPh1) { "loglevel"_a = CPS::Logger::Level::off) .def("set_parameters", &CPS::SP::Ph1::Switch::setParameters, "open_resistance"_a, "closed_resistance"_a, - // cppcheck-suppress assignBoolToPointer + // cppcheck-suppress assignBoolToPointer "closed"_a = false) .def("open", &CPS::SP::Ph1::Switch::open) .def("close", &CPS::SP::Ph1::Switch::close) @@ -167,7 +167,7 @@ void addSPPh1Components(py::module_ mSPPh1) { "loglevel"_a = CPS::Logger::Level::off) .def("set_parameters", &CPS::SP::Ph1::varResSwitch::setParameters, "open_resistance"_a, "closed_resistance"_a, - // cppcheck-suppress assignBoolToPointer + // cppcheck-suppress assignBoolToPointer "closed"_a = false) .def("open", &CPS::SP::Ph1::varResSwitch::open) .def("close", &CPS::SP::Ph1::varResSwitch::close) @@ -304,7 +304,7 @@ void addSPPh1Components(py::module_ mSPPh1) { "loglevel"_a = CPS::Logger::Level::off) .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off, - // cppcheck-suppress assignBoolToPointer + // cppcheck-suppress assignBoolToPointer "with_trafo"_a = false) .def("set_parameters", &CPS::SP::Ph1::AvVoltageSourceInverterDQ::setParameters, diff --git a/dpsim/src/pybind/main.cpp b/dpsim/src/pybind/main.cpp index 39f3c235b5..51d9c4e9ac 100644 --- a/dpsim/src/pybind/main.cpp +++ b/dpsim/src/pybind/main.cpp @@ -200,8 +200,7 @@ PYBIND11_MODULE(dpsimpy, m) { .def("do_steady_state_init", &DPsim::Simulation::doSteadyStateInit) .def("do_frequency_parallelization", &DPsim::Simulation::doFrequencyParallelization) - .def("do_split_subnets", - &DPsim::Simulation::doSplitSubnets) + .def("do_split_subnets", &DPsim::Simulation::doSplitSubnets) .def("set_tearing_components", &DPsim::Simulation::setTearingComponents) .def("add_event", &DPsim::Simulation::addEvent) .def("set_solver_component_behaviour", @@ -270,7 +269,9 @@ PYBIND11_MODULE(dpsimpy, m) { py::class_>(m, "Interface"); - py::class_>(m, "DataLoggerInterface") + py::class_>(m, + "DataLoggerInterface") .def("log_attribute", py::overload_cast( @@ -284,12 +285,14 @@ PYBIND11_MODULE(dpsimpy, m) { "names"_a, "attr"_a) /// Compatibility method. Might be removed later when the python examples have been fully adapted.; .def("log_attribute", - [](DPsim::DataLoggerInterface &logger, const std::vector &names, - const CPS::String &attr, const CPS::IdentifiedObject &comp) { + [](DPsim::DataLoggerInterface &logger, + const std::vector &names, const CPS::String &attr, + const CPS::IdentifiedObject &comp) { logger.logAttribute(names, comp.attribute(attr)); }); - py::class_>(m, "Logger") + py::class_>(m, "Logger") .def(py::init()) .def_static("set_log_dir", &CPS::Logger::setLogDir) .def_static("get_log_dir", &CPS::Logger::logDir) From 5f86a25e385e8aa34775f1fc5c9fae0a30f0e4ff Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:43:43 +0100 Subject: [PATCH 049/168] feat(cmake): Add install target Signed-off-by: Steffen Vogel --- CMakeLists.txt | 7 ++++++- docs/doxygen/CMakeLists.txt | 5 +++++ docs/sphinx/CMakeLists.txt | 6 +++++- dpsim-models/CMakeLists.txt | 18 ++++++++++++++++++ dpsim-villas/CMakeLists.txt | 26 ++++++++++++++++++++++++++ dpsim/CMakeLists.txt | 18 ++++++++++++++++++ dpsim/src/pybind/CMakeLists.txt | 8 ++++++++ 7 files changed, 86 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5df8818ae4..cf57badcea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,6 +75,7 @@ endif() set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +include(GNUInstallDirs) include(CheckCXXCompilerFlag) if(MSVC) # Silence Visual Studio deprecation warnings @@ -255,6 +256,10 @@ if(WITH_CUDA) # END OF WORKAROUND endif() +if(WITH_PYBIND) + set(CMAKE_INSTALL_PYTHON_SITEPACKAGESDIR "${CMAKE_INSTALL_LIBDIR}/python${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}/site-packages") +endif() + add_subdirectory(dpsim-models) add_subdirectory(dpsim) @@ -281,7 +286,7 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) add_feature_info(MAGMA WITH_MAGMA "MAGMA features") add_feature_info(MNASolverPlugin WITH_MNASOLVERPLUGIN "MNASolver Plugins") add_feature_info(OpenMP WITH_OPENMP "OpenMP-based parallelisation") - add_feature_info(PyBind WITH_PYBIND "PyBind module") + add_feature_info(Pybind WITH_PYBIND "Python extension / bindings") add_feature_info(RealTime WITH_RT "Extended real-time features") add_feature_info(Sundials WITH_SUNDIALS "Sundials solvers") add_feature_info(VILLASnode WITH_VILLAS "Interface DPsim solvers via VILLASnode interfaces") diff --git a/docs/doxygen/CMakeLists.txt b/docs/doxygen/CMakeLists.txt index 4aa11c973f..a1d44e1a63 100644 --- a/docs/doxygen/CMakeLists.txt +++ b/docs/doxygen/CMakeLists.txt @@ -16,4 +16,9 @@ if(DOXYGEN_FOUND) WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Generating API documentation with Doxygen" VERBATIM ) + + install(DIRECTORY ${DOXYGEN_HTML_DIR} + DESTINATION ${CMAKE_INSTALL_DOCDIR}/doxygen + OPTIONAL + ) endif() diff --git a/docs/sphinx/CMakeLists.txt b/docs/sphinx/CMakeLists.txt index 51c227708e..eeb5c10d0f 100644 --- a/docs/sphinx/CMakeLists.txt +++ b/docs/sphinx/CMakeLists.txt @@ -19,7 +19,7 @@ if(WITH_PYBIND) @ONLY ) - # We add the path of the freshly build dpsim.so module to Python path here + # We add the path of the freshly build dpsimpy extension to Python path here add_custom_target(docs COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${CMAKE_BINARY_DIR}:$ENV{PYTHONPATH} @@ -34,5 +34,9 @@ if(WITH_PYBIND) dpsimpy ) + install(DIRECTORY ${SPHINX_HTML_DIR} + DESTINATION ${CMAKE_INSTALL_DOCDIR}/sphinx + OPTIONAL + ) endif() endif() diff --git a/dpsim-models/CMakeLists.txt b/dpsim-models/CMakeLists.txt index 8f18461ec0..6c013de297 100644 --- a/dpsim-models/CMakeLists.txt +++ b/dpsim-models/CMakeLists.txt @@ -16,3 +16,21 @@ set(MODELS_LIBRARIES ) add_subdirectory(src) + +file(GLOB_RECURSE HEADER_FILES include/*.h) + +target_sources(dpsim-models PUBLIC + FILE_SET public_headers + TYPE HEADERS + BASE_DIRS include + FILES "${HEADER_FILES}" +) + +install(TARGETS dpsim-models + EXPORT dpsim-models + FILE_SET public_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) diff --git a/dpsim-villas/CMakeLists.txt b/dpsim-villas/CMakeLists.txt index 5ea6cd3950..10f3ef681f 100644 --- a/dpsim-villas/CMakeLists.txt +++ b/dpsim-villas/CMakeLists.txt @@ -5,6 +5,14 @@ if(WITH_PYBIND) LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" ) target_link_libraries(dpsimpyvillas PRIVATE dpsim-villas) + + install(TARGETS dpsimpyvillas + EXPORT dpsimpyvillas + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_PYTHON_SITEPACKAGESDIR} + ) endif() add_subdirectory(src) @@ -12,3 +20,21 @@ add_subdirectory(src) if(DPSIM_BUILD_EXAMPLES) add_subdirectory(examples) endif() + +file(GLOB_RECURSE HEADER_FILES include/*.h) + +target_sources(dpsim-villas PUBLIC + FILE_SET public_headers + TYPE HEADERS + BASE_DIRS include + FILES "${HEADER_FILES}" +) + +install(TARGETS dpsim-villas + EXPORT dpsim-villas + FILE_SET public_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) diff --git a/dpsim/CMakeLists.txt b/dpsim/CMakeLists.txt index d821891211..3f78075f5f 100644 --- a/dpsim/CMakeLists.txt +++ b/dpsim/CMakeLists.txt @@ -18,3 +18,21 @@ endif() if(DPSIM_BUILD_EXAMPLES) add_subdirectory(examples) endif() + +file(GLOB_RECURSE HEADER_FILES include/*.h) + +target_sources(dpsim PUBLIC + FILE_SET public_headers + TYPE HEADERS + BASE_DIRS include + FILES "${HEADER_FILES}" +) + +install(TARGETS dpsim + EXPORT dpsim + FILE_SET public_headers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} +) diff --git a/dpsim/src/pybind/CMakeLists.txt b/dpsim/src/pybind/CMakeLists.txt index 07b5a88111..7e9734b3ca 100644 --- a/dpsim/src/pybind/CMakeLists.txt +++ b/dpsim/src/pybind/CMakeLists.txt @@ -16,3 +16,11 @@ set_target_properties(dpsimpy ) target_link_libraries(dpsimpy PRIVATE dpsim) target_include_directories(dpsimpy PUBLIC ${DPSIMPY_INCLUDE_DIRS}) + +install(TARGETS dpsimpy + EXPORT dpsimpy + INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_PYTHON_SITEPACKAGESDIR} +) From 62ace29a48fefe6d6e405994686999a83a26ac16 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 6 Apr 2025 12:44:38 +0200 Subject: [PATCH 050/168] feat(pre-commit): Enable pretty-format-json hook Signed-off-by: Steffen Vogel --- .pre-commit-config.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6d679c16d9..0294b97bc8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,12 +15,12 @@ repos: exclude: .devcontainer/devcontainer\.json - id: check-toml - id: check-added-large-files - # - id: pretty-format-json - # # black has its own mind of formatting Jupyter notebooks - # exclude: \.ipynb$|^.devcontainer/devcontainer\.json$|package-lock\.json$ - # args: - # - --no-sort-keys - # - --autofix + - id: pretty-format-json + # black has its own mind of formatting Jupyter notebooks + exclude: \.ipynb$|^.devcontainer/devcontainer\.json$|package-lock\.json$ + args: + - --no-sort-keys + - --autofix - repo: https://github.com/pre-commit/mirrors-clang-format rev: "v17.0.6" From a25427b30a1d683deea14c5837e7ce151ded6790 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 6 Apr 2025 12:45:10 +0200 Subject: [PATCH 051/168] fix(style): Fix JSON formatting Signed-off-by: Steffen Vogel --- ...ationalParams_SMIB_Fault_SyngenParams.json | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/configs/example_configs_json/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault_SyngenParams.json b/configs/example_configs_json/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault_SyngenParams.json index e87b22dcba..81947e416c 100644 --- a/configs/example_configs_json/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault_SyngenParams.json +++ b/configs/example_configs_json/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault_SyngenParams.json @@ -1,17 +1,17 @@ { - "name": "EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault_JsonSyngenParams", - "options": { - "Rs" : 0.003, - "Ll" : 0.15, - "Ld" : 1.8099, - "Lq" : 1.7600, - "Ld_t" : 0.2999, - "Ld_s" : 0.2299, - "Lq_t" : 0.6500, - "Lq_s" : 0.2500, - "Td0_t" : 8.0669, - "Td0_s" : 0.0300, - "Tq0_t" : 0.9991, - "Tq0_s" : 0.0700 - } + "name": "EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault_JsonSyngenParams", + "options": { + "Rs": 0.003, + "Ll": 0.15, + "Ld": 1.8099, + "Lq": 1.76, + "Ld_t": 0.2999, + "Ld_s": 0.2299, + "Lq_t": 0.65, + "Lq_s": 0.25, + "Td0_t": 8.0669, + "Td0_s": 0.03, + "Tq0_t": 0.9991, + "Tq0_s": 0.07 + } } From 745d553f6578d279c5918b537b8c58927b4f9257 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 6 Apr 2025 12:51:41 +0200 Subject: [PATCH 052/168] feat(pre-commit): Enable black hook for formatting Python code Signed-off-by: Steffen Vogel --- .pre-commit-config.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0294b97bc8..612e5426b1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -36,8 +36,8 @@ repos: # alias: ec # Using this mirror lets us use mypyc-compiled black, which is about 2x faster - # - repo: https://github.com/psf/black-pre-commit-mirror - # rev: "23.3.0" - # hooks: - # - id: black - # - id: black-jupyter + - repo: https://github.com/psf/black-pre-commit-mirror + rev: "23.3.0" + hooks: + - id: black + - id: black-jupyter From cc4b4ee2990eeb5419284d5c2d338d98f107d73a Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 6 Apr 2025 12:52:25 +0200 Subject: [PATCH 053/168] fix(style): Apply black formatting to all Python and Jupyter Notebook files Signed-off-by: Steffen Vogel --- docs/sphinx/conf.py.in | 30 +- .../Circuits/CS_R2CL print_attributes.ipynb | 114 +- examples/Notebooks/Circuits/CS_R2CL.ipynb | 140 +- ...SMIB_ReducedOrderSG_VBR_PCM_LoadStep.ipynb | 355 ++- ...SMIB_ReducedOrderSG_VBR_TPM_LoadStep.ipynb | 120 +- .../Compare_EMT_DP_Slack_PiLine_PQLoad.ipynb | 179 +- ...7odTrapez_DP_SynGenTrStab_SMIB_Fault.ipynb | 367 ++- ...DQ7odTrapez_EMT_SynGenVBR_SMIB_Fault.ipynb | 263 +- ...rams_Vs_FundamentalParams_SMIB_Fault.ipynb | 83 +- ...rams_Vs_FundamentalParams_SMIB_Fault.ipynb | 83 +- ...CC_9bus_IdealCS_DP_WSCC_9bus_IdealVS.ipynb | 161 +- ...CC_9bus_IdealVS_DP_WSCC_9bus_IdealVS.ipynb | 154 +- ...dation_ReducedOrderSG_VBR_Load_Fault.ipynb | 336 ++- ...derSG_VBR_SMIB_Fault_withControllers.ipynb | 571 +++-- .../DP_SP_SynGenTrStab_3Bus_Fault.ipynb | 668 +++-- .../DP_SP_SynGenTrStab_3Bus_SteadyState.ipynb | 644 +++-- .../DP_SP_SynGenTrStab_SMIB_Fault.ipynb | 398 ++- .../DP_SP_SynGenTrStab_SMIB_SteadyState.ipynb | 358 ++- .../DP_Slack_PiLine_PQLoad_with_PF_Init.ipynb | 90 +- .../Circuits/DP_Slack_PiLine_VSI_Ramp.ipynb | 114 +- .../DP_Slack_PiLine_VSI_with_PF_Init.ipynb | 248 +- ...PiLine_PQLoad_FrequencyRamp_CosineFM.ipynb | 153 +- .../Circuits/EMT_DP_SP_Slack_PiLine_VSI.ipynb | 675 +++-- ...MT_DP_Slack_PiLine_VSI_Control_OnOff.ipynb | 718 ++++-- .../Notebooks/Circuits/EMT_DP_VS_Init.ipynb | 238 +- .../Notebooks/Circuits/EMT_DP_VS_RLC.ipynb | 597 +++-- .../Circuits/EMT_Ph3_compare_RC_SSN.ipynb | 275 ++- ...EMT_Slack_PiLine_PQLoad_with_PF_Init.ipynb | 124 +- .../EMT_Slack_PiLine_VSI_with_PF_Init.ipynb | 183 +- ...Slack_PiLine_VSI_with_PF_Init_Params.ipynb | 314 ++- ...alParams_SMIB_Fault_JsonSyngenParams.ipynb | 208 +- ...Params_SMIB_Fault_ParamsModification.ipynb | 113 +- .../EMT_SynGenDQ7odTrapez_SMIB_Fault.ipynb | 181 +- .../RL_SourceStep_ParameterStudy.ipynb | 518 ++-- .../SP_Slack_PiLine_VSI_with_PF_Init.ipynb | 146 +- ...derSG_VBR_SMIB_Fault_withControllers.ipynb | 2174 ++++++++++++----- ...ducedOrderSG_VBR_SMIB_Fault_withPSAT.ipynb | 1342 +++++++--- examples/Notebooks/Circuits/VS_CS_R4.ipynb | 208 +- examples/Notebooks/Circuits/VS_R2L3.ipynb | 249 +- examples/Notebooks/Circuits/VS_RC1.ipynb | 140 +- examples/Notebooks/Circuits/VS_RL1.ipynb | 196 +- examples/Notebooks/Circuits/VS_SW_RL1.ipynb | 474 ++-- .../Notebooks/Components/Diakoptics.ipynb | 200 +- .../Components/Inverter_Grid_Test.ipynb | 181 +- examples/Notebooks/Components/Line.ipynb | 727 ++++-- examples/Notebooks/Components/Slack.ipynb | 414 +++- .../Notebooks/Components/SynGenDq7od.ipynb | 377 +-- .../SynGenDq7od_ParameterStudy.ipynb | 574 +++-- .../SynGenDq7od_SteadyState_DP_EMT.ipynb | 361 ++- .../SynGenDq7od_ThreePhFault_DP_EMT.ipynb | 454 ++-- .../Notebooks/Components/SynGen_trStab.ipynb | 123 +- .../SynGen_trStab_logger_test.ipynb | 45 +- ...gen_9Order_DCIM_VBR_Governor_Exciter.ipynb | 338 ++- examples/Notebooks/Components/Trafo.ipynb | 592 +++-- .../Notebooks/Features/AsynchronousIO.ipynb | 12 +- examples/Notebooks/Features/Graphviz.ipynb | 24 +- .../Notebooks/Features/Progressbars.ipynb | 24 +- examples/Notebooks/Features/Widgets.ipynb | 57 +- .../CIGRE_MV_pf-interactive-dpsimpy.ipynb | 40 +- .../Grids/CIGRE_MV_powerflow-dpsimpy.ipynb | 64 +- .../CIGRE_MV_powerflow_profiles-dpsimpy.ipynb | 102 +- .../Notebooks/Grids/DP_CIGRE_MV_withDG.ipynb | 401 ++- .../DP_CIGRE_MV_withDG_withLoadStep.ipynb | 442 ++-- .../Grids/DP_CIGRE_MV_withoutDG.ipynb | 152 +- .../Grids/DP_WSCC9bus_SGTrStab.ipynb | 146 +- .../Grids/DP_WSCC9bus_SGTrStab_Switch.ipynb | 157 +- .../Grids/DP_WSCC9bus_SGVoltageSource.ipynb | 128 +- .../Notebooks/Grids/EMT_CIGRE_MV_withDG.ipynb | 381 ++- .../EMT_CIGRE_MV_withDG_withLoadStep.ipynb | 231 +- .../Grids/EMT_CIGRE_MV_withoutDG.ipynb | 160 +- .../Notebooks/Grids/IEEE_LV_powerflow.ipynb | 64 +- .../Notebooks/Grids/PF_CIGRE_MV_withDG.ipynb | 94 +- .../SP_SMIB_SynGenTrStab_KundurExample1.ipynb | 296 ++- ...bus_SG4thOrder_Fault_PSAT_Validation.ipynb | 379 ++- ...9bus_SGTrStab_Switch_PSAT_Validation.ipynb | 326 ++- examples/Notebooks/Grids/case14.ipynb | 21 +- examples/Notebooks/Grids/case145.ipynb | 21 +- examples/Notebooks/Grids/case300.ipynb | 21 +- examples/Notebooks/Grids/case9.ipynb | 21 +- ...derVBR_SparseLU_KLU_fault_comparison.ipynb | 297 ++- ...alidate_KLU_using_different_settings.ipynb | 120 +- ...LU_KLU_using_partial_refactorization.ipynb | 160 +- .../Performance/Inverter_Grid_Perf.ipynb | 256 +- .../Performance/WSCC_9bus_iterations.ipynb | 223 +- ...oupled_validate_SparseLU_DenseLU_KLU.ipynb | 77 +- .../Performance/WSCC_9bus_parallel.ipynb | 434 +++- .../Performance/WSCC_9bus_split.ipynb | 59 +- .../Performance/multimachine_parallel.ipynb | 96 +- examples/Notebooks/Quickstart Guide.ipynb | 20 +- examples/Notebooks/Understanding_DP.ipynb | 476 ++-- examples/Notebooks/matpower-case9.ipynb | 68 +- examples/Python/Base/test_async.py | 19 +- examples/Python/Base/test_attribute.py | 17 +- examples/Python/Base/test_simulation.py | 10 +- examples/Python/Base/test_singlestepping.py | 15 +- examples/Python/CIM/dpsim-cim.py | 4 +- examples/Python/Circuits/test_circuit.py | 28 +- examples/Python/RealTime/test_realtime.py | 14 +- .../RuntimeMeas/decoupling_9bus_comp.py | 87 +- .../RuntimeMeas/decoupling_9bus_existing.py | 73 +- .../Python/RuntimeMeas/decoupling_sched.py | 50 +- .../RuntimeMeas/diakoptics_splitsize.py | 46 +- .../RuntimeMeas/fix_powertransformers.py | 30 +- examples/Python/RuntimeMeas/meas_utils.py | 141 +- examples/Python/RuntimeMeas/mult_split.py | 49 +- examples/Python/RuntimeMeas/sched_nthreads.py | 54 +- examples/conftest.py | 64 +- .../ShmemDistributedDirect.ipynb | 20 +- examples/villas-deprecated/ShmemExample.ipynb | 2 +- .../cigre-mv-pf-profiles-shmem.ipynb | 113 +- .../shmem-distributed-villas.py | 61 +- .../test_shmem_cigre_mv_pf_profiles.py | 161 +- .../test_shmem_distributed_direct.py | 42 +- .../test_shmem_import_export.py | 80 +- examples/villas/dpsim-file.py | 36 +- .../villas/dpsim-mqtt-cigre-mv-pf-profiles.py | 90 +- .../villas/dpsim-mqtt-import-export-MIMO.py | 196 +- examples/villas/dpsim-mqtt-import-export.py | 138 +- examples/villas/dpsim-mqtt-producer.py | 14 +- examples/villas/dpsim-mqtt.py | 42 +- .../villas/shmem-distributed-reference.py | 22 +- python/src/dpsim/__init__.py | 4 +- python/src/dpsim/matpower.py | 362 ++- setup.py | 54 +- 124 files changed, 17880 insertions(+), 9396 deletions(-) diff --git a/docs/sphinx/conf.py.in b/docs/sphinx/conf.py.in index 5b8cc1c977..ee91abb4eb 100755 --- a/docs/sphinx/conf.py.in +++ b/docs/sphinx/conf.py.in @@ -20,38 +20,36 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = [ - 'sphinx.ext.autodoc' -] +extensions = ["sphinx.ext.autodoc"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'about' +master_doc = "about" # General information about the project. -project = '@PROJECT_NAME@' -copyright = '@PROJECT_COPYRIGHT@' -author = '@PROJECT_AUTHOR@' +project = "@PROJECT_NAME@" +copyright = "@PROJECT_COPYRIGHT@" +author = "@PROJECT_AUTHOR@" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '@DPSIM_VERSION@' +version = "@DPSIM_VERSION@" # The full version, including alpha/beta/rc tags. -release = '@DPSIM_VERSION@-@DPSIM_RELEASE@' +release = "@DPSIM_VERSION@-@DPSIM_RELEASE@" # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = False @@ -62,15 +60,15 @@ todo_include_todos = False # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'sphinx_rtd_theme' +html_theme = "sphinx_rtd_theme" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = [ ] +html_static_path = [] -#html_logo = '@CMAKE_CURRENT_SOURCE_DIR@/images/dpsim.png' +# html_logo = '@CMAKE_CURRENT_SOURCE_DIR@/images/dpsim.png' html_context = { - 'source_url_prefix': "@PROJECT_VCS_URL@/docs/", + "source_url_prefix": "@PROJECT_VCS_URL@/docs/", } diff --git a/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb b/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb index d7ee214c4b..ed5222c411 100644 --- a/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb +++ b/examples/Notebooks/Circuits/CS_R2CL print_attributes.ipynb @@ -34,24 +34,24 @@ "# DPsim EMT simulation\n", "import dpsimpy\n", "\n", - "name = 'EMT_CS_R2CL'\n", + "name = \"EMT_CS_R2CL\"\n", "\n", "# Nodes\n", "gnd = dpsimpy.emt.SimNode.gnd\n", - "n1 = dpsimpy.emt.SimNode('n1')\n", - "n2 = dpsimpy.emt.SimNode('n2')\n", + "n1 = dpsimpy.emt.SimNode(\"n1\")\n", + "n2 = dpsimpy.emt.SimNode(\"n2\")\n", "\n", "# Components\n", - "cs = dpsimpy.emt.ph1.CurrentSource('cs')\n", + "cs = dpsimpy.emt.ph1.CurrentSource(\"cs\")\n", "cs.I_ref = complex(10, 0)\n", "cs.f_src = 50\n", - "r1 = dpsimpy.emt.ph1.Resistor('r_1')\n", + "r1 = dpsimpy.emt.ph1.Resistor(\"r_1\")\n", "r1.R = 1\n", - "c1 = dpsimpy.emt.ph1.Capacitor('c_1')\n", + "c1 = dpsimpy.emt.ph1.Capacitor(\"c_1\")\n", "c1.C = 0.001\n", - "l1 = dpsimpy.emt.ph1.Inductor('l_1')\n", + "l1 = dpsimpy.emt.ph1.Inductor(\"l_1\")\n", "l1.L = 0.001\n", - "r2 = dpsimpy.emt.ph1.Resistor('r_2')\n", + "r2 = dpsimpy.emt.ph1.Resistor(\"r_2\")\n", "r2.R = 1\n", "\n", "cs.print_attribute_list()\n", @@ -60,9 +60,9 @@ "l1.print_attribute_list()\n", "r2.print_attribute_list()\n", "\n", - "cs.print_attribute('v_intf')\n", - "cs.print_attribute('right_vector')\n", - "l1.print_attribute('L')\n", + "cs.print_attribute(\"v_intf\")\n", + "cs.print_attribute(\"right_vector\")\n", + "l1.print_attribute(\"L\")\n", "\n", "# Connections\n", "cs.connect([gnd, n1])\n", @@ -76,10 +76,10 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(name)\n", - "logger.log_attribute('n1.v', 'v', n1)\n", - "logger.log_attribute('n2.v', 'v', n2)\n", - "logger.log_attribute('cs.i_intf', 'i_intf', cs)\n", - "logger.log_attribute('c_1.i_intf', 'i_intf', c1)\n", + "logger.log_attribute(\"n1.v\", \"v\", n1)\n", + "logger.log_attribute(\"n2.v\", \"v\", n2)\n", + "logger.log_attribute(\"cs.i_intf\", \"i_intf\", cs)\n", + "logger.log_attribute(\"c_1.i_intf\", \"i_intf\", c1)\n", "\n", "sim = dpsimpy.Simulation(name)\n", "sim.set_domain(dpsimpy.Domain.EMT)\n", @@ -105,9 +105,9 @@ "source": [ "sim.run()\n", "print(cs)\n", - "cs.print_attribute('v_intf')\n", - "cs.print_attribute('right_vector')\n", - "l1.print_attribute('L')" + "cs.print_attribute(\"v_intf\")\n", + "cs.print_attribute(\"right_vector\")\n", + "l1.print_attribute(\"L\")" ] }, { @@ -117,11 +117,11 @@ "outputs": [], "source": [ "# read EMT results\n", - "work_dir = 'logs/'\n", - "log_name = 'EMT_CS_R2CL'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/\"\n", + "log_name = \"EMT_CS_R2CL\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_emt = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "ts_dpsim_emt = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -130,15 +130,15 @@ "metadata": {}, "outputs": [], "source": [ - "v1_emt = 'n1.v'\n", - "v2_emt = 'n2.v'\n", - "i01_emt = 'cs.i_intf'\n", - "i12_emt = 'c_1.i_intf'\n", + "v1_emt = \"n1.v\"\n", + "v2_emt = \"n2.v\"\n", + "i01_emt = \"cs.i_intf\"\n", + "i12_emt = \"c_1.i_intf\"\n", "\n", - "ts_dpsim_emt[v1_emt].label = 'v1 EMT'\n", - "ts_dpsim_emt[v2_emt].label = 'v2 EMT'\n", - "ts_dpsim_emt[i01_emt].label = 'i01 EMT'\n", - "ts_dpsim_emt[i12_emt].label = 'i12 EMT'\n", + "ts_dpsim_emt[v1_emt].label = \"v1 EMT\"\n", + "ts_dpsim_emt[v2_emt].label = \"v2 EMT\"\n", + "ts_dpsim_emt[i01_emt].label = \"i01 EMT\"\n", + "ts_dpsim_emt[i12_emt].label = \"i12 EMT\"\n", "pt.plot_timeseries(1, ts_dpsim_emt[v1_emt])\n", "pt.plot_timeseries(1, ts_dpsim_emt[v2_emt])\n", "pt.plot_timeseries(2, ts_dpsim_emt[i01_emt])\n", @@ -161,23 +161,23 @@ "# DPsim DP simulation\n", "import dpsimpy\n", "\n", - "name = 'DP_CS_R2CL'\n", + "name = \"DP_CS_R2CL\"\n", "\n", "# Nodes\n", "gnd = dpsimpy.dp.SimNode.gnd\n", - "n1 = dpsimpy.dp.SimNode('n1')\n", - "n2 = dpsimpy.dp.SimNode('n2')\n", + "n1 = dpsimpy.dp.SimNode(\"n1\")\n", + "n2 = dpsimpy.dp.SimNode(\"n2\")\n", "\n", "# Components\n", - "cs = dpsimpy.dp.ph1.CurrentSource('cs')\n", - "cs.I_ref = complex(10,0)\n", - "r1 = dpsimpy.dp.ph1.Resistor('r_1')\n", + "cs = dpsimpy.dp.ph1.CurrentSource(\"cs\")\n", + "cs.I_ref = complex(10, 0)\n", + "r1 = dpsimpy.dp.ph1.Resistor(\"r_1\")\n", "r1.R = 1\n", - "c1 = dpsimpy.dp.ph1.Capacitor('c_1')\n", + "c1 = dpsimpy.dp.ph1.Capacitor(\"c_1\")\n", "c1.C = 0.001\n", - "l1 = dpsimpy.dp.ph1.Inductor('l_1')\n", + "l1 = dpsimpy.dp.ph1.Inductor(\"l_1\")\n", "l1.L = 0.001\n", - "r2 = dpsimpy.dp.ph1.Resistor('r_2')\n", + "r2 = dpsimpy.dp.ph1.Resistor(\"r_2\")\n", "r2.R = 1\n", "\n", "print(cs)\n", @@ -194,14 +194,14 @@ "r2.connect([n2, gnd])\n", "\n", "# Define system topology\n", - "system = dpsimpy.SystemTopology(50, [gnd, n1, n2], [cs, r1, c1, l1, r2]);\n", + "system = dpsimpy.SystemTopology(50, [gnd, n1, n2], [cs, r1, c1, l1, r2])\n", "\n", "# Logging\n", "logger = dpsimpy.Logger(name)\n", - "logger.log_attribute('n1.v', 'v', n1)\n", - "logger.log_attribute('n2.v', 'v', n2)\n", - "logger.log_attribute('cs.i_intf', 'i_intf', cs)\n", - "logger.log_attribute('c_1.i_intf', 'i_intf', c1)\n", + "logger.log_attribute(\"n1.v\", \"v\", n1)\n", + "logger.log_attribute(\"n2.v\", \"v\", n2)\n", + "logger.log_attribute(\"cs.i_intf\", \"i_intf\", cs)\n", + "logger.log_attribute(\"c_1.i_intf\", \"i_intf\", c1)\n", "\n", "sim = dpsimpy.Simulation(name)\n", "sim.set_system(system)\n", @@ -235,13 +235,13 @@ "outputs": [], "source": [ "# read DP results\n", - "work_dir = 'logs/'\n", - "log_name = 'DP_CS_R2CL'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/\"\n", + "log_name = \"DP_CS_R2CL\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_dp = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_dp = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "\n", - "#convert to emt\n", + "# convert to emt\n", "ts_dpsim_dp_emt = ts.frequency_shift_list(ts_dpsim_dp, 50)" ] }, @@ -251,15 +251,15 @@ "metadata": {}, "outputs": [], "source": [ - "v1_dp = 'n1.v_shift'\n", - "v2_dp = 'n2.v_shift'\n", - "i01_dp = 'cs.i_intf_shift'\n", - "i12_dp = 'c_1.i_intf_shift'\n", + "v1_dp = \"n1.v_shift\"\n", + "v2_dp = \"n2.v_shift\"\n", + "i01_dp = \"cs.i_intf_shift\"\n", + "i12_dp = \"c_1.i_intf_shift\"\n", "\n", - "ts_dpsim_dp_emt[v1_dp].label = 'v1 DP'\n", - "ts_dpsim_dp_emt[v2_dp].label = 'v2 DP'\n", - "ts_dpsim_dp_emt[i01_dp].label = 'i01 DP'\n", - "ts_dpsim_dp_emt[i12_dp].label = 'i12 DP'\n", + "ts_dpsim_dp_emt[v1_dp].label = \"v1 DP\"\n", + "ts_dpsim_dp_emt[v2_dp].label = \"v2 DP\"\n", + "ts_dpsim_dp_emt[i01_dp].label = \"i01 DP\"\n", + "ts_dpsim_dp_emt[i12_dp].label = \"i12 DP\"\n", "pt.plot_timeseries(1, ts_dpsim_dp_emt[v1_dp])\n", "pt.plot_timeseries(1, ts_dpsim_dp_emt[v2_dp])\n", "pt.plot_timeseries(2, ts_dpsim_dp_emt[i01_dp])\n", diff --git a/examples/Notebooks/Circuits/CS_R2CL.ipynb b/examples/Notebooks/Circuits/CS_R2CL.ipynb index 70fc1173f3..e6ecccadb6 100644 --- a/examples/Notebooks/Circuits/CS_R2CL.ipynb +++ b/examples/Notebooks/Circuits/CS_R2CL.ipynb @@ -16,10 +16,10 @@ "import villas.dataprocessing.readtools as rt\n", "import villas.dataprocessing.plottools as pt\n", "from villas.dataprocessing.timeseries import TimeSeries as ts\n", - "import math \n", + "import math\n", "import dpsimpy\n", "\n", - "#%matplotlib widget\n" + "# %matplotlib widget" ] }, { @@ -36,28 +36,28 @@ "outputs": [], "source": [ "# DPsim EMT simulation\n", - "name = 'EMT_CS_R2CL'\n", + "name = \"EMT_CS_R2CL\"\n", "\n", "# Nodes\n", "gnd = dpsimpy.emt.SimNode.gnd\n", - "n1 = dpsimpy.emt.SimNode('n1')\n", - "n2 = dpsimpy.emt.SimNode('n2')\n", + "n1 = dpsimpy.emt.SimNode(\"n1\")\n", + "n2 = dpsimpy.emt.SimNode(\"n2\")\n", "\n", "# initialize node voltages as in modelica\n", "n1.set_initial_voltage(complex(6.26676, -2.13813) * math.sqrt(3))\n", "n2.set_initial_voltage(complex(-0.539123, 0.42205) * math.sqrt(3))\n", "\n", "# Components\n", - "cs = dpsimpy.emt.ph1.CurrentSource('cs')\n", + "cs = dpsimpy.emt.ph1.CurrentSource(\"cs\")\n", "cs.I_ref = complex(10, 0)\n", "cs.f_src = 50\n", - "r1 = dpsimpy.emt.ph1.Resistor('r_1', dpsimpy.LogLevel.off)\n", + "r1 = dpsimpy.emt.ph1.Resistor(\"r_1\", dpsimpy.LogLevel.off)\n", "r1.R = 1\n", - "c1 = dpsimpy.emt.ph1.Capacitor('c_1', dpsimpy.LogLevel.off)\n", + "c1 = dpsimpy.emt.ph1.Capacitor(\"c_1\", dpsimpy.LogLevel.off)\n", "c1.C = 0.001\n", - "l1 = dpsimpy.emt.ph1.Inductor('l_1', dpsimpy.LogLevel.off)\n", + "l1 = dpsimpy.emt.ph1.Inductor(\"l_1\", dpsimpy.LogLevel.off)\n", "l1.L = 0.001\n", - "r2 = dpsimpy.emt.ph1.Resistor('r_2')\n", + "r2 = dpsimpy.emt.ph1.Resistor(\"r_2\")\n", "r2.R = 1\n", "\n", "# Connections\n", @@ -72,11 +72,11 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(name)\n", - "logger.log_attribute('n1.v', 'v', n1)\n", - "logger.log_attribute('n2.v', 'v', n2)\n", - "logger.log_attribute('cs.i_intf', 'i_intf', cs)\n", - "logger.log_attribute('c_1.i_intf', 'i_intf', c1)\n", - "logger.log_attribute('l_1.i_intf', 'i_intf', l1)\n", + "logger.log_attribute(\"n1.v\", \"v\", n1)\n", + "logger.log_attribute(\"n2.v\", \"v\", n2)\n", + "logger.log_attribute(\"cs.i_intf\", \"i_intf\", cs)\n", + "logger.log_attribute(\"c_1.i_intf\", \"i_intf\", c1)\n", + "logger.log_attribute(\"l_1.i_intf\", \"i_intf\", l1)\n", "\n", "sim = dpsimpy.Simulation(name)\n", "sim.set_domain(dpsimpy.Domain.EMT)\n", @@ -110,11 +110,11 @@ "outputs": [], "source": [ "# read EMT results\n", - "work_dir = 'logs/'\n", - "log_name = 'EMT_CS_R2CL'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/\"\n", + "log_name = \"EMT_CS_R2CL\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_emt = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "ts_dpsim_emt = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -123,15 +123,15 @@ "metadata": {}, "outputs": [], "source": [ - "v1_emt = 'n1.v'\n", - "v2_emt = 'n2.v'\n", - "ic1_emt = 'c_1.i_intf'\n", - "il1_emt = 'l_1.i_intf'\n", + "v1_emt = \"n1.v\"\n", + "v2_emt = \"n2.v\"\n", + "ic1_emt = \"c_1.i_intf\"\n", + "il1_emt = \"l_1.i_intf\"\n", "\n", - "ts_dpsim_emt[v1_emt].label = 'v1 EMT'\n", - "ts_dpsim_emt[v2_emt].label = 'v2 EMT'\n", - "ts_dpsim_emt[ic1_emt].label = 'ic1 EMT'\n", - "ts_dpsim_emt[il1_emt].label = 'il1 EMT'\n", + "ts_dpsim_emt[v1_emt].label = \"v1 EMT\"\n", + "ts_dpsim_emt[v2_emt].label = \"v2 EMT\"\n", + "ts_dpsim_emt[ic1_emt].label = \"ic1 EMT\"\n", + "ts_dpsim_emt[il1_emt].label = \"il1 EMT\"\n", "pt.plot_timeseries(1, ts_dpsim_emt[v1_emt])\n", "pt.plot_timeseries(1, ts_dpsim_emt[v2_emt])\n", "pt.plot_timeseries(2, ts_dpsim_emt[ic1_emt])\n", @@ -152,27 +152,27 @@ "outputs": [], "source": [ "# DPsim DP simulation\n", - "name = 'DP_CS_R2CL'\n", + "name = \"DP_CS_R2CL\"\n", "\n", "# Nodes\n", "gnd = dpsimpy.dp.SimNode.gnd\n", - "n1 = dpsimpy.dp.SimNode('n1')\n", - "n2 = dpsimpy.dp.SimNode('n2')\n", + "n1 = dpsimpy.dp.SimNode(\"n1\")\n", + "n2 = dpsimpy.dp.SimNode(\"n2\")\n", "\n", "# initialize node voltages as in simulunk\n", "n1.set_initial_voltage(complex(6.26676, -2.13813) * math.sqrt(2))\n", "n2.set_initial_voltage(complex(-0.539123, 0.42205) * math.sqrt(2))\n", "\n", "# Components\n", - "cs = dpsimpy.dp.ph1.CurrentSource('cs')\n", - "cs.I_ref = complex(10,0)\n", - "r1 = dpsimpy.dp.ph1.Resistor('r_1')\n", + "cs = dpsimpy.dp.ph1.CurrentSource(\"cs\")\n", + "cs.I_ref = complex(10, 0)\n", + "r1 = dpsimpy.dp.ph1.Resistor(\"r_1\")\n", "r1.R = 1\n", - "c1 = dpsimpy.dp.ph1.Capacitor('c_1')\n", + "c1 = dpsimpy.dp.ph1.Capacitor(\"c_1\")\n", "c1.C = 0.001\n", - "l1 = dpsimpy.dp.ph1.Inductor('l_1')\n", + "l1 = dpsimpy.dp.ph1.Inductor(\"l_1\")\n", "l1.L = 0.001\n", - "r2 = dpsimpy.dp.ph1.Resistor('r_2')\n", + "r2 = dpsimpy.dp.ph1.Resistor(\"r_2\")\n", "r2.R = 1\n", "\n", "# Connections\n", @@ -187,11 +187,11 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(name)\n", - "logger.log_attribute('n1.v', 'v', n1)\n", - "logger.log_attribute('n2.v', 'v', n2)\n", - "logger.log_attribute('cs.i_intf', 'i_intf', cs)\n", - "logger.log_attribute('c_1.i_intf', 'i_intf', c1)\n", - "logger.log_attribute('l_1.i_intf', 'i_intf', l1)\n", + "logger.log_attribute(\"n1.v\", \"v\", n1)\n", + "logger.log_attribute(\"n2.v\", \"v\", n2)\n", + "logger.log_attribute(\"cs.i_intf\", \"i_intf\", cs)\n", + "logger.log_attribute(\"c_1.i_intf\", \"i_intf\", c1)\n", + "logger.log_attribute(\"l_1.i_intf\", \"i_intf\", l1)\n", "\n", "sim = dpsimpy.Simulation(name)\n", "sim.set_system(system)\n", @@ -225,13 +225,13 @@ "outputs": [], "source": [ "# read DP results\n", - "work_dir = 'logs/'\n", - "log_name = 'DP_CS_R2CL'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/\"\n", + "log_name = \"DP_CS_R2CL\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_dp = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_dp = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "\n", - "#convert to emt\n", + "# convert to emt\n", "ts_dpsim_dp_emt = ts.frequency_shift_list(ts_dpsim_dp, 50)" ] }, @@ -241,15 +241,15 @@ "metadata": {}, "outputs": [], "source": [ - "v1_dp = 'n1.v_shift'\n", - "v2_dp = 'n2.v_shift'\n", - "ic1_dp = 'c_1.i_intf_shift'\n", - "il1_dp = 'l_1.i_intf_shift'\n", + "v1_dp = \"n1.v_shift\"\n", + "v2_dp = \"n2.v_shift\"\n", + "ic1_dp = \"c_1.i_intf_shift\"\n", + "il1_dp = \"l_1.i_intf_shift\"\n", "\n", - "ts_dpsim_dp_emt[v1_dp].label = 'v1 DP'\n", - "ts_dpsim_dp_emt[v2_dp].label = 'v2 DP'\n", - "ts_dpsim_dp_emt[ic1_dp].label = 'ic1 DP'\n", - "ts_dpsim_dp_emt[il1_dp].label = 'il1 DP'\n", + "ts_dpsim_dp_emt[v1_dp].label = \"v1 DP\"\n", + "ts_dpsim_dp_emt[v2_dp].label = \"v2 DP\"\n", + "ts_dpsim_dp_emt[ic1_dp].label = \"ic1 DP\"\n", + "ts_dpsim_dp_emt[il1_dp].label = \"il1 DP\"\n", "pt.plot_timeseries(1, ts_dpsim_dp_emt[v1_dp])\n", "pt.plot_timeseries(1, ts_dpsim_dp_emt[v2_dp])\n", "pt.plot_timeseries(2, ts_dpsim_dp_emt[ic1_dp])\n", @@ -274,12 +274,12 @@ "import os\n", "import urllib.request\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/62d774a31d40663368487e2751f93ed3ee53139d/Modelica/BasicGrids/CS_R2CL_Modelica.csv'\n", - "local_file = 'reference-results/CS_R2CL_Modelica.csv'\n", - "urllib.request.urlretrieve(url, local_file) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/62d774a31d40663368487e2751f93ed3ee53139d/Modelica/BasicGrids/CS_R2CL_Modelica.csv\"\n", + "local_file = \"reference-results/CS_R2CL_Modelica.csv\"\n", + "urllib.request.urlretrieve(url, local_file)\n", "\n", "ts_mod = rt.read_timeseries_simulink(local_file)" ] @@ -290,15 +290,15 @@ "metadata": {}, "outputs": [], "source": [ - "v1_mod = 'capacitor.v1'\n", - "v2_mod = 'capacitor.v2'\n", - "ic1_mod = 'capacitor.i'\n", - "il1_mod = 'inductor.i'\n", + "v1_mod = \"capacitor.v1\"\n", + "v2_mod = \"capacitor.v2\"\n", + "ic1_mod = \"capacitor.i\"\n", + "il1_mod = \"inductor.i\"\n", "\n", - "ts_mod[v1_mod].label = 'v1 Mod'\n", - "ts_mod[v2_mod].label = 'v2 Mod'\n", - "ts_mod[ic1_mod].label = 'ic1 Mod'\n", - "ts_mod[il1_mod].label = 'il1 Mod'\n", + "ts_mod[v1_mod].label = \"v1 Mod\"\n", + "ts_mod[v2_mod].label = \"v2 Mod\"\n", + "ts_mod[ic1_mod].label = \"ic1 Mod\"\n", + "ts_mod[il1_mod].label = \"il1 Mod\"\n", "pt.plot_timeseries(1, ts_mod[v1_mod])\n", "pt.plot_timeseries(1, ts_mod[v2_mod])\n", "pt.plot_timeseries(2, ts_mod[ic1_mod])\n", @@ -318,13 +318,13 @@ "metadata": {}, "outputs": [], "source": [ - "v1_emt = 'n1.v'\n", - "v2_emt = 'n2.v'\n", + "v1_emt = \"n1.v\"\n", + "v2_emt = \"n2.v\"\n", "\n", "# plot v1\n", "pt.plot_timeseries(1, ts_dpsim_emt[v1_emt])\n", "pt.plot_timeseries(1, ts_dpsim_dp_emt[v1_dp])\n", - "pt.plot_timeseries(1, ts_dpsim_dp['n1.v'].abs())\n", + "pt.plot_timeseries(1, ts_dpsim_dp[\"n1.v\"].abs())\n", "pt.plot_timeseries(1, ts_mod[v1_mod])\n", "# plot v2\n", "pt.plot_timeseries(2, ts_dpsim_emt[v2_emt])\n", diff --git a/examples/Notebooks/Circuits/Compare_DP_SMIB_ReducedOrderSG_VBR_PCM_LoadStep.ipynb b/examples/Notebooks/Circuits/Compare_DP_SMIB_ReducedOrderSG_VBR_PCM_LoadStep.ipynb index 878c3c61f1..f9e55507ff 100644 --- a/examples/Notebooks/Circuits/Compare_DP_SMIB_ReducedOrderSG_VBR_PCM_LoadStep.ipynb +++ b/examples/Notebooks/Circuits/Compare_DP_SMIB_ReducedOrderSG_VBR_PCM_LoadStep.ipynb @@ -33,7 +33,7 @@ "import matplotlib.pyplot as plt\n", "import dpsimpy\n", "\n", - "#%matplotlib widget" + "# %matplotlib widget" ] }, { @@ -50,13 +50,18 @@ "metadata": {}, "outputs": [], "source": [ - "root_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", - "path_exec = root_path + '/build/dpsim/examples/cxx/'\n", + "root_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", + "path_exec = root_path + \"/build/dpsim/examples/cxx/\"\n", "\n", - "name_executable_vbr = 'DP_SMIB_ReducedOrderSG_LoadStep'\n", + "name_executable_vbr = \"DP_SMIB_ReducedOrderSG_LoadStep\"\n", "name_vbr = \"DP_SMIB_ReducedOrderSG_VBR_LoadStep\"\n", "\n", - "name_executable_pcm = 'DP_SMIB_ReducedOrderSGIterative_LoadStep'\n", + "name_executable_pcm = \"DP_SMIB_ReducedOrderSGIterative_LoadStep\"\n", "name_pcm = \"DP_SMIB_ReducedOrderSGIterativePCM_LoadStep\"\n", "\n", "# times in s\n", @@ -71,14 +76,14 @@ "max_iter = 10\n", "tolerance = 1e-6\n", "\n", - "roi_begin_idx = int(roi_begin/timestep_pcm)\n", - "roi_end_idx = int(roi_end/timestep_pcm)\n", + "roi_begin_idx = int(roi_begin / timestep_pcm)\n", + "roi_end_idx = int(roi_end / timestep_pcm)\n", "\n", - "logs_path = 'logs'\n", + "logs_path = \"logs\"\n", "if not os.path.exists(logs_path):\n", " os.mkdir(logs_path)\n", - " \n", - "var_name = 'SynGen.Te'\n", + "\n", + "var_name = \"SynGen.Te\"\n", "\n", "te_ref = 0.5454986888690558" ] @@ -102,14 +107,14 @@ "### Power System\n", "nominal_voltage_hv = 230e3\n", "nominal_voltage_mv = 24e3\n", - "ratio = nominal_voltage_mv/nominal_voltage_hv\n", + "ratio = nominal_voltage_mv / nominal_voltage_hv\n", "frequency = 60\n", "omega = 2 * pi * frequency\n", "\n", "### Generator\n", "nom_power = 555e6\n", "set_point_active_power = 300e6\n", - "set_point_voltage = 1.05*nominal_voltage_mv\n", + "set_point_voltage = 1.05 * nominal_voltage_mv\n", "H = 3.7\n", "Td0_t = 8.0669\n", "Td0_s = 0.0300\n", @@ -125,16 +130,16 @@ "Lq = 1.7600\n", "L0 = 0.15\n", "Taa = 0\n", - " \n", + "\n", "### PiLine parameters calculated from CIGRE Benchmark system\n", "line_length = 100\n", - "line_resistance = 1.27e-4 * 529 * line_length * pow(ratio,2)\n", - "line_inductance = 9.05e-4 * 529 / omega * line_length * pow(ratio,2)\n", - "line_capacitance = (1.81e-3 / 529) / omega * line_length / pow(ratio,2)\n", + "line_resistance = 1.27e-4 * 529 * line_length * pow(ratio, 2)\n", + "line_inductance = 9.05e-4 * 529 / omega * line_length * pow(ratio, 2)\n", + "line_capacitance = (1.81e-3 / 529) / omega * line_length / pow(ratio, 2)\n", "line_conductance = 0.0048\n", "\n", "### Load step\n", - "load_step_activePower = 100e6; " + "load_step_activePower = 100e6;" ] }, { @@ -156,16 +161,20 @@ "\n", "### Nodes\n", "gnd_pf = dpsimpy.sp.SimNode.gnd\n", - "n1_pf = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single)\n", - "n2_pf = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single)\n", + "n1_pf = dpsimpy.sp.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "n2_pf = dpsimpy.sp.SimNode(\"n2\", dpsimpy.PhaseType.Single)\n", "\n", "### Components\n", "\n", "# syncrhon generator\n", - "gen_pf = dpsimpy.sp.ph1.SynchronGenerator('gen', dpsimpy.LogLevel.debug)\n", - "gen_pf.set_parameters(rated_apparent_power=nom_power, rated_voltage=nominal_voltage_mv, \n", - " set_point_active_power=set_point_active_power, set_point_voltage=set_point_voltage, \n", - " powerflow_bus_type=dpsimpy.PowerflowBusType.PV)\n", + "gen_pf = dpsimpy.sp.ph1.SynchronGenerator(\"gen\", dpsimpy.LogLevel.debug)\n", + "gen_pf.set_parameters(\n", + " rated_apparent_power=nom_power,\n", + " rated_voltage=nominal_voltage_mv,\n", + " set_point_active_power=set_point_active_power,\n", + " set_point_voltage=set_point_voltage,\n", + " powerflow_bus_type=dpsimpy.PowerflowBusType.PV,\n", + ")\n", "gen_pf.set_base_voltage(nominal_voltage_mv)\n", "gen_pf.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PV)\n", "\n", @@ -176,8 +185,10 @@ "extnet_pf.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", "\n", "# PiLine\n", - "pi_line_pf = dpsimpy.sp.ph1.PiLine('Pi_Line_pf', dpsimpy.LogLevel.debug)\n", - "pi_line_pf.set_parameters(R=line_resistance, L=line_inductance, C=line_capacitance, G=line_conductance)\n", + "pi_line_pf = dpsimpy.sp.ph1.PiLine(\"Pi_Line_pf\", dpsimpy.LogLevel.debug)\n", + "pi_line_pf.set_parameters(\n", + " R=line_resistance, L=line_inductance, C=line_capacitance, G=line_conductance\n", + ")\n", "pi_line_pf.set_base_voltage(nominal_voltage_mv)\n", "\n", "### Connections\n", @@ -186,14 +197,16 @@ "extnet_pf.connect([n2_pf])\n", "\n", "### Define system topology\n", - "system_pf = dpsimpy.SystemTopology(frequency, [n1_pf, n2_pf], [gen_pf, pi_line_pf, extnet_pf])\n", + "system_pf = dpsimpy.SystemTopology(\n", + " frequency, [n1_pf, n2_pf], [gen_pf, pi_line_pf, extnet_pf]\n", + ")\n", "\n", "# Logging\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", - "logger_pf.log_attribute('n1.v', 'v', n1_pf)\n", - "logger_pf.log_attribute('n2.v', 'v', n2_pf)\n", - "logger_pf.log_attribute('p_inj', 'p_inj', extnet_pf)\n", - "logger_pf.log_attribute('q_inj', 'q_inj', extnet_pf)\n", + "logger_pf.log_attribute(\"n1.v\", \"v\", n1_pf)\n", + "logger_pf.log_attribute(\"n2.v\", \"v\", n2_pf)\n", + "logger_pf.log_attribute(\"p_inj\", \"p_inj\", extnet_pf)\n", + "logger_pf.log_attribute(\"q_inj\", \"q_inj\", extnet_pf)\n", "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", "sim_pf.set_system(system_pf)\n", @@ -220,83 +233,157 @@ "metadata": {}, "outputs": [], "source": [ - "def dp_reducedOrderSG_loadStep(sim_pf, gen_pf, gen_model=\"4TPM\", event_time=0.1, final_time=0.5, time_step=10e-6, max_iter=10, tolerance=1e-6):\n", - " \n", + "def dp_reducedOrderSG_loadStep(\n", + " sim_pf,\n", + " gen_pf,\n", + " gen_model=\"4TPM\",\n", + " event_time=0.1,\n", + " final_time=0.5,\n", + " time_step=10e-6,\n", + " max_iter=10,\n", + " tolerance=1e-6,\n", + "):\n", " ### DPsim DP simulation\n", " name = \"DP_SMIB_ReducedOrderSGIterative_LoadStep_\" + gen_model\n", " dpsimpy.Logger.set_log_dir(\"logs/\" + name)\n", "\n", " ### Nodes\n", " gnd = dpsimpy.dp.SimNode.gnd\n", - " n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single) \n", - " n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single)\n", + " n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + " n2 = dpsimpy.dp.SimNode(\"n2\", dpsimpy.PhaseType.Single)\n", "\n", " ### Components\n", "\n", " # syncrhon generator\n", " gen = None\n", - " if (gen_model==\"4VBR\"):\n", - " gen = dpsimpy.dp.ph1.SynchronGenerator4OrderVBR('gen', dpsimpy.LogLevel.debug)\n", - " gen.set_operational_parameters_per_unit(nom_power=nom_power, nom_voltage=nominal_voltage_mv, nom_frequency=frequency, \n", - " H=H, Ld=Ld, Lq=Lq, L0=L0, Ld_t=Ld_t, Lq_t=Lq_t, Td0_t=Td0_t, Tq0_t=Tq0_t)\t\t\n", - " elif (gen_model==\"6VBR\"):\n", - " gen = dpsimpy.dp.ph1.SynchronGenerator6bOrderVBR('gen', dpsimpy.LogLevel.debug)\n", - " gen.set_operational_parameters_per_unit(nom_power=nom_power, nom_voltage=nominal_voltage_mv, nom_frequency=frequency, \n", - " H=H, Ld=Ld, Lq=Lq, L0=L0, Ld_t=Ld_t, Lq_t=Lq_t, Td0_t=Td0_t, Tq0_t=Tq0_t,\n", - " Ld_s=Ld_s, Lq_s=Lq_s, Td0_s=Td0_s, Tq0_s=Tq0_s)\n", - " elif (gen_model==\"4TPM\"):\n", - " gen = dpsimpy.dp.ph1.SynchronGenerator4OrderTPM('gen', dpsimpy.LogLevel.debug)\n", - " gen.set_operational_parameters_per_unit(nom_power=nom_power, nom_voltage=nominal_voltage_mv, nom_frequency=frequency, \n", - " H=H, Ld=Ld, Lq=Lq, L0=L0, Ld_t=Ld_t, Lq_t=Lq_t, Td0_t=Td0_t, Tq0_t=Tq0_t)\n", + " if gen_model == \"4VBR\":\n", + " gen = dpsimpy.dp.ph1.SynchronGenerator4OrderVBR(\"gen\", dpsimpy.LogLevel.debug)\n", + " gen.set_operational_parameters_per_unit(\n", + " nom_power=nom_power,\n", + " nom_voltage=nominal_voltage_mv,\n", + " nom_frequency=frequency,\n", + " H=H,\n", + " Ld=Ld,\n", + " Lq=Lq,\n", + " L0=L0,\n", + " Ld_t=Ld_t,\n", + " Lq_t=Lq_t,\n", + " Td0_t=Td0_t,\n", + " Tq0_t=Tq0_t,\n", + " )\n", + " elif gen_model == \"6VBR\":\n", + " gen = dpsimpy.dp.ph1.SynchronGenerator6bOrderVBR(\"gen\", dpsimpy.LogLevel.debug)\n", + " gen.set_operational_parameters_per_unit(\n", + " nom_power=nom_power,\n", + " nom_voltage=nominal_voltage_mv,\n", + " nom_frequency=frequency,\n", + " H=H,\n", + " Ld=Ld,\n", + " Lq=Lq,\n", + " L0=L0,\n", + " Ld_t=Ld_t,\n", + " Lq_t=Lq_t,\n", + " Td0_t=Td0_t,\n", + " Tq0_t=Tq0_t,\n", + " Ld_s=Ld_s,\n", + " Lq_s=Lq_s,\n", + " Td0_s=Td0_s,\n", + " Tq0_s=Tq0_s,\n", + " )\n", + " elif gen_model == \"4TPM\":\n", + " gen = dpsimpy.dp.ph1.SynchronGenerator4OrderTPM(\"gen\", dpsimpy.LogLevel.debug)\n", + " gen.set_operational_parameters_per_unit(\n", + " nom_power=nom_power,\n", + " nom_voltage=nominal_voltage_mv,\n", + " nom_frequency=frequency,\n", + " H=H,\n", + " Ld=Ld,\n", + " Lq=Lq,\n", + " L0=L0,\n", + " Ld_t=Ld_t,\n", + " Lq_t=Lq_t,\n", + " Td0_t=Td0_t,\n", + " Tq0_t=Tq0_t,\n", + " )\n", " gen.set_max_iterations(max_iter=max_iter)\n", " gen.set_tolerance(tolerance=tolerance)\n", - " elif (gen_model==\"4PCM\"):\n", - " gen = dpsimpy.dp.ph1.SynchronGenerator4OrderPCM('gen', dpsimpy.LogLevel.debug)\n", - " gen.set_operational_parameters_per_unit(nom_power=nom_power, nom_voltage=nominal_voltage_mv, nom_frequency=frequency, \n", - " H=H, Ld=Ld, Lq=Lq, L0=L0, Ld_t=Ld_t, Lq_t=Lq_t, Td0_t=Td0_t, Tq0_t=Tq0_t)\n", + " elif gen_model == \"4PCM\":\n", + " gen = dpsimpy.dp.ph1.SynchronGenerator4OrderPCM(\"gen\", dpsimpy.LogLevel.debug)\n", + " gen.set_operational_parameters_per_unit(\n", + " nom_power=nom_power,\n", + " nom_voltage=nominal_voltage_mv,\n", + " nom_frequency=frequency,\n", + " H=H,\n", + " Ld=Ld,\n", + " Lq=Lq,\n", + " L0=L0,\n", + " Ld_t=Ld_t,\n", + " Lq_t=Lq_t,\n", + " Td0_t=Td0_t,\n", + " Tq0_t=Tq0_t,\n", + " )\n", " gen.set_max_iterations(max_iter=max_iter)\n", - " gen.set_tolerance(tolerance=tolerance)\t\t\n", - " elif (gen_model==\"6PCM\"):\n", - " gen = dpsimpy.dp.ph1.SynchronGenerator6OrderPCM('gen', dpsimpy.LogLevel.debug)\n", - " gen.set_operational_parameters_per_unit(nom_power=nom_power, nom_voltage=nominal_voltage_mv, nom_frequency=frequency, \n", - " H=H, Ld=Ld, Lq=Lq, L0=L0, Ld_t=Ld_t, Lq_t=Lq_t, Td0_t=Td0_t, Tq0_t=Tq0_t,\n", - " Ld_s=Ld_s, Lq_s=Lq_s, Td0_s=Td0_s, Tq0_s=Tq0_s)\n", + " gen.set_tolerance(tolerance=tolerance)\n", + " elif gen_model == \"6PCM\":\n", + " gen = dpsimpy.dp.ph1.SynchronGenerator6OrderPCM(\"gen\", dpsimpy.LogLevel.debug)\n", + " gen.set_operational_parameters_per_unit(\n", + " nom_power=nom_power,\n", + " nom_voltage=nominal_voltage_mv,\n", + " nom_frequency=frequency,\n", + " H=H,\n", + " Ld=Ld,\n", + " Lq=Lq,\n", + " L0=L0,\n", + " Ld_t=Ld_t,\n", + " Lq_t=Lq_t,\n", + " Td0_t=Td0_t,\n", + " Tq0_t=Tq0_t,\n", + " Ld_s=Ld_s,\n", + " Lq_s=Lq_s,\n", + " Td0_s=Td0_s,\n", + " Tq0_s=Tq0_s,\n", + " )\n", " gen.set_max_iterations(max_iter=max_iter)\n", " gen.set_tolerance(tolerance=tolerance)\n", "\n", " # Switch\n", - " switch = dpsimpy.dp.ph1.Switch('Load_Add_Switch_', dpsimpy.LogLevel.debug)\n", - " resistance = abs(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0])**2 / load_step_activePower\n", + " switch = dpsimpy.dp.ph1.Switch(\"Load_Add_Switch_\", dpsimpy.LogLevel.debug)\n", + " resistance = (\n", + " abs(sim_pf.get_idobj_attr(n1_pf.name(), \"v\").get()[0][0]) ** 2\n", + " / load_step_activePower\n", + " )\n", " switch.set_parameters(1e9, resistance)\n", " switch.open()\n", "\n", " # pi line\n", - " pi_line = dpsimpy.dp.ph1.PiLine('PiLine', dpsimpy.LogLevel.debug)\n", - " pi_line.set_parameters(series_resistance=line_resistance,\n", - " series_inductance=line_inductance,\n", - " parallel_capacitance=line_capacitance,\n", - " parallel_conductance=line_conductance)\n", + " pi_line = dpsimpy.dp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", + " pi_line.set_parameters(\n", + " series_resistance=line_resistance,\n", + " series_inductance=line_inductance,\n", + " parallel_capacitance=line_capacitance,\n", + " parallel_conductance=line_conductance,\n", + " )\n", "\n", " # Slack\n", - " slack = dpsimpy.dp.ph1.NetworkInjection('slack', dpsimpy.LogLevel.debug)\n", + " slack = dpsimpy.dp.ph1.NetworkInjection(\"slack\", dpsimpy.LogLevel.debug)\n", " slack.set_parameters(V_ref=nominal_voltage_mv)\n", - " \n", + "\n", " ### Connections\n", " gen.connect([n1])\n", " switch.connect([gnd, n1])\n", " pi_line.connect([n1, n2])\n", " slack.connect([n2])\n", - " \n", + "\n", " ### Define system topology\n", " system = dpsimpy.SystemTopology(frequency, [n1, n2], [gen, pi_line, slack, switch])\n", "\n", " ### Logging\n", " logger = dpsimpy.Logger(name)\n", - " logger.log_attribute('Te', 'Te', gen)\n", + " logger.log_attribute(\"Te\", \"Te\", gen)\n", "\n", " # init node voltages and SG power with power flow\n", " system.init_with_powerflow(system_pf, dpsimpy.Domain.DP)\n", - " \n", + "\n", " ### Simulation\n", " sim = dpsimpy.Simulation(name, dpsimpy.LogLevel.debug)\n", " sim.set_system(system)\n", @@ -304,15 +391,15 @@ " sim.set_domain(dpsimpy.Domain.DP)\n", " sim.set_time_step(time_step)\n", " sim.set_final_time(final_time)\n", - " if (gen_model==\"4VBR\" or gen_model==\"6VBR\"):\n", + " if gen_model == \"4VBR\" or gen_model == \"6VBR\":\n", " sim.do_system_matrix_recomputation(True)\n", - " \n", + "\n", " sw_event_1 = dpsimpy.event.SwitchEvent(event_time, switch, True)\n", " sim.add_event(sw_event_1)\n", - " \n", + "\n", " sim.add_logger(logger)\n", " sim.run()\n", - " \n", + "\n", " return name" ] }, @@ -338,7 +425,14 @@ "metadata": {}, "outputs": [], "source": [ - "log_name = dp_reducedOrderSG_loadStep(sim_pf, gen_pf, gen_model=\"4VBR\", event_time=load_step_time, final_time=end_time, time_step=timestep_vbr)" + "log_name = dp_reducedOrderSG_loadStep(\n", + " sim_pf,\n", + " gen_pf,\n", + " gen_model=\"4VBR\",\n", + " event_time=load_step_time,\n", + " final_time=end_time,\n", + " time_step=timestep_vbr,\n", + ")" ] }, { @@ -351,9 +445,17 @@ "\n", "file_path = os.getcwd() + \"/logs/\" + log_name + \"/\" + log_name + \".csv\"\n", "ts_dpsim_4VBR = read_timeseries_dpsim(file_path)\n", - "ts_dpsim_4VBR['Te'] = TimeSeries('Te', ts_dpsim_4VBR['Te'].interpolate(timestep_pcm).time, ts_dpsim_4VBR['Te'].interpolate(timestep_pcm).values)\n", - "ts_dpsim_4VBR_roi={}\n", - "ts_dpsim_4VBR_roi['Te'] = TimeSeries('Te', ts_dpsim_4VBR['Te'].time[roi_begin_idx:roi_end_idx], ts_dpsim_4VBR['Te'].values[roi_begin_idx:roi_end_idx])" + "ts_dpsim_4VBR[\"Te\"] = TimeSeries(\n", + " \"Te\",\n", + " ts_dpsim_4VBR[\"Te\"].interpolate(timestep_pcm).time,\n", + " ts_dpsim_4VBR[\"Te\"].interpolate(timestep_pcm).values,\n", + ")\n", + "ts_dpsim_4VBR_roi = {}\n", + "ts_dpsim_4VBR_roi[\"Te\"] = TimeSeries(\n", + " \"Te\",\n", + " ts_dpsim_4VBR[\"Te\"].time[roi_begin_idx:roi_end_idx],\n", + " ts_dpsim_4VBR[\"Te\"].values[roi_begin_idx:roi_end_idx],\n", + ")" ] }, { @@ -370,7 +472,14 @@ "metadata": {}, "outputs": [], "source": [ - "log_name = dp_reducedOrderSG_loadStep(sim_pf, gen_pf, gen_model=\"6VBR\", event_time=load_step_time, final_time=end_time, time_step=timestep_vbr)" + "log_name = dp_reducedOrderSG_loadStep(\n", + " sim_pf,\n", + " gen_pf,\n", + " gen_model=\"6VBR\",\n", + " event_time=load_step_time,\n", + " final_time=end_time,\n", + " time_step=timestep_vbr,\n", + ")" ] }, { @@ -383,9 +492,17 @@ "\n", "file_path = os.getcwd() + \"/logs/\" + log_name + \"/\" + log_name + \".csv\"\n", "ts_dpsim_6VBR = read_timeseries_dpsim(file_path)\n", - "ts_dpsim_6VBR['Te'] = TimeSeries('Te', ts_dpsim_6VBR['Te'].interpolate(timestep_pcm).time, ts_dpsim_6VBR['Te'].interpolate(timestep_pcm).values)\n", - "ts_dpsim_6VBR_roi={}\n", - "ts_dpsim_6VBR_roi['Te'] = TimeSeries('Te', ts_dpsim_6VBR['Te'].time[roi_begin_idx:roi_end_idx], ts_dpsim_6VBR['Te'].values[roi_begin_idx:roi_end_idx])" + "ts_dpsim_6VBR[\"Te\"] = TimeSeries(\n", + " \"Te\",\n", + " ts_dpsim_6VBR[\"Te\"].interpolate(timestep_pcm).time,\n", + " ts_dpsim_6VBR[\"Te\"].interpolate(timestep_pcm).values,\n", + ")\n", + "ts_dpsim_6VBR_roi = {}\n", + "ts_dpsim_6VBR_roi[\"Te\"] = TimeSeries(\n", + " \"Te\",\n", + " ts_dpsim_6VBR[\"Te\"].time[roi_begin_idx:roi_end_idx],\n", + " ts_dpsim_6VBR[\"Te\"].values[roi_begin_idx:roi_end_idx],\n", + ")" ] }, { @@ -402,7 +519,16 @@ "metadata": {}, "outputs": [], "source": [ - "log_name = dp_reducedOrderSG_loadStep(sim_pf, gen_pf, gen_model=\"4PCM\", event_time=load_step_time, final_time=end_time, time_step=timestep_pcm, max_iter=max_iter, tolerance=tolerance)" + "log_name = dp_reducedOrderSG_loadStep(\n", + " sim_pf,\n", + " gen_pf,\n", + " gen_model=\"4PCM\",\n", + " event_time=load_step_time,\n", + " final_time=end_time,\n", + " time_step=timestep_pcm,\n", + " max_iter=max_iter,\n", + " tolerance=tolerance,\n", + ")" ] }, { @@ -415,8 +541,12 @@ "\n", "file_path = os.getcwd() + \"/logs/\" + log_name + \"/\" + log_name + \".csv\"\n", "ts_dpsim_4PCM = read_timeseries_dpsim(file_path)\n", - "ts_dpsim_4PCM_roi={}\n", - "ts_dpsim_4PCM_roi['Te'] = TimeSeries('Te', ts_dpsim_4PCM['Te'].time[roi_begin_idx:roi_end_idx], ts_dpsim_4PCM['Te'].values[roi_begin_idx:roi_end_idx])" + "ts_dpsim_4PCM_roi = {}\n", + "ts_dpsim_4PCM_roi[\"Te\"] = TimeSeries(\n", + " \"Te\",\n", + " ts_dpsim_4PCM[\"Te\"].time[roi_begin_idx:roi_end_idx],\n", + " ts_dpsim_4PCM[\"Te\"].values[roi_begin_idx:roi_end_idx],\n", + ")" ] }, { @@ -433,7 +563,16 @@ "metadata": {}, "outputs": [], "source": [ - "log_name = dp_reducedOrderSG_loadStep(sim_pf, gen_pf, gen_model=\"6PCM\", event_time=load_step_time, final_time=end_time, time_step=timestep_pcm, max_iter=max_iter, tolerance=tolerance)" + "log_name = dp_reducedOrderSG_loadStep(\n", + " sim_pf,\n", + " gen_pf,\n", + " gen_model=\"6PCM\",\n", + " event_time=load_step_time,\n", + " final_time=end_time,\n", + " time_step=timestep_pcm,\n", + " max_iter=max_iter,\n", + " tolerance=tolerance,\n", + ")" ] }, { @@ -445,8 +584,12 @@ "# read Simulink log file\n", "file_path = os.getcwd() + \"/logs/\" + log_name + \"/\" + log_name + \".csv\"\n", "ts_dpsim_6PCM = read_timeseries_dpsim(file_path)\n", - "ts_dpsim_6PCM_roi={}\n", - "ts_dpsim_6PCM_roi['Te'] = TimeSeries('Te', ts_dpsim_6PCM['Te'].time[roi_begin_idx:roi_end_idx], ts_dpsim_6PCM['Te'].values[roi_begin_idx:roi_end_idx])" + "ts_dpsim_6PCM_roi = {}\n", + "ts_dpsim_6PCM_roi[\"Te\"] = TimeSeries(\n", + " \"Te\",\n", + " ts_dpsim_6PCM[\"Te\"].time[roi_begin_idx:roi_end_idx],\n", + " ts_dpsim_6PCM[\"Te\"].values[roi_begin_idx:roi_end_idx],\n", + ")" ] }, { @@ -472,8 +615,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(ts_dpsim_4VBR['Te'].time, ts_dpsim_4VBR['Te'].values, label='VBR')\n", - "plt.plot(ts_dpsim_4PCM['Te'].time, ts_dpsim_4PCM['Te'].values, linestyle='--', label='4 Order PCM - MaxIter 10')\n", + "plt.plot(ts_dpsim_4VBR[\"Te\"].time, ts_dpsim_4VBR[\"Te\"].values, label=\"VBR\")\n", + "plt.plot(\n", + " ts_dpsim_4PCM[\"Te\"].time,\n", + " ts_dpsim_4PCM[\"Te\"].values,\n", + " linestyle=\"--\",\n", + " label=\"4 Order PCM - MaxIter 10\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -484,9 +632,13 @@ "metadata": {}, "outputs": [], "source": [ - "rmse = ts_dpsim_4VBR_roi['Te'].rmse(ts_dpsim_4PCM_roi['Te'], ts_dpsim_4VBR_roi['Te'])/te_ref*100\n", - "print('RMSE of PCM 4 Order = {}%'.format(rmse))\n", - "assert(rmse<0.449)" + "rmse = (\n", + " ts_dpsim_4VBR_roi[\"Te\"].rmse(ts_dpsim_4PCM_roi[\"Te\"], ts_dpsim_4VBR_roi[\"Te\"])\n", + " / te_ref\n", + " * 100\n", + ")\n", + "print(\"RMSE of PCM 4 Order = {}%\".format(rmse))\n", + "assert rmse < 0.449" ] }, { @@ -504,8 +656,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(ts_dpsim_6VBR['Te'].time, ts_dpsim_6VBR['Te'].values, label='6 Order VBR')\n", - "plt.plot(ts_dpsim_6PCM['Te'].time, ts_dpsim_6PCM['Te'].values, linestyle='--', label='6 Order PCM - MaxIter 10')\n", + "plt.plot(ts_dpsim_6VBR[\"Te\"].time, ts_dpsim_6VBR[\"Te\"].values, label=\"6 Order VBR\")\n", + "plt.plot(\n", + " ts_dpsim_6PCM[\"Te\"].time,\n", + " ts_dpsim_6PCM[\"Te\"].values,\n", + " linestyle=\"--\",\n", + " label=\"6 Order PCM - MaxIter 10\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -516,9 +673,13 @@ "metadata": {}, "outputs": [], "source": [ - "rmse = ts_dpsim_6VBR_roi['Te'].rmse(ts_dpsim_6PCM_roi['Te'], ts_dpsim_6VBR_roi['Te'])/te_ref*100\n", - "print('RMSE of PCM 6 Order = {}%'.format(rmse))\n", - "assert(rmse<0.381)" + "rmse = (\n", + " ts_dpsim_6VBR_roi[\"Te\"].rmse(ts_dpsim_6PCM_roi[\"Te\"], ts_dpsim_6VBR_roi[\"Te\"])\n", + " / te_ref\n", + " * 100\n", + ")\n", + "print(\"RMSE of PCM 6 Order = {}%\".format(rmse))\n", + "assert rmse < 0.381" ] }, { diff --git a/examples/Notebooks/Circuits/Compare_DP_SMIB_ReducedOrderSG_VBR_TPM_LoadStep.ipynb b/examples/Notebooks/Circuits/Compare_DP_SMIB_ReducedOrderSG_VBR_TPM_LoadStep.ipynb index 8b698f4583..0c05a17f1a 100644 --- a/examples/Notebooks/Circuits/Compare_DP_SMIB_ReducedOrderSG_VBR_TPM_LoadStep.ipynb +++ b/examples/Notebooks/Circuits/Compare_DP_SMIB_ReducedOrderSG_VBR_TPM_LoadStep.ipynb @@ -32,7 +32,7 @@ "from villas.dataprocessing.timeseries import *\n", "import matplotlib.pyplot as plt\n", "\n", - "#%matplotlib widget" + "# %matplotlib widget" ] }, { @@ -49,13 +49,18 @@ "metadata": {}, "outputs": [], "source": [ - "root_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", - "path_exec = root_path + '/build/dpsim/examples/cxx/'\n", + "root_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", + "path_exec = root_path + \"/build/dpsim/examples/cxx/\"\n", "\n", - "name_executable_vbr = 'DP_SMIB_ReducedOrderSG_LoadStep'\n", + "name_executable_vbr = \"DP_SMIB_ReducedOrderSG_LoadStep\"\n", "name_vbr = \"DP_SMIB_ReducedOrderSG_VBR_LoadStep\"\n", "\n", - "name_executable_tpm = 'DP_SMIB_ReducedOrderSGIterative_LoadStep'\n", + "name_executable_tpm = \"DP_SMIB_ReducedOrderSGIterative_LoadStep\"\n", "name_tpm = \"DP_SMIB_ReducedOrderSGIterative_LoadStep\"\n", "\n", "# times in s\n", @@ -67,19 +72,19 @@ "# tpm config params\n", "max_iter_array = [0, 1, 2, 5, 10, 20]\n", "tolerance = 1e-10\n", - "sg_model = '4TPM'\n", + "sg_model = \"4TPM\"\n", "\n", "\n", - "roi_begin_idx = int(roi_begin/timestep)\n", - "roi_end_idx = int(roi_end/timestep)\n", + "roi_begin_idx = int(roi_begin / timestep)\n", + "roi_end_idx = int(roi_end / timestep)\n", "\n", - "timestep_str = '{:1.6f}'.format(timestep)\n", + "timestep_str = \"{:1.6f}\".format(timestep)\n", "\n", - "logs_path = 'logs'\n", + "logs_path = \"logs\"\n", "if not os.path.exists(logs_path):\n", " os.mkdir(logs_path)\n", - " \n", - "var_name = 'SynGen.Te'\n", + "\n", + "var_name = \"SynGen.Te\"\n", "\n", "te_ref = 0.5454986888690558" ] @@ -99,15 +104,19 @@ "outputs": [], "source": [ "options_list_vbr = []\n", - "options_list_vbr.append('loadStepEventTime=' + str(load_step_time))\n", - "options_list_vbr.append('TimeStep=' + timestep_str)\n", - "options_list_vbr.append('SimName=' + name_vbr)\n", + "options_list_vbr.append(\"loadStepEventTime=\" + str(load_step_time))\n", + "options_list_vbr.append(\"TimeStep=\" + timestep_str)\n", + "options_list_vbr.append(\"SimName=\" + name_vbr)\n", "\n", "args_options_list_vbr = []\n", "for option in options_list_vbr:\n", - " args_options_list_vbr.extend(['--option', option])\n", + " args_options_list_vbr.extend([\"--option\", option])\n", "\n", - "simVBR = subprocess.Popen([path_exec + name_executable_vbr] + args_options_list_vbr, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "simVBR = subprocess.Popen(\n", + " [path_exec + name_executable_vbr] + args_options_list_vbr,\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(simVBR.communicate()[0].decode())" ] }, @@ -119,7 +128,11 @@ "source": [ "results_path_vbr = logs_path + \"/\" + name_vbr + \"/\" + name_vbr + \".csv\"\n", "ts_vbr = read_timeseries_dpsim(results_path_vbr)[var_name]\n", - "ts_vbr_roi = TimeSeries(ts_vbr.name+'roi',ts_vbr.time[roi_begin_idx:roi_end_idx],ts_vbr.values[roi_begin_idx:roi_end_idx])" + "ts_vbr_roi = TimeSeries(\n", + " ts_vbr.name + \"roi\",\n", + " ts_vbr.time[roi_begin_idx:roi_end_idx],\n", + " ts_vbr.values[roi_begin_idx:roi_end_idx],\n", + ")" ] }, { @@ -137,18 +150,29 @@ "outputs": [], "source": [ "options_list_tpm = []\n", - "options_list_tpm.append('loadStepEventTime=' + str(load_step_time))\n", - "options_list_tpm.append('TimeStep=' + timestep_str)\n", - "options_list_tpm.append('Tolerance=' + str(tolerance))\n", - "options_list_tpm.append('SGModel=' + str(sg_model)) \n", + "options_list_tpm.append(\"loadStepEventTime=\" + str(load_step_time))\n", + "options_list_tpm.append(\"TimeStep=\" + timestep_str)\n", + "options_list_tpm.append(\"Tolerance=\" + str(tolerance))\n", + "options_list_tpm.append(\"SGModel=\" + str(sg_model))\n", "\n", "args_options_list_tpm = []\n", "for option in options_list_tpm:\n", - " args_options_list_tpm.extend(['--option', option])\n", + " args_options_list_tpm.extend([\"--option\", option])\n", "\n", "for max_iter in max_iter_array:\n", - " name_iter = name_tpm + '_MaxIter' + str(max_iter)\n", - " simTPM = subprocess.Popen([path_exec + name_executable_tpm, '--option', 'SimName=' + name_iter, '--option', 'MaxIter=' + str(max_iter)] + args_options_list_tpm, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + " name_iter = name_tpm + \"_MaxIter\" + str(max_iter)\n", + " simTPM = subprocess.Popen(\n", + " [\n", + " path_exec + name_executable_tpm,\n", + " \"--option\",\n", + " \"SimName=\" + name_iter,\n", + " \"--option\",\n", + " \"MaxIter=\" + str(max_iter),\n", + " ]\n", + " + args_options_list_tpm,\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + " )\n", " print(simTPM.communicate()[0].decode())" ] }, @@ -163,10 +187,16 @@ "ts_tpm = []\n", "ts_tpm_roi = []\n", "for max_iter in max_iter_array:\n", - " name_iter = name_tpm + '_MaxIter' + str(max_iter)\n", + " name_iter = name_tpm + \"_MaxIter\" + str(max_iter)\n", " results_path_iter = logs_path + \"/\" + name_iter + \"/\" + name_iter + \".csv\"\n", " ts_tpm.append(read_timeseries_dpsim(results_path_iter)[var_name])\n", - " ts_tpm_roi.append(TimeSeries(ts_tpm[-1].name+'roi',ts_tpm[-1].time[roi_begin_idx:roi_end_idx],ts_tpm[-1].values[roi_begin_idx:roi_end_idx]))" + " ts_tpm_roi.append(\n", + " TimeSeries(\n", + " ts_tpm[-1].name + \"roi\",\n", + " ts_tpm[-1].time[roi_begin_idx:roi_end_idx],\n", + " ts_tpm[-1].values[roi_begin_idx:roi_end_idx],\n", + " )\n", + " )" ] }, { @@ -192,11 +222,16 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(ts_vbr.time, ts_vbr.values, label='VBR')\n", + "plt.plot(ts_vbr.time, ts_vbr.values, label=\"VBR\")\n", "\n", "for max_iter in max_iter_array:\n", " max_iter_idx = max_iter_array.index(max_iter)\n", - " plt.plot(ts_tpm[max_iter_idx].time, ts_tpm[max_iter_idx].values, linestyle='--', label='TPM - MaxIter' + str(max_iter))\n", + " plt.plot(\n", + " ts_tpm[max_iter_idx].time,\n", + " ts_tpm[max_iter_idx].values,\n", + " linestyle=\"--\",\n", + " label=\"TPM - MaxIter\" + str(max_iter),\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -217,11 +252,16 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(ts_vbr_roi.time, ts_vbr_roi.values, label='VBR')\n", + "plt.plot(ts_vbr_roi.time, ts_vbr_roi.values, label=\"VBR\")\n", "\n", "for max_iter in max_iter_array:\n", " max_iter_idx = max_iter_array.index(max_iter)\n", - " plt.plot(ts_tpm_roi[max_iter_idx].time, ts_tpm_roi[max_iter_idx].values, linestyle='--', label='TPM - MaxIter' + str(max_iter))\n", + " plt.plot(\n", + " ts_tpm_roi[max_iter_idx].time,\n", + " ts_tpm_roi[max_iter_idx].values,\n", + " linestyle=\"--\",\n", + " label=\"TPM - MaxIter\" + str(max_iter),\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -244,8 +284,10 @@ "rmse_list = []\n", "for max_iter in max_iter_array:\n", " max_iter_idx = max_iter_array.index(max_iter)\n", - " rmse_list.append(ts_vbr_roi.rmse(ts_tpm_roi[max_iter_idx], ts_vbr_roi)/te_ref*100)\n", - " print('RMSE of TPM with MaxIter={}: {}%'.format(max_iter,rmse_list[-1]))" + " rmse_list.append(\n", + " ts_vbr_roi.rmse(ts_tpm_roi[max_iter_idx], ts_vbr_roi) / te_ref * 100\n", + " )\n", + " print(\"RMSE of TPM with MaxIter={}: {}%\".format(max_iter, rmse_list[-1]))" ] }, { @@ -262,12 +304,12 @@ "metadata": {}, "outputs": [], "source": [ - "assert(rmse_list[0]<0.32)\n", - "assert(rmse_list[1]<0.54)\n", - "assert(rmse_list[2]<0.31)\n", - "assert(rmse_list[3]<0.07)\n", - "assert(rmse_list[4]<0.003)\n", - "assert(rmse_list[5]<2.4e-5)" + "assert rmse_list[0] < 0.32\n", + "assert rmse_list[1] < 0.54\n", + "assert rmse_list[2] < 0.31\n", + "assert rmse_list[3] < 0.07\n", + "assert rmse_list[4] < 0.003\n", + "assert rmse_list[5] < 2.4e-5" ] } ], diff --git a/examples/Notebooks/Circuits/Compare_EMT_DP_Slack_PiLine_PQLoad.ipynb b/examples/Notebooks/Circuits/Compare_EMT_DP_Slack_PiLine_PQLoad.ipynb index 61ecca2b9b..546fa81c99 100644 --- a/examples/Notebooks/Circuits/Compare_EMT_DP_Slack_PiLine_PQLoad.ipynb +++ b/examples/Notebooks/Circuits/Compare_EMT_DP_Slack_PiLine_PQLoad.ipynb @@ -40,23 +40,23 @@ "# POWERFLOW FOR INITIALIZATION\n", "time_step_pf = final_time\n", "final_time_pf = final_time + time_step_pf\n", - "sim_name_pf = 'EMT_Slack_PiLine_PQLoad_with_PF_Init_PF'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "sim_name_pf = \"EMT_Slack_PiLine_PQLoad_with_PF_Init_PF\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "\n", "# Components\n", - "n1_pf = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single)\n", - "n2_pf = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single)\n", + "n1_pf = dpsimpy.sp.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "n2_pf = dpsimpy.sp.SimNode(\"n2\", dpsimpy.PhaseType.Single)\n", "\n", - "extnet_pf = dpsimpy.sp.ph1.NetworkInjection('Slack', dpsimpy.LogLevel.debug)\n", + "extnet_pf = dpsimpy.sp.ph1.NetworkInjection(\"Slack\", dpsimpy.LogLevel.debug)\n", "extnet_pf.set_parameters(voltage_set_point=V_nom)\n", "extnet_pf.set_base_voltage(V_nom)\n", "extnet_pf.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", "\n", - "line_pf = dpsimpy.sp.ph1.PiLine('PiLine', dpsimpy.LogLevel.debug)\n", + "line_pf = dpsimpy.sp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", "line_pf.set_parameters(R=line_resistance, L=line_inductance, C=line_capacitance)\n", "line_pf.set_base_voltage(V_nom)\n", "\n", - "load_pf = dpsimpy.sp.ph1.Shunt('Load', dpsimpy.LogLevel.debug)\n", + "load_pf = dpsimpy.sp.ph1.Shunt(\"Load\", dpsimpy.LogLevel.debug)\n", "load_pf.set_parameters(G=p_load_nom / (V_nom**2), B=-q_load_nom / (V_nom**2))\n", "load_pf.set_base_voltage(V_nom)\n", "\n", @@ -68,9 +68,9 @@ "\n", "# Logging\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", - "logger_pf.log_attribute('v1', 'v', n1_pf)\n", - "logger_pf.log_attribute('v2', 'v', n2_pf)\n", - "logger_pf.log_attribute('i12', 'i_intf', line_pf)\n", + "logger_pf.log_attribute(\"v1\", \"v\", n1_pf)\n", + "logger_pf.log_attribute(\"v2\", \"v\", n2_pf)\n", + "logger_pf.log_attribute(\"i12\", \"i_intf\", line_pf)\n", "\n", "# Simulation\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", @@ -88,52 +88,58 @@ "# DYNAMIC SIMULATION\n", "time_step_emt = time_step\n", "final_time_emt = final_time + time_step_emt\n", - "sim_name_emt = 'EMT_Slack_PiLine_PQLoad_with_PF_Init_EMT'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_emt)\n", + "sim_name_emt = \"EMT_Slack_PiLine_PQLoad_with_PF_Init_EMT\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_emt)\n", "\n", "# Components\n", "gnd = dpsimpy.emt.SimNode.gnd\n", - "n1_emt = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", - "n2_emt = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "n1_emt = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.ABC)\n", + "n2_emt = dpsimpy.emt.SimNode(\"n2\", dpsimpy.PhaseType.ABC)\n", "\n", - "extnet_emt = dpsimpy.emt.ph3.NetworkInjection('Slack', dpsimpy.LogLevel.debug)\n", - "line_emt = dpsimpy.emt.ph3.PiLine('PiLine', dpsimpy.LogLevel.debug)\n", + "extnet_emt = dpsimpy.emt.ph3.NetworkInjection(\"Slack\", dpsimpy.LogLevel.debug)\n", + "line_emt = dpsimpy.emt.ph3.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", "\n", - "line_emt.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(line_resistance),\n", - " dpsimpy.Math.single_phase_parameter_to_three_phase(line_inductance),\n", - " dpsimpy.Math.single_phase_parameter_to_three_phase(line_capacitance))\n", + "line_emt.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(line_resistance),\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(line_inductance),\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(line_capacitance),\n", + ")\n", "\n", - "load_emt = dpsimpy.emt.ph3.RXLoad('Load', dpsimpy.LogLevel.debug)\n", - "load_emt.set_parameters(dpsimpy.Math.single_phase_power_to_three_phase(p_load_nom),\n", - " dpsimpy.Math.single_phase_power_to_three_phase(q_load_nom),\n", - " V_nom)\n", + "load_emt = dpsimpy.emt.ph3.RXLoad(\"Load\", dpsimpy.LogLevel.debug)\n", + "load_emt.set_parameters(\n", + " dpsimpy.Math.single_phase_power_to_three_phase(p_load_nom),\n", + " dpsimpy.Math.single_phase_power_to_three_phase(q_load_nom),\n", + " V_nom,\n", + ")\n", "\n", "\n", "# Topology\n", "extnet_emt.connect([n1_emt])\n", "line_emt.connect([n1_emt, n2_emt])\n", "load_emt.connect([n2_emt])\n", - "system_emt = dpsimpy.SystemTopology(50, [n1_emt, n2_emt], [extnet_emt, line_emt, load_emt])\n", + "system_emt = dpsimpy.SystemTopology(\n", + " 50, [n1_emt, n2_emt], [extnet_emt, line_emt, load_emt]\n", + ")\n", "\n", "# Initialization of dynamic topology\n", "system_emt.init_with_powerflow(system_pf, dpsimpy.Domain.EMT)\n", "\n", "# Logging\n", "logger_emt = dpsimpy.Logger(sim_name_emt)\n", - "logger_emt.log_attribute('v1', 'v', n1_emt)\n", - "logger_emt.log_attribute('v2', 'v', n2_emt)\n", - "logger_emt.log_attribute('i12', 'i_intf', line_emt)\n", - "logger_emt.log_attribute('irx', 'i_intf', load_emt)\n", + "logger_emt.log_attribute(\"v1\", \"v\", n1_emt)\n", + "logger_emt.log_attribute(\"v2\", \"v\", n2_emt)\n", + "logger_emt.log_attribute(\"i12\", \"i_intf\", line_emt)\n", + "logger_emt.log_attribute(\"irx\", \"i_intf\", load_emt)\n", "\n", "# load step sized in absolute terms\n", "load_switch = dpsimpy.emt.ph3.Switch(\"Load_Add_Switch_n2\", dpsimpy.LogLevel.debug)\n", - "connection_node = system_emt.node('n2')\n", - "resistance = np.abs(connection_node.initial_single_voltage())**2 / 100e3\n", - "load_switch.set_parameters(np.identity(3)*1e9, np.identity(3)*resistance)\n", + "connection_node = system_emt.node(\"n2\")\n", + "resistance = np.abs(connection_node.initial_single_voltage()) ** 2 / 100e3\n", + "load_switch.set_parameters(np.identity(3) * 1e9, np.identity(3) * resistance)\n", "load_switch.open()\n", "system_emt.add(load_switch)\n", - "system_emt.connect_component(load_switch, [gnd, system_emt.node('n2')])\n", - "logger_emt.log_attribute('switchedload_i', 'i_intf', load_switch)\n", + "system_emt.connect_component(load_switch, [gnd, system_emt.node(\"n2\")])\n", + "logger_emt.log_attribute(\"switchedload_i\", \"i_intf\", load_switch)\n", "load_step_event = dpsimpy.event.SwitchEvent3Ph(0.1 - time_step_emt, load_switch, True)\n", "\n", "# Simulation\n", @@ -175,23 +181,23 @@ "# POWERFLOW FOR INITIALIZATION\n", "time_step_pf = final_time\n", "final_time_pf = final_time + time_step_pf\n", - "sim_name_pf = 'DP_Slack_PiLine_PQLoad_with_PF_Init_PF'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "sim_name_pf = \"DP_Slack_PiLine_PQLoad_with_PF_Init_PF\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "\n", "# Components\n", - "n1_pf = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single)\n", - "n2_pf = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single)\n", + "n1_pf = dpsimpy.sp.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "n2_pf = dpsimpy.sp.SimNode(\"n2\", dpsimpy.PhaseType.Single)\n", "\n", - "extnet_pf = dpsimpy.sp.ph1.NetworkInjection('Slack', dpsimpy.LogLevel.debug)\n", + "extnet_pf = dpsimpy.sp.ph1.NetworkInjection(\"Slack\", dpsimpy.LogLevel.debug)\n", "extnet_pf.set_parameters(voltage_set_point=V_nom)\n", "extnet_pf.set_base_voltage(V_nom)\n", "extnet_pf.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", "\n", - "line_pf = dpsimpy.sp.ph1.PiLine('PiLine', dpsimpy.LogLevel.debug)\n", + "line_pf = dpsimpy.sp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", "line_pf.set_parameters(R=line_resistance, L=line_inductance, C=line_capacitance)\n", "line_pf.set_base_voltage(V_nom)\n", "\n", - "load_pf = dpsimpy.sp.ph1.Shunt('Load', dpsimpy.LogLevel.debug)\n", + "load_pf = dpsimpy.sp.ph1.Shunt(\"Load\", dpsimpy.LogLevel.debug)\n", "load_pf.set_parameters(G=p_load_nom / V_nom**2, B=-q_load_nom / V_nom**2)\n", "load_pf.set_base_voltage(V_nom)\n", "\n", @@ -203,9 +209,9 @@ "\n", "# Logging\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", - "logger_pf.log_attribute('v1', 'v', n1_pf)\n", - "logger_pf.log_attribute('v2', 'v', n2_pf)\n", - "logger_pf.log_attribute('i12', 'i_intf', line_pf)\n", + "logger_pf.log_attribute(\"v1\", \"v\", n1_pf)\n", + "logger_pf.log_attribute(\"v2\", \"v\", n2_pf)\n", + "logger_pf.log_attribute(\"i12\", \"i_intf\", line_pf)\n", "\n", "# Simulation\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", @@ -222,21 +228,21 @@ "# DYNAMIC SIMULATION\n", "time_step_dp = time_step\n", "final_time_dp = final_time + time_step_dp\n", - "sim_name_dp = 'DP_Slack_PiLine_PQLoad_with_PF_Init_DP'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_dp)\n", + "sim_name_dp = \"DP_Slack_PiLine_PQLoad_with_PF_Init_DP\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_dp)\n", "\n", "# Components\n", "gnd = dpsimpy.dp.SimNode.gnd\n", - "n1_dp = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single)\n", - "n2_dp = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single)\n", + "n1_dp = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "n2_dp = dpsimpy.dp.SimNode(\"n2\", dpsimpy.PhaseType.Single)\n", "\n", - "extnet_dp = dpsimpy.dp.ph1.NetworkInjection('Slack', dpsimpy.LogLevel.debug)\n", + "extnet_dp = dpsimpy.dp.ph1.NetworkInjection(\"Slack\", dpsimpy.LogLevel.debug)\n", "extnet_dp.set_parameters(complex(V_nom, 0))\n", "\n", - "line_dp = dpsimpy.dp.ph1.PiLine('PiLine', dpsimpy.LogLevel.debug)\n", + "line_dp = dpsimpy.dp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", "line_dp.set_parameters(line_resistance, line_inductance, line_capacitance)\n", "\n", - "load_dp = dpsimpy.dp.ph1.RXLoad('Load', dpsimpy.LogLevel.debug)\n", + "load_dp = dpsimpy.dp.ph1.RXLoad(\"Load\", dpsimpy.LogLevel.debug)\n", "load_dp.set_parameters(p_load_nom, q_load_nom, V_nom)\n", "\n", "# Topology\n", @@ -250,20 +256,20 @@ "\n", "# Logging\n", "logger_dp = dpsimpy.Logger(sim_name_dp)\n", - "logger_dp.log_attribute('v1', 'v', n1_dp)\n", - "logger_dp.log_attribute('v2', 'v', n2_dp)\n", - "logger_dp.log_attribute('i12', 'i_intf', line_dp)\n", - "logger_dp.log_attribute('irx', 'i_intf', load_dp)\n", + "logger_dp.log_attribute(\"v1\", \"v\", n1_dp)\n", + "logger_dp.log_attribute(\"v2\", \"v\", n2_dp)\n", + "logger_dp.log_attribute(\"i12\", \"i_intf\", line_dp)\n", + "logger_dp.log_attribute(\"irx\", \"i_intf\", load_dp)\n", "\n", "# load step sized in absolute terms\n", "load_switch = dpsimpy.dp.ph1.Switch(\"Load_Add_Switch_n2\", dpsimpy.LogLevel.debug)\n", - "connection_node = system_dp.node('n2')\n", - "resistance = np.abs(connection_node.initial_single_voltage())**2 / 100e3\n", + "connection_node = system_dp.node(\"n2\")\n", + "resistance = np.abs(connection_node.initial_single_voltage()) ** 2 / 100e3\n", "load_switch.set_parameters(1e9, resistance)\n", "load_switch.open()\n", "system_dp.add(load_switch)\n", - "system_dp.connect_component(load_switch, [gnd, system_dp.node('n2')])\n", - "logger_dp.log_attribute('switchedload_i', 'i_intf', load_switch)\n", + "system_dp.connect_component(load_switch, [gnd, system_dp.node(\"n2\")])\n", + "logger_dp.log_attribute(\"switchedload_i\", \"i_intf\", load_switch)\n", "load_step_event = dpsimpy.event.SwitchEvent(0.1 - time_step_dp, load_switch, True)\n", "\n", "# Simulation\n", @@ -290,14 +296,14 @@ "metadata": {}, "outputs": [], "source": [ - "model_name = 'Slack_PiLine_PQLoad_with_PF_Init'\n", + "model_name = \"Slack_PiLine_PQLoad_with_PF_Init\"\n", "\n", - "path_DP = 'logs/' + 'DP_' + model_name + '_DP/'\n", - "dpsim_result_file_DP = path_DP + 'DP_' + model_name + '_DP.csv'\n", + "path_DP = \"logs/\" + \"DP_\" + model_name + \"_DP/\"\n", + "dpsim_result_file_DP = path_DP + \"DP_\" + model_name + \"_DP.csv\"\n", "ts_dpsim_DP = read_timeseries_csv(dpsim_result_file_DP)\n", "\n", - "path_EMT = 'logs/' + 'EMT_' + model_name + '_EMT/'\n", - "dpsim_result_file_EMT = path_EMT + 'EMT_' + model_name + '_EMT.csv'\n", + "path_EMT = \"logs/\" + \"EMT_\" + model_name + \"_EMT/\"\n", + "dpsim_result_file_EMT = path_EMT + \"EMT_\" + model_name + \"_EMT.csv\"\n", "ts_dpsim_EMT = read_timeseries_csv(dpsim_result_file_EMT)" ] }, @@ -316,15 +322,24 @@ "source": [ "import matplotlib.pyplot as plt\n", "\n", - "#%matplotlib widget\n", + "# %matplotlib widget\n", "\n", - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", + "\n", + "var_names = [\"v1\", \"v2\"]\n", + "for var_name in var_names:\n", + " plt.plot(\n", + " ts_dpsim_EMT[var_name + \"_0\"].interpolate(50e-6).time,\n", + " np.sqrt(3 / 2) * ts_dpsim_EMT[var_name + \"_0\"].interpolate(50e-6).values,\n", + " label=\"EMT\",\n", + " )\n", + " plt.plot(\n", + " ts_dpsim_DP[var_name].interpolate(50e-6).time,\n", + " ts_dpsim_DP[var_name].interpolate(50e-6).frequency_shift(50).values,\n", + " label=\"DP backshift\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", - "var_names = ['v1','v2']\n", - "for var_name in var_names: \n", - " plt.plot(ts_dpsim_EMT[var_name+'_0'].interpolate(50e-6).time, np.sqrt(3/2)*ts_dpsim_EMT[var_name+'_0'].interpolate(50e-6).values, label='EMT')\n", - " plt.plot(ts_dpsim_DP[var_name].interpolate(50e-6).time, ts_dpsim_DP[var_name].interpolate(50e-6).frequency_shift(50).values, label='DP backshift', linestyle='--')\n", - " \n", "plt.legend()\n", "plt.show()" ] @@ -342,14 +357,22 @@ "metadata": {}, "outputs": [], "source": [ - "var_name = 'i12'\n", - "\n", - "ts_emt_compare = TimeSeries('ts_emt_compare', ts_dpsim_EMT[var_name+'_0'].interpolate(50e-6).time, np.sqrt(3/2)*ts_dpsim_EMT[var_name+'_0'].interpolate(50e-6).values)\n", - "ts_dp_compare = TimeSeries('ts_dp_compare', ts_dpsim_DP[var_name].interpolate(50e-6).time, ts_dpsim_DP[var_name].interpolate(50e-6).frequency_shift(50).values)\n", - "\n", - "plt.figure(figsize=(12,8))\n", - "plt.plot(ts_emt_compare.time, ts_emt_compare.values, label='EMT')\n", - "plt.plot(ts_dp_compare.time, ts_dp_compare.values, label='DP backshift', linestyle='--')\n", + "var_name = \"i12\"\n", + "\n", + "ts_emt_compare = TimeSeries(\n", + " \"ts_emt_compare\",\n", + " ts_dpsim_EMT[var_name + \"_0\"].interpolate(50e-6).time,\n", + " np.sqrt(3 / 2) * ts_dpsim_EMT[var_name + \"_0\"].interpolate(50e-6).values,\n", + ")\n", + "ts_dp_compare = TimeSeries(\n", + " \"ts_dp_compare\",\n", + " ts_dpsim_DP[var_name].interpolate(50e-6).time,\n", + " ts_dpsim_DP[var_name].interpolate(50e-6).frequency_shift(50).values,\n", + ")\n", + "\n", + "plt.figure(figsize=(12, 8))\n", + "plt.plot(ts_emt_compare.time, ts_emt_compare.values, label=\"EMT\")\n", + "plt.plot(ts_dp_compare.time, ts_dp_compare.values, label=\"DP backshift\", linestyle=\"--\")\n", "plt.legend()\n", "plt.show()" ] diff --git a/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_DP_SynGenTrStab_SMIB_Fault.ipynb b/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_DP_SynGenTrStab_SMIB_Fault.ipynb index 7547add118..5027bd41c5 100644 --- a/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_DP_SynGenTrStab_SMIB_Fault.ipynb +++ b/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_DP_SynGenTrStab_SMIB_Fault.ipynb @@ -22,7 +22,7 @@ "import math\n", "import dpsimpy\n", "\n", - "#matplotlib widget" + "# matplotlib widget" ] }, { @@ -69,15 +69,15 @@ "Td0_s = 0.0300\n", "Tq0_s = 0.0700\n", "\n", - "# Operation point synchronous generator \n", + "# Operation point synchronous generator\n", "set_point_active_power = 300e6\n", - "set_point_voltage = 1.05*V_nom_MV\n", + "set_point_voltage = 1.05 * V_nom_MV\n", "\n", "# Breaker\n", "breaker_open = 1e9\n", "breaker_closed = 0.001\n", "\n", - "# Line \n", + "# Line\n", "line_lenght = 100\n", "line_resistance = 1.27e-4 * 529.0 * line_lenght * ratio**2\n", "line_inductance = 9.05e-4 * 529.0 * line_lenght * ratio**2 / nom_omega\n", @@ -85,7 +85,7 @@ "line_conductance = 8e-2\n", "\n", "# Simulation parameters\n", - "sim_name = \"EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault\";\n", + "sim_name = \"EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault\"\n", "final_time = 1.0\n", "time_step = 10e-6\n", "start_time_fault = 0.2" @@ -116,10 +116,13 @@ "\n", "# Synchronous generator ideal model\n", "gen_pf = dpsimpy.sp.ph1.SynchronGenerator(\"SynGen\", dpsimpy.LogLevel.debug)\n", - "gen_pf.set_parameters(rated_apparent_power=555e6, rated_voltage=24e3,\n", - " set_point_active_power=set_point_active_power,\n", - " set_point_voltage=set_point_voltage,\n", - " powerflow_bus_type=dpsimpy.PowerflowBusType.PV)\n", + "gen_pf.set_parameters(\n", + " rated_apparent_power=555e6,\n", + " rated_voltage=24e3,\n", + " set_point_active_power=set_point_active_power,\n", + " set_point_voltage=set_point_voltage,\n", + " powerflow_bus_type=dpsimpy.PowerflowBusType.PV,\n", + ")\n", "gen_pf.set_base_voltage(V_nom_MV)\n", "gen_pf.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PV)\n", "\n", @@ -131,14 +134,18 @@ "\n", "# Line\n", "line_pf = dpsimpy.sp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", - "line_pf.set_parameters(line_resistance, line_inductance, line_capacitance, line_conductance)\n", + "line_pf.set_parameters(\n", + " line_resistance, line_inductance, line_capacitance, line_conductance\n", + ")\n", "line_pf.set_base_voltage(V_nom_MV)\n", "\n", "# Topology\n", "gen_pf.connect([n1_pf])\n", "line_pf.connect([n1_pf, n2_pf])\n", "extnet_pf.connect([n2_pf])\n", - "system_pf = dpsimpy.SystemTopology(nom_freq, [n1_pf, n2_pf], [gen_pf, line_pf, extnet_pf])\n", + "system_pf = dpsimpy.SystemTopology(\n", + " nom_freq, [n1_pf, n2_pf], [gen_pf, line_pf, extnet_pf]\n", + ")\n", "\n", "# Logging\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", @@ -175,7 +182,7 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir(\"logs/\"+sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Extract relevant powerflow results\n", "init_terminal_volt = np.abs(n1_pf.single_voltage() * dpsimpy.RMS3PH_TO_PEAK1PH)\n", @@ -192,12 +199,30 @@ "# Synch\n", "gen = dpsimpy.emt.ph3.SynchronGeneratorDQTrapez(\"SynGen\", dpsimpy.LogLevel.debug)\n", "gen.set_parameters_operational_per_unit(\n", - " nom_power=555e6, nom_volt=24e3, nom_freq=60, pole_number=2, nom_field_cur=1300,\n", - " Rs=Rs, Ld=Ld, Lq=Lq, Ld_t=Ld_t, Lq_t=Lq_t, Ld_s=Ld_s, Lq_s=Lq_s, Ll=Ll, Td0_t=Td0_t, Tq0_t=Tq0_t,\n", - " Td0_s=Td0_s, Tq0_s=Tq0_s, inertia=H, init_active_power=init_active_power, init_reactive_power=init_reactive_power,\n", - " init_terminal_volt=init_terminal_volt, init_volt_angle=init_volt_angle, init_field_voltage=7.0821,\n", - " init_mech_power=init_mech_power\n", - " \n", + " nom_power=555e6,\n", + " nom_volt=24e3,\n", + " nom_freq=60,\n", + " pole_number=2,\n", + " nom_field_cur=1300,\n", + " Rs=Rs,\n", + " Ld=Ld,\n", + " Lq=Lq,\n", + " Ld_t=Ld_t,\n", + " Lq_t=Lq_t,\n", + " Ld_s=Ld_s,\n", + " Lq_s=Lq_s,\n", + " Ll=Ll,\n", + " Td0_t=Td0_t,\n", + " Tq0_t=Tq0_t,\n", + " Td0_s=Td0_s,\n", + " Tq0_s=Tq0_s,\n", + " inertia=H,\n", + " init_active_power=init_active_power,\n", + " init_reactive_power=init_reactive_power,\n", + " init_terminal_volt=init_terminal_volt,\n", + " init_volt_angle=init_volt_angle,\n", + " init_field_voltage=7.0821,\n", + " init_mech_power=init_mech_power,\n", ")\n", "\n", "# Grid bus as Slack\n", @@ -205,15 +230,19 @@ "\n", "# Line\n", "line = dpsimpy.emt.ph3.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", - "line.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(line_resistance),\n", - " dpsimpy.Math.single_phase_parameter_to_three_phase(line_inductance),\n", - " dpsimpy.Math.single_phase_parameter_to_three_phase(line_capacitance),\n", - " dpsimpy.Math.single_phase_parameter_to_three_phase(line_conductance))\n", + "line.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(line_resistance),\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(line_inductance),\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(line_capacitance),\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(line_conductance),\n", + ")\n", "\n", "# Breaker\n", "fault = dpsimpy.emt.ph3.Switch(\"Br_fault\", dpsimpy.LogLevel.debug)\n", - "fault.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(breaker_open),\n", - " dpsimpy.Math.single_phase_parameter_to_three_phase(breaker_closed))\n", + "fault.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(breaker_open),\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(breaker_closed),\n", + ")\n", "fault.open()\n", "\n", "# Topology\n", @@ -285,7 +314,7 @@ "H = 5\n", "Xpd = 0.31\n", "Rs = 0.003 * 0\n", - "D=1.5\n", + "D = 1.5\n", "\n", "# Initialization parameters\n", "init_mech_power = 300e6\n", @@ -297,8 +326,8 @@ "\n", "# PiLine parameters calculated from CIGRE Benchmark system\n", "line_resistance = 6.7\n", - "line_inductance = 47.0/nom_omega\n", - "line_capacitance = 3.42e-4/nom_omega\n", + "line_inductance = 47.0 / nom_omega\n", + "line_capacitance = 3.42e-4 / nom_omega\n", "line_conductance = 0\n", "\n", "# Parameters for powerflow initialization\n", @@ -310,7 +339,7 @@ "switch_closed = 0.1\n", "\n", "# Simulation parameters\n", - "sim_name = \"DP_SynGenTrStab_SMIB_Fault\";\n", + "sim_name = \"DP_SynGenTrStab_SMIB_Fault\"\n", "final_time = 20\n", "time_step = 0.001\n", "start_fault_event = True\n", @@ -346,10 +375,13 @@ "\n", "# Synchronous generator ideal model\n", "gen_pf = dpsimpy.sp.ph1.SynchronGenerator(\"Generator\", dpsimpy.LogLevel.debug)\n", - "gen_pf.set_parameters(rated_apparent_power=nom_power, rated_voltage=nom_ph_ph_volt_RMS,\n", - " set_point_active_power=init_active_power,\n", - " set_point_voltage=set_point_voltage*t_ratio,\n", - " powerflow_bus_type=dpsimpy.PowerflowBusType.PV)\n", + "gen_pf.set_parameters(\n", + " rated_apparent_power=nom_power,\n", + " rated_voltage=nom_ph_ph_volt_RMS,\n", + " set_point_active_power=init_active_power,\n", + " set_point_voltage=set_point_voltage * t_ratio,\n", + " powerflow_bus_type=dpsimpy.PowerflowBusType.PV,\n", + ")\n", "gen_pf.set_base_voltage(V_nom)\n", "gen_pf.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PV)\n", "\n", @@ -361,7 +393,9 @@ "\n", "# Line\n", "line_pf = dpsimpy.sp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", - "line_pf.set_parameters(line_resistance, line_inductance, line_capacitance, line_conductance)\n", + "line_pf.set_parameters(\n", + " line_resistance, line_inductance, line_capacitance, line_conductance\n", + ")\n", "line_pf.set_base_voltage(V_nom)\n", "\n", "# Switch\n", @@ -374,7 +408,9 @@ "fault_pf.connect([dpsimpy.sp.SimNode.gnd, n1_pf])\n", "line_pf.connect([n1_pf, n2_pf])\n", "extnet_pf.connect([n2_pf])\n", - "system_pf = dpsimpy.SystemTopology(nom_freq, [n1_pf, n2_pf], [gen_pf, line_pf, extnet_pf, fault_pf])\n", + "system_pf = dpsimpy.SystemTopology(\n", + " nom_freq, [n1_pf, n2_pf], [gen_pf, line_pf, extnet_pf, fault_pf]\n", + ")\n", "\n", "# Logging\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", @@ -407,8 +443,8 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name_dp = sim_name + \"_DP\" \n", - "dpsimpy.Logger.set_log_dir(\"logs/\"+sim_name_dp)\n", + "sim_name_dp = sim_name + \"_DP\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_dp)\n", "\n", "# Nodes\n", "n1_dp = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", @@ -418,8 +454,14 @@ "gen_dp = dpsimpy.dp.ph1.SynchronGeneratorTrStab(\"SynGen\", dpsimpy.LogLevel.debug)\n", "# Xpd is given in p.u of generator base at transfomer primary side and should be transformed to network side\n", "gen_dp.set_standard_parameters_PU(\n", - " nom_power=nom_power, nom_volt = nom_ph_ph_volt_RMS, nom_freq=nom_freq,\n", - " Xpd = Xpd*t_ratio**2, inertia=cmd_Inertia*H, Rs=Rs, D=cmd_Damping*D)\n", + " nom_power=nom_power,\n", + " nom_volt=nom_ph_ph_volt_RMS,\n", + " nom_freq=nom_freq,\n", + " Xpd=Xpd * t_ratio**2,\n", + " inertia=cmd_Inertia * H,\n", + " Rs=Rs,\n", + " D=cmd_Damping * D,\n", + ")\n", "\n", "init_apparent_power = gen_pf.get_apparent_power()\n", "gen_dp.set_initial_values(init_apparent_power, init_mech_power)\n", @@ -429,7 +471,9 @@ "\n", "# Line\n", "line_dp = dpsimpy.dp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", - "line_dp.set_parameters(line_resistance, line_inductance, line_capacitance, line_conductance)\n", + "line_dp.set_parameters(\n", + " line_resistance, line_inductance, line_capacitance, line_conductance\n", + ")\n", "\n", "# Switch\n", "fault_dp = dpsimpy.dp.ph1.varResSwitch(\"Br_fault\", dpsimpy.LogLevel.debug)\n", @@ -442,7 +486,9 @@ "line_dp.connect([n1_dp, n2_dp])\n", "extnet_dp.connect([n2_dp])\n", "fault_dp.connect([dpsimpy.dp.SimNode.gnd, n1_dp])\n", - "system_dp = dpsimpy.SystemTopology(nom_freq, [n1_dp, n2_dp], [gen_dp, line_dp, fault_dp, extnet_dp])\n", + "system_dp = dpsimpy.SystemTopology(\n", + " nom_freq, [n1_dp, n2_dp], [gen_dp, line_dp, fault_dp, extnet_dp]\n", + ")\n", "\n", "\n", "# Initialization of dynamic topology\n", @@ -484,11 +530,11 @@ "if start_fault_event:\n", " sw1 = dpsimpy.event.SwitchEvent(start_time_fault, fault_dp, True)\n", " sim_dp.add_event(sw1)\n", - " \n", + "\n", "if end_fault_event:\n", " sw2 = dpsimpy.event.SwitchEvent(end_time_fault, fault_dp, False)\n", " sim_dp.add_event(sw2)\n", - " \n", + "\n", "sim_dp.run()" ] }, @@ -506,10 +552,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault/'\n", - "log_name = 'EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_emt3ph_DQ7odTrapez = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault/\"\n", + "log_name = \"EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_emt3ph_DQ7odTrapez = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -526,10 +572,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/DP_SynGenTrStab_SMIB_Fault_DP/'\n", - "log_name = 'DP_SynGenTrStab_SMIB_Fault_DP'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dp1ph_TrStab = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/DP_SynGenTrStab_SMIB_Fault_DP/\"\n", + "log_name = \"DP_SynGenTrStab_SMIB_Fault_DP\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dp1ph_TrStab = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -546,24 +592,32 @@ "metadata": {}, "outputs": [], "source": [ - "plt.style.use('default')\n", - "#plt.rcParams.update({'font.size': 22})\n", + "plt.style.use(\"default\")\n", + "# plt.rcParams.update({'font.size': 22})\n", "\n", - "timestep=10e-6;\n", - "t_begin=0\n", - "t_end=5\n", + "timestep = 10e-6\n", + "t_begin = 0\n", + "t_end = 5\n", "\n", "# Fault at t=0.1 s untill t=0.15s\n", - "begin_idx = int(t_begin/timestep)\n", - "end_idx= int(t_end/timestep)\n", + "begin_idx = int(t_begin / timestep)\n", + "end_idx = int(t_end / timestep)\n", + "\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Generator emf (V)\", fontsize=18)\n", + "\n", + "for name in [\"Ep\"]:\n", + " # plt.plot(ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).time[begin_idx:end_idx], np.sqrt(3/2)*ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).values[begin_idx:end_idx], label=name + ' Full model (9th order)')\n", + " plt.plot(\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_dp1ph_TrStab[name]\n", + " .interpolate(timestep)\n", + " .frequency_shift(60)\n", + " .values[begin_idx:end_idx],\n", + " label=name + \" Classical model (2nd order)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Generator emf (V)', fontsize=18)\n", - "\n", - "for name in ['Ep']:\n", - " #plt.plot(ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).time[begin_idx:end_idx], np.sqrt(3/2)*ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).values[begin_idx:end_idx], label=name + ' Full model (9th order)')\n", - " plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).frequency_shift(60).values[begin_idx:end_idx], label=name + ' Classical model (2nd order)', linestyle='--')\n", - " \n", "plt.legend()\n", "plt.show()" ] @@ -582,13 +636,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Generator terminal voltage (V)', fontsize=18)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Generator terminal voltage (V)\", fontsize=18)\n", + "\n", + "for name in [\"v_gen\"]:\n", + " plt.plot(\n", + " ts_emt3ph_DQ7odTrapez[name + \"_0\"]\n", + " .interpolate(timestep)\n", + " .time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2)\n", + " * ts_emt3ph_DQ7odTrapez[name + \"_0\"]\n", + " .interpolate(timestep)\n", + " .values[begin_idx:end_idx],\n", + " label=name + \" Full model (9th order)\",\n", + " )\n", + " # plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).frequency_shift(60).values[begin_idx:end_idx], label=name + ' Classical model (2nd order)', linestyle='--')\n", "\n", - "for name in ['v_gen']:\n", - " plt.plot(ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).time[begin_idx:end_idx], np.sqrt(3/2)*ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).values[begin_idx:end_idx], label=name + ' Full model (9th order)')\n", - " #plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).frequency_shift(60).values[begin_idx:end_idx], label=name + ' Classical model (2nd order)', linestyle='--')\n", - " \n", "plt.legend(fontsize=14)\n", "plt.show()" ] @@ -607,12 +670,29 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Generator terminal current (V)', fontsize=18)\n", - "\n", - "for name in ['i_gen']:\n", - " plt.plot(ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).time[begin_idx:end_idx], np.sqrt(3/2)*ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).values[begin_idx:end_idx], label=name + ' Full model (9th order)')\n", - " plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).frequency_shift(60).values[begin_idx:end_idx], label=name + ' Classical model (2nd order)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Generator terminal current (V)\", fontsize=18)\n", + "\n", + "for name in [\"i_gen\"]:\n", + " plt.plot(\n", + " ts_emt3ph_DQ7odTrapez[name + \"_0\"]\n", + " .interpolate(timestep)\n", + " .time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2)\n", + " * ts_emt3ph_DQ7odTrapez[name + \"_0\"]\n", + " .interpolate(timestep)\n", + " .values[begin_idx:end_idx],\n", + " label=name + \" Full model (9th order)\",\n", + " )\n", + " plt.plot(\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_dp1ph_TrStab[name]\n", + " .interpolate(timestep)\n", + " .frequency_shift(60)\n", + " .values[begin_idx:end_idx],\n", + " label=name + \" Classical model (2nd order)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -632,11 +712,28 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "\n", - "for name in ['v_line']:\n", - " plt.plot(ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).time[begin_idx:end_idx], np.sqrt(3/2)*ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).values[begin_idx:end_idx], label=name + ' Full model (9th order)')\n", - " plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).frequency_shift(60).values[begin_idx:end_idx], label=name + ' Classical model (2nd order)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "\n", + "for name in [\"v_line\"]:\n", + " plt.plot(\n", + " ts_emt3ph_DQ7odTrapez[name + \"_0\"]\n", + " .interpolate(timestep)\n", + " .time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2)\n", + " * ts_emt3ph_DQ7odTrapez[name + \"_0\"]\n", + " .interpolate(timestep)\n", + " .values[begin_idx:end_idx],\n", + " label=name + \" Full model (9th order)\",\n", + " )\n", + " plt.plot(\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_dp1ph_TrStab[name]\n", + " .interpolate(timestep)\n", + " .frequency_shift(60)\n", + " .values[begin_idx:end_idx],\n", + " label=name + \" Classical model (2nd order)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -656,11 +753,28 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "\n", - "for name in ['i_line']:\n", - " plt.plot(ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).time[begin_idx:end_idx], np.sqrt(3/2)*ts_emt3ph_DQ7odTrapez[name + '_0'].interpolate(timestep).values[begin_idx:end_idx], label=name + ' Full model (9th order)')\n", - " plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).frequency_shift(60).values[begin_idx:end_idx], label=name + ' Classical model (2nd order)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "\n", + "for name in [\"i_line\"]:\n", + " plt.plot(\n", + " ts_emt3ph_DQ7odTrapez[name + \"_0\"]\n", + " .interpolate(timestep)\n", + " .time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2)\n", + " * ts_emt3ph_DQ7odTrapez[name + \"_0\"]\n", + " .interpolate(timestep)\n", + " .values[begin_idx:end_idx],\n", + " label=name + \" Full model (9th order)\",\n", + " )\n", + " plt.plot(\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_dp1ph_TrStab[name]\n", + " .interpolate(timestep)\n", + " .frequency_shift(60)\n", + " .values[begin_idx:end_idx],\n", + " label=name + \" Classical model (2nd order)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -680,19 +794,31 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.xlabel('time (s)', fontsize=20)\n", - "plt.ylabel('Rotor frequency (Hz)', fontsize=20)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.xlabel(\"time (s)\", fontsize=20)\n", + "plt.ylabel(\"Rotor frequency (Hz)\", fontsize=20)\n", "plt.xticks(fontsize=18)\n", "plt.yticks(fontsize=18)\n", - "#plt.ylim(59,61)\n", - "\n", - "#if x_axis limits are changed above, change them again to consider the complete duration\n", - "\n", - "#ROCOF\n", - "for name in ['wr_gen']:\n", - " plt.plot(ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).time[begin_idx:end_idx], ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).values[begin_idx:end_idx]*60, label='Full model (9th order)')\n", - " plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).values[begin_idx:end_idx]*60/377, label='Classical model (2nd order)', linestyle='--')\n", + "# plt.ylim(59,61)\n", + "\n", + "# if x_axis limits are changed above, change them again to consider the complete duration\n", + "\n", + "# ROCOF\n", + "for name in [\"wr_gen\"]:\n", + " plt.plot(\n", + " ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).values[begin_idx:end_idx]\n", + " * 60,\n", + " label=\"Full model (9th order)\",\n", + " )\n", + " plt.plot(\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).values[begin_idx:end_idx]\n", + " * 60\n", + " / 377,\n", + " label=\"Classical model (2nd order)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend(fontsize=18)\n", "plt.show()" @@ -712,13 +838,25 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Rotor angular velocity (rad/s)', fontsize=18)\n", - "\n", - "\n", - "for name in ['wr_gen']:\n", - " plt.plot(ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).time[begin_idx:end_idx], 2*math.pi*60*ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).values[begin_idx:end_idx], label=name +' Full model (9th order)')\n", - " plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).values[begin_idx:end_idx], label=name + ' Classical model (2nd order)' , linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Rotor angular velocity (rad/s)\", fontsize=18)\n", + "\n", + "\n", + "for name in [\"wr_gen\"]:\n", + " plt.plot(\n", + " ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " 2\n", + " * math.pi\n", + " * 60\n", + " * ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).values[begin_idx:end_idx],\n", + " label=name + \" Full model (9th order)\",\n", + " )\n", + " plt.plot(\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).values[begin_idx:end_idx],\n", + " label=name + \" Classical model (2nd order)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -738,10 +876,23 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for name in ['delta_r']:\n", - " plt.plot(ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).time[begin_idx:end_idx], ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).values[begin_idx:end_idx]*180/3.14, label=name + ' Full model (9th order)')\n", - " plt.plot(ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx], ts_dp1ph_TrStab[name].interpolate(timestep).values[begin_idx:end_idx]*180/3.14, label=name + ' Classical model (2nd order)', linestyle='--')\n" + "plt.figure(figsize=(12, 8))\n", + "for name in [\"delta_r\"]:\n", + " plt.plot(\n", + " ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_emt3ph_DQ7odTrapez[name].interpolate(timestep).values[begin_idx:end_idx]\n", + " * 180\n", + " / 3.14,\n", + " label=name + \" Full model (9th order)\",\n", + " )\n", + " plt.plot(\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).time[begin_idx:end_idx],\n", + " ts_dp1ph_TrStab[name].interpolate(timestep).values[begin_idx:end_idx]\n", + " * 180\n", + " / 3.14,\n", + " label=name + \" Classical model (2nd order)\",\n", + " linestyle=\"--\",\n", + " )" ] }, { diff --git a/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_EMT_SynGenVBR_SMIB_Fault.ipynb b/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_EMT_SynGenVBR_SMIB_Fault.ipynb index 2efd159990..9e2258e02e 100644 --- a/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_EMT_SynGenVBR_SMIB_Fault.ipynb +++ b/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_EMT_SynGenVBR_SMIB_Fault.ipynb @@ -22,12 +22,17 @@ "import os\n", "import subprocess\n", "\n", - "#%matplotlib widget\n", + "# %matplotlib widget\n", "timestep = 10e-6\n", "duration = 1.0\n", "\n", - "dpsim_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", - "path_exec = dpsim_path + '/build/dpsim/examples/cxx/'" + "dpsim_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", + "path_exec = dpsim_path + \"/build/dpsim/examples/cxx/\"" ] }, { @@ -43,13 +48,25 @@ "metadata": {}, "outputs": [], "source": [ - "model_name = 'EMT_SynGenDQ7odTrapez_SMIB_Fault'\n", + "model_name = \"EMT_SynGenDQ7odTrapez_SMIB_Fault\"\n", "\n", - "sim = subprocess.Popen([path_exec+model_name, '--name', model_name, '--timestep', str(timestep), '--duration', str(duration)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + model_name,\n", + " \"--name\",\n", + " model_name,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path_res = 'logs/' + model_name + '/'\n", - "dpsim_result_file_res = path_res + model_name + '.csv'\n", + "path_res = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file_res = path_res + model_name + \".csv\"\n", "ts_dcim = read_timeseries_csv(dpsim_result_file_res)" ] }, @@ -66,13 +83,25 @@ "metadata": {}, "outputs": [], "source": [ - "model_name = 'EMT_SynGenVBR_SMIB_Fault'\n", + "model_name = \"EMT_SynGenVBR_SMIB_Fault\"\n", "\n", - "sim = subprocess.Popen([path_exec+model_name, '--name', model_name, '--timestep', str(timestep), '--duration', str(duration)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + model_name,\n", + " \"--name\",\n", + " model_name,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path_res = 'logs/' + model_name + '/'\n", - "dpsim_result_file_res = path_res + model_name + '.csv'\n", + "path_res = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file_res = path_res + model_name + \".csv\"\n", "ts_vbr = read_timeseries_csv(dpsim_result_file_res)" ] }, @@ -89,11 +118,11 @@ "metadata": {}, "outputs": [], "source": [ - "t_begin=0\n", - "t_end=1\n", + "t_begin = 0\n", + "t_end = 1\n", "\n", - "begin_idx = int(t_begin/timestep)\n", - "end_idx= int(t_end/timestep)" + "begin_idx = int(t_begin / timestep)\n", + "end_idx = int(t_end / timestep)" ] }, { @@ -109,13 +138,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Network node voltage (V)', fontsize=18)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Network node voltage (V)\", fontsize=18)\n", + "\n", + "for name in [\"v1\", \"v2\"]:\n", + " plt.plot(\n", + " ts_dcim[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_dcim[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_vbr[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", - "for name in ['v1', 'v2']:\n", - " plt.plot(ts_dcim[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_dcim[name + '_0'].values[begin_idx:end_idx], label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_vbr[name + '_0'].values[begin_idx:end_idx], label=name+' (VBR)', linestyle='--')\n", - " \n", "plt.legend(fontsize=14)\n", "plt.show()" ] @@ -133,13 +171,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Generator terminal voltage (V)', fontsize=18)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Generator terminal voltage (V)\", fontsize=18)\n", + "\n", + "for name in [\"v_gen\"]:\n", + " plt.plot(\n", + " ts_dcim[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_dcim[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_vbr[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", - "for name in ['v_gen']:\n", - " plt.plot(ts_dcim[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_dcim[name + '_0'].values[begin_idx:end_idx], label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_vbr[name + '_0'].values[begin_idx:end_idx], label=name+' (VBR)', linestyle='--')\n", - " \n", "plt.legend(fontsize=14)\n", "plt.show()" ] @@ -157,12 +204,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Generator terminal current (A)', fontsize=18)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Generator terminal current (A)\", fontsize=18)\n", "\n", - "for name in ['i_gen']:\n", - " plt.plot(ts_dcim[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_dcim[name + '_0'].values[begin_idx:end_idx], label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_vbr[name + '_0'].values[begin_idx:end_idx], label=name+' (VBR)', linestyle='--')\n", + "for name in [\"i_gen\"]:\n", + " plt.plot(\n", + " ts_dcim[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_dcim[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_vbr[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -181,11 +237,20 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['v_line']:\n", - " plt.plot(ts_dcim[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_dcim[name + '_0'].values[begin_idx:end_idx], label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_vbr[name + '_0'].values[begin_idx:end_idx], label=name+' (VBR)', linestyle='--')\n", + "for name in [\"v_line\"]:\n", + " plt.plot(\n", + " ts_dcim[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_dcim[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_vbr[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -204,11 +269,20 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['i_line']:\n", - " plt.plot(ts_dcim[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_dcim[name + '_0'].values[begin_idx:end_idx], label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_vbr[name + '_0'].values[begin_idx:end_idx], label=name+' (VBR)', linestyle='--')\n", + "for name in [\"i_line\"]:\n", + " plt.plot(\n", + " ts_dcim[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_dcim[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_vbr[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -227,15 +301,24 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.xlabel('time (s)', fontsize=20)\n", - "plt.ylabel('Rotor frequency (Hz)', fontsize=20)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.xlabel(\"time (s)\", fontsize=20)\n", + "plt.ylabel(\"Rotor frequency (Hz)\", fontsize=20)\n", "plt.xticks(fontsize=18)\n", "plt.yticks(fontsize=18)\n", "\n", - "for name in ['wr_gen']:\n", - " plt.plot(ts_dcim[name].time[begin_idx:end_idx], ts_dcim[name].values[begin_idx:end_idx]*60, label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name].time[begin_idx:end_idx], ts_vbr[name].values[begin_idx:end_idx]*60, label=name+' (VBR)', linestyle='--')\n", + "for name in [\"wr_gen\"]:\n", + " plt.plot(\n", + " ts_dcim[name].time[begin_idx:end_idx],\n", + " ts_dcim[name].values[begin_idx:end_idx] * 60,\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name].time[begin_idx:end_idx],\n", + " ts_vbr[name].values[begin_idx:end_idx] * 60,\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend(fontsize=18)\n", "plt.show()" @@ -254,13 +337,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Rotor angular velocity (rad/s)', fontsize=18)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Rotor angular velocity (rad/s)\", fontsize=18)\n", "\n", "\n", - "for name in ['wr_gen']:\n", - " plt.plot(ts_dcim[name].time[begin_idx:end_idx], 2*math.pi*60*ts_dcim[name].values[begin_idx:end_idx], label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name].time[begin_idx:end_idx], 2*math.pi*60*ts_vbr[name].values[begin_idx:end_idx], label=name+' (VBR)', linestyle='--')\n", + "for name in [\"wr_gen\"]:\n", + " plt.plot(\n", + " ts_dcim[name].time[begin_idx:end_idx],\n", + " 2 * math.pi * 60 * ts_dcim[name].values[begin_idx:end_idx],\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name].time[begin_idx:end_idx],\n", + " 2 * math.pi * 60 * ts_vbr[name].values[begin_idx:end_idx],\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -279,10 +371,19 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for name in ['delta_r']:\n", - " plt.plot(ts_dcim[name].time[begin_idx:end_idx], ts_dcim[name].values[begin_idx:end_idx]*180/3.14, label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name].time[begin_idx:end_idx], ts_vbr[name].values[begin_idx:end_idx]*180/3.14, label=name+' (VBR)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "for name in [\"delta_r\"]:\n", + " plt.plot(\n", + " ts_dcim[name].time[begin_idx:end_idx],\n", + " ts_dcim[name].values[begin_idx:end_idx] * 180 / 3.14,\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name].time[begin_idx:end_idx],\n", + " ts_vbr[name].values[begin_idx:end_idx] * 180 / 3.14,\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -300,13 +401,31 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for name in ['T_e']:\n", - " plt.plot(ts_dcim[name].time[begin_idx:end_idx], ts_dcim[name].values[begin_idx:end_idx], label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name].time[begin_idx:end_idx], -ts_vbr[name].values[begin_idx:end_idx], label=name+' (VBR)', linestyle='--')\n", - "for name in ['T_m']:\n", - " plt.plot(ts_dcim[name].time[begin_idx:end_idx], ts_dcim[name].values[begin_idx:end_idx], label=name+' (DCIM)')\n", - " plt.plot(ts_vbr[name].time[begin_idx:end_idx], -ts_vbr[name].values[begin_idx:end_idx], label=name+' (VBR)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "for name in [\"T_e\"]:\n", + " plt.plot(\n", + " ts_dcim[name].time[begin_idx:end_idx],\n", + " ts_dcim[name].values[begin_idx:end_idx],\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name].time[begin_idx:end_idx],\n", + " -ts_vbr[name].values[begin_idx:end_idx],\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", + "for name in [\"T_m\"]:\n", + " plt.plot(\n", + " ts_dcim[name].time[begin_idx:end_idx],\n", + " ts_dcim[name].values[begin_idx:end_idx],\n", + " label=name + \" (DCIM)\",\n", + " )\n", + " plt.plot(\n", + " ts_vbr[name].time[begin_idx:end_idx],\n", + " -ts_vbr[name].values[begin_idx:end_idx],\n", + " label=name + \" (VBR)\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -325,14 +444,18 @@ "outputs": [], "source": [ "diff = {}\n", - "for name in ['v_gen_0', 'v_gen_1', 'v_gen_2']:\n", - " diff[name] = ts_dcim[name].rmse(ts_dcim[name], ts_vbr[name])/np.max(ts_dcim[name].values)\n", - " print(name + ': ' + str(diff[name]))\n", - " assert(diff[name]) < 1.86e-6\n", - "for name in ['i_gen_0', 'i_gen_1', 'i_gen_2']:\n", - " diff[name] = ts_dcim[name].rmse(ts_dcim[name], ts_vbr[name])/np.max(ts_dcim[name].values)\n", - " print(name + ': ' + str(diff[name]))\n", - " assert(diff[name]) < 5e-4" + "for name in [\"v_gen_0\", \"v_gen_1\", \"v_gen_2\"]:\n", + " diff[name] = ts_dcim[name].rmse(ts_dcim[name], ts_vbr[name]) / np.max(\n", + " ts_dcim[name].values\n", + " )\n", + " print(name + \": \" + str(diff[name]))\n", + " assert (diff[name]) < 1.86e-6\n", + "for name in [\"i_gen_0\", \"i_gen_1\", \"i_gen_2\"]:\n", + " diff[name] = ts_dcim[name].rmse(ts_dcim[name], ts_vbr[name]) / np.max(\n", + " ts_dcim[name].values\n", + " )\n", + " print(name + \": \" + str(diff[name]))\n", + " assert (diff[name]) < 5e-4" ] } ], diff --git a/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_OperationalParams_Vs_FundamentalParams_SMIB_Fault.ipynb b/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_OperationalParams_Vs_FundamentalParams_SMIB_Fault.ipynb index 9d8bb9bb82..4248baf750 100644 --- a/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_OperationalParams_Vs_FundamentalParams_SMIB_Fault.ipynb +++ b/examples/Notebooks/Circuits/Compare_EMT_SynGenDQ7odTrapez_OperationalParams_Vs_FundamentalParams_SMIB_Fault.ipynb @@ -22,15 +22,20 @@ "import os\n", "import subprocess\n", "\n", - "#%matplotlib widget\n", + "# %matplotlib widget\n", "timestep = 10e-6\n", "duration = 1.0\n", "\n", - "begin_idx=0\n", - "end_idx=-1\n", + "begin_idx = 0\n", + "end_idx = -1\n", "\n", - "dpsim_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", - "path_exec = dpsim_path + '/build/dpsim/examples/cxx/'" + "dpsim_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", + "path_exec = dpsim_path + \"/build/dpsim/examples/cxx/\"" ] }, { @@ -46,13 +51,25 @@ "metadata": {}, "outputs": [], "source": [ - "model_name_fundamental = 'EMT_SynGenDQ7odTrapez_SMIB_Fault'\n", + "model_name_fundamental = \"EMT_SynGenDQ7odTrapez_SMIB_Fault\"\n", "\n", - "sim = subprocess.Popen([path_exec+model_name_fundamental, '--name', model_name_fundamental, '--timestep', str(timestep), '--duration', str(duration)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + model_name_fundamental,\n", + " \"--name\",\n", + " model_name_fundamental,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path_res = 'logs/' + model_name_fundamental + '/'\n", - "dpsim_result_file_res = path_res + model_name_fundamental + '.csv'\n", + "path_res = \"logs/\" + model_name_fundamental + \"/\"\n", + "dpsim_result_file_res = path_res + model_name_fundamental + \".csv\"\n", "ts_fundamental = read_timeseries_csv(dpsim_result_file_res)" ] }, @@ -69,13 +86,25 @@ "metadata": {}, "outputs": [], "source": [ - "model_name_operational = 'EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault'\n", + "model_name_operational = \"EMT_SynGenDQ7odTrapez_OperationalParams_SMIB_Fault\"\n", "\n", - "sim = subprocess.Popen([path_exec+model_name_operational, '--name', model_name_operational, '--timestep', str(timestep), '--duration', str(duration)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + model_name_operational,\n", + " \"--name\",\n", + " model_name_operational,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path_res = 'logs/' + model_name_operational + '/'\n", - "dpsim_result_file_res = path_res + model_name_operational + '.csv'\n", + "path_res = \"logs/\" + model_name_operational + \"/\"\n", + "dpsim_result_file_res = path_res + model_name_operational + \".csv\"\n", "ts_operational = read_timeseries_csv(dpsim_result_file_res)" ] }, @@ -92,12 +121,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Generator terminal current (V)', fontsize=18)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Generator terminal current (V)\", fontsize=18)\n", "\n", - "for name in ['i_gen']:\n", - " plt.plot(ts_fundamental[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_fundamental[name + '_0'].values[begin_idx:end_idx], label=name)\n", - " plt.plot(ts_operational[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_operational[name + '_0'].values[begin_idx:end_idx], linestyle='--', label=name)\n", + "for name in [\"i_gen\"]:\n", + " plt.plot(\n", + " ts_fundamental[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_fundamental[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name,\n", + " )\n", + " plt.plot(\n", + " ts_operational[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_operational[name + \"_0\"].values[begin_idx:end_idx],\n", + " linestyle=\"--\",\n", + " label=name,\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -109,7 +147,14 @@ "metadata": {}, "outputs": [], "source": [ - "assert(np.max(ts_fundamental[name + '_0'].values[begin_idx:end_idx]-ts_operational[name + '_0'].values[begin_idx:end_idx])/np.max(ts_fundamental[name + '_0'].values[begin_idx:end_idx]) < 1e-3)" + "assert (\n", + " np.max(\n", + " ts_fundamental[name + \"_0\"].values[begin_idx:end_idx]\n", + " - ts_operational[name + \"_0\"].values[begin_idx:end_idx]\n", + " )\n", + " / np.max(ts_fundamental[name + \"_0\"].values[begin_idx:end_idx])\n", + " < 1e-3\n", + ")" ] } ], diff --git a/examples/Notebooks/Circuits/Compare_EMT_SynGenVBR_OperationalParams_Vs_FundamentalParams_SMIB_Fault.ipynb b/examples/Notebooks/Circuits/Compare_EMT_SynGenVBR_OperationalParams_Vs_FundamentalParams_SMIB_Fault.ipynb index fc28812993..6c012e4cf3 100644 --- a/examples/Notebooks/Circuits/Compare_EMT_SynGenVBR_OperationalParams_Vs_FundamentalParams_SMIB_Fault.ipynb +++ b/examples/Notebooks/Circuits/Compare_EMT_SynGenVBR_OperationalParams_Vs_FundamentalParams_SMIB_Fault.ipynb @@ -22,15 +22,20 @@ "import os\n", "import subprocess\n", "\n", - "#%matplotlib widget\n", + "# %matplotlib widget\n", "timestep = 10e-6\n", "duration = 1.0\n", "\n", - "begin_idx=0\n", - "end_idx=-1\n", + "begin_idx = 0\n", + "end_idx = -1\n", "\n", - "dpsim_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", - "path_exec = dpsim_path + '/build/dpsim/examples/cxx/'" + "dpsim_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", + "path_exec = dpsim_path + \"/build/dpsim/examples/cxx/\"" ] }, { @@ -46,13 +51,25 @@ "metadata": {}, "outputs": [], "source": [ - "model_name_fundamental = 'EMT_SynGenVBR_SMIB_Fault'\n", + "model_name_fundamental = \"EMT_SynGenVBR_SMIB_Fault\"\n", "\n", - "sim = subprocess.Popen([path_exec+model_name_fundamental, '--name', model_name_fundamental, '--timestep', str(timestep), '--duration', str(duration)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + model_name_fundamental,\n", + " \"--name\",\n", + " model_name_fundamental,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path_res = 'logs/' + model_name_fundamental + '/'\n", - "dpsim_result_file_res = path_res + model_name_fundamental + '.csv'\n", + "path_res = \"logs/\" + model_name_fundamental + \"/\"\n", + "dpsim_result_file_res = path_res + model_name_fundamental + \".csv\"\n", "ts_fundamental = read_timeseries_csv(dpsim_result_file_res)" ] }, @@ -69,13 +86,25 @@ "metadata": {}, "outputs": [], "source": [ - "model_name_operational = 'EMT_SynGenVBR_OperationalParams_SMIB_Fault'\n", + "model_name_operational = \"EMT_SynGenVBR_OperationalParams_SMIB_Fault\"\n", "\n", - "sim = subprocess.Popen([path_exec+model_name_operational, '--name', model_name_operational, '--timestep', str(timestep), '--duration', str(duration)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + model_name_operational,\n", + " \"--name\",\n", + " model_name_operational,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path_res = 'logs/' + model_name_operational + '/'\n", - "dpsim_result_file_res = path_res + model_name_operational + '.csv'\n", + "path_res = \"logs/\" + model_name_operational + \"/\"\n", + "dpsim_result_file_res = path_res + model_name_operational + \".csv\"\n", "ts_operational = read_timeseries_csv(dpsim_result_file_res)" ] }, @@ -92,12 +121,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "plt.ylabel('Generator terminal current (V)', fontsize=18)\n", + "plt.figure(figsize=(12, 8))\n", + "plt.ylabel(\"Generator terminal current (V)\", fontsize=18)\n", "\n", - "for name in ['i_gen']:\n", - " plt.plot(ts_fundamental[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_fundamental[name + '_0'].values[begin_idx:end_idx], label=name)\n", - " plt.plot(ts_operational[name + '_0'].time[begin_idx:end_idx], np.sqrt(3/2)*ts_operational[name + '_0'].values[begin_idx:end_idx], linestyle='--', label=name)\n", + "for name in [\"i_gen\"]:\n", + " plt.plot(\n", + " ts_fundamental[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_fundamental[name + \"_0\"].values[begin_idx:end_idx],\n", + " label=name,\n", + " )\n", + " plt.plot(\n", + " ts_operational[name + \"_0\"].time[begin_idx:end_idx],\n", + " np.sqrt(3 / 2) * ts_operational[name + \"_0\"].values[begin_idx:end_idx],\n", + " linestyle=\"--\",\n", + " label=name,\n", + " )\n", "\n", "plt.legend()\n", "plt.show()" @@ -109,7 +147,14 @@ "metadata": {}, "outputs": [], "source": [ - "assert(np.max(ts_fundamental[name + '_0'].values[begin_idx:end_idx]-ts_operational[name + '_0'].values[begin_idx:end_idx])/np.max(ts_fundamental[name + '_0'].values[begin_idx:end_idx]) < 1e-3)" + "assert (\n", + " np.max(\n", + " ts_fundamental[name + \"_0\"].values[begin_idx:end_idx]\n", + " - ts_operational[name + \"_0\"].values[begin_idx:end_idx]\n", + " )\n", + " / np.max(ts_fundamental[name + \"_0\"].values[begin_idx:end_idx])\n", + " < 1e-3\n", + ")" ] } ], diff --git a/examples/Notebooks/Circuits/Compare_EMT_WSCC_9bus_IdealCS_DP_WSCC_9bus_IdealVS.ipynb b/examples/Notebooks/Circuits/Compare_EMT_WSCC_9bus_IdealCS_DP_WSCC_9bus_IdealVS.ipynb index 365277d7ca..34eb46eb33 100644 --- a/examples/Notebooks/Circuits/Compare_EMT_WSCC_9bus_IdealCS_DP_WSCC_9bus_IdealVS.ipynb +++ b/examples/Notebooks/Circuits/Compare_EMT_WSCC_9bus_IdealCS_DP_WSCC_9bus_IdealVS.ipynb @@ -16,18 +16,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09/WSCC-09'\n", - "filename = 'WSCC-09'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09/WSCC-09\"\n", + "filename = \"WSCC-09\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -46,16 +48,21 @@ "import os\n", "import subprocess\n", "\n", - "PEAK1PH_TO_RMS3PH=np.sqrt(3./2.)\n", + "PEAK1PH_TO_RMS3PH = np.sqrt(3.0 / 2.0)\n", "\n", - "name = 'DP_WSCC-9bus_IdealVS'\n", - "name_emt = 'EMT_WSCC-9bus_IdealCS'\n", + "name = \"DP_WSCC-9bus_IdealVS\"\n", + "name_emt = \"EMT_WSCC-9bus_IdealCS\"\n", "\n", "timestep = 100e-6\n", "duration = 0.1\n", "\n", - "root_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", - "path_exec = root_path + '/build/dpsim/examples/cxx/'" + "root_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", + "path_exec = root_path + \"/build/dpsim/examples/cxx/\"" ] }, { @@ -71,9 +78,35 @@ "metadata": {}, "outputs": [], "source": [ - "sim = subprocess.Popen([path_exec+name, '--timestep', str(timestep), '--duration', str(duration), files[0], files[1], files[2]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " files[0],\n", + " files[1],\n", + " files[2],\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", - "sim = subprocess.Popen([path_exec+name_emt, '--timestep', str(timestep), '--duration', str(duration), files[0], files[1], files[2]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_emt,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " files[0],\n", + " files[1],\n", + " files[2],\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())" ] }, @@ -90,19 +123,19 @@ "metadata": {}, "outputs": [], "source": [ - "model_name = 'DP_WSCC-9bus_IdealVS'\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "model_name = \"DP_WSCC-9bus_IdealVS\"\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_dp = read_timeseries_csv(dpsim_result_file)\n", "\n", - "model_name = 'EMT_WSCC-9bus_IdealCS'\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "model_name = \"EMT_WSCC-9bus_IdealCS\"\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_emt = read_timeseries_csv(dpsim_result_file)\n", "\n", - "model_name = 'EMT_WSCC-9bus_IdealCS_PF'\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "model_name = \"EMT_WSCC-9bus_IdealCS_PF\"\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_pf = read_timeseries_csv(dpsim_result_file)" ] }, @@ -119,14 +152,25 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for phase in ['0']: #, '1','2']:\n", - " for name in ['v1_'+phase, 'v2_'+phase, 'v3_'+phase]:\n", - " plt.plot(ts_dpsim_emt[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt[name].values, label=name + ' (EMT)')\n", - "for name in ['v1', 'v2', 'v3']:\n", - " plt.plot(ts_dpsim_dp[name].time, ts_dpsim_dp[name].abs().values, label=name + ' (DP)')\n", - "for name in ['BUS1.V', 'BUS2.V', 'BUS3.V']:\n", - " plt.plot(ts_dpsim_pf[name].time, ts_dpsim_pf[name].abs().values, label=name + ' (PF)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "for phase in [\"0\"]: # , '1','2']:\n", + " for name in [\"v1_\" + phase, \"v2_\" + phase, \"v3_\" + phase]:\n", + " plt.plot(\n", + " ts_dpsim_emt[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt[name].values,\n", + " label=name + \" (EMT)\",\n", + " )\n", + "for name in [\"v1\", \"v2\", \"v3\"]:\n", + " plt.plot(\n", + " ts_dpsim_dp[name].time, ts_dpsim_dp[name].abs().values, label=name + \" (DP)\"\n", + " )\n", + "for name in [\"BUS1.V\", \"BUS2.V\", \"BUS3.V\"]:\n", + " plt.plot(\n", + " ts_dpsim_pf[name].time,\n", + " ts_dpsim_pf[name].abs().values,\n", + " label=name + \" (PF)\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -144,11 +188,18 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for name in ['v1', 'v2', 'v3']:\n", - " plt.plot(ts_dpsim_dp[name].time, ts_dpsim_dp[name].phase().values, label=name + ' (DP)')\n", - "for name in ['BUS1.V', 'BUS2.V', 'BUS3.V']:\n", - " plt.plot(ts_dpsim_pf[name].time, ts_dpsim_pf[name].phase().values, label=name + ' (PF)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "for name in [\"v1\", \"v2\", \"v3\"]:\n", + " plt.plot(\n", + " ts_dpsim_dp[name].time, ts_dpsim_dp[name].phase().values, label=name + \" (DP)\"\n", + " )\n", + "for name in [\"BUS1.V\", \"BUS2.V\", \"BUS3.V\"]:\n", + " plt.plot(\n", + " ts_dpsim_pf[name].time,\n", + " ts_dpsim_pf[name].phase().values,\n", + " label=name + \" (PF)\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -166,12 +217,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for phase in ['0']: #,'1','2']:\n", - " for name in ['GEN1.I_'+phase, 'GEN2.I_'+phase, 'GEN3.I_'+phase]:\n", - " plt.plot(ts_dpsim_emt[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt[name].values, label=name + '(EMT)')\n", - "for name in ['GEN1.I', 'GEN2.I', 'GEN3.I']:\n", - " plt.plot(ts_dpsim_dp[name].interpolate(timestep).time, ts_dpsim_dp[name].interpolate(timestep).frequency_shift(60).values, label=name + '(DP)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "for phase in [\"0\"]: # ,'1','2']:\n", + " for name in [\"GEN1.I_\" + phase, \"GEN2.I_\" + phase, \"GEN3.I_\" + phase]:\n", + " plt.plot(\n", + " ts_dpsim_emt[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt[name].values,\n", + " label=name + \"(EMT)\",\n", + " )\n", + "for name in [\"GEN1.I\", \"GEN2.I\", \"GEN3.I\"]:\n", + " plt.plot(\n", + " ts_dpsim_dp[name].interpolate(timestep).time,\n", + " ts_dpsim_dp[name].interpolate(timestep).frequency_shift(60).values,\n", + " label=name + \"(DP)\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -191,12 +251,17 @@ "source": [ "ts_emt_rms3ph = {}\n", "rmse_rel = {}\n", - "for name in ['GEN1.I', 'GEN2.I', 'GEN3.I']:\n", - " ts_emt_rms3ph[name+'_0'] = ts_dpsim_emt[name+'_0']\n", - " ts_emt_rms3ph[name+'_0'].values = PEAK1PH_TO_RMS3PH*ts_emt_rms3ph[name+'_0'].values\n", - " rmse_rel[name] = ts_dpsim_dp[name].rmse(ts_emt_rms3ph[name+'_0'], ts_dpsim_dp[name].interpolate(timestep).frequency_shift(60))/np.max(ts_dpsim_dp[name].abs().values)\n", - " print('Rel. RMSE for {}: {}'.format(name, rmse_rel[name]))\n", - " assert(rmse_rel[name]<1e-2)" + "for name in [\"GEN1.I\", \"GEN2.I\", \"GEN3.I\"]:\n", + " ts_emt_rms3ph[name + \"_0\"] = ts_dpsim_emt[name + \"_0\"]\n", + " ts_emt_rms3ph[name + \"_0\"].values = (\n", + " PEAK1PH_TO_RMS3PH * ts_emt_rms3ph[name + \"_0\"].values\n", + " )\n", + " rmse_rel[name] = ts_dpsim_dp[name].rmse(\n", + " ts_emt_rms3ph[name + \"_0\"],\n", + " ts_dpsim_dp[name].interpolate(timestep).frequency_shift(60),\n", + " ) / np.max(ts_dpsim_dp[name].abs().values)\n", + " print(\"Rel. RMSE for {}: {}\".format(name, rmse_rel[name]))\n", + " assert rmse_rel[name] < 1e-2" ] }, { diff --git a/examples/Notebooks/Circuits/Compare_EMT_WSCC_9bus_IdealVS_DP_WSCC_9bus_IdealVS.ipynb b/examples/Notebooks/Circuits/Compare_EMT_WSCC_9bus_IdealVS_DP_WSCC_9bus_IdealVS.ipynb index eb31a868aa..2b5768a42d 100644 --- a/examples/Notebooks/Circuits/Compare_EMT_WSCC_9bus_IdealVS_DP_WSCC_9bus_IdealVS.ipynb +++ b/examples/Notebooks/Circuits/Compare_EMT_WSCC_9bus_IdealVS_DP_WSCC_9bus_IdealVS.ipynb @@ -16,18 +16,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09/WSCC-09'\n", - "filename = 'WSCC-09'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09/WSCC-09\"\n", + "filename = \"WSCC-09\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -48,16 +50,21 @@ "\n", "# %matplotlib widget\n", "\n", - "PEAK1PH_TO_RMS3PH=np.sqrt(3./2.)\n", + "PEAK1PH_TO_RMS3PH = np.sqrt(3.0 / 2.0)\n", "\n", - "name = 'DP_WSCC-9bus_IdealVS'\n", - "name_emt = 'EMT_WSCC-9bus_IdealVS'\n", + "name = \"DP_WSCC-9bus_IdealVS\"\n", + "name_emt = \"EMT_WSCC-9bus_IdealVS\"\n", "\n", "timestep = 10e-6\n", "duration = 0.1\n", "\n", - "root_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", - "path_exec = root_path + '/build/dpsim/examples/cxx/'" + "root_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", + "path_exec = root_path + \"/build/dpsim/examples/cxx/\"" ] }, { @@ -73,9 +80,35 @@ "metadata": {}, "outputs": [], "source": [ - "sim = subprocess.Popen([path_exec+name, '--timestep', str(timestep), '--duration', str(duration), files[0], files[1], files[2]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " files[0],\n", + " files[1],\n", + " files[2],\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", - "sim = subprocess.Popen([path_exec+name_emt, '--timestep', str(timestep), '--duration', str(duration), files[0], files[1], files[2]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_emt,\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " files[0],\n", + " files[1],\n", + " files[2],\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())" ] }, @@ -92,14 +125,14 @@ "metadata": {}, "outputs": [], "source": [ - "model_name = 'DP_WSCC-9bus_IdealVS'\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "model_name = \"DP_WSCC-9bus_IdealVS\"\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_dp = read_timeseries_csv(dpsim_result_file)\n", "\n", - "model_name = 'EMT_WSCC-9bus_IdealVS'\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "model_name = \"EMT_WSCC-9bus_IdealVS\"\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_emt = read_timeseries_csv(dpsim_result_file)" ] }, @@ -116,12 +149,18 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for name in ['v1', 'v2', 'v3']:\n", - " plt.plot(ts_dpsim_dp[name].time, ts_dpsim_dp[name].abs().values, label=name + '(DP)')\n", - "for phase in ['0']:\n", - " for name in ['v1_'+phase, 'v2_'+phase, 'v3_'+phase]:\n", - " plt.plot(ts_dpsim_emt[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt[name].values, label=name + '(EMT)')\n", + "plt.figure(figsize=(12, 8))\n", + "for name in [\"v1\", \"v2\", \"v3\"]:\n", + " plt.plot(\n", + " ts_dpsim_dp[name].time, ts_dpsim_dp[name].abs().values, label=name + \"(DP)\"\n", + " )\n", + "for phase in [\"0\"]:\n", + " for name in [\"v1_\" + phase, \"v2_\" + phase, \"v3_\" + phase]:\n", + " plt.plot(\n", + " ts_dpsim_emt[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt[name].values,\n", + " label=name + \"(EMT)\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -141,12 +180,17 @@ "source": [ "ts_emt_rms3ph = {}\n", "rmse_rel = {}\n", - "for name in ['v1', 'v2', 'v3']:\n", - " ts_emt_rms3ph[name+'_0'] = ts_dpsim_emt[name+'_0']\n", - " ts_emt_rms3ph[name+'_0'].values = PEAK1PH_TO_RMS3PH*ts_emt_rms3ph[name+'_0'].values\n", - " rmse_rel[name] = ts_dpsim_dp[name].rmse(ts_emt_rms3ph[name+'_0'], ts_dpsim_dp[name].interpolate(timestep).frequency_shift(60))/np.max(ts_dpsim_dp[name].abs().values)\n", - " print('Rel. RMSE for {}: {}'.format(name, rmse_rel[name]))\n", - " assert(rmse_rel[name]<1e-5)" + "for name in [\"v1\", \"v2\", \"v3\"]:\n", + " ts_emt_rms3ph[name + \"_0\"] = ts_dpsim_emt[name + \"_0\"]\n", + " ts_emt_rms3ph[name + \"_0\"].values = (\n", + " PEAK1PH_TO_RMS3PH * ts_emt_rms3ph[name + \"_0\"].values\n", + " )\n", + " rmse_rel[name] = ts_dpsim_dp[name].rmse(\n", + " ts_emt_rms3ph[name + \"_0\"],\n", + " ts_dpsim_dp[name].interpolate(timestep).frequency_shift(60),\n", + " ) / np.max(ts_dpsim_dp[name].abs().values)\n", + " print(\"Rel. RMSE for {}: {}\".format(name, rmse_rel[name]))\n", + " assert rmse_rel[name] < 1e-5" ] }, { @@ -162,9 +206,11 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for name in ['v1', 'v2', 'v3']:\n", - " plt.plot(ts_dpsim_dp[name].time, ts_dpsim_dp[name].phase().values, label=name + '(DP)')" + "plt.figure(figsize=(12, 8))\n", + "for name in [\"v1\", \"v2\", \"v3\"]:\n", + " plt.plot(\n", + " ts_dpsim_dp[name].time, ts_dpsim_dp[name].phase().values, label=name + \"(DP)\"\n", + " )" ] }, { @@ -180,12 +226,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for phase in ['0']:\n", - " for name in ['GEN1.I_'+phase, 'GEN2.I_'+phase, 'GEN3.I_'+phase]:\n", - " plt.plot(ts_dpsim_emt[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt[name].values, label=name + '(EMT)')\n", - "for name in ['GEN1.I', 'GEN2.I', 'GEN3.I']:\n", - " plt.plot(ts_dpsim_dp[name].time, ts_dpsim_dp[name].frequency_shift(60).values, label=name + '(DP)', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "for phase in [\"0\"]:\n", + " for name in [\"GEN1.I_\" + phase, \"GEN2.I_\" + phase, \"GEN3.I_\" + phase]:\n", + " plt.plot(\n", + " ts_dpsim_emt[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt[name].values,\n", + " label=name + \"(EMT)\",\n", + " )\n", + "for name in [\"GEN1.I\", \"GEN2.I\", \"GEN3.I\"]:\n", + " plt.plot(\n", + " ts_dpsim_dp[name].time,\n", + " ts_dpsim_dp[name].frequency_shift(60).values,\n", + " label=name + \"(DP)\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -205,12 +260,17 @@ "source": [ "ts_emt_rms3ph = {}\n", "rmse_rel = {}\n", - "for name in ['GEN1.I', 'GEN2.I', 'GEN3.I']:\n", - " ts_emt_rms3ph[name+'_0'] = ts_dpsim_emt[name+'_0']\n", - " ts_emt_rms3ph[name+'_0'].values = PEAK1PH_TO_RMS3PH*ts_emt_rms3ph[name+'_0'].values\n", - " rmse_rel[name] = ts_dpsim_dp[name].rmse(ts_emt_rms3ph[name+'_0'], ts_dpsim_dp[name].interpolate(timestep).frequency_shift(60))/np.max(ts_dpsim_dp[name].abs().values)\n", - " print('Rel. RMSE for {}: {}'.format(name, rmse_rel[name]))\n", - " assert(rmse_rel[name]<1e-2)" + "for name in [\"GEN1.I\", \"GEN2.I\", \"GEN3.I\"]:\n", + " ts_emt_rms3ph[name + \"_0\"] = ts_dpsim_emt[name + \"_0\"]\n", + " ts_emt_rms3ph[name + \"_0\"].values = (\n", + " PEAK1PH_TO_RMS3PH * ts_emt_rms3ph[name + \"_0\"].values\n", + " )\n", + " rmse_rel[name] = ts_dpsim_dp[name].rmse(\n", + " ts_emt_rms3ph[name + \"_0\"],\n", + " ts_dpsim_dp[name].interpolate(timestep).frequency_shift(60),\n", + " ) / np.max(ts_dpsim_dp[name].abs().values)\n", + " print(\"Rel. RMSE for {}: {}\".format(name, rmse_rel[name]))\n", + " assert rmse_rel[name] < 1e-2" ] }, { diff --git a/examples/Notebooks/Circuits/DP_EMT_Validation_ReducedOrderSG_VBR_Load_Fault.ipynb b/examples/Notebooks/Circuits/DP_EMT_Validation_ReducedOrderSG_VBR_Load_Fault.ipynb index 89cc767c57..dab5d8680d 100644 --- a/examples/Notebooks/Circuits/DP_EMT_Validation_ReducedOrderSG_VBR_Load_Fault.ipynb +++ b/examples/Notebooks/Circuits/DP_EMT_Validation_ReducedOrderSG_VBR_Load_Fault.ipynb @@ -23,17 +23,30 @@ "import os\n", "import subprocess\n", "\n", - "#%matplotlib widget\n", + "# %matplotlib widget\n", "\n", - "name = ['SP_ReducedOrderSG_VBR_Load_Fault', 'DP_ReducedOrderSG_VBR_Load_Fault', 'EMT_ReducedOrderSG_VBR_Load_Fault']\n", - "options = ['SGModel=3', 'SGModel=4', 'SGModel=6a', 'SGModel=6b']\n", + "name = [\n", + " \"SP_ReducedOrderSG_VBR_Load_Fault\",\n", + " \"DP_ReducedOrderSG_VBR_Load_Fault\",\n", + " \"EMT_ReducedOrderSG_VBR_Load_Fault\",\n", + "]\n", + "options = [\"SGModel=3\", \"SGModel=4\", \"SGModel=6a\", \"SGModel=6b\"]\n", "\n", - "dpsim_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", + "dpsim_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", "\n", - "path_exec = dpsim_path + '/build/dpsim/examples/cxx/'\n", + "path_exec = dpsim_path + \"/build/dpsim/examples/cxx/\"\n", "for i in range(len(name)):\n", - " for j in range (len(options)):\n", - " sim = subprocess.Popen([path_exec + name[i], '-o', options[j]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + " for j in range(len(options)):\n", + " sim = subprocess.Popen(\n", + " [path_exec + name[i], \"-o\", options[j]],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + " )\n", " print(sim.communicate()[0].decode())\n", " print(path_exec + name[i])" ] @@ -61,10 +74,10 @@ "import os\n", "\n", "work_dir = os.getcwd() + \"/logs/\"\n", - "file_name_3Order = 'SynGen3Order_VBR_Load_Fault'\n", - "file_name_4Order = 'SynGen4Order_VBR_Load_Fault'\n", - "file_name_6aOrder = 'SynGen6aOrder_VBR_Load_Fault'\n", - "file_name_6bOrder = 'SynGen6bOrder_VBR_Load_Fault'\n", + "file_name_3Order = \"SynGen3Order_VBR_Load_Fault\"\n", + "file_name_4Order = \"SynGen4Order_VBR_Load_Fault\"\n", + "file_name_6aOrder = \"SynGen6aOrder_VBR_Load_Fault\"\n", + "file_name_6bOrder = \"SynGen6bOrder_VBR_Load_Fault\"\n", "\n", "ts_dpsim_SP = []\n", "ts_dpsim_SP_shift = []\n", @@ -73,16 +86,22 @@ "ts_dpsim_EMT = []\n", "file_names = [file_name_3Order, file_name_4Order, file_name_6aOrder, file_name_6bOrder]\n", "for i in range(len(file_names)):\n", - " path_logfile = work_dir + \"SP_\" + file_names[i] + \"/\" + \"SP_\" + file_names[i] + \".csv\"\n", + " path_logfile = (\n", + " work_dir + \"SP_\" + file_names[i] + \"/\" + \"SP_\" + file_names[i] + \".csv\"\n", + " )\n", " ts_dpsim_SP.append(read_timeseries_dpsim(path_logfile))\n", " ts_dpsim_SP_shift.append(ts.frequency_shift_list(ts_dpsim_SP[i], 60))\n", - " \n", - " path_logfile = work_dir + \"DP_\" + file_names[i] + \"/\" + \"DP_\" + file_names[i] + \".csv\"\n", + "\n", + " path_logfile = (\n", + " work_dir + \"DP_\" + file_names[i] + \"/\" + \"DP_\" + file_names[i] + \".csv\"\n", + " )\n", " ts_dpsim_DP.append(read_timeseries_dpsim(path_logfile))\n", " ts_dpsim_DP_shift.append(ts.frequency_shift_list(ts_dpsim_DP[i], 60))\n", " print(path_logfile)\n", - " \n", - " path_logfile = work_dir + \"EMT_\" + file_names[i] + \"/\" + \"EMT_\" + file_names[i] + \".csv\"\n", + "\n", + " path_logfile = (\n", + " work_dir + \"EMT_\" + file_names[i] + \"/\" + \"EMT_\" + file_names[i] + \".csv\"\n", + " )\n", " ts_dpsim_EMT.append(read_timeseries_dpsim(path_logfile))" ] }, @@ -101,94 +120,161 @@ "source": [ "width = 16\n", "height = 4\n", - "color_EMT = 'black'\n", - "color_SP = 'C10'\n", - "color_DP = 'C11'\n", - "linestyle_EMT = '-'\n", - "linestyle_SP = '-'\n", - "linestyle_DP = 'dashed'\n", - "common_time=50e-6\n", - "roi_start=0\n", - "roi_end=4.5\n", - "roi = range(int(roi_start/common_time), int(roi_end/common_time))\n", + "color_EMT = \"black\"\n", + "color_SP = \"C10\"\n", + "color_DP = \"C11\"\n", + "linestyle_EMT = \"-\"\n", + "linestyle_SP = \"-\"\n", + "linestyle_DP = \"dashed\"\n", + "common_time = 50e-6\n", + "roi_start = 0\n", + "roi_end = 4.5\n", + "roi = range(int(roi_start / common_time), int(roi_end / common_time))\n", + "\n", "\n", "def plot_etorque(SGOrder):\n", - " if SGOrder==3:\n", - " idx=0\n", - " if SGOrder==4:\n", - " idx=1\n", - " if SGOrder==6:\n", + " if SGOrder == 3:\n", + " idx = 0\n", + " if SGOrder == 4:\n", + " idx = 1\n", + " if SGOrder == 6:\n", " # Marconato's model\n", - " idx=2\n", - " if SGOrder==7:\n", + " idx = 2\n", + " if SGOrder == 7:\n", " # Anderson's model\n", - " idx=3\n", - " \n", + " idx = 3\n", + "\n", " time = ts_dpsim_EMT[idx][\"Te\"].interpolate(common_time).time[roi]\n", " values_emt = ts_dpsim_EMT[idx][\"Te\"].interpolate(common_time).values[roi]\n", " values_sp = ts_dpsim_SP[idx][\"Te\"].interpolate(common_time).values[roi]\n", " values_dp = ts_dpsim_DP[idx][\"Te\"].interpolate(common_time).values[roi]\n", - " \n", + "\n", " fig = plt.figure(figsize=(width, height))\n", - " plt.plot(time, values_emt, label='EMT', linestyle=linestyle_EMT, color=color_EMT, linewidth=3) \n", - " plt.plot(time, values_sp, label='SP', color=color_SP, linestyle=linestyle_SP, linewidth=3) \n", - " plt.plot(time, values_dp, label='DP', color=color_DP, linestyle=linestyle_DP, linewidth=3) \n", - " plt.ylabel('Electrical torque (p.u.)')\n", - " plt.xlabel('Time (s)')\n", + " plt.plot(\n", + " time,\n", + " values_emt,\n", + " label=\"EMT\",\n", + " linestyle=linestyle_EMT,\n", + " color=color_EMT,\n", + " linewidth=3,\n", + " )\n", + " plt.plot(\n", + " time, values_sp, label=\"SP\", color=color_SP, linestyle=linestyle_SP, linewidth=3\n", + " )\n", + " plt.plot(\n", + " time, values_dp, label=\"DP\", color=color_DP, linestyle=linestyle_DP, linewidth=3\n", + " )\n", + " plt.ylabel(\"Electrical torque (p.u.)\")\n", + " plt.xlabel(\"Time (s)\")\n", " plt.xlim(0, 4.5)\n", " plt.grid()\n", - " plt.legend(loc='lower right')\n", + " plt.legend(loc=\"lower right\")\n", " plt.show()\n", - " \n", - " #calculate RMSE\n", - " nom_value = 0.540541 # power flow result\n", - " rmse_emt = ts_dpsim_SP[idx][\"Te\"].rmse(ts_dpsim_SP[idx][\"Te\"].interpolate(common_time), ts_dpsim_EMT[idx][\"Te\"].interpolate(common_time))\n", - " print('RMSE EMT = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) '.format(rmse_emt, rmse_emt/nom_value*100, nom_value))\n", - " rmse_dp = ts_dpsim_SP[idx][\"Te\"].rmse(ts_dpsim_SP[idx][\"Te\"].interpolate(common_time), ts_dpsim_DP[idx][\"Te\"].interpolate(common_time))\n", - " print('RMSE DP = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) '.format(rmse_dp, rmse_dp/nom_value*100, nom_value))\n", - " \n", - " return (rmse_emt/nom_value*100, rmse_dp/nom_value*100)\n", - " \n", - " \n", + "\n", + " # calculate RMSE\n", + " nom_value = 0.540541 # power flow result\n", + " rmse_emt = ts_dpsim_SP[idx][\"Te\"].rmse(\n", + " ts_dpsim_SP[idx][\"Te\"].interpolate(common_time),\n", + " ts_dpsim_EMT[idx][\"Te\"].interpolate(common_time),\n", + " )\n", + " print(\n", + " \"RMSE EMT = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) \".format(\n", + " rmse_emt, rmse_emt / nom_value * 100, nom_value\n", + " )\n", + " )\n", + " rmse_dp = ts_dpsim_SP[idx][\"Te\"].rmse(\n", + " ts_dpsim_SP[idx][\"Te\"].interpolate(common_time),\n", + " ts_dpsim_DP[idx][\"Te\"].interpolate(common_time),\n", + " )\n", + " print(\n", + " \"RMSE DP = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) \".format(\n", + " rmse_dp, rmse_dp / nom_value * 100, nom_value\n", + " )\n", + " )\n", + "\n", + " return (rmse_emt / nom_value * 100, rmse_dp / nom_value * 100)\n", + "\n", + "\n", "def plot_elecVar(SGOrder, variable_EMT, variable_SP, variable_DP, ylabel):\n", - " if SGOrder==3:\n", - " idx=0\n", - " if SGOrder==4:\n", - " idx=1\n", - " if SGOrder==6:\n", + " if SGOrder == 3:\n", + " idx = 0\n", + " if SGOrder == 4:\n", + " idx = 1\n", + " if SGOrder == 6:\n", " # Marconato's model\n", - " idx=2\n", - " if SGOrder==7:\n", + " idx = 2\n", + " if SGOrder == 7:\n", " # Anderson's model\n", - " idx=3\n", - " \n", + " idx = 3\n", + "\n", " time = ts_dpsim_EMT[idx][variable_EMT].interpolate(common_time).time[roi]\n", " values_emt = ts_dpsim_EMT[idx][variable_EMT].interpolate(common_time).values[roi]\n", - " values_sp = np.sqrt(2/3) * ts_dpsim_SP_shift[idx][variable_SP].interpolate(common_time).values[roi]\n", - " values_dp = np.sqrt(2/3) * ts_dpsim_DP_shift[idx][variable_DP].interpolate(common_time).values[roi] \n", - " \n", + " values_sp = (\n", + " np.sqrt(2 / 3)\n", + " * ts_dpsim_SP_shift[idx][variable_SP].interpolate(common_time).values[roi]\n", + " )\n", + " values_dp = (\n", + " np.sqrt(2 / 3)\n", + " * ts_dpsim_DP_shift[idx][variable_DP].interpolate(common_time).values[roi]\n", + " )\n", + "\n", " fig = plt.figure(figsize=(width, height))\n", - " plt.plot(time, values_emt, label='EMT', linestyle=linestyle_EMT, color=color_EMT, linewidth=3) \n", - " plt.plot(time, values_sp, label='SP', color=color_SP, linestyle=linestyle_SP, linewidth=3) \n", - " plt.plot(time, values_dp, label='DP', color=color_DP, linestyle=linestyle_DP, linewidth=3) \n", + " plt.plot(\n", + " time,\n", + " values_emt,\n", + " label=\"EMT\",\n", + " linestyle=linestyle_EMT,\n", + " color=color_EMT,\n", + " linewidth=3,\n", + " )\n", + " plt.plot(\n", + " time, values_sp, label=\"SP\", color=color_SP, linestyle=linestyle_SP, linewidth=3\n", + " )\n", + " plt.plot(\n", + " time, values_dp, label=\"DP\", color=color_DP, linestyle=linestyle_DP, linewidth=3\n", + " )\n", " plt.ylabel(ylabel)\n", - " plt.xlabel('Time (s)')\n", + " plt.xlabel(\"Time (s)\")\n", " plt.xlim(0.9, 1.2)\n", " plt.grid()\n", - " plt.legend(loc='lower right')\n", + " plt.legend(loc=\"lower right\")\n", " plt.show()\n", - " \n", - " #calculate RMSE\n", - " ts_dpsim_SP_real = TimeSeries(variable_SP, ts_dpsim_SP_shift[idx][variable_SP].time, np.sqrt(2/3) * ts_dpsim_SP_shift[idx][variable_SP].values.real)\n", - " rmse_emt = ts_dpsim_SP_real.rmse(ts_dpsim_SP_real.interpolate(common_time), ts_dpsim_EMT[idx][variable_EMT].interpolate(common_time))\n", - " nom_value = abs(max(ts_dpsim_SP_shift[idx][variable_SP].values[0:int(0.5/common_time)]))\n", - " print('RMSE EMT = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) '.format(rmse_emt, rmse_emt/nom_value*100, nom_value))\n", - " \n", - " ts_dpsim_DP_real = TimeSeries(variable_DP, ts_dpsim_DP_shift[idx][variable_DP].time, np.sqrt(2/3) * ts_dpsim_DP_shift[idx][variable_DP].values.real)\n", - " rmse_dp = ts_dpsim_SP_real.rmse(ts_dpsim_SP_real.interpolate(common_time), ts_dpsim_DP_real.interpolate(common_time))\n", - " print('RMSE DP = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) '.format(rmse_dp, rmse_dp/nom_value*100, nom_value))\n", - " \n", - " return (rmse_emt/nom_value*100, rmse_dp/nom_value*100)" + "\n", + " # calculate RMSE\n", + " ts_dpsim_SP_real = TimeSeries(\n", + " variable_SP,\n", + " ts_dpsim_SP_shift[idx][variable_SP].time,\n", + " np.sqrt(2 / 3) * ts_dpsim_SP_shift[idx][variable_SP].values.real,\n", + " )\n", + " rmse_emt = ts_dpsim_SP_real.rmse(\n", + " ts_dpsim_SP_real.interpolate(common_time),\n", + " ts_dpsim_EMT[idx][variable_EMT].interpolate(common_time),\n", + " )\n", + " nom_value = abs(\n", + " max(ts_dpsim_SP_shift[idx][variable_SP].values[0 : int(0.5 / common_time)])\n", + " )\n", + " print(\n", + " \"RMSE EMT = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) \".format(\n", + " rmse_emt, rmse_emt / nom_value * 100, nom_value\n", + " )\n", + " )\n", + "\n", + " ts_dpsim_DP_real = TimeSeries(\n", + " variable_DP,\n", + " ts_dpsim_DP_shift[idx][variable_DP].time,\n", + " np.sqrt(2 / 3) * ts_dpsim_DP_shift[idx][variable_DP].values.real,\n", + " )\n", + " rmse_dp = ts_dpsim_SP_real.rmse(\n", + " ts_dpsim_SP_real.interpolate(common_time),\n", + " ts_dpsim_DP_real.interpolate(common_time),\n", + " )\n", + " print(\n", + " \"RMSE DP = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) \".format(\n", + " rmse_dp, rmse_dp / nom_value * 100, nom_value\n", + " )\n", + " )\n", + "\n", + " return (rmse_emt / nom_value * 100, rmse_dp / nom_value * 100)" ] }, { @@ -275,16 +361,16 @@ "metadata": {}, "outputs": [], "source": [ - "tol = 0.001 # %\n", + "tol = 0.001 # %\n", "\n", - "assert(rmse_emt_3order 1 and step=='+str(load_idx))\n", + " for load_idx in range(1, max_step):\n", + " pd_test_list = pd_test.query(\"timestep > 1 and step==\" + str(load_idx))\n", " test_list = []\n", " for index, row in pd_test_list.iterrows():\n", - " test_list.append(row['values']['v3_intpl_shift'])\n", + " test_list.append(row[\"values\"][\"v3_intpl_shift\"])\n", "\n", - " ref = pd_ref.query('timestep == 1 and step=='+str(load_idx)).iloc[0]['values']['v3_shift']\n", + " ref = pd_ref.query(\"timestep == 1 and step==\" + str(load_idx)).iloc[0][\n", + " \"values\"\n", + " ][\"v3_shift\"]\n", " mae_dp, diff_list = calc_dpsim_variable_timestep_mae(ref, test_list)\n", " mae_dp_list.append(mae_dp)\n", - " \n", + "\n", " return mae_dp_list" ] }, @@ -104,14 +108,14 @@ "outputs": [], "source": [ "def calc_mae_dp_no_step(pd_ref, pd_test):\n", - " pd_test_list = pd_test.query('timestep > 1')\n", + " pd_test_list = pd_test.query(\"timestep > 1\")\n", " test_list = []\n", " for index, row in pd_test_list.iterrows():\n", - " test_list.append(row['values']['v3_intpl_shift'])\n", + " test_list.append(row[\"values\"][\"v3_intpl_shift\"])\n", "\n", - " ref = pd_ref.query('timestep == 1').iloc[0]['values']['v3_shift']\n", + " ref = pd_ref.query(\"timestep == 1\").iloc[0][\"values\"][\"v3_shift\"]\n", " mae_dp, diff_list = calc_dpsim_variable_timestep_mae(ref, test_list)\n", - " \n", + "\n", " return mae_dp" ] }, @@ -124,16 +128,18 @@ "def calc_mae_emt(pd_ref, pd_test, max_step=11):\n", " mae_emt_list = []\n", "\n", - " for load_idx in range(1,max_step): \n", - " pd_test_list = pd_test.query('timestep > 1 and step=='+str(load_idx))\n", + " for load_idx in range(1, max_step):\n", + " pd_test_list = pd_test.query(\"timestep > 1 and step==\" + str(load_idx))\n", " test_list = []\n", " for index, row in pd_test_list.iterrows():\n", - " test_list.append(row['values']['v3_intpl'])\n", + " test_list.append(row[\"values\"][\"v3_intpl\"])\n", "\n", - " ref = pd_ref.query('timestep == 1 and step=='+str(load_idx)).iloc[0]['values']['v3']\n", + " ref = pd_ref.query(\"timestep == 1 and step==\" + str(load_idx)).iloc[0][\n", + " \"values\"\n", + " ][\"v3\"]\n", " mae, diff_list = calc_dpsim_variable_timestep_mae(ref, test_list)\n", " mae_emt_list.append(mae)\n", - " \n", + "\n", " return mae_emt_list" ] }, @@ -143,15 +149,15 @@ "metadata": {}, "outputs": [], "source": [ - "def calc_mae_emt_no_step(pd_ref, pd_test): \n", - " pd_test_list = pd_test.query('timestep > 1')\n", + "def calc_mae_emt_no_step(pd_ref, pd_test):\n", + " pd_test_list = pd_test.query(\"timestep > 1\")\n", " test_list = []\n", " for index, row in pd_test_list.iterrows():\n", - " test_list.append(row['values']['v3_intpl'])\n", + " test_list.append(row[\"values\"][\"v3_intpl\"])\n", "\n", - " ref = pd_ref.query('timestep == 1').iloc[0]['values']['v3']\n", + " ref = pd_ref.query(\"timestep == 1\").iloc[0][\"values\"][\"v3\"]\n", " mae, diff_list = calc_dpsim_variable_timestep_mae(ref, test_list)\n", - " \n", + "\n", " return mae" ] }, @@ -170,31 +176,33 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " logs_dir = '../../../logs_source_step/'\n", - " log_name = logs_dir+'DP_RL_SourceStep_T' + str(ts_idx) + '/' \\\n", - " 'DP_RL_SourceStep_T' + str(ts_idx)\n", + "for ts_idx in range(1, 21):\n", + " logs_dir = \"../../../logs_source_step/\"\n", + " log_name = logs_dir + \"DP_RL_SourceStep_T\" + str(\n", + " ts_idx\n", + " ) + \"/\" \"DP_RL_SourceStep_T\" + str(ts_idx)\n", "\n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", " ts_curr = ts.frequency_shift_list(ts_curr, 50)\n", - " result_list.append({'timestep': ts_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"values\": ts_curr})\n", + "\n", "pd_dp_1 = pd.DataFrame(result_list)\n", "\n", "result_list = []\n", - "for ts_idx in range(40,401,20):\n", - " logs_dir = '../../../logs_source_step/'\n", - " log_name = logs_dir+'DP_RL_SourceStep_T' + str(ts_idx) + '/' \\\n", - " 'DP_RL_SourceStep_T' + str(ts_idx)\n", + "for ts_idx in range(40, 401, 20):\n", + " logs_dir = \"../../../logs_source_step/\"\n", + " log_name = logs_dir + \"DP_RL_SourceStep_T\" + str(\n", + " ts_idx\n", + " ) + \"/\" \"DP_RL_SourceStep_T\" + str(ts_idx)\n", "\n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", " ts_curr = ts.frequency_shift_list(ts_curr, 50)\n", - " result_list.append({'timestep': ts_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"values\": ts_curr})\n", + "\n", "pd_dp_2 = pd.DataFrame(result_list)" ] }, @@ -206,18 +214,19 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " for load_idx in range(1,11):\n", - " logs_dir = '../../../logs_source_step/'\n", - " log_name = logs_dir+'DP_RL_SourceStep_T' + str(ts_idx) + '_V' + str(load_idx) + '/' \\\n", - " 'DP_RL_SourceStep_T' + str(ts_idx) + '_V' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(1, 21):\n", + " for load_idx in range(1, 11):\n", + " logs_dir = \"../../../logs_source_step/\"\n", + " log_name = logs_dir + \"DP_RL_SourceStep_T\" + str(ts_idx) + \"_V\" + str(\n", + " load_idx\n", + " ) + \"/\" \"DP_RL_SourceStep_T\" + str(ts_idx) + \"_V\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", " ts_curr = ts.frequency_shift_list(ts_curr, 50)\n", - " result_list.append({'timestep': ts_idx, 'step': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"step\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_dp_vstep_1 = pd.DataFrame(result_list)" ] }, @@ -227,8 +236,8 @@ "metadata": {}, "outputs": [], "source": [ - "curr = pd_dp_1.query('timestep=='+str(1))['values'].values[0]\n", - "plt.plot(curr['v3_shift'].time, curr['v3_shift'].values)" + "curr = pd_dp_1.query(\"timestep==\" + str(1))[\"values\"].values[0]\n", + "plt.plot(curr[\"v3_shift\"].time, curr[\"v3_shift\"].values)" ] }, { @@ -237,7 +246,7 @@ "metadata": {}, "outputs": [], "source": [ - "nom_amp = max(curr['v3_shift'].values)" + "nom_amp = max(curr[\"v3_shift\"].values)" ] }, { @@ -248,8 +257,10 @@ "source": [ "sourcestep = 9\n", "timestep = 20\n", - "curr = pd_dp_vstep_1.query('timestep=='+str(timestep)+' and step=='+str(sourcestep))['values'].values[0]\n", - "plt.plot(curr['v3_intpl_shift'].time, curr['v3_intpl_shift'].values)" + "curr = pd_dp_vstep_1.query(\n", + " \"timestep==\" + str(timestep) + \" and step==\" + str(sourcestep)\n", + ")[\"values\"].values[0]\n", + "plt.plot(curr[\"v3_intpl_shift\"].time, curr[\"v3_intpl_shift\"].values)" ] }, { @@ -268,21 +279,27 @@ "outputs": [], "source": [ "import matplotlib.ticker as ticker\n", + "\n", "ax = plt.figure().gca()\n", "ax.xaxis.set_major_locator(ticker.MultipleLocator(0.0002))\n", "\n", - "timesteps = np.arange(2,21)*0.00005\n", - "for load_idx in range(1,10,4): \n", - " plt.plot(timesteps, mae_dp_list_1[load_idx] / nom_amp, 'o-', label=str(load_idx*10+10)+'% step')\n", - "#plt.ylim([-0.01,0.2])\n", - "#plt.xlim([0,0.0009])\n", + "timesteps = np.arange(2, 21) * 0.00005\n", + "for load_idx in range(1, 10, 4):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_dp_list_1[load_idx] / nom_amp,\n", + " \"o-\",\n", + " label=str(load_idx * 10 + 10) + \"% step\",\n", + " )\n", + "# plt.ylim([-0.01,0.2])\n", + "# plt.xlim([0,0.0009])\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean relative error voltage')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean relative error voltage\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_rl_source_step_voltage_1ms.pdf')" + "plt.savefig(\"dp_rl_source_step_voltage_1ms.pdf\")" ] }, { @@ -293,10 +310,17 @@ "source": [ "sourcestep = 4\n", "timestep = 15\n", - "curr = pd_dp_vstep_1.query('timestep=='+str(1)+' and step=='+str(sourcestep))['values'].values[0]\n", - "curr_vts = pd_dp_vstep_1.query('timestep=='+str(timestep)+' and step=='+str(sourcestep))['values'].values[0]\n", - "min_len = min(curr['v3_shift'].values.shape, curr_vts['v3_intpl_shift'].values.shape)[0]\n", - "plt.plot(curr['v3_shift'].time[:min_len], curr['v3_shift'].values[:min_len] - curr_vts['v3_intpl_shift'].values[:min_len])" + "curr = pd_dp_vstep_1.query(\"timestep==\" + str(1) + \" and step==\" + str(sourcestep))[\n", + " \"values\"\n", + "].values[0]\n", + "curr_vts = pd_dp_vstep_1.query(\n", + " \"timestep==\" + str(timestep) + \" and step==\" + str(sourcestep)\n", + ")[\"values\"].values[0]\n", + "min_len = min(curr[\"v3_shift\"].values.shape, curr_vts[\"v3_intpl_shift\"].values.shape)[0]\n", + "plt.plot(\n", + " curr[\"v3_shift\"].time[:min_len],\n", + " curr[\"v3_shift\"].values[:min_len] - curr_vts[\"v3_intpl_shift\"].values[:min_len],\n", + ")" ] }, { @@ -307,18 +331,19 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(40,401,20):\n", - " for load_idx in range(1,11):\n", - " logs_dir = '../../../logs_source_step/'\n", - " log_name = logs_dir+'DP_RL_SourceStep_T' + str(ts_idx) + '_V' + str(load_idx) + '/' \\\n", - " 'DP_RL_SourceStep_T' + str(ts_idx) + '_V' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(40, 401, 20):\n", + " for load_idx in range(1, 11):\n", + " logs_dir = \"../../../logs_source_step/\"\n", + " log_name = logs_dir + \"DP_RL_SourceStep_T\" + str(ts_idx) + \"_V\" + str(\n", + " load_idx\n", + " ) + \"/\" \"DP_RL_SourceStep_T\" + str(ts_idx) + \"_V\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", " ts_curr = ts.frequency_shift_list(ts_curr, 50)\n", - " result_list.append({'timestep': ts_idx, 'step': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"step\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_dp_vstep_2 = pd.DataFrame(result_list)" ] }, @@ -330,8 +355,10 @@ "source": [ "sourcestep = 2\n", "timestep = 360\n", - "curr = pd_dp_vstep_2.query('timestep=='+str(timestep)+' and step=='+str(sourcestep))['values'].values[0]\n", - "plt.plot(curr['v3_intpl_shift'].time, curr['v3_intpl_shift'].values)" + "curr = pd_dp_vstep_2.query(\n", + " \"timestep==\" + str(timestep) + \" and step==\" + str(sourcestep)\n", + ")[\"values\"].values[0]\n", + "plt.plot(curr[\"v3_intpl_shift\"].time, curr[\"v3_intpl_shift\"].values)" ] }, { @@ -349,18 +376,23 @@ "metadata": {}, "outputs": [], "source": [ - "timesteps = np.arange(40,401,20)*0.00005\n", - "for load_idx in range(1,10,4): \n", - " plt.plot(timesteps, mae_dp_list_2[load_idx] / nom_amp, 'o-', label=str(load_idx*10+10)+'% step')\n", - "#plt.ylim([-0.01,0.2])\n", - "#plt.xlim([0,0.0009])\n", + "timesteps = np.arange(40, 401, 20) * 0.00005\n", + "for load_idx in range(1, 10, 4):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_dp_list_2[load_idx] / nom_amp,\n", + " \"o-\",\n", + " label=str(load_idx * 10 + 10) + \"% step\",\n", + " )\n", + "# plt.ylim([-0.01,0.2])\n", + "# plt.xlim([0,0.0009])\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean relative error voltage')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean relative error voltage\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_rl_source_step_voltage_20ms.pdf')" + "plt.savefig(\"dp_rl_source_step_voltage_20ms.pdf\")" ] }, { @@ -378,29 +410,31 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " logs_dir = '../../../logs_source_step/'\n", - " log_name = logs_dir+'EMT_RL_SourceStep_T' + str(ts_idx) + '/' \\\n", - " 'EMT_RL_SourceStep_T' + str(ts_idx)\n", + "for ts_idx in range(1, 21):\n", + " logs_dir = \"../../../logs_source_step/\"\n", + " log_name = logs_dir + \"EMT_RL_SourceStep_T\" + str(\n", + " ts_idx\n", + " ) + \"/\" \"EMT_RL_SourceStep_T\" + str(ts_idx)\n", "\n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", - " result_list.append({'timestep': ts_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"values\": ts_curr})\n", + "\n", "pd_emt_1 = pd.DataFrame(result_list)\n", "\n", "result_list = []\n", - "for ts_idx in range(40,401,20):\n", - " logs_dir = '../../../logs_source_step/'\n", - " log_name = logs_dir+'EMT_RL_SourceStep_T' + str(ts_idx) + '/' \\\n", - " 'EMT_RL_SourceStep_T' + str(ts_idx)\n", + "for ts_idx in range(40, 401, 20):\n", + " logs_dir = \"../../../logs_source_step/\"\n", + " log_name = logs_dir + \"EMT_RL_SourceStep_T\" + str(\n", + " ts_idx\n", + " ) + \"/\" \"EMT_RL_SourceStep_T\" + str(ts_idx)\n", "\n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", - " result_list.append({'timestep': ts_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"values\": ts_curr})\n", + "\n", "pd_emt_2 = pd.DataFrame(result_list)" ] }, @@ -412,17 +446,18 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " for load_idx in range(1,11):\n", - " logs_dir = '../../../logs_source_step/'\n", - " log_name = logs_dir+'EMT_RL_SourceStep_T' + str(ts_idx) + '_V' + str(load_idx) + '/' \\\n", - " 'EMT_RL_SourceStep_T' + str(ts_idx) + '_V' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(1, 21):\n", + " for load_idx in range(1, 11):\n", + " logs_dir = \"../../../logs_source_step/\"\n", + " log_name = logs_dir + \"EMT_RL_SourceStep_T\" + str(ts_idx) + \"_V\" + str(\n", + " load_idx\n", + " ) + \"/\" \"EMT_RL_SourceStep_T\" + str(ts_idx) + \"_V\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", - " result_list.append({'timestep': ts_idx, 'step': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"step\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_emt_vstep_1 = pd.DataFrame(result_list)" ] }, @@ -434,8 +469,10 @@ "source": [ "sourcestep = 1\n", "timestep = 20\n", - "curr = pd_emt_vstep_1.query('timestep=='+str(timestep)+' and step=='+str(sourcestep))['values'].values[0]\n", - "plt.plot(curr['v3_intpl'].time, curr['v3_intpl'].values)" + "curr = pd_emt_vstep_1.query(\n", + " \"timestep==\" + str(timestep) + \" and step==\" + str(sourcestep)\n", + ")[\"values\"].values[0]\n", + "plt.plot(curr[\"v3_intpl\"].time, curr[\"v3_intpl\"].values)" ] }, { @@ -453,22 +490,32 @@ "metadata": {}, "outputs": [], "source": [ - "timesteps = np.arange(2,21)*0.00005\n", + "timesteps = np.arange(2, 21) * 0.00005\n", "\n", - "for i in range(1,10,4): \n", - " plt.plot(timesteps, mae_dp_list_1[i] / nom_amp, 'o-', label=str(i*10+10)+'% step, dp')\n", - "for i in range(1,10,4): \n", - " plt.plot(timesteps, mae_emt_list_1[i] / nom_amp, 'o-', label=str(i*10+10)+'% step, emt')\n", + "for i in range(1, 10, 4):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_dp_list_1[i] / nom_amp,\n", + " \"o-\",\n", + " label=str(i * 10 + 10) + \"% step, dp\",\n", + " )\n", + "for i in range(1, 10, 4):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_emt_list_1[i] / nom_amp,\n", + " \"o-\",\n", + " label=str(i * 10 + 10) + \"% step, emt\",\n", + " )\n", "\n", - "#plt.ylim([-0.01,0.2])\n", - "#plt.xlim([0,0.0009])\n", + "# plt.ylim([-0.01,0.2])\n", + "# plt.xlim([0,0.0009])\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean relative error voltage')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean relative error voltage\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_emt_rl_source_step_voltage_1ms.pdf')" + "plt.savefig(\"dp_emt_rl_source_step_voltage_1ms.pdf\")" ] }, { @@ -479,16 +526,17 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(40,401,20):\n", - " for load_idx in range(1,11):\n", - " log_dir = '../../../logs_source_step/'\n", - " log_name = log_dir + 'EMT_RL_SourceStep_T' + str(ts_idx) + '_V' + str(load_idx) + '/' \\\n", - " 'EMT_RL_SourceStep_T' + str(ts_idx) + '_V' + str(load_idx) \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(40, 401, 20):\n", + " for load_idx in range(1, 11):\n", + " log_dir = \"../../../logs_source_step/\"\n", + " log_name = log_dir + \"EMT_RL_SourceStep_T\" + str(ts_idx) + \"_V\" + str(\n", + " load_idx\n", + " ) + \"/\" \"EMT_RL_SourceStep_T\" + str(ts_idx) + \"_V\" + str(load_idx)\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", - " result_list.append({'timestep': ts_idx, 'step': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"step\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_emt_vstep_2 = pd.DataFrame(result_list)" ] }, @@ -500,8 +548,10 @@ "source": [ "sourcestep = 2\n", "timestep = 200\n", - "curr = pd_emt_vstep_2.query('timestep=='+str(timestep)+' and step=='+str(sourcestep))['values'].values[0]\n", - "plt.plot(curr['v3_intpl'].time, curr['v3_intpl'].values)" + "curr = pd_emt_vstep_2.query(\n", + " \"timestep==\" + str(timestep) + \" and step==\" + str(sourcestep)\n", + ")[\"values\"].values[0]\n", + "plt.plot(curr[\"v3_intpl\"].time, curr[\"v3_intpl\"].values)" ] }, { @@ -519,21 +569,31 @@ "metadata": {}, "outputs": [], "source": [ - "timesteps = np.arange(40,401,20)*0.00005\n", + "timesteps = np.arange(40, 401, 20) * 0.00005\n", "\n", - "for load_idx in range(1,10,4): \n", - " plt.plot(timesteps, mae_dp_list_2[load_idx] / nom_amp, 'o-', label=str(load_idx*10+10)+'% step, dp')\n", + "for load_idx in range(1, 10, 4):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_dp_list_2[load_idx] / nom_amp,\n", + " \"o-\",\n", + " label=str(load_idx * 10 + 10) + \"% step, dp\",\n", + " )\n", "\n", - "for load_idx in range(1,10,4): \n", - " plt.plot(timesteps, mae_emt_list_2[load_idx] / nom_amp, 'o-', label=str(load_idx*10+10)+'% step, emt')\n", + "for load_idx in range(1, 10, 4):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_emt_list_2[load_idx] / nom_amp,\n", + " \"o-\",\n", + " label=str(load_idx * 10 + 10) + \"% step, emt\",\n", + " )\n", "\n", - "#plt.ylim([0,0.1])\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean relative error voltage')\n", + "# plt.ylim([0,0.1])\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean relative error voltage\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_emt_rl_source_step_voltage_20ms.pdf')" + "plt.savefig(\"dp_emt_rl_source_step_voltage_20ms.pdf\")" ] }, { @@ -558,18 +618,19 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " for load_idx in range(1,11):\n", - " log_dir = '../../../logs_source_step/'\n", - " log_name = log_dir + 'DP_RL_SourceStep_T' + str(ts_idx) + '_F' + str(load_idx) + '/' \\\n", - " 'DP_RL_SourceStep_T' + str(ts_idx) + '_F' + str(load_idx)\n", + "for ts_idx in range(1, 21):\n", + " for load_idx in range(1, 11):\n", + " log_dir = \"../../../logs_source_step/\"\n", + " log_name = log_dir + \"DP_RL_SourceStep_T\" + str(ts_idx) + \"_F\" + str(\n", + " load_idx\n", + " ) + \"/\" \"DP_RL_SourceStep_T\" + str(ts_idx) + \"_F\" + str(load_idx)\n", "\n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", " ts_curr = ts.frequency_shift_list(ts_curr, 50)\n", - " result_list.append({'timestep': ts_idx, 'step': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"step\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_dp_fstep_1 = pd.DataFrame(result_list)" ] }, @@ -581,8 +642,10 @@ "source": [ "sourcestep = 8\n", "timestep = 15\n", - "curr = pd_dp_fstep_1.query('timestep=='+str(timestep)+' and step=='+str(sourcestep))['values'].values[0]\n", - "plt.plot(curr['v3_intpl_shift'].time, curr['v3_intpl_shift'].values)" + "curr = pd_dp_fstep_1.query(\n", + " \"timestep==\" + str(timestep) + \" and step==\" + str(sourcestep)\n", + ")[\"values\"].values[0]\n", + "plt.plot(curr[\"v3_intpl_shift\"].time, curr[\"v3_intpl_shift\"].values)" ] }, { @@ -601,17 +664,22 @@ "metadata": {}, "outputs": [], "source": [ - "timesteps = np.arange(2,21)*0.00005\n", - "plt.plot(timesteps, mae_dp_1 / nom_amp, 'o-', label='freq. dev. 0Hz')\n", - "for i in range(0,4,2): \n", - " plt.plot(timesteps, mae_dp_fstep_1[i] / nom_amp, 'o-', label='freq. dev. '+str(i+1)+'Hz')\n", + "timesteps = np.arange(2, 21) * 0.00005\n", + "plt.plot(timesteps, mae_dp_1 / nom_amp, \"o-\", label=\"freq. dev. 0Hz\")\n", + "for i in range(0, 4, 2):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_dp_fstep_1[i] / nom_amp,\n", + " \"o-\",\n", + " label=\"freq. dev. \" + str(i + 1) + \"Hz\",\n", + " )\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean relative error voltage')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean relative error voltage\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_rl_source_step_frequency_1ms.pdf')" + "plt.savefig(\"dp_rl_source_step_frequency_1ms.pdf\")" ] }, { @@ -622,18 +690,19 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(40,401,20):\n", - " for load_idx in range(1,11):\n", - " log_dir = '../../../logs_source_step/'\n", - " log_name = log_dir + 'DP_RL_SourceStep_T' + str(ts_idx) + '_F' + str(load_idx) + '/' \\\n", - " 'DP_RL_SourceStep_T' + str(ts_idx) + '_F' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(40, 401, 20):\n", + " for load_idx in range(1, 11):\n", + " log_dir = \"../../../logs_source_step/\"\n", + " log_name = log_dir + \"DP_RL_SourceStep_T\" + str(ts_idx) + \"_F\" + str(\n", + " load_idx\n", + " ) + \"/\" \"DP_RL_SourceStep_T\" + str(ts_idx) + \"_F\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", " ts_curr = ts.frequency_shift_list(ts_curr, 50)\n", - " result_list.append({'timestep': ts_idx, 'step': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"step\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_dp_fstep_2 = pd.DataFrame(result_list)" ] }, @@ -653,17 +722,22 @@ "metadata": {}, "outputs": [], "source": [ - "timesteps = np.arange(40,401,20)*0.00005\n", - "plt.plot(timesteps, mae_dp_2 / nom_amp, 'o-', label='freq. dev. 0Hz')\n", - "for i in range(0,4,2): \n", - " plt.plot(timesteps, mae_dp_fstep_2[i] / nom_amp, 'o-', label='freq. dev. '+str(i+1)+'Hz')\n", + "timesteps = np.arange(40, 401, 20) * 0.00005\n", + "plt.plot(timesteps, mae_dp_2 / nom_amp, \"o-\", label=\"freq. dev. 0Hz\")\n", + "for i in range(0, 4, 2):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_dp_fstep_2[i] / nom_amp,\n", + " \"o-\",\n", + " label=\"freq. dev. \" + str(i + 1) + \"Hz\",\n", + " )\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean relative error voltage')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean relative error voltage\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_rl_source_step_frequency_20ms.pdf')" + "plt.savefig(\"dp_rl_source_step_frequency_20ms.pdf\")" ] }, { @@ -681,17 +755,18 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " for load_idx in range(1,11):\n", - " log_dir = '../../../logs_source_step/'\n", - " log_name = log_dir + 'EMT_RL_SourceStep_T' + str(ts_idx) + '_F' + str(load_idx) + '/' \\\n", - " 'EMT_RL_SourceStep_T' + str(ts_idx) + '_F' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(1, 21):\n", + " for load_idx in range(1, 11):\n", + " log_dir = \"../../../logs_source_step/\"\n", + " log_name = log_dir + \"EMT_RL_SourceStep_T\" + str(ts_idx) + \"_F\" + str(\n", + " load_idx\n", + " ) + \"/\" \"EMT_RL_SourceStep_T\" + str(ts_idx) + \"_F\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", - " result_list.append({'timestep': ts_idx, 'step': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"step\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_emt_fstep_1 = pd.DataFrame(result_list)" ] }, @@ -711,22 +786,32 @@ "metadata": {}, "outputs": [], "source": [ - "timesteps = np.arange(2,21)*0.00005\n", + "timesteps = np.arange(2, 21) * 0.00005\n", "\n", - "plt.plot(timesteps, mae_dp_1 / nom_amp, 'o-', label='freq. dev. 0Hz, dp')\n", - "for i in range(0,4,2): \n", - " plt.plot(timesteps, mae_dp_fstep_1[i] / nom_amp, 'o-', label='freq. dev. '+str(i+1)+'Hz, dp')\n", + "plt.plot(timesteps, mae_dp_1 / nom_amp, \"o-\", label=\"freq. dev. 0Hz, dp\")\n", + "for i in range(0, 4, 2):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_dp_fstep_1[i] / nom_amp,\n", + " \"o-\",\n", + " label=\"freq. dev. \" + str(i + 1) + \"Hz, dp\",\n", + " )\n", "\n", - "plt.plot(timesteps, mae_emt_1 / nom_amp, 'o-', label='freq. dev. 0Hz, emt')\n", - "for i in range(0,4,2): \n", - " plt.plot(timesteps, mae_emt_fstep_1[i] / nom_amp, 'o-', label='freq. dev. '+str(i+1)+'Hz, emt')\n", + "plt.plot(timesteps, mae_emt_1 / nom_amp, \"o-\", label=\"freq. dev. 0Hz, emt\")\n", + "for i in range(0, 4, 2):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_emt_fstep_1[i] / nom_amp,\n", + " \"o-\",\n", + " label=\"freq. dev. \" + str(i + 1) + \"Hz, emt\",\n", + " )\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean relative error voltage')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean relative error voltage\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_emt_rl_source_step_frequency_1ms.pdf')" + "plt.savefig(\"dp_emt_rl_source_step_frequency_1ms.pdf\")" ] }, { @@ -737,17 +822,18 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(40,401,20):\n", - " for load_idx in range(1,11):\n", - " log_dir = '../../../logs_source_step/'\n", - " log_name = log_dir+'EMT_RL_SourceStep_T' + str(ts_idx) + '_F' + str(load_idx) + '/' \\\n", - " 'EMT_RL_SourceStep_T' + str(ts_idx) + '_F' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(40, 401, 20):\n", + " for load_idx in range(1, 11):\n", + " log_dir = \"../../../logs_source_step/\"\n", + " log_name = log_dir + \"EMT_RL_SourceStep_T\" + str(ts_idx) + \"_F\" + str(\n", + " load_idx\n", + " ) + \"/\" \"EMT_RL_SourceStep_T\" + str(ts_idx) + \"_F\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", - " result_list.append({'timestep': ts_idx, 'step': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"step\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_emt_fstep_2 = pd.DataFrame(result_list)" ] }, @@ -767,25 +853,35 @@ "metadata": {}, "outputs": [], "source": [ - "timesteps = np.arange(40,401,20)*0.00005\n", + "timesteps = np.arange(40, 401, 20) * 0.00005\n", + "\n", + "plt.plot(timesteps, mae_dp_2 / nom_amp, \"o-\", label=\"freq. dev. 0Hz, dp\")\n", + "for i in range(0, 4, 2):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_dp_fstep_2[i] / nom_amp,\n", + " \"o-\",\n", + " label=\"freq. dev. \" + str(i + 1) + \"Hz, dp\",\n", + " )\n", "\n", - "plt.plot(timesteps, mae_dp_2 / nom_amp, 'o-', label='freq. dev. 0Hz, dp')\n", - "for i in range(0,4,2): \n", - " plt.plot(timesteps, mae_dp_fstep_2[i] / nom_amp, 'o-', label='freq. dev. '+str(i+1)+'Hz, dp')\n", + "plt.plot(timesteps, mae_emt_2 / nom_amp, \"o-\", label=\"freq. dev. 0Hz, emt\")\n", + "for i in range(0, 4, 2):\n", + " plt.plot(\n", + " timesteps,\n", + " mae_emt_fstep_2[i] / nom_amp,\n", + " \"o-\",\n", + " label=\"freq. dev. \" + str(i + 1) + \"Hz, emt\",\n", + " )\n", "\n", - "plt.plot(timesteps, mae_emt_2 / nom_amp, 'o-', label='freq. dev. 0Hz, emt')\n", - "for i in range(0,4,2): \n", - " plt.plot(timesteps, mae_emt_fstep_2[i] / nom_amp, 'o-', label='freq. dev. '+str(i+1)+'Hz, emt')\n", - " \n", - "#plt.xlim([0.0015,0.008])\n", - "#plt.ylim([0,400])\n", - "#plt.ylim([0,0.1])\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean relative error voltage')\n", + "# plt.xlim([0.0015,0.008])\n", + "# plt.ylim([0,400])\n", + "# plt.ylim([0,0.1])\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean relative error voltage\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_emt_rl_source_step_frequency_20ms.pdf')" + "plt.savefig(\"dp_emt_rl_source_step_frequency_20ms.pdf\")" ] }, { diff --git a/examples/Notebooks/Circuits/SP_Slack_PiLine_VSI_with_PF_Init.ipynb b/examples/Notebooks/Circuits/SP_Slack_PiLine_VSI_with_PF_Init.ipynb index abf0935cbc..6417a12d54 100644 --- a/examples/Notebooks/Circuits/SP_Slack_PiLine_VSI_with_PF_Init.ipynb +++ b/examples/Notebooks/Circuits/SP_Slack_PiLine_VSI_with_PF_Init.ipynb @@ -67,22 +67,22 @@ "time_step_pf = final_time\n", "final_time_pf = final_time + time_step_pf\n", "sim_name_pf = sim_name + \"_PF\"\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "\n", "# Components\n", - "n1_pf = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single)\n", - "n2_pf = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single)\n", + "n1_pf = dpsimpy.sp.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "n2_pf = dpsimpy.sp.SimNode(\"n2\", dpsimpy.PhaseType.Single)\n", "\n", - "extnet_pf = dpsimpy.sp.ph1.NetworkInjection('Slack', dpsimpy.LogLevel.debug)\n", + "extnet_pf = dpsimpy.sp.ph1.NetworkInjection(\"Slack\", dpsimpy.LogLevel.debug)\n", "extnet_pf.set_parameters(voltage_set_point=V_nom)\n", "extnet_pf.set_base_voltage(V_nom)\n", "extnet_pf.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", "\n", - "line_pf = dpsimpy.sp.ph1.PiLine('PiLine', dpsimpy.LogLevel.debug)\n", - "line_pf.set_parameters(R=0.5*5, L=0.5/314*5, C=50e-6/314*5)\n", + "line_pf = dpsimpy.sp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", + "line_pf.set_parameters(R=0.5 * 5, L=0.5 / 314 * 5, C=50e-6 / 314 * 5)\n", "line_pf.set_base_voltage(V_nom)\n", "\n", - "load_pf = dpsimpy.sp.ph1.Load('Load', dpsimpy.LogLevel.debug)\n", + "load_pf = dpsimpy.sp.ph1.Load(\"Load\", dpsimpy.LogLevel.debug)\n", "load_pf.set_parameters(active_power=-100e3, reactive_power=-50e3, nominal_voltage=20e3)\n", "load_pf.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PQ)\n", "\n", @@ -94,8 +94,8 @@ "\n", "# Logging\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", - "logger_pf.log_attribute('v1', 'v', n1_pf)\n", - "logger_pf.log_attribute('v2', 'v', n2_pf)\n", + "logger_pf.log_attribute(\"v1\", \"v\", n1_pf)\n", + "logger_pf.log_attribute(\"v2\", \"v\", n2_pf)\n", "\n", "# Simulation\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", @@ -125,28 +125,50 @@ "time_step_sp = time_step\n", "final_time_sp = final_time + time_step_sp\n", "sim_name_sp = sim_name + \"_SP\"\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_sp)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_sp)\n", "\n", "# Components\n", "gnd = dpsimpy.sp.SimNode.gnd\n", - "n1_sp = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single)\n", - "n2_sp = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single)\n", + "n1_sp = dpsimpy.sp.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "n2_sp = dpsimpy.sp.SimNode(\"n2\", dpsimpy.PhaseType.Single)\n", "\n", - "extnet_sp = dpsimpy.sp.ph1.NetworkInjection('Slack', dpsimpy.LogLevel.debug)\n", + "extnet_sp = dpsimpy.sp.ph1.NetworkInjection(\"Slack\", dpsimpy.LogLevel.debug)\n", "extnet_sp.set_parameters(complex(V_nom, 0))\n", "\n", - "line_sp = dpsimpy.sp.ph1.PiLine('PiLine', dpsimpy.LogLevel.debug)\n", - "line_sp.set_parameters(R=0.5*5, L=(0.5/314)*5, C=(50e-6/314)*5)\n", + "line_sp = dpsimpy.sp.ph1.PiLine(\"PiLine\", dpsimpy.LogLevel.debug)\n", + "line_sp.set_parameters(R=0.5 * 5, L=(0.5 / 314) * 5, C=(50e-6 / 314) * 5)\n", "\n", - "pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ(\"pv\", \"pv\", dpsimpy.LogLevel.debug, with_trafo=True)\n", + "pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ(\n", + " \"pv\", \"pv\", dpsimpy.LogLevel.debug, with_trafo=True\n", + ")\n", "pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=V_nom, p_ref=100e3, q_ref=50e3)\n", - "pv.set_controller_parameters(Kp_pll=cmd_scale_P * 0.25, Ki_pll=cmd_scale_I * 0.2,\n", - " Kp_power_ctrl=cmd_scale_P *0.001, Ki_power_ctrl=cmd_scale_I * 0.008 ,\n", - " Kp_curr_ctrl=cmd_scale_P * 0.3, Ki_curr_ctrl=cmd_scale_I * 1, omega_cutoff=2*np.pi*50)\n", - "pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - "pv.set_transformer_parameters(nom_voltage_end_1=V_nom, nom_voltage_end_2=1500, rated_power = 5e6,\n", - " ratio_abs=V_nom / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3)\n", - "pv.set_initial_state_values(p_init=100e3, q_init=50e3, phi_d_init=0, phi_q_init=0, gamma_d_init=0, gamma_q_init=0)\n", + "pv.set_controller_parameters(\n", + " Kp_pll=cmd_scale_P * 0.25,\n", + " Ki_pll=cmd_scale_I * 0.2,\n", + " Kp_power_ctrl=cmd_scale_P * 0.001,\n", + " Ki_power_ctrl=cmd_scale_I * 0.008,\n", + " Kp_curr_ctrl=cmd_scale_P * 0.3,\n", + " Ki_curr_ctrl=cmd_scale_I * 1,\n", + " omega_cutoff=2 * np.pi * 50,\n", + ")\n", + "pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + "pv.set_transformer_parameters(\n", + " nom_voltage_end_1=V_nom,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=V_nom / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + ")\n", + "pv.set_initial_state_values(\n", + " p_init=100e3,\n", + " q_init=50e3,\n", + " phi_d_init=0,\n", + " phi_q_init=0,\n", + " gamma_d_init=0,\n", + " gamma_q_init=0,\n", + ")\n", "pv.with_control(pv_with_control)\n", "\n", "# Topology\n", @@ -160,45 +182,53 @@ "\n", "# Logging\n", "logger_sp = dpsimpy.Logger(sim_name_sp)\n", - "logger_sp.log_attribute('v1', 'v', n1_sp)\n", - "logger_sp.log_attribute('v2', 'v', n2_sp)\n", - "logger_sp.log_attribute('i12', 'i_intf', line_sp)\n", + "logger_sp.log_attribute(\"v1\", \"v\", n1_sp)\n", + "logger_sp.log_attribute(\"v2\", \"v\", n2_sp)\n", + "logger_sp.log_attribute(\"i12\", \"i_intf\", line_sp)\n", "\n", "\n", "input_names = [\n", - " \"pv_powerctrl_input_pref\", \"pv_powerctrl_input_qref\", \"pv_powerctrl_input_vcd\",\n", - " \"pv_powerctrl_input_vcq\", \"pv_powerctrl_input_ircd\", \"pv_powerctrl_input_ircq\"\n", + " \"pv_powerctrl_input_pref\",\n", + " \"pv_powerctrl_input_qref\",\n", + " \"pv_powerctrl_input_vcd\",\n", + " \"pv_powerctrl_input_vcq\",\n", + " \"pv_powerctrl_input_ircd\",\n", + " \"pv_powerctrl_input_ircq\",\n", "]\n", - "logger_sp.log_attribute(input_names, 'powerctrl_inputs', pv)\n", + "logger_sp.log_attribute(input_names, \"powerctrl_inputs\", pv)\n", "\n", "state_names = [\n", - " \"pv_powerctrl_state_p\", \"pv_powerctrl_state_q\", \"pv_powerctrl_state_phid\",\n", - " \"pv_powerctrl_state_phiq\", \"pv_powerctrl_state_gammad\", \"pv_powerctrl_state_gammaq\"\n", + " \"pv_powerctrl_state_p\",\n", + " \"pv_powerctrl_state_q\",\n", + " \"pv_powerctrl_state_phid\",\n", + " \"pv_powerctrl_state_phiq\",\n", + " \"pv_powerctrl_state_gammad\",\n", + " \"pv_powerctrl_state_gammaq\",\n", "]\n", - "logger_sp.log_attribute(state_names, 'powerctrl_states', pv)\n", + "logger_sp.log_attribute(state_names, \"powerctrl_states\", pv)\n", "\n", - "output_names = [\n", - " \"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"\n", - "]\n", + "output_names = [\"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"]\n", "\n", - "logger_sp.log_attribute(output_names, 'powerctrl_outputs', pv)\n", + "logger_sp.log_attribute(output_names, \"powerctrl_outputs\", pv)\n", "\n", - "logger_sp.log_attribute('pv_v_intf', 'v_intf', pv)\n", - "logger_sp.log_attribute('pv_i_intf', 'i_intf', pv)\n", - "logger_sp.log_attribute('pv_pll_output', 'pll_output', pv)\n", - "logger_sp.log_attribute('pv_vsref', 'Vsref', pv)\n", - "logger_sp.log_attribute('pv_vs', 'Vs', pv)\n", + "logger_sp.log_attribute(\"pv_v_intf\", \"v_intf\", pv)\n", + "logger_sp.log_attribute(\"pv_i_intf\", \"i_intf\", pv)\n", + "logger_sp.log_attribute(\"pv_pll_output\", \"pll_output\", pv)\n", + "logger_sp.log_attribute(\"pv_vsref\", \"Vsref\", pv)\n", + "logger_sp.log_attribute(\"pv_vs\", \"Vs\", pv)\n", "\n", "# load step sized in absolute terms\n", "load_switch = dpsimpy.sp.ph1.Switch(\"Load_Add_Switch_n2\", dpsimpy.LogLevel.debug)\n", - "connection_node = system_sp.node('n2')\n", - "resistance = np.abs(connection_node.initial_single_voltage())**2 / 10e6\n", + "connection_node = system_sp.node(\"n2\")\n", + "resistance = np.abs(connection_node.initial_single_voltage()) ** 2 / 10e6\n", "load_switch.set_parameters(1e9, resistance)\n", "load_switch.open()\n", "system_sp.add(load_switch)\n", - "system_sp.connect_component(load_switch, [gnd, system_sp.node('n2')])\n", - "logger_sp.log_attribute('switchedload_i', 'i_intf', load_switch)\n", - "load_step_event = dpsimpy.event.SwitchEvent(np.round(5.0/time_step)*time_step, load_switch, True)\n", + "system_sp.connect_component(load_switch, [gnd, system_sp.node(\"n2\")])\n", + "logger_sp.log_attribute(\"switchedload_i\", \"i_intf\", load_switch)\n", + "load_step_event = dpsimpy.event.SwitchEvent(\n", + " np.round(5.0 / time_step) * time_step, load_switch, True\n", + ")\n", "\n", "# Simulation\n", "sim_sp = dpsimpy.Simulation(sim_name_sp, dpsimpy.LogLevel.debug)\n", @@ -224,9 +254,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'SP_Slack_PiLine_VSI_with_PF_Init_PF'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"SP_Slack_PiLine_VSI_with_PF_Init_PF\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim_pf = read_timeseries_csv(dpsim_result_file)" ] @@ -244,9 +274,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'SP_Slack_PiLine_VSI_with_PF_Init_SP'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"SP_Slack_PiLine_VSI_with_PF_Init_SP\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -257,13 +287,13 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name == 'v1' or ts_name == 'v2':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name == \"v1\" or ts_name == \"v2\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", - "for ts_name, ts_obj in ts_dpsim_pf.items():\n", - " if ts_name == 'v1' or ts_name == 'v2':\n", - " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name+'_pf', linestyle=':')\n", + "for ts_name, ts_obj in ts_dpsim_pf.items():\n", + " if ts_name == \"v1\" or ts_name == \"v2\":\n", + " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name + \"_pf\", linestyle=\":\")\n", "plt.legend()\n", "plt.show()" ] diff --git a/examples/Notebooks/Circuits/SP_Validation_ReducedOrderSG_VBR_SMIB_Fault_withControllers.ipynb b/examples/Notebooks/Circuits/SP_Validation_ReducedOrderSG_VBR_SMIB_Fault_withControllers.ipynb index 01661e900f..7544de1814 100644 --- a/examples/Notebooks/Circuits/SP_Validation_ReducedOrderSG_VBR_SMIB_Fault_withControllers.ipynb +++ b/examples/Notebooks/Circuits/SP_Validation_ReducedOrderSG_VBR_SMIB_Fault_withControllers.ipynb @@ -28,17 +28,26 @@ "import os\n", "import subprocess\n", "\n", - "#%matplotlib widget\n", + "# %matplotlib widget\n", "\n", - "name = 'SP_ReducedOrderSG_SMIB_Fault'\n", - "options = ['SGModel=3', 'SGModel=4', 'SGModel=6a', 'SGModel=6b']\n", + "name = \"SP_ReducedOrderSG_SMIB_Fault\"\n", + "options = [\"SGModel=3\", \"SGModel=4\", \"SGModel=6a\", \"SGModel=6b\"]\n", "\n", - "dpsim_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", + "dpsim_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", "\n", - "path_exec = dpsim_path + '/build/dpsim/examples/cxx/'\n", + "path_exec = dpsim_path + \"/build/dpsim/examples/cxx/\"\n", "for i in range(len(options)):\n", - " sim = subprocess.Popen([path_exec + name, '-o', options[i], '-oWithExciter=true', '-oFinalTime=10'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", - " print(sim.communicate()[0].decode())\n" + " sim = subprocess.Popen(\n", + " [path_exec + name, \"-o\", options[i], \"-oWithExciter=true\", \"-oFinalTime=10\"],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + " )\n", + " print(sim.communicate()[0].decode())" ] }, { @@ -66,10 +75,10 @@ "import os\n", "\n", "work_dir = os.getcwd() + \"/logs/\"\n", - "file_name_3Order = 'SP_SynGen3Order_VBR_SMIB_Fault'\n", - "file_name_4Order = 'SP_SynGen4Order_VBR_SMIB_Fault'\n", - "file_name_6aOrder = 'SP_SynGen6aOrder_VBR_SMIB_Fault'\n", - "file_name_6bOrder = 'SP_SynGen6bOrder_VBR_SMIB_Fault'\n", + "file_name_3Order = \"SP_SynGen3Order_VBR_SMIB_Fault\"\n", + "file_name_4Order = \"SP_SynGen4Order_VBR_SMIB_Fault\"\n", + "file_name_6aOrder = \"SP_SynGen6aOrder_VBR_SMIB_Fault\"\n", + "file_name_6bOrder = \"SP_SynGen6bOrder_VBR_SMIB_Fault\"\n", "\n", "\n", "path_logfile = work_dir + file_name_3Order + \"/\" + file_name_3Order + \".csv\"\n", @@ -103,21 +112,27 @@ "source": [ "import urllib.request\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/SMIB-Fault/PSAT_3OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.txt'\n", - "local_file_3Order = 'reference-results/PSAT_3OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.out'\n", - "urllib.request.urlretrieve(url, local_file_3Order) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/SMIB-Fault/PSAT_3OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.txt\"\n", + "local_file_3Order = (\n", + " \"reference-results/PSAT_3OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.out\"\n", + ")\n", + "urllib.request.urlretrieve(url, local_file_3Order)\n", "ts_psat_3Order = read_timeseries_dpsim(local_file_3Order)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/SMIB-Fault/PSAT_4OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.txt'\n", - "local_file_4Order = 'reference-results/PSAT_4OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.out'\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/SMIB-Fault/PSAT_4OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.txt\"\n", + "local_file_4Order = (\n", + " \"reference-results/PSAT_4OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.out\"\n", + ")\n", "urllib.request.urlretrieve(url, local_file_4Order)\n", "ts_psat_4Order = read_timeseries_dpsim(local_file_4Order)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/SMIB-Fault/PSAT_6OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.txt'\n", - "local_file_6Order = 'reference-results/PSAT_6OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.out'\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/SMIB-Fault/PSAT_6OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.txt\"\n", + "local_file_6Order = (\n", + " \"reference-results/PSAT_6OrderSyGen_withExciter_SMIB_Fault_100mS_TS_1mS.out\"\n", + ")\n", "urllib.request.urlretrieve(url, local_file_6Order)\n", "ts_psat_6Order = read_timeseries_dpsim(local_file_6Order)" ] @@ -147,21 +162,21 @@ "metadata": {}, "outputs": [], "source": [ - "#calculate vd and vq\n", - "angle = ts_psat_3Order['delta'].values - ts_psat_3Order['theta_bus1'].values\n", - "V_bus1 = ts_psat_3Order['V_Bus1'].values\n", + "# calculate vd and vq\n", + "angle = ts_psat_3Order[\"delta\"].values - ts_psat_3Order[\"theta_bus1\"].values\n", + "V_bus1 = ts_psat_3Order[\"V_Bus1\"].values\n", "vd = V_bus1 * np.sin(angle)\n", - "ts_psat_3Order['vd'] = TimeSeries('vd', ts_psat_3Order['V_Bus1'].time, vd)\n", + "ts_psat_3Order[\"vd\"] = TimeSeries(\"vd\", ts_psat_3Order[\"V_Bus1\"].time, vd)\n", "vq = V_bus1 * np.cos(angle)\n", - "ts_psat_3Order['vq'] = TimeSeries('vq', ts_psat_3Order['V_Bus1'].time, vq)\n", + "ts_psat_3Order[\"vq\"] = TimeSeries(\"vq\", ts_psat_3Order[\"V_Bus1\"].time, vq)\n", "\n", - "#calculate id and iq in PSAT\n", + "# calculate id and iq in PSAT\n", "Xd_t = 0.299900\n", "Xq = 1.7600\n", - "i_d = (ts_psat_3Order['eq_t'].values - ts_psat_3Order['vq'].values) / Xd_t\n", - "ts_psat_3Order['id'] = TimeSeries('id', ts_psat_3Order['eq_t'].time, i_d)\n", - "i_q = ts_psat_3Order['vd'].values / Xq\n", - "ts_psat_3Order['iq'] = TimeSeries('iq', ts_psat_3Order['vd'].time, i_q)" + "i_d = (ts_psat_3Order[\"eq_t\"].values - ts_psat_3Order[\"vq\"].values) / Xd_t\n", + "ts_psat_3Order[\"id\"] = TimeSeries(\"id\", ts_psat_3Order[\"eq_t\"].time, i_d)\n", + "i_q = ts_psat_3Order[\"vd\"].values / Xq\n", + "ts_psat_3Order[\"iq\"] = TimeSeries(\"iq\", ts_psat_3Order[\"vd\"].time, i_q)" ] }, { @@ -180,21 +195,21 @@ "metadata": {}, "outputs": [], "source": [ - "#calculate vd and vq\n", - "angle = ts_psat_4Order['delta'].values - ts_psat_4Order['theta_bus1'].values\n", - "V_bus1 = ts_psat_4Order['V_Bus1'].values\n", + "# calculate vd and vq\n", + "angle = ts_psat_4Order[\"delta\"].values - ts_psat_4Order[\"theta_bus1\"].values\n", + "V_bus1 = ts_psat_4Order[\"V_Bus1\"].values\n", "vd = V_bus1 * np.sin(angle)\n", - "ts_psat_4Order['vd'] = TimeSeries('vd', ts_psat_4Order['V_Bus1'].time, vd)\n", + "ts_psat_4Order[\"vd\"] = TimeSeries(\"vd\", ts_psat_4Order[\"V_Bus1\"].time, vd)\n", "vq = V_bus1 * np.cos(angle)\n", - "ts_psat_4Order['vq'] = TimeSeries('vq', ts_psat_4Order['V_Bus1'].time, vq)\n", - " \n", - "#calculate id and iq in PSAT\n", + "ts_psat_4Order[\"vq\"] = TimeSeries(\"vq\", ts_psat_4Order[\"V_Bus1\"].time, vq)\n", + "\n", + "# calculate id and iq in PSAT\n", "Xd = 0.299900\n", "Xq = 0.650000\n", - "i_d = (ts_psat_4Order['eq_t'].values - ts_psat_4Order['vq'].values) / Xd\n", - "ts_psat_4Order['id'] = TimeSeries('id', ts_psat_4Order['eq_t'].time, i_d)\n", - "i_q = -(ts_psat_4Order['ed_t'].values - ts_psat_4Order['vd'].values) / Xq\n", - "ts_psat_4Order['iq'] = TimeSeries('iq', ts_psat_4Order['ed_t'].time, i_q)" + "i_d = (ts_psat_4Order[\"eq_t\"].values - ts_psat_4Order[\"vq\"].values) / Xd\n", + "ts_psat_4Order[\"id\"] = TimeSeries(\"id\", ts_psat_4Order[\"eq_t\"].time, i_d)\n", + "i_q = -(ts_psat_4Order[\"ed_t\"].values - ts_psat_4Order[\"vd\"].values) / Xq\n", + "ts_psat_4Order[\"iq\"] = TimeSeries(\"iq\", ts_psat_4Order[\"ed_t\"].time, i_q)" ] }, { @@ -213,21 +228,21 @@ "metadata": {}, "outputs": [], "source": [ - "#calculate vd and vq\n", - "angle = ts_psat_6Order['delta'].values - ts_psat_6Order['theta_bus1'].values\n", - "V_bus1 = ts_psat_6Order['V_Bus1'].values\n", + "# calculate vd and vq\n", + "angle = ts_psat_6Order[\"delta\"].values - ts_psat_6Order[\"theta_bus1\"].values\n", + "V_bus1 = ts_psat_6Order[\"V_Bus1\"].values\n", "vd = V_bus1 * np.sin(angle)\n", - "ts_psat_6Order['vd'] = TimeSeries('vd', ts_psat_6Order['V_Bus1'].time, vd)\n", + "ts_psat_6Order[\"vd\"] = TimeSeries(\"vd\", ts_psat_6Order[\"V_Bus1\"].time, vd)\n", "vq = V_bus1 * np.cos(angle)\n", - "ts_psat_6Order['vq'] = TimeSeries('vq', ts_psat_6Order['V_Bus1'].time, vq)\n", + "ts_psat_6Order[\"vq\"] = TimeSeries(\"vq\", ts_psat_6Order[\"V_Bus1\"].time, vq)\n", "\n", - "#calculate id and iq in PSAT\\n\",\n", + "# calculate id and iq in PSAT\\n\",\n", "Xd_s = 0.2299\n", "Xq_s = 0.2500\n", - "i_d = (ts_psat_6Order['eq_s'].values - ts_psat_6Order['vq'].values) / Xd_s\n", - "ts_psat_6Order['id'] = TimeSeries('id', ts_psat_6Order['eq_s'].time, i_d)\n", - "i_q = -(ts_psat_6Order['ed_s'].values - ts_psat_6Order['vd'].values) / Xq_s\n", - "ts_psat_6Order['iq'] = TimeSeries('iq', ts_psat_6Order['ed_s'].time, i_q)" + "i_d = (ts_psat_6Order[\"eq_s\"].values - ts_psat_6Order[\"vq\"].values) / Xd_s\n", + "ts_psat_6Order[\"id\"] = TimeSeries(\"id\", ts_psat_6Order[\"eq_s\"].time, i_d)\n", + "i_q = -(ts_psat_6Order[\"ed_s\"].values - ts_psat_6Order[\"vd\"].values) / Xq_s\n", + "ts_psat_6Order[\"iq\"] = TimeSeries(\"iq\", ts_psat_6Order[\"ed_s\"].time, i_q)" ] }, { @@ -248,70 +263,70 @@ }, "outputs": [], "source": [ - "#nominal values (per unit)\n", + "# nominal values (per unit)\n", "nominal_values = {}\n", - "nominal_values['Te'] = 0.540541\n", - "nominal_values['Tm'] = 0.540541\n", - "nominal_values['Edq0_0'] = 0.403062 #4th order model\n", - "nominal_values['Edq0_1'] = 0.944802 #3th and 4th order model\n", - "nominal_values['Edq0_t_0'] = 0.392200 #6 order model\n", - "nominal_values['Edq0_t_1'] = 0.946405 #6 order model\n", - "nominal_values['Edq0_s_0'] = 0.548309 #6 order model\n", - "nominal_values['Edq0_s_1'] = 0.918731 #6 order model\n", - "nominal_values['Vdq0_0'] = 0.639089\n", - "nominal_values['Vdq0_1'] = 0.833106\n", - "nominal_values['Idq0_0'] = 0.372443\n", - "nominal_values['Idq0_1'] = 0.363119\n", - "nominal_values['delta'] = 0.909230\n", - "nominal_values['w_r'] = 1.0\n", - "nominal_values['Ef'] = 1.507191\n", - "nominal_values['Vm'] = 1.05\n", - "nominal_values['Vr'] = 0.5127179\n", - "nominal_values['Vis'] = -0.1507191\n", + "nominal_values[\"Te\"] = 0.540541\n", + "nominal_values[\"Tm\"] = 0.540541\n", + "nominal_values[\"Edq0_0\"] = 0.403062 # 4th order model\n", + "nominal_values[\"Edq0_1\"] = 0.944802 # 3th and 4th order model\n", + "nominal_values[\"Edq0_t_0\"] = 0.392200 # 6 order model\n", + "nominal_values[\"Edq0_t_1\"] = 0.946405 # 6 order model\n", + "nominal_values[\"Edq0_s_0\"] = 0.548309 # 6 order model\n", + "nominal_values[\"Edq0_s_1\"] = 0.918731 # 6 order model\n", + "nominal_values[\"Vdq0_0\"] = 0.639089\n", + "nominal_values[\"Vdq0_1\"] = 0.833106\n", + "nominal_values[\"Idq0_0\"] = 0.372443\n", + "nominal_values[\"Idq0_1\"] = 0.363119\n", + "nominal_values[\"delta\"] = 0.909230\n", + "nominal_values[\"w_r\"] = 1.0\n", + "nominal_values[\"Ef\"] = 1.507191\n", + "nominal_values[\"Vm\"] = 1.05\n", + "nominal_values[\"Vr\"] = 0.5127179\n", + "nominal_values[\"Vis\"] = -0.1507191\n", "\n", "nominal_grid_voltage = 24e3\n", "\n", "#\n", "titles = {}\n", - "titles['Te'] = 'Electrical Torque'\n", - "titles['Tm'] = 'Mechanical Torque'\n", - "titles['Edq0_0'] = 'd-component of the voltage behind the transient reactance'\n", - "titles['Edq0_1'] = 'q-component of the voltage behind the transient reactance'\n", - "titles['Edq0_t_0'] = 'd-component of the voltage behind the transient reactance'\n", - "titles['Edq0_t_1'] = 'd-component of the voltage behind the transient reactance'\n", - "titles['Edq0_s_0'] = 'd-component of the voltage behind the sub-transient reactance'\n", - "titles['Edq0_s_1'] = 'd-component of the voltage behind the sub-transient reactance'\n", - "titles['Vdq0_0'] = 'd-component of the terminal voltage'\n", - "titles['Vdq0_1'] = 'q-component of the terminal voltage'\n", - "titles['Idq0_0'] = 'd-component of the terminal current'\n", - "titles['Idq0_1'] = 'q-component of the terminal current'\n", - "titles['delta'] = 'Delta'\n", - "titles['w_r'] = 'Mechanical Omega'\n", - "titles['Ef'] = 'Exiter output'\n", - "titles['Vm'] = 'Output of voltage transducer'\n", - "titles['Vr'] = 'Regulator output'\n", - "titles['Vis'] = 'Output of stablizing feedback'\n", + "titles[\"Te\"] = \"Electrical Torque\"\n", + "titles[\"Tm\"] = \"Mechanical Torque\"\n", + "titles[\"Edq0_0\"] = \"d-component of the voltage behind the transient reactance\"\n", + "titles[\"Edq0_1\"] = \"q-component of the voltage behind the transient reactance\"\n", + "titles[\"Edq0_t_0\"] = \"d-component of the voltage behind the transient reactance\"\n", + "titles[\"Edq0_t_1\"] = \"d-component of the voltage behind the transient reactance\"\n", + "titles[\"Edq0_s_0\"] = \"d-component of the voltage behind the sub-transient reactance\"\n", + "titles[\"Edq0_s_1\"] = \"d-component of the voltage behind the sub-transient reactance\"\n", + "titles[\"Vdq0_0\"] = \"d-component of the terminal voltage\"\n", + "titles[\"Vdq0_1\"] = \"q-component of the terminal voltage\"\n", + "titles[\"Idq0_0\"] = \"d-component of the terminal current\"\n", + "titles[\"Idq0_1\"] = \"q-component of the terminal current\"\n", + "titles[\"delta\"] = \"Delta\"\n", + "titles[\"w_r\"] = \"Mechanical Omega\"\n", + "titles[\"Ef\"] = \"Exiter output\"\n", + "titles[\"Vm\"] = \"Output of voltage transducer\"\n", + "titles[\"Vr\"] = \"Regulator output\"\n", + "titles[\"Vis\"] = \"Output of stablizing feedback\"\n", "\n", "#\n", "ylabels = {}\n", - "ylabels['Te'] = 'Torque (p.u.)'\n", - "ylabels['Tm'] = 'Torque (p.u.)'\n", - "ylabels['Edq0_0'] = 'Ed_t (p.u.)'\n", - "ylabels['Edq0_1'] = 'Eq_t (p.u.)'\n", - "ylabels['Edq0_t_0'] = 'Ed_t (p.u.)'\n", - "ylabels['Edq0_t_1'] = 'Eq_t (p.u.)'\n", - "ylabels['Edq0_s_0'] = 'Ed_s (p.u.)'\n", - "ylabels['Edq0_s_1'] = 'Eq_s (p.u.)'\n", - "ylabels['Vdq0_0'] = 'Vd (p.u.)'\n", - "ylabels['Vdq0_1'] = 'Vq (p.u.)'\n", - "ylabels['Idq0_0'] = 'Id (p.u.)'\n", - "ylabels['Idq0_1'] = 'Iq (p.u.)'\n", - "ylabels['delta'] = 'Delta (rad)'\n", - "ylabels['w_r'] = 'w_r (p.u.)'\n", - "ylabels['Ef'] = 'Ef (p.u.)'\n", - "ylabels['Vm'] = 'Vm (p.u.)'\n", - "ylabels['Vr'] = 'Vr (p.u.)'\n", - "ylabels['Vis'] = 'Vr2 (p.u.)'" + "ylabels[\"Te\"] = \"Torque (p.u.)\"\n", + "ylabels[\"Tm\"] = \"Torque (p.u.)\"\n", + "ylabels[\"Edq0_0\"] = \"Ed_t (p.u.)\"\n", + "ylabels[\"Edq0_1\"] = \"Eq_t (p.u.)\"\n", + "ylabels[\"Edq0_t_0\"] = \"Ed_t (p.u.)\"\n", + "ylabels[\"Edq0_t_1\"] = \"Eq_t (p.u.)\"\n", + "ylabels[\"Edq0_s_0\"] = \"Ed_s (p.u.)\"\n", + "ylabels[\"Edq0_s_1\"] = \"Eq_s (p.u.)\"\n", + "ylabels[\"Vdq0_0\"] = \"Vd (p.u.)\"\n", + "ylabels[\"Vdq0_1\"] = \"Vq (p.u.)\"\n", + "ylabels[\"Idq0_0\"] = \"Id (p.u.)\"\n", + "ylabels[\"Idq0_1\"] = \"Iq (p.u.)\"\n", + "ylabels[\"delta\"] = \"Delta (rad)\"\n", + "ylabels[\"w_r\"] = \"w_r (p.u.)\"\n", + "ylabels[\"Ef\"] = \"Ef (p.u.)\"\n", + "ylabels[\"Vm\"] = \"Vm (p.u.)\"\n", + "ylabels[\"Vr\"] = \"Vr (p.u.)\"\n", + "ylabels[\"Vis\"] = \"Vr2 (p.u.)\"" ] }, { @@ -331,76 +346,148 @@ "outputs": [], "source": [ "timestep_common = 10e-6\n", - "t_begin=0\n", - "t_end=20\n", - "begin_idx = int(t_begin/timestep_common)\n", - "end_idx= int(t_end/timestep_common)\n", + "t_begin = 0\n", + "t_end = 20\n", + "begin_idx = int(t_begin / timestep_common)\n", + "end_idx = int(t_end / timestep_common)\n", "\n", - "#plot Results\n", + "# plot Results\n", "width = 12\n", "height = 4\n", "\n", - "def plot_variable(title, varname_dpsim, varname_psat, ts_dpsim, ts_psat, nominal_values, ylabels):\n", + "\n", + "def plot_variable(\n", + " title, varname_dpsim, varname_psat, ts_dpsim, ts_psat, nominal_values, ylabels\n", + "):\n", " fig1 = plt.figure(figsize=(width, height))\n", - " plt.plot(ts_dpsim[varname_dpsim].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim[varname_dpsim].interpolate(timestep_common).values[begin_idx:end_idx], label='DPSim')\n", - " plt.plot(ts_psat[varname_psat].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[varname_psat].interpolate(timestep_common).values[begin_idx:end_idx], '--', label='PSAT')\n", - " #plt.plot(ts_psat_3Order_[varname_psat].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat_3Order_[varname_psat].interpolate(timestep_common).values[begin_idx:end_idx], '--', label='PSAT')\n", - " plt.legend(loc='lower right')\n", - " plt.xlabel('time (s)')\n", + " plt.plot(\n", + " ts_dpsim[varname_dpsim].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim[varname_dpsim].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=\"DPSim\",\n", + " )\n", + " plt.plot(\n", + " ts_psat[varname_psat].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[varname_psat].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " \"--\",\n", + " label=\"PSAT\",\n", + " )\n", + " # plt.plot(ts_psat_3Order_[varname_psat].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat_3Order_[varname_psat].interpolate(timestep_common).values[begin_idx:end_idx], '--', label='PSAT')\n", + " plt.legend(loc=\"lower right\")\n", + " plt.xlabel(\"time (s)\")\n", " plt.ylabel(ylabels[varname_dpsim])\n", " plt.grid()\n", " plt.xlim([0, 10])\n", " plt.show\n", - " \n", - " #calculate RMSE\n", + "\n", + " # calculate RMSE\n", " nom_value = nominal_values[varname_dpsim]\n", - " rmse = ts_dpsim[varname_dpsim].rmse(ts_dpsim[varname_dpsim].interpolate(timestep_common), ts_psat[varname_psat].interpolate(timestep_common))\n", - " print('RMSE {:s} = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) '.format(varname_dpsim, rmse, rmse/nom_value*100, nom_value))\n", - " \n", - " return rmse/nom_value*100\n", - "\n", - "def plot_node_volt_abs(varname_dpsim, varname_psat, ts_dpsim, ts_psat, nominal_voltage, ylabels):\n", - " \n", - " #convert dpsim voltage to magnitude value and per-unit for comparison with psat\n", - " ts_dpsim_abs_pu = TimeSeries(varname_dpsim+'_abs_pu', ts_dpsim[varname_dpsim].interpolate(timestep_common).time, ts_dpsim[varname_dpsim].interpolate(timestep_common).abs().values/nominal_voltage)\n", - " \n", + " rmse = ts_dpsim[varname_dpsim].rmse(\n", + " ts_dpsim[varname_dpsim].interpolate(timestep_common),\n", + " ts_psat[varname_psat].interpolate(timestep_common),\n", + " )\n", + " print(\n", + " \"RMSE {:s} = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) \".format(\n", + " varname_dpsim, rmse, rmse / nom_value * 100, nom_value\n", + " )\n", + " )\n", + "\n", + " return rmse / nom_value * 100\n", + "\n", + "\n", + "def plot_node_volt_abs(\n", + " varname_dpsim, varname_psat, ts_dpsim, ts_psat, nominal_voltage, ylabels\n", + "):\n", + " # convert dpsim voltage to magnitude value and per-unit for comparison with psat\n", + " ts_dpsim_abs_pu = TimeSeries(\n", + " varname_dpsim + \"_abs_pu\",\n", + " ts_dpsim[varname_dpsim].interpolate(timestep_common).time,\n", + " ts_dpsim[varname_dpsim].interpolate(timestep_common).abs().values\n", + " / nominal_voltage,\n", + " )\n", + "\n", " fig1 = plt.figure(figsize=(width, height))\n", - " plt.plot(ts_dpsim_abs_pu.time[begin_idx:end_idx], ts_dpsim_abs_pu.values[begin_idx:end_idx], label='DPSim')\n", - " plt.plot(ts_psat[varname_psat].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[varname_psat].interpolate(timestep_common).values[begin_idx:end_idx], '--', label='PSAT')\n", - " plt.legend(loc='lower right')\n", - " plt.xlabel('time (s)')\n", + " plt.plot(\n", + " ts_dpsim_abs_pu.time[begin_idx:end_idx],\n", + " ts_dpsim_abs_pu.values[begin_idx:end_idx],\n", + " label=\"DPSim\",\n", + " )\n", + " plt.plot(\n", + " ts_psat[varname_psat].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[varname_psat].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " \"--\",\n", + " label=\"PSAT\",\n", + " )\n", + " plt.legend(loc=\"lower right\")\n", + " plt.xlabel(\"time (s)\")\n", " plt.show\n", - " \n", - " #calculate RMSE\n", - " rmse = ts_dpsim[varname_dpsim].rmse(ts_dpsim_abs_pu, ts_psat[varname_psat].interpolate(timestep_common))\n", - " print('RMSE {:s} = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) '.format(varname_dpsim, rmse, rmse/1.0*100, 1.0))\n", - " \n", - " return rmse/1.0*100\n", - "\n", - "\n", - "def plot_node_volt_angle(varname_dpsim, varname_psat, ts_dpsim, ts_psat, nominal_voltage, ylabels):\n", - " #limit rmse to post-fault evaluation\n", - " t_post_begin=1.1\n", - " t_post_end=20\n", - " begin_post_idx = int(t_post_begin/timestep_common)\n", - " end_post_idx= int(t_post_end/timestep_common)\n", - " \n", - " #convert psat angle to deg and in range from\n", - " ts_psat_deg = TimeSeries(varname_psat+'_deg', ts_psat[varname_psat].interpolate(timestep_common).time, ts_psat[varname_psat].interpolate(timestep_common).values/np.pi*180)\n", - " \n", + "\n", + " # calculate RMSE\n", + " rmse = ts_dpsim[varname_dpsim].rmse(\n", + " ts_dpsim_abs_pu, ts_psat[varname_psat].interpolate(timestep_common)\n", + " )\n", + " print(\n", + " \"RMSE {:s} = {:.6f} (pu), which is {:.3f}% of the nominal value = {:.3f} (pu) \".format(\n", + " varname_dpsim, rmse, rmse / 1.0 * 100, 1.0\n", + " )\n", + " )\n", + "\n", + " return rmse / 1.0 * 100\n", + "\n", + "\n", + "def plot_node_volt_angle(\n", + " varname_dpsim, varname_psat, ts_dpsim, ts_psat, nominal_voltage, ylabels\n", + "):\n", + " # limit rmse to post-fault evaluation\n", + " t_post_begin = 1.1\n", + " t_post_end = 20\n", + " begin_post_idx = int(t_post_begin / timestep_common)\n", + " end_post_idx = int(t_post_end / timestep_common)\n", + "\n", + " # convert psat angle to deg and in range from\n", + " ts_psat_deg = TimeSeries(\n", + " varname_psat + \"_deg\",\n", + " ts_psat[varname_psat].interpolate(timestep_common).time,\n", + " ts_psat[varname_psat].interpolate(timestep_common).values / np.pi * 180,\n", + " )\n", + "\n", " fig2 = plt.figure(figsize=(width, height))\n", - " plt.plot(ts_dpsim[varname_dpsim].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim[varname_dpsim].interpolate(timestep_common).phase().values[begin_idx:end_idx], label='DPSim')\n", - " plt.plot(ts_psat_deg.time[begin_idx:end_idx], ts_psat_deg.values[begin_idx:end_idx], '--', label='PSAT')\n", - " plt.legend(loc='lower right')\n", - " plt.xlabel('time (s)')\n", + " plt.plot(\n", + " ts_dpsim[varname_dpsim].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim[varname_dpsim]\n", + " .interpolate(timestep_common)\n", + " .phase()\n", + " .values[begin_idx:end_idx],\n", + " label=\"DPSim\",\n", + " )\n", + " plt.plot(\n", + " ts_psat_deg.time[begin_idx:end_idx],\n", + " ts_psat_deg.values[begin_idx:end_idx],\n", + " \"--\",\n", + " label=\"PSAT\",\n", + " )\n", + " plt.legend(loc=\"lower right\")\n", + " plt.xlabel(\"time (s)\")\n", " plt.show\n", - " \n", - " #calculate RMSE\n", - " ts_dpsim_deg_post = TimeSeries(varname_dpsim+'_deg_post', ts_dpsim[varname_dpsim].interpolate(timestep_common).time[begin_post_idx:end_post_idx], ts_dpsim[varname_dpsim].interpolate(timestep_common).phase().values[begin_post_idx:end_post_idx])\n", - " ts_psat_deg_post = TimeSeries(varname_psat+'_deg_post', ts_psat_deg.time[begin_post_idx:end_post_idx], ts_psat_deg.values[begin_post_idx:end_post_idx])\n", + "\n", + " # calculate RMSE\n", + " ts_dpsim_deg_post = TimeSeries(\n", + " varname_dpsim + \"_deg_post\",\n", + " ts_dpsim[varname_dpsim]\n", + " .interpolate(timestep_common)\n", + " .time[begin_post_idx:end_post_idx],\n", + " ts_dpsim[varname_dpsim]\n", + " .interpolate(timestep_common)\n", + " .phase()\n", + " .values[begin_post_idx:end_post_idx],\n", + " )\n", + " ts_psat_deg_post = TimeSeries(\n", + " varname_psat + \"_deg_post\",\n", + " ts_psat_deg.time[begin_post_idx:end_post_idx],\n", + " ts_psat_deg.values[begin_post_idx:end_post_idx],\n", + " )\n", " rmse = ts_dpsim[varname_dpsim].rmse(ts_dpsim_deg_post, ts_psat_deg_post)\n", - " print('RMSE Post-Fault {:s} = {:.6f} (deg)'.format(varname_dpsim, rmse))\n", - " \n", + " print(\"RMSE Post-Fault {:s} = {:.6f} (deg)\".format(varname_dpsim, rmse))\n", + "\n", " return rmse" ] }, @@ -432,7 +519,15 @@ "varname_dpsim = \"Te\"\n", "varname_psat = \"p\"\n", "\n", - "rmse_torque = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)" + "rmse_torque = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")" ] }, { @@ -454,7 +549,15 @@ "varname_dpsim = \"Ef\"\n", "varname_psat = \"vf\"\n", "\n", - "rmse_ef = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)" + "rmse_ef = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")" ] }, { @@ -476,7 +579,15 @@ "varname_dpsim = \"Edq0_1\"\n", "varname_psat = \"eq_t\"\n", "\n", - "rmse_eq = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)" + "rmse_eq = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")" ] }, { @@ -498,7 +609,15 @@ "varname_dpsim = \"Vdq0_0\"\n", "varname_psat = \"vd\"\n", "\n", - "rmse_vd = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)" + "rmse_vd = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")" ] }, { @@ -520,7 +639,15 @@ "varname_dpsim = \"Vdq0_1\"\n", "varname_psat = \"vq\"\n", "\n", - "rmse_vq = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)" + "rmse_vq = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")" ] }, { @@ -542,9 +669,17 @@ "varname_dpsim = \"Idq0_0\"\n", "varname_psat = \"id\"\n", "\n", - "rmse_id = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)\n", - "#plt.plot(ts_dpsim_3Order[varname_dpsim].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat_3Order[varname_psat].interpolate(timestep_common).values[begin_idx:end_idx]- ts_dpsim_3Order[varname_dpsim].interpolate(timestep_common).values[begin_idx:end_idx])\n", - "#plt.ylim([0, 0.02])" + "rmse_id = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")\n", + "# plt.plot(ts_dpsim_3Order[varname_dpsim].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat_3Order[varname_psat].interpolate(timestep_common).values[begin_idx:end_idx]- ts_dpsim_3Order[varname_dpsim].interpolate(timestep_common).values[begin_idx:end_idx])\n", + "# plt.ylim([0, 0.02])" ] }, { @@ -566,7 +701,15 @@ "varname_dpsim = \"Idq0_1\"\n", "varname_psat = \"iq\"\n", "\n", - "rmse_iq = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)" + "rmse_iq = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")" ] }, { @@ -588,7 +731,15 @@ "varname_dpsim = \"delta\"\n", "varname_psat = \"delta\"\n", "\n", - "rmse_delta = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)" + "rmse_delta = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")" ] }, { @@ -610,7 +761,15 @@ "varname_dpsim = \"w_r\"\n", "varname_psat = \"omega\"\n", "\n", - "rmse_omega = plot_variable(titles, varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_values, ylabels)" + "rmse_omega = plot_variable(\n", + " titles,\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_values,\n", + " ylabels,\n", + ")" ] }, { @@ -632,7 +791,14 @@ "varname_dpsim = \"v1\"\n", "varname_psat = \"V_Bus1\"\n", "\n", - "rmse_v1_abs = plot_node_volt_abs(varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_grid_voltage, ylabels)" + "rmse_v1_abs = plot_node_volt_abs(\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_grid_voltage,\n", + " ylabels,\n", + ")" ] }, { @@ -645,7 +811,14 @@ "varname_dpsim = \"v1\"\n", "varname_psat = \"theta_bus1\"\n", "\n", - "rmse_v1_angle = plot_node_volt_angle(varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_grid_voltage, ylabels)" + "rmse_v1_angle = plot_node_volt_angle(\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_grid_voltage,\n", + " ylabels,\n", + ")" ] }, { @@ -658,7 +831,14 @@ "varname_dpsim = \"v2\"\n", "varname_psat = \"V_Bus3\"\n", "\n", - "rmse_v2_abs = plot_node_volt_abs(varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_grid_voltage, ylabels)" + "rmse_v2_abs = plot_node_volt_abs(\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_grid_voltage,\n", + " ylabels,\n", + ")" ] }, { @@ -671,7 +851,14 @@ "varname_dpsim = \"v2\"\n", "varname_psat = \"theta_bus3\"\n", "\n", - "rmse_v2_angle = plot_node_volt_angle(varname_dpsim, varname_psat, ts_dpsim_3Order, ts_psat_3Order, nominal_grid_voltage, ylabels)" + "rmse_v2_angle = plot_node_volt_angle(\n", + " varname_dpsim,\n", + " varname_psat,\n", + " ts_dpsim_3Order,\n", + " ts_psat_3Order,\n", + " nominal_grid_voltage,\n", + " ylabels,\n", + ")" ] }, { @@ -690,24 +877,24 @@ "metadata": {}, "outputs": [], "source": [ - "tol = 1.5 # %\n", - "tol_id = 7 # %\n", - "tol_deg_v1 = 0.2 # deg\n", - "tol_deg_v2 = 1e-12 # deg\n", + "tol = 1.5 # %\n", + "tol_id = 7 # %\n", + "tol_deg_v1 = 0.2 # deg\n", + "tol_deg_v2 = 1e-12 # deg\n", "\n", - "assert(rmse_torque 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", - " result_list.append({'timestep': ts_idx, 'load': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"load\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_emt_ode = pd.DataFrame(result_list)" ], "outputs": [], @@ -486,20 +583,24 @@ "source": [ "loadstep = 8\n", "timestep = 1\n", - "curr = pd_emt_ode.query('timestep=='+str(timestep)+' and load=='+str(loadstep))['values'].values[0]\n", - "plt.plot(curr['i_gen_0'].time, curr['i_gen_0'].values, color = '#939393ff')\n", - "plt.plot(curr['i_gen_1'].time, curr['i_gen_1'].values, color = '#939393ff')\n", - "plt.plot(curr['i_gen_2'].time, curr['i_gen_2'].values, color = '#939393ff')\n", + "curr = pd_emt_ode.query(\"timestep==\" + str(timestep) + \" and load==\" + str(loadstep))[\n", + " \"values\"\n", + "].values[0]\n", + "plt.plot(curr[\"i_gen_0\"].time, curr[\"i_gen_0\"].values, color=\"#939393ff\")\n", + "plt.plot(curr[\"i_gen_1\"].time, curr[\"i_gen_1\"].values, color=\"#939393ff\")\n", + "plt.plot(curr[\"i_gen_2\"].time, curr[\"i_gen_2\"].values, color=\"#939393ff\")\n", "\n", "timestep = 8\n", - "curr = pd_emt_ode.query('timestep=='+str(timestep)+' and load=='+str(loadstep))['values'].values[0]\n", - "plt.plot(curr['i_gen_0_intpl'].time, curr['i_gen_0_intpl'].values, linestyle='-.')\n", - "plt.plot(curr['i_gen_1_intpl'].time, curr['i_gen_1_intpl'].values, linestyle='-.')\n", - "plt.plot(curr['i_gen_2_intpl'].time, curr['i_gen_2_intpl'].values, linestyle='-.')\n", - "\n", - "#plt.xlim([0.19,0.21])\n", - "plt.xlim([0.09,0.12])\n", - "#plt.ylim([-15000,15000])" + "curr = pd_emt_ode.query(\"timestep==\" + str(timestep) + \" and load==\" + str(loadstep))[\n", + " \"values\"\n", + "].values[0]\n", + "plt.plot(curr[\"i_gen_0_intpl\"].time, curr[\"i_gen_0_intpl\"].values, linestyle=\"-.\")\n", + "plt.plot(curr[\"i_gen_1_intpl\"].time, curr[\"i_gen_1_intpl\"].values, linestyle=\"-.\")\n", + "plt.plot(curr[\"i_gen_2_intpl\"].time, curr[\"i_gen_2_intpl\"].values, linestyle=\"-.\")\n", + "\n", + "# plt.xlim([0.19,0.21])\n", + "plt.xlim([0.09, 0.12])\n", + "# plt.ylim([-15000,15000])" ], "outputs": [], "metadata": {} @@ -510,17 +611,32 @@ "source": [ "loadstep = 2\n", "timestep = 2\n", - "curr = pd_emt_ode.query('timestep=='+str(1)+' and load=='+str(loadstep))['values'].values[0]\n", - "curr_ts = pd_emt_ode.query('timestep=='+str(timestep)+' and load=='+str(loadstep))['values'].values[0]\n", - "min_length = 3000 #min(curr['i_gen_0'].values.shape, curr_ts['i_gen_0_intpl'].values.shape)[0]\n", - "plt.plot(curr['i_gen_0'].time[:min_length], curr['i_gen_0'].values[:min_length] - curr_ts['i_gen_0_intpl'].values[:min_length])\n", - "plt.plot(curr['i_gen_1'].time[:min_length], curr['i_gen_1'].values[:min_length] - curr_ts['i_gen_1_intpl'].values[:min_length])\n", - "plt.plot(curr['i_gen_2'].time[:min_length], curr['i_gen_2'].values[:min_length] - curr_ts['i_gen_2_intpl'].values[:min_length])\n", - "\n", - "#plt.xlim([0.09,0.15])\n", - "#plt.ylim([-2000,2000])\n", - "#plt.xlim([0.19,0.21])\n", - "#plt.ylim([-15000,15000])" + "curr = pd_emt_ode.query(\"timestep==\" + str(1) + \" and load==\" + str(loadstep))[\n", + " \"values\"\n", + "].values[0]\n", + "curr_ts = pd_emt_ode.query(\n", + " \"timestep==\" + str(timestep) + \" and load==\" + str(loadstep)\n", + ")[\"values\"].values[0]\n", + "min_length = (\n", + " 3000 # min(curr['i_gen_0'].values.shape, curr_ts['i_gen_0_intpl'].values.shape)[0]\n", + ")\n", + "plt.plot(\n", + " curr[\"i_gen_0\"].time[:min_length],\n", + " curr[\"i_gen_0\"].values[:min_length] - curr_ts[\"i_gen_0_intpl\"].values[:min_length],\n", + ")\n", + "plt.plot(\n", + " curr[\"i_gen_1\"].time[:min_length],\n", + " curr[\"i_gen_1\"].values[:min_length] - curr_ts[\"i_gen_1_intpl\"].values[:min_length],\n", + ")\n", + "plt.plot(\n", + " curr[\"i_gen_2\"].time[:min_length],\n", + " curr[\"i_gen_2\"].values[:min_length] - curr_ts[\"i_gen_2_intpl\"].values[:min_length],\n", + ")\n", + "\n", + "# plt.xlim([0.09,0.15])\n", + "# plt.ylim([-2000,2000])\n", + "# plt.xlim([0.19,0.21])\n", + "# plt.ylim([-15000,15000])" ], "outputs": [], "metadata": {} @@ -531,6 +647,7 @@ "source": [ "import numpy as np\n", "\n", + "\n", "def calc_dpsim_variable_timestep_mae(ref, test_list):\n", " # find the minimum number of time steps available in the list of timeseries results\n", " min_length = ref.values.shape[0]\n", @@ -540,17 +657,19 @@ " min_length = 3000\n", " # calculate maximum amplitude of EMT reference signal to normalize error\n", " max_amp = np.max(np.abs(ref.values[:min_length]))\n", - " print('max. amplitude: ' +str(max_amp))\n", + " print(\"max. amplitude: \" + str(max_amp))\n", " # Calculate difference for each timeseries with respect to the 50µs reference\n", " diff_list = []\n", " for test in test_list:\n", - " diff_list.append( (test.values[:min_length] - ref.values[:min_length]) )#/ max_amp )\n", + " diff_list.append(\n", + " (test.values[:min_length] - ref.values[:min_length])\n", + " ) # / max_amp )\n", "\n", " # calculate mean absolute error\n", " mae = []\n", " for diff in diff_list:\n", - " mae.append( np.sum(np.abs(diff)) / min_length )\n", - " \n", + " mae.append(np.sum(np.abs(diff)) / min_length)\n", + "\n", " return mae, diff_list" ], "outputs": [], @@ -562,16 +681,18 @@ "source": [ "mae_emt_ode_list = []\n", "\n", - "for load_idx in range(0,11): \n", - " pd_test_list = pd_emt_ode.query('timestep > 1 and load=='+str(load_idx))\n", + "for load_idx in range(0, 11):\n", + " pd_test_list = pd_emt_ode.query(\"timestep > 1 and load==\" + str(load_idx))\n", " test_list = []\n", " for index, row in pd_test_list.iterrows():\n", - " test_list.append(row['values']['i_gen_0_intpl'])\n", - " \n", - " ref = pd_emt_ode.query('timestep == 1 and load=='+str(load_idx)).iloc[0]['values']['i_gen_0']\n", + " test_list.append(row[\"values\"][\"i_gen_0_intpl\"])\n", + "\n", + " ref = pd_emt_ode.query(\"timestep == 1 and load==\" + str(load_idx)).iloc[0][\n", + " \"values\"\n", + " ][\"i_gen_0\"]\n", " mae_emt_ode, diff_list = calc_dpsim_variable_timestep_mae(ref, test_list)\n", " mae_emt_ode_list.append(mae_emt_ode)\n", - " #print(mae_emt_ode)" + " # print(mae_emt_ode)" ], "outputs": [], "metadata": {} @@ -580,20 +701,20 @@ "cell_type": "code", "execution_count": null, "source": [ - "timesteps = np.arange(2,21)*0.00005\n", - "for load_idx in range(1,11,2): \n", - " plt.plot(timesteps, mae_emt_ode_list[load_idx], 'o-', label='step '+str(load_idx))\n", + "timesteps = np.arange(2, 21) * 0.00005\n", + "for load_idx in range(1, 11, 2):\n", + " plt.plot(timesteps, mae_emt_ode_list[load_idx], \"o-\", label=\"step \" + str(load_idx))\n", "plt.legend()\n", - "#plt.ylim([-0.01,0.1])\n", - "plt.ylim([0,3000])\n", - "plt.xlim([0,0.0009])\n", + "# plt.ylim([-0.01,0.1])\n", + "plt.ylim([0, 3000])\n", + "plt.xlim([0, 0.0009])\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean absolute error current (A)')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean absolute error current (A)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('emt_ode_syngen_mae.pdf')" + "plt.savefig(\"emt_ode_syngen_mae.pdf\")" ], "outputs": [], "metadata": {} @@ -611,18 +732,19 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " for load_idx in range(0,11):\n", - " log_dir = 'logs/'\n", - " log_name = log_dir+'DP_SynGenDq7odODE_T' + str(ts_idx) + '_L' + str(load_idx) + '/' \\\n", - " 'DP_SynGenDq7odODE_T' + str(ts_idx) + '_L' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(1, 21):\n", + " for load_idx in range(0, 11):\n", + " log_dir = \"logs/\"\n", + " log_name = log_dir + \"DP_SynGenDq7odODE_T\" + str(ts_idx) + \"_L\" + str(\n", + " load_idx\n", + " ) + \"/\" \"DP_SynGenDq7odODE_T\" + str(ts_idx) + \"_L\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", " ts_curr = ts.frequency_shift_list(ts_curr, 60)\n", - " result_list.append({'timestep': ts_idx, 'load': load_idx, 'values': ts_curr}) \n", - " \n", + " result_list.append({\"timestep\": ts_idx, \"load\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_dp_ode = pd.DataFrame(result_list)" ], "outputs": [], @@ -643,16 +765,18 @@ "source": [ "mae_dp_ode_list = []\n", "\n", - "for load_idx in range(0,11): \n", - " pd_test_list = pd_dp_ode.query('timestep > 1 and load=='+str(load_idx))\n", + "for load_idx in range(0, 11):\n", + " pd_test_list = pd_dp_ode.query(\"timestep > 1 and load==\" + str(load_idx))\n", " test_list = []\n", " for index, row in pd_test_list.iterrows():\n", - " test_list.append(row['values']['i_gen_0_intpl_shift'])\n", - " \n", - " ref = pd_dp_ode.query('timestep == 1 and load=='+str(load_idx)).iloc[0]['values']['i_gen_0_shift']\n", + " test_list.append(row[\"values\"][\"i_gen_0_intpl_shift\"])\n", + "\n", + " ref = pd_dp_ode.query(\"timestep == 1 and load==\" + str(load_idx)).iloc[0][\"values\"][\n", + " \"i_gen_0_shift\"\n", + " ]\n", " mae, diff_list = calc_dpsim_variable_timestep_mae(ref, test_list)\n", - " #print(mae)\n", - " mae_dp_ode_list.append(mae) " + " # print(mae)\n", + " mae_dp_ode_list.append(mae)" ], "outputs": [], "metadata": {} @@ -661,20 +785,20 @@ "cell_type": "code", "execution_count": null, "source": [ - "timesteps = np.arange(2,21)*0.00005\n", - "for load_idx in range(1,11,2): \n", - " plt.plot(timesteps, mae_dp_ode_list[load_idx], 'o-', label='load '+str(load_idx))\n", + "timesteps = np.arange(2, 21) * 0.00005\n", + "for load_idx in range(1, 11, 2):\n", + " plt.plot(timesteps, mae_dp_ode_list[load_idx], \"o-\", label=\"load \" + str(load_idx))\n", "plt.legend()\n", - "#plt.ylim([-0.01,0.3])\n", - "plt.ylim([0,200])\n", - "plt.xlim([0,0.0009])\n", + "# plt.ylim([-0.01,0.3])\n", + "plt.ylim([0, 200])\n", + "plt.xlim([0, 0.0009])\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean absolute error current (A)')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean absolute error current (A)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_ode_syngen_mae.pdf')" + "plt.savefig(\"dp_ode_syngen_mae.pdf\")" ], "outputs": [], "metadata": {} @@ -692,17 +816,18 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " for load_idx in range(0,11):\n", - " log_dir = 'logs/'\n", - " log_name = 'logs/EMT_SynGenDq7odTrapez_T' + str(ts_idx) + '_L' + str(load_idx) + '/' \\\n", - " 'EMT_SynGenDq7odTrapez_T' + str(ts_idx) + '_L' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(1, 21):\n", + " for load_idx in range(0, 11):\n", + " log_dir = \"logs/\"\n", + " log_name = \"logs/EMT_SynGenDq7odTrapez_T\" + str(ts_idx) + \"_L\" + str(\n", + " load_idx\n", + " ) + \"/\" \"EMT_SynGenDq7odTrapez_T\" + str(ts_idx) + \"_L\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", - " ts_curr = ts.interpolate_list(ts_curr, 0.00005) \n", - " result_list.append({'timestep': ts_idx, 'load': load_idx, 'values': ts_curr}) \n", - " \n", + " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", + " result_list.append({\"timestep\": ts_idx, \"load\": load_idx, \"values\": ts_curr})\n", + "\n", "pd_emt_trapez = pd.DataFrame(result_list)" ], "outputs": [], @@ -722,16 +847,18 @@ "execution_count": null, "source": [ "mae_emt_trapez_list = []\n", - "for load_idx in range(0,11): \n", - " pd_test_list = pd_emt_trapez.query('timestep > 1 and load=='+str(load_idx))\n", + "for load_idx in range(0, 11):\n", + " pd_test_list = pd_emt_trapez.query(\"timestep > 1 and load==\" + str(load_idx))\n", " test_list = []\n", " for index, row in pd_test_list.iterrows():\n", - " test_list.append(row['values']['i_gen_0_intpl'])\n", - " \n", - " ref = pd_emt_trapez.query('timestep == 1 and load=='+str(load_idx)).iloc[0]['values']['i_gen_0']\n", + " test_list.append(row[\"values\"][\"i_gen_0_intpl\"])\n", + "\n", + " ref = pd_emt_trapez.query(\"timestep == 1 and load==\" + str(load_idx)).iloc[0][\n", + " \"values\"\n", + " ][\"i_gen_0\"]\n", " mae, diff_list = calc_dpsim_variable_timestep_mae(ref, test_list)\n", - " #print(mae)\n", - " mae_emt_trapez_list.append(mae) " + " # print(mae)\n", + " mae_emt_trapez_list.append(mae)" ], "outputs": [], "metadata": {} @@ -740,20 +867,22 @@ "cell_type": "code", "execution_count": null, "source": [ - "timesteps = np.arange(2,21)*0.00005\n", - "for load_idx in range(1,11,2): \n", - " plt.plot(timesteps, mae_emt_trapez_list[load_idx], 'o-', label='load '+str(load_idx))\n", + "timesteps = np.arange(2, 21) * 0.00005\n", + "for load_idx in range(1, 11, 2):\n", + " plt.plot(\n", + " timesteps, mae_emt_trapez_list[load_idx], \"o-\", label=\"load \" + str(load_idx)\n", + " )\n", "plt.legend()\n", - "#plt.ylim([-0.01,0.3])\n", - "plt.ylim([0,3000])\n", - "plt.xlim([0,0.0009])\n", + "# plt.ylim([-0.01,0.3])\n", + "plt.ylim([0, 3000])\n", + "plt.xlim([0, 0.0009])\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean absolute error current (A)')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean absolute error current (A)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('dp_trpz_syngen_mae.pdf')" + "plt.savefig(\"dp_trpz_syngen_mae.pdf\")" ], "outputs": [], "metadata": {} @@ -771,17 +900,18 @@ "source": [ "%%capture\n", "result_list = []\n", - "for ts_idx in range(1,21):\n", - " for load_idx in range(0,11):\n", - " log_dir = '../../../logs/'\n", - " log_name = log_dir+'DP_SynGenDq7odTrapez_T' + str(ts_idx) + '_L' + str(load_idx) + '/' \\\n", - " 'DP_SynGenDq7odTrapez_T' + str(ts_idx) + '_L' + str(load_idx)\n", - " \n", - " ts_curr = rt.read_timeseries_dpsim(log_name + '.csv')\n", + "for ts_idx in range(1, 21):\n", + " for load_idx in range(0, 11):\n", + " log_dir = \"../../../logs/\"\n", + " log_name = log_dir + \"DP_SynGenDq7odTrapez_T\" + str(ts_idx) + \"_L\" + str(\n", + " load_idx\n", + " ) + \"/\" \"DP_SynGenDq7odTrapez_T\" + str(ts_idx) + \"_L\" + str(load_idx)\n", + "\n", + " ts_curr = rt.read_timeseries_dpsim(log_name + \".csv\")\n", " if ts_idx > 1:\n", - " ts_curr = ts.interpolate_list(ts_curr, 0.00005) \n", + " ts_curr = ts.interpolate_list(ts_curr, 0.00005)\n", " ts_curr = ts.frequency_shift_list(ts_curr, 60)\n", - " result_list.append({'timestep': ts_idx, 'load': load_idx, 'values': ts_curr}) \n", + " result_list.append({\"timestep\": ts_idx, \"load\": load_idx, \"values\": ts_curr})\n", "\n", "pd_dp_trapez = pd.DataFrame(result_list)" ], @@ -802,16 +932,18 @@ "execution_count": null, "source": [ "mae_dp_trapez_list = []\n", - "for load_idx in range(0,11): \n", - " pd_test_list = pd_dp_trapez.query('timestep > 1 and load=='+str(load_idx))\n", + "for load_idx in range(0, 11):\n", + " pd_test_list = pd_dp_trapez.query(\"timestep > 1 and load==\" + str(load_idx))\n", " test_list = []\n", " for index, row in pd_test_list.iterrows():\n", - " test_list.append(row['values']['i_gen_0_intpl_shift'])\n", - " \n", - " ref = pd_dp_trapez.query('timestep == 1 and load=='+str(load_idx)).iloc[0]['values']['i_gen_0_shift']\n", + " test_list.append(row[\"values\"][\"i_gen_0_intpl_shift\"])\n", + "\n", + " ref = pd_dp_trapez.query(\"timestep == 1 and load==\" + str(load_idx)).iloc[0][\n", + " \"values\"\n", + " ][\"i_gen_0_shift\"]\n", " mae, diff_list = calc_dpsim_variable_timestep_mae(ref, test_list)\n", - " #print(mae)\n", - " mae_dp_trapez_list.append(mae) " + " # print(mae)\n", + " mae_dp_trapez_list.append(mae)" ], "outputs": [], "metadata": {} @@ -820,20 +952,22 @@ "cell_type": "code", "execution_count": null, "source": [ - "timesteps = np.arange(2,21)*0.00005\n", - "for load_idx in range(1,11,2): \n", - " plt.plot(timesteps, mae_dp_trapez_list[load_idx], 'o-', label='load '+str(load_idx))\n", + "timesteps = np.arange(2, 21) * 0.00005\n", + "for load_idx in range(1, 11, 2):\n", + " plt.plot(\n", + " timesteps, mae_dp_trapez_list[load_idx], \"o-\", label=\"load \" + str(load_idx)\n", + " )\n", "plt.legend()\n", - "#plt.ylim([-0.01,0.3])\n", - "plt.xlim([0,0.0009])\n", - "plt.ylim([0,200])\n", + "# plt.ylim([-0.01,0.3])\n", + "plt.xlim([0, 0.0009])\n", + "plt.ylim([0, 200])\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean absolute error current (A)')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean absolute error current (A)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('emt_trpz_syngen_mae.pdf')" + "plt.savefig(\"emt_trpz_syngen_mae.pdf\")" ], "outputs": [], "metadata": {} @@ -842,20 +976,22 @@ "cell_type": "code", "execution_count": null, "source": [ - "timesteps = np.arange(2,21)*0.00005\n", - "for load_idx in range(1,11,2): \n", - " plt.plot(timesteps, mae_dp_trapez_list[load_idx], 'o-', label='load '+str(load_idx))\n", + "timesteps = np.arange(2, 21) * 0.00005\n", + "for load_idx in range(1, 11, 2):\n", + " plt.plot(\n", + " timesteps, mae_dp_trapez_list[load_idx], \"o-\", label=\"load \" + str(load_idx)\n", + " )\n", "plt.legend()\n", - "#plt.ylim([-0.01,0.3])\n", - "#plt.xlim([0,0.0009])\n", - "#plt.ylim([0,200])\n", + "# plt.ylim([-0.01,0.3])\n", + "# plt.xlim([0,0.0009])\n", + "# plt.ylim([0,200])\n", "\n", - "plt.xlabel('timestep (s)')\n", - "plt.ylabel('mean absolute error current (A)')\n", + "plt.xlabel(\"timestep (s)\")\n", + "plt.ylabel(\"mean absolute error current (A)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('emt_trpz_syngen_mae.pdf')" + "plt.savefig(\"emt_trpz_syngen_mae.pdf\")" ], "outputs": [], "metadata": {} @@ -865,16 +1001,26 @@ "execution_count": null, "source": [ "loadstep = 5\n", - "curr = pd_dp_trapez.query('timestep=='+str(1)+' and load=='+str(loadstep))['values'].values[0]\n", - "plt.plot(curr['i_gen_0_shift'].time, curr['i_gen_0_shift'].values, color = '#939393ff')\n", - "plt.plot(curr['i_gen_1_shift'].time, curr['i_gen_1_shift'].values, color = '#939393ff')\n", - "plt.plot(curr['i_gen_2_shift'].time, curr['i_gen_2_shift'].values, color = '#939393ff')\n", + "curr = pd_dp_trapez.query(\"timestep==\" + str(1) + \" and load==\" + str(loadstep))[\n", + " \"values\"\n", + "].values[0]\n", + "plt.plot(curr[\"i_gen_0_shift\"].time, curr[\"i_gen_0_shift\"].values, color=\"#939393ff\")\n", + "plt.plot(curr[\"i_gen_1_shift\"].time, curr[\"i_gen_1_shift\"].values, color=\"#939393ff\")\n", + "plt.plot(curr[\"i_gen_2_shift\"].time, curr[\"i_gen_2_shift\"].values, color=\"#939393ff\")\n", "\n", "timestep = 12\n", - "curr = pd_dp_trapez.query('timestep=='+str(timestep)+' and load=='+str(loadstep))['values'].values[0]\n", - "plt.plot(curr['i_gen_0_intpl_shift'].time, curr['i_gen_0_intpl_shift'].values, linestyle='-.')\n", - "plt.plot(curr['i_gen_1_intpl_shift'].time, curr['i_gen_1_intpl_shift'].values, linestyle='-.')\n", - "plt.plot(curr['i_gen_2_intpl_shift'].time, curr['i_gen_2_intpl_shift'].values, linestyle='-.')" + "curr = pd_dp_trapez.query(\"timestep==\" + str(timestep) + \" and load==\" + str(loadstep))[\n", + " \"values\"\n", + "].values[0]\n", + "plt.plot(\n", + " curr[\"i_gen_0_intpl_shift\"].time, curr[\"i_gen_0_intpl_shift\"].values, linestyle=\"-.\"\n", + ")\n", + "plt.plot(\n", + " curr[\"i_gen_1_intpl_shift\"].time, curr[\"i_gen_1_intpl_shift\"].values, linestyle=\"-.\"\n", + ")\n", + "plt.plot(\n", + " curr[\"i_gen_2_intpl_shift\"].time, curr[\"i_gen_2_intpl_shift\"].values, linestyle=\"-.\"\n", + ")" ], "outputs": [], "metadata": {} diff --git a/examples/Notebooks/Components/SynGenDq7od_SteadyState_DP_EMT.ipynb b/examples/Notebooks/Components/SynGenDq7od_SteadyState_DP_EMT.ipynb index d100b71b0d..99f4c98950 100644 --- a/examples/Notebooks/Components/SynGenDq7od_SteadyState_DP_EMT.ipynb +++ b/examples/Notebooks/Components/SynGenDq7od_SteadyState_DP_EMT.ipynb @@ -43,8 +43,8 @@ "# Define simulation parameters\n", "time_step = 0.00005\n", "final_time = 0.3\n", - "sim_name = 'DP_SynGenDq7odODE_SteadyState'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"DP_SynGenDq7odODE_SteadyState\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -79,22 +79,45 @@ "breaker_closed = 0.001\n", "\n", "# Nodes\n", - "init_volt_n1 = [init_terminal_volt * np.exp(init_volt_angle * 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3)* 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3)* 1j)]\n", - "n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.ABC, init_volt_n1)\n", + "init_volt_n1 = [\n", + " init_terminal_volt * np.exp(init_volt_angle * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3) * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3) * 1j),\n", + "]\n", + "n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.ABC, init_volt_n1)\n", "\n", "# Components\n", - "gen = dpsimpy.dp.ph3.SynchronGeneratorDQODE('SynGen')\n", - "gen.set_parameters_fundamental_per_unit(nom_power, nom_ph_ph_volt_rms, nom_freq, pole_num, nom_field_curr, Rs,\n", - " Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,\n", - " Llkq2, H, init_active_power, init_reactive_power, init_terminal_volt, init_volt_angle,\n", - " init_mech_power)\n", - "\n", - "res = dpsimpy.dp.ph3.SeriesResistor('R_load')\n", + "gen = dpsimpy.dp.ph3.SynchronGeneratorDQODE(\"SynGen\")\n", + "gen.set_parameters_fundamental_per_unit(\n", + " nom_power,\n", + " nom_ph_ph_volt_rms,\n", + " nom_freq,\n", + " pole_num,\n", + " nom_field_curr,\n", + " Rs,\n", + " Ll,\n", + " Lmd,\n", + " Lmq,\n", + " Rfd,\n", + " Llfd,\n", + " Rkd,\n", + " Llkd,\n", + " Rkq1,\n", + " Llkq1,\n", + " Rkq2,\n", + " Llkq2,\n", + " H,\n", + " init_active_power,\n", + " init_reactive_power,\n", + " init_terminal_volt,\n", + " init_volt_angle,\n", + " init_mech_power,\n", + ")\n", + "\n", + "res = dpsimpy.dp.ph3.SeriesResistor(\"R_load\")\n", "res.set_parameters(R_load)\n", "\n", - "fault = dpsimpy.dp.ph3.SeriesSwitch('Br_fault')\n", + "fault = dpsimpy.dp.ph3.SeriesSwitch(\"Br_fault\")\n", "fault.set_parameters(breaker_open, breaker_closed)\n", "\n", "# Connections\n", @@ -104,10 +127,10 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_load', 'i_intf', res)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", - "logger.log_attribute('wr_gen', 'w_r', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_load\", \"i_intf\", res)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", + "logger.log_attribute(\"wr_gen\", \"w_r\", gen)\n", "\n", "# System\n", "sys = dpsimpy.SystemTopology(60, [n1], [gen, res, fault])\n", @@ -140,8 +163,8 @@ "# Define simulation parameters\n", "time_step = 0.00005\n", "final_time = 0.3\n", - "sim_name = 'EMT_SynGenDq7odODE_SteadyState'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"EMT_SynGenDq7odODE_SteadyState\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -176,22 +199,45 @@ "breaker_closed = 0.001\n", "\n", "# Nodes\n", - "init_volt_n1 = [init_terminal_volt * np.exp(init_volt_angle * 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3)* 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3)* 1j)]\n", - "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC, init_volt_n1)\n", + "init_volt_n1 = [\n", + " init_terminal_volt * np.exp(init_volt_angle * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3) * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3) * 1j),\n", + "]\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.ABC, init_volt_n1)\n", "\n", "# Components\n", - "gen = dpsimpy.emt.ph3.SynchronGeneratorDQODE('SynGen')\n", - "gen.set_parameters_fundamental_per_unit(nom_power, nom_ph_ph_volt_rms, nom_freq, pole_num, nom_field_curr, Rs,\n", - " Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,\n", - " Llkq2, H, init_active_power, init_reactive_power, init_terminal_volt, init_volt_angle,\n", - " init_mech_power)\n", - "\n", - "res = dpsimpy.emt.ph3.SeriesResistor('R_load')\n", + "gen = dpsimpy.emt.ph3.SynchronGeneratorDQODE(\"SynGen\")\n", + "gen.set_parameters_fundamental_per_unit(\n", + " nom_power,\n", + " nom_ph_ph_volt_rms,\n", + " nom_freq,\n", + " pole_num,\n", + " nom_field_curr,\n", + " Rs,\n", + " Ll,\n", + " Lmd,\n", + " Lmq,\n", + " Rfd,\n", + " Llfd,\n", + " Rkd,\n", + " Llkd,\n", + " Rkq1,\n", + " Llkq1,\n", + " Rkq2,\n", + " Llkq2,\n", + " H,\n", + " init_active_power,\n", + " init_reactive_power,\n", + " init_terminal_volt,\n", + " init_volt_angle,\n", + " init_mech_power,\n", + ")\n", + "\n", + "res = dpsimpy.emt.ph3.SeriesResistor(\"R_load\")\n", "res.set_parameters(R_load)\n", "\n", - "fault = dpsimpy.emt.ph3.SeriesSwitch('Br_fault')\n", + "fault = dpsimpy.emt.ph3.SeriesSwitch(\"Br_fault\")\n", "fault.set_parameters(breaker_open, breaker_closed)\n", "\n", "# Connections\n", @@ -201,10 +247,10 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_load', 'i_intf', res)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", - "logger.log_attribute('wr_gen', 'w_r', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_load\", \"i_intf\", res)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", + "logger.log_attribute(\"wr_gen\", \"w_r\", gen)\n", "\n", "# System\n", "sys = dpsimpy.SystemTopology(60, [n1], [gen, res, fault])\n", @@ -237,8 +283,8 @@ "# Define simulation parameters\n", "time_step = 0.0005\n", "final_time = 0.03\n", - "sim_name = 'DP_SynGenDq7odTrapez_SteadyState'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"DP_SynGenDq7odTrapez_SteadyState\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -273,22 +319,45 @@ "breaker_closed = 0.001\n", "\n", "# Nodes\n", - "init_volt_n1 = [init_terminal_volt * np.exp(init_volt_angle * 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3)* 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3)* 1j)]\n", - "n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.ABC, init_volt_n1)\n", + "init_volt_n1 = [\n", + " init_terminal_volt * np.exp(init_volt_angle * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3) * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3) * 1j),\n", + "]\n", + "n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.ABC, init_volt_n1)\n", "\n", "# Components\n", - "gen = dpsimpy.dp.ph3.SynchronGeneratorDQTrapez('SynGen')\n", - "gen.set_parameters_fundamental_per_unit(nom_power, nom_ph_ph_volt_rms, nom_freq, pole_num, nom_field_curr, Rs,\n", - " Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,\n", - " Llkq2, H, init_active_power, init_reactive_power, init_terminal_volt, init_volt_angle,\n", - " init_mech_power)\n", - "\n", - "res = dpsimpy.dp.ph3.SeriesResistor('R_load')\n", + "gen = dpsimpy.dp.ph3.SynchronGeneratorDQTrapez(\"SynGen\")\n", + "gen.set_parameters_fundamental_per_unit(\n", + " nom_power,\n", + " nom_ph_ph_volt_rms,\n", + " nom_freq,\n", + " pole_num,\n", + " nom_field_curr,\n", + " Rs,\n", + " Ll,\n", + " Lmd,\n", + " Lmq,\n", + " Rfd,\n", + " Llfd,\n", + " Rkd,\n", + " Llkd,\n", + " Rkq1,\n", + " Llkq1,\n", + " Rkq2,\n", + " Llkq2,\n", + " H,\n", + " init_active_power,\n", + " init_reactive_power,\n", + " init_terminal_volt,\n", + " init_volt_angle,\n", + " init_mech_power,\n", + ")\n", + "\n", + "res = dpsimpy.dp.ph3.SeriesResistor(\"R_load\")\n", "res.set_parameters(R_load)\n", "\n", - "fault = dpsimpy.dp.ph3.SeriesSwitch('Br_fault')\n", + "fault = dpsimpy.dp.ph3.SeriesSwitch(\"Br_fault\")\n", "fault.set_parameters(breaker_open, breaker_closed)\n", "\n", "# Connections\n", @@ -298,8 +367,8 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", "\n", "# System\n", "sys = dpsimpy.SystemTopology(60, [n1], [gen, res, fault])\n", @@ -332,8 +401,8 @@ "# Define simulation parameters\n", "time_step = 0.00005\n", "final_time = 0.3\n", - "sim_name = 'EMT_SynGenDq7odTrapez_SteadyState'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"EMT_SynGenDq7odTrapez_SteadyState\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -368,22 +437,45 @@ "breaker_closed = 0.001\n", "\n", "# Nodes\n", - "init_volt_n1 = [init_terminal_volt * np.exp(init_volt_angle * 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3)* 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3)* 1j)]\n", - "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC, init_volt_n1)\n", + "init_volt_n1 = [\n", + " init_terminal_volt * np.exp(init_volt_angle * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3) * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3) * 1j),\n", + "]\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.ABC, init_volt_n1)\n", "\n", "# Components\n", - "gen = dpsimpy.emt.ph3.SynchronGeneratorDQTrapez('SynGen')\n", - "gen.set_parameters_fundamental_per_unit(nom_power, nom_ph_ph_volt_rms, nom_freq, pole_num, nom_field_curr, Rs,\n", - " Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,\n", - " Llkq2, H, init_active_power, init_reactive_power, init_terminal_volt, init_volt_angle,\n", - " init_mech_power)\n", - "\n", - "res = dpsimpy.emt.ph3.SeriesResistor('R_load')\n", + "gen = dpsimpy.emt.ph3.SynchronGeneratorDQTrapez(\"SynGen\")\n", + "gen.set_parameters_fundamental_per_unit(\n", + " nom_power,\n", + " nom_ph_ph_volt_rms,\n", + " nom_freq,\n", + " pole_num,\n", + " nom_field_curr,\n", + " Rs,\n", + " Ll,\n", + " Lmd,\n", + " Lmq,\n", + " Rfd,\n", + " Llfd,\n", + " Rkd,\n", + " Llkd,\n", + " Rkq1,\n", + " Llkq1,\n", + " Rkq2,\n", + " Llkq2,\n", + " H,\n", + " init_active_power,\n", + " init_reactive_power,\n", + " init_terminal_volt,\n", + " init_volt_angle,\n", + " init_mech_power,\n", + ")\n", + "\n", + "res = dpsimpy.emt.ph3.SeriesResistor(\"R_load\")\n", "res.set_parameters(R_load)\n", "\n", - "fault = dpsimpy.emt.ph3.SeriesSwitch('Br_fault')\n", + "fault = dpsimpy.emt.ph3.SeriesSwitch(\"Br_fault\")\n", "fault.set_parameters(breaker_open, breaker_closed)\n", "\n", "# Connections\n", @@ -393,10 +485,10 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_load', 'i_intf', res)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", - "logger.log_attribute('wr_gen', 'w_r', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_load\", \"i_intf\", res)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", + "logger.log_attribute(\"wr_gen\", \"w_r\", gen)\n", "\n", "# System\n", "sys = dpsimpy.SystemTopology(60, [n1], [gen, res, fault])\n", @@ -425,10 +517,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/DP_SynGenDq7odODE_SteadyState/'\n", - "log_name = 'DP_SynGenDq7odODE_SteadyState'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_ode_ststate = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/DP_SynGenDq7odODE_SteadyState/\"\n", + "log_name = \"DP_SynGenDq7odODE_SteadyState\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_ode_ststate = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_ode_ststate_emt = ts.frequency_shift_list(ts_dpsim_ode_ststate, 60)" ] }, @@ -440,7 +532,13 @@ "source": [ "ts_dpsim_ode_ststate_phasors = ts.phasors(ts_dpsim_ode_ststate)\n", "for node, phasor in ts_dpsim_ode_ststate_phasors.items():\n", - " print(node + ': ' + str(phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[0])\n", + " )" ] }, { @@ -449,10 +547,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/EMT_SynGenDq7odODE_SteadyState/'\n", - "log_name = 'EMT_SynGenDq7odODE_SteadyState'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_emt_ode_ststate = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/EMT_SynGenDq7odODE_SteadyState/\"\n", + "log_name = \"EMT_SynGenDq7odODE_SteadyState\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_emt_ode_ststate = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -461,12 +559,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_ode_ststate_emt['v1_0_shift'].time, ts_dpsim_ode_ststate_emt['v1_0_shift'].values)\n", - "plt.plot(ts_dpsim_ode_ststate_emt['v1_1_shift'].time, ts_dpsim_ode_ststate_emt['v1_1_shift'].values)\n", - "plt.plot(ts_dpsim_ode_ststate_emt['v1_2_shift'].time, ts_dpsim_ode_ststate_emt['v1_2_shift'].values)\n", - "plt.plot(ts_dpsim_emt_ode_ststate['v1_0'].time, ts_dpsim_emt_ode_ststate['v1_0'].values)\n", - "plt.plot(ts_dpsim_emt_ode_ststate['v1_1'].time, ts_dpsim_emt_ode_ststate['v1_1'].values)\n", - "plt.plot(ts_dpsim_emt_ode_ststate['v1_2'].time, ts_dpsim_emt_ode_ststate['v1_2'].values)\n", + "plt.plot(\n", + " ts_dpsim_ode_ststate_emt[\"v1_0_shift\"].time,\n", + " ts_dpsim_ode_ststate_emt[\"v1_0_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_ststate_emt[\"v1_1_shift\"].time,\n", + " ts_dpsim_ode_ststate_emt[\"v1_1_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_ststate_emt[\"v1_2_shift\"].time,\n", + " ts_dpsim_ode_ststate_emt[\"v1_2_shift\"].values,\n", + ")\n", + "plt.plot(ts_dpsim_emt_ode_ststate[\"v1_0\"].time, ts_dpsim_emt_ode_ststate[\"v1_0\"].values)\n", + "plt.plot(ts_dpsim_emt_ode_ststate[\"v1_1\"].time, ts_dpsim_emt_ode_ststate[\"v1_1\"].values)\n", + "plt.plot(ts_dpsim_emt_ode_ststate[\"v1_2\"].time, ts_dpsim_emt_ode_ststate[\"v1_2\"].values)\n", "plt.show()" ] }, @@ -483,10 +590,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/DP_SynGenDq7odTrapez_SteadyState/'\n", - "log_name = 'DP_SynGenDq7odTrapez_SteadyState'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_trpz_ststate = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/DP_SynGenDq7odTrapez_SteadyState/\"\n", + "log_name = \"DP_SynGenDq7odTrapez_SteadyState\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_trpz_ststate = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_trpz_ststate_emt = ts.frequency_shift_list(ts_dpsim_trpz_ststate, 60)" ] }, @@ -496,10 +603,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/EMT_SynGenDq7odTrapez_SteadyState/'\n", - "log_name = 'EMT_SynGenDq7odTrapez_SteadyState'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_emt_trpz_ststate = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/EMT_SynGenDq7odTrapez_SteadyState/\"\n", + "log_name = \"EMT_SynGenDq7odTrapez_SteadyState\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_emt_trpz_ststate = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -508,12 +615,27 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_trpz_ststate_emt['v1_0_shift'].time, ts_dpsim_trpz_ststate_emt['v1_0_shift'].values)\n", - "plt.plot(ts_dpsim_trpz_ststate_emt['v1_1_shift'].time, ts_dpsim_trpz_ststate_emt['v1_1_shift'].values)\n", - "plt.plot(ts_dpsim_trpz_ststate_emt['v1_2_shift'].time, ts_dpsim_trpz_ststate_emt['v1_2_shift'].values)\n", - "plt.plot(ts_dpsim_emt_trpz_ststate['v1_0'].time, ts_dpsim_emt_trpz_ststate['v1_0'].values)\n", - "plt.plot(ts_dpsim_emt_trpz_ststate['v1_1'].time, ts_dpsim_emt_trpz_ststate['v1_1'].values)\n", - "plt.plot(ts_dpsim_emt_trpz_ststate['v1_2'].time, ts_dpsim_emt_trpz_ststate['v1_2'].values)\n", + "plt.plot(\n", + " ts_dpsim_trpz_ststate_emt[\"v1_0_shift\"].time,\n", + " ts_dpsim_trpz_ststate_emt[\"v1_0_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_trpz_ststate_emt[\"v1_1_shift\"].time,\n", + " ts_dpsim_trpz_ststate_emt[\"v1_1_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_trpz_ststate_emt[\"v1_2_shift\"].time,\n", + " ts_dpsim_trpz_ststate_emt[\"v1_2_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_trpz_ststate[\"v1_0\"].time, ts_dpsim_emt_trpz_ststate[\"v1_0\"].values\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_trpz_ststate[\"v1_1\"].time, ts_dpsim_emt_trpz_ststate[\"v1_1\"].values\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_trpz_ststate[\"v1_2\"].time, ts_dpsim_emt_trpz_ststate[\"v1_2\"].values\n", + ")\n", "plt.show()" ] }, @@ -534,12 +656,12 @@ "import os\n", "import urllib.request\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Simulink/SynchronousGenerator/SynGen_dq_7th_SteadyState/SL_SynGenDq7od_SteadyState_v_i.csv'\n", - "local_file = 'reference-results/SL_SynGenDq7od_SteadyState_v_i.csv'\n", - "urllib.request.urlretrieve(url, local_file) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Simulink/SynchronousGenerator/SynGen_dq_7th_SteadyState/SL_SynGenDq7od_SteadyState_v_i.csv\"\n", + "local_file = \"reference-results/SL_SynGenDq7od_SteadyState_v_i.csv\"\n", + "urllib.request.urlretrieve(url, local_file)\n", "\n", "ts_sl_ststate = rt.read_timeseries_simulink(local_file)" ] @@ -550,10 +672,10 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_sl_ststate['i1'].time, ts_sl_ststate['i1'].values)\n", - "plt.plot(ts_sl_ststate['i2'].time, ts_sl_ststate['i2'].values)\n", - "plt.plot(ts_sl_ststate['i3'].time, ts_sl_ststate['i3'].values)\n", - "plt.xlim(0,0.03)" + "plt.plot(ts_sl_ststate[\"i1\"].time, ts_sl_ststate[\"i1\"].values)\n", + "plt.plot(ts_sl_ststate[\"i2\"].time, ts_sl_ststate[\"i2\"].values)\n", + "plt.plot(ts_sl_ststate[\"i3\"].time, ts_sl_ststate[\"i3\"].values)\n", + "plt.xlim(0, 0.03)" ] }, { @@ -569,13 +691,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_ode_ststate_emt['i_load_0_shift'].time, ts_dpsim_ode_ststate_emt['i_load_0_shift'].values)\n", - "plt.plot(ts_dpsim_ode_ststate_emt['i_load_1_shift'].time, ts_dpsim_ode_ststate_emt['i_load_1_shift'].values)\n", - "plt.plot(ts_dpsim_ode_ststate_emt['i_load_2_shift'].time, ts_dpsim_ode_ststate_emt['i_load_2_shift'].values)\n", - "plt.plot(ts_sl_ststate['i1'].time, ts_sl_ststate['i1'].values)\n", - "plt.plot(ts_sl_ststate['i2'].time, ts_sl_ststate['i2'].values)\n", - "plt.plot(ts_sl_ststate['i3'].time, ts_sl_ststate['i3'].values)\n", - "plt.xlim(0,0.03)" + "plt.plot(\n", + " ts_dpsim_ode_ststate_emt[\"i_load_0_shift\"].time,\n", + " ts_dpsim_ode_ststate_emt[\"i_load_0_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_ststate_emt[\"i_load_1_shift\"].time,\n", + " ts_dpsim_ode_ststate_emt[\"i_load_1_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_ststate_emt[\"i_load_2_shift\"].time,\n", + " ts_dpsim_ode_ststate_emt[\"i_load_2_shift\"].values,\n", + ")\n", + "plt.plot(ts_sl_ststate[\"i1\"].time, ts_sl_ststate[\"i1\"].values)\n", + "plt.plot(ts_sl_ststate[\"i2\"].time, ts_sl_ststate[\"i2\"].values)\n", + "plt.plot(ts_sl_ststate[\"i3\"].time, ts_sl_ststate[\"i3\"].values)\n", + "plt.xlim(0, 0.03)" ] }, { diff --git a/examples/Notebooks/Components/SynGenDq7od_ThreePhFault_DP_EMT.ipynb b/examples/Notebooks/Components/SynGenDq7od_ThreePhFault_DP_EMT.ipynb index 780edc6f62..58286c9bbf 100644 --- a/examples/Notebooks/Components/SynGenDq7od_ThreePhFault_DP_EMT.ipynb +++ b/examples/Notebooks/Components/SynGenDq7od_ThreePhFault_DP_EMT.ipynb @@ -46,8 +46,8 @@ "# Define simulation parameters\n", "time_step = 0.00005\n", "final_time = 0.3\n", - "sim_name = 'DP_SynGenDq7odODE_ThreePhFault'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"DP_SynGenDq7odODE_ThreePhFault\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -82,22 +82,45 @@ "breaker_closed = 0.001\n", "\n", "# Nodes\n", - "init_volt_n1 = [init_terminal_volt * np.exp(init_volt_angle * 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3)* 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3)* 1j)]\n", - "n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.ABC, init_volt_n1)\n", + "init_volt_n1 = [\n", + " init_terminal_volt * np.exp(init_volt_angle * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3) * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3) * 1j),\n", + "]\n", + "n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.ABC, init_volt_n1)\n", "\n", "# Components\n", - "gen = dpsimpy.dp.ph3.SynchronGeneratorDQODE('SynGen')\n", - "gen.set_parameters_fundamental_per_unit(nom_power, nom_ph_ph_volt_rms, nom_freq, pole_num, nom_field_curr, Rs,\n", - " Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,\n", - " Llkq2, H, init_active_power, init_reactive_power, init_terminal_volt, init_volt_angle,\n", - " init_mech_power)\n", - "\n", - "res = dpsimpy.dp.ph3.SeriesResistor('R_load')\n", + "gen = dpsimpy.dp.ph3.SynchronGeneratorDQODE(\"SynGen\")\n", + "gen.set_parameters_fundamental_per_unit(\n", + " nom_power,\n", + " nom_ph_ph_volt_rms,\n", + " nom_freq,\n", + " pole_num,\n", + " nom_field_curr,\n", + " Rs,\n", + " Ll,\n", + " Lmd,\n", + " Lmq,\n", + " Rfd,\n", + " Llfd,\n", + " Rkd,\n", + " Llkd,\n", + " Rkq1,\n", + " Llkq1,\n", + " Rkq2,\n", + " Llkq2,\n", + " H,\n", + " init_active_power,\n", + " init_reactive_power,\n", + " init_terminal_volt,\n", + " init_volt_angle,\n", + " init_mech_power,\n", + ")\n", + "\n", + "res = dpsimpy.dp.ph3.SeriesResistor(\"R_load\")\n", "res.set_parameters(R_load)\n", "\n", - "fault = dpsimpy.dp.ph3.SeriesSwitch('Br_fault')\n", + "fault = dpsimpy.dp.ph3.SeriesSwitch(\"Br_fault\")\n", "fault.set_parameters(breaker_open, breaker_closed)\n", "\n", "# Connections\n", @@ -107,10 +130,10 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_load', 'i_intf', res)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", - "logger.log_attribute('wr_gen', 'w_r', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_load\", \"i_intf\", res)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", + "logger.log_attribute(\"wr_gen\", \"w_r\", gen)\n", "\n", "# System\n", "sys = dpsimpy.SystemTopology(60, [n1], [gen, res, fault])\n", @@ -150,8 +173,8 @@ "# Define simulation parameters\n", "time_step = 0.00005\n", "final_time = 0.3\n", - "sim_name = 'EMT_SynGenDq7odODE_ThreePhFault'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"EMT_SynGenDq7odODE_ThreePhFault\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -186,22 +209,45 @@ "breaker_closed = 0.001\n", "\n", "# Nodes\n", - "init_volt_n1 = [init_terminal_volt * np.exp(init_volt_angle * 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3)* 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3)* 1j)]\n", - "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC, init_volt_n1)\n", + "init_volt_n1 = [\n", + " init_terminal_volt * np.exp(init_volt_angle * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3) * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3) * 1j),\n", + "]\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.ABC, init_volt_n1)\n", "\n", "# Components\n", - "gen = dpsimpy.emt.ph3.SynchronGeneratorDQODE('SynGen')\n", - "gen.set_parameters_fundamental_per_unit(nom_power, nom_ph_ph_volt_rms, nom_freq, pole_num, nom_field_curr, Rs,\n", - " Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,\n", - " Llkq2, H, init_active_power, init_reactive_power, init_terminal_volt, init_volt_angle,\n", - " init_mech_power)\n", - "\n", - "res = dpsimpy.emt.ph3.SeriesResistor('R_load')\n", + "gen = dpsimpy.emt.ph3.SynchronGeneratorDQODE(\"SynGen\")\n", + "gen.set_parameters_fundamental_per_unit(\n", + " nom_power,\n", + " nom_ph_ph_volt_rms,\n", + " nom_freq,\n", + " pole_num,\n", + " nom_field_curr,\n", + " Rs,\n", + " Ll,\n", + " Lmd,\n", + " Lmq,\n", + " Rfd,\n", + " Llfd,\n", + " Rkd,\n", + " Llkd,\n", + " Rkq1,\n", + " Llkq1,\n", + " Rkq2,\n", + " Llkq2,\n", + " H,\n", + " init_active_power,\n", + " init_reactive_power,\n", + " init_terminal_volt,\n", + " init_volt_angle,\n", + " init_mech_power,\n", + ")\n", + "\n", + "res = dpsimpy.emt.ph3.SeriesResistor(\"R_load\")\n", "res.set_parameters(R_load)\n", "\n", - "fault = dpsimpy.emt.ph3.SeriesSwitch('Br_fault')\n", + "fault = dpsimpy.emt.ph3.SeriesSwitch(\"Br_fault\")\n", "fault.set_parameters(breaker_open, breaker_closed)\n", "\n", "# Connections\n", @@ -211,10 +257,10 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_load', 'i_intf', res)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", - "logger.log_attribute('wr_gen', 'w_r', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_load\", \"i_intf\", res)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", + "logger.log_attribute(\"wr_gen\", \"w_r\", gen)\n", "\n", "# System\n", "sys = dpsimpy.SystemTopology(60, [n1], [gen, res, fault])\n", @@ -254,8 +300,8 @@ "# Define simulation parameters\n", "time_step = 0.00005\n", "final_time = 0.3\n", - "sim_name = 'DP_SynGenDq7odTrapez_ThreePhFault'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"DP_SynGenDq7odTrapez_ThreePhFault\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -290,22 +336,45 @@ "breaker_closed = 0.001\n", "\n", "# Nodes\n", - "init_volt_n1 = [init_terminal_volt * np.exp(init_volt_angle * 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3)* 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3)* 1j)]\n", - "n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.ABC, init_volt_n1)\n", + "init_volt_n1 = [\n", + " init_terminal_volt * np.exp(init_volt_angle * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3) * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3) * 1j),\n", + "]\n", + "n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.ABC, init_volt_n1)\n", "\n", "# Components\n", - "gen = dpsimpy.dp.ph3.SynchronGeneratorDQTrapez('SynGen')\n", - "gen.set_parameters_fundamental_per_unit(nom_power, nom_ph_ph_volt_rms, nom_freq, pole_num, nom_field_curr, Rs,\n", - " Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,\n", - " Llkq2, H, init_active_power, init_reactive_power, init_terminal_volt, init_volt_angle,\n", - " init_mech_power)\n", - "\n", - "res = dpsimpy.dp.ph3.SeriesResistor('R_load')\n", + "gen = dpsimpy.dp.ph3.SynchronGeneratorDQTrapez(\"SynGen\")\n", + "gen.set_parameters_fundamental_per_unit(\n", + " nom_power,\n", + " nom_ph_ph_volt_rms,\n", + " nom_freq,\n", + " pole_num,\n", + " nom_field_curr,\n", + " Rs,\n", + " Ll,\n", + " Lmd,\n", + " Lmq,\n", + " Rfd,\n", + " Llfd,\n", + " Rkd,\n", + " Llkd,\n", + " Rkq1,\n", + " Llkq1,\n", + " Rkq2,\n", + " Llkq2,\n", + " H,\n", + " init_active_power,\n", + " init_reactive_power,\n", + " init_terminal_volt,\n", + " init_volt_angle,\n", + " init_mech_power,\n", + ")\n", + "\n", + "res = dpsimpy.dp.ph3.SeriesResistor(\"R_load\")\n", "res.set_parameters(R_load)\n", "\n", - "fault = dpsimpy.dp.ph3.SeriesSwitch('Br_fault')\n", + "fault = dpsimpy.dp.ph3.SeriesSwitch(\"Br_fault\")\n", "fault.set_parameters(breaker_open, breaker_closed)\n", "\n", "# Connections\n", @@ -315,8 +384,8 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", "\n", "# System\n", "sys = dpsimpy.SystemTopology(60, [n1], [gen, res, fault])\n", @@ -356,8 +425,8 @@ "# Define simulation parameters\n", "time_step = 0.00005\n", "final_time = 0.3\n", - "sim_name = 'EMT_SynGenDq7odTrapez_ThreePhFault'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"EMT_SynGenDq7odTrapez_ThreePhFault\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -392,22 +461,45 @@ "breaker_closed = 0.001\n", "\n", "# Nodes\n", - "init_volt_n1 = [init_terminal_volt * np.exp(init_volt_angle * 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3)* 1j),\n", - " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3)* 1j)]\n", - "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC, init_volt_n1)\n", + "init_volt_n1 = [\n", + " init_terminal_volt * np.exp(init_volt_angle * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle - 2 * np.pi / 3) * 1j),\n", + " init_terminal_volt * np.exp((init_volt_angle + 2 * np.pi / 3) * 1j),\n", + "]\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.ABC, init_volt_n1)\n", "\n", "# Components\n", - "gen = dpsimpy.emt.ph3.SynchronGeneratorDQTrapez('SynGen')\n", - "gen.set_parameters_fundamental_per_unit(nom_power, nom_ph_ph_volt_rms, nom_freq, pole_num, nom_field_curr, Rs,\n", - " Ll, Lmd, Lmq, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2,\n", - " Llkq2, H, init_active_power, init_reactive_power, init_terminal_volt, init_volt_angle,\n", - " init_mech_power)\n", - "\n", - "res = dpsimpy.emt.ph3.SeriesResistor('R_load')\n", + "gen = dpsimpy.emt.ph3.SynchronGeneratorDQTrapez(\"SynGen\")\n", + "gen.set_parameters_fundamental_per_unit(\n", + " nom_power,\n", + " nom_ph_ph_volt_rms,\n", + " nom_freq,\n", + " pole_num,\n", + " nom_field_curr,\n", + " Rs,\n", + " Ll,\n", + " Lmd,\n", + " Lmq,\n", + " Rfd,\n", + " Llfd,\n", + " Rkd,\n", + " Llkd,\n", + " Rkq1,\n", + " Llkq1,\n", + " Rkq2,\n", + " Llkq2,\n", + " H,\n", + " init_active_power,\n", + " init_reactive_power,\n", + " init_terminal_volt,\n", + " init_volt_angle,\n", + " init_mech_power,\n", + ")\n", + "\n", + "res = dpsimpy.emt.ph3.SeriesResistor(\"R_load\")\n", "res.set_parameters(R_load)\n", "\n", - "fault = dpsimpy.emt.ph3.SeriesSwitch('Br_fault')\n", + "fault = dpsimpy.emt.ph3.SeriesSwitch(\"Br_fault\")\n", "fault.set_parameters(breaker_open, breaker_closed)\n", "\n", "# Connections\n", @@ -417,10 +509,10 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_load', 'i_intf', res)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", - "logger.log_attribute('wr_gen', 'w_r', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_load\", \"i_intf\", res)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", + "logger.log_attribute(\"wr_gen\", \"w_r\", gen)\n", "\n", "# System\n", "sys = dpsimpy.SystemTopology(60, [n1], [gen, res, fault])\n", @@ -456,10 +548,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/DP_SynGenDq7odODE_ThreePhFault/'\n", - "log_name = 'DP_SynGenDq7odODE_ThreePhFault'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_ode_tpf = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/DP_SynGenDq7odODE_ThreePhFault/\"\n", + "log_name = \"DP_SynGenDq7odODE_ThreePhFault\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_ode_tpf = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_ode_tpf_emt = ts.frequency_shift_list(ts_dpsim_ode_tpf, 60)" ] }, @@ -471,7 +563,13 @@ "source": [ "ts_dpsim_ode_tpf_phasors = ts.phasors(ts_dpsim_ode_tpf)\n", "for node, phasor in ts_dpsim_ode_tpf_phasors.items():\n", - " print(node + ': ' + str(phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[0])\n", + " )" ] }, { @@ -480,10 +578,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/EMT_SynGenDq7odODE_ThreePhFault/'\n", - "log_name = 'EMT_SynGenDq7odODE_ThreePhFault'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_emt_ode_tpf = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/EMT_SynGenDq7odODE_ThreePhFault/\"\n", + "log_name = \"EMT_SynGenDq7odODE_ThreePhFault\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_emt_ode_tpf = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -492,9 +590,15 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_ode_tpf_emt['v1_0_shift'].time, ts_dpsim_ode_tpf_emt['v1_0_shift'].values)\n", - "plt.plot(ts_dpsim_ode_tpf_emt['v1_1_shift'].time, ts_dpsim_ode_tpf_emt['v1_1_shift'].values)\n", - "plt.plot(ts_dpsim_ode_tpf_emt['v1_2_shift'].time, ts_dpsim_ode_tpf_emt['v1_2_shift'].values)\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"v1_0_shift\"].time, ts_dpsim_ode_tpf_emt[\"v1_0_shift\"].values\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"v1_1_shift\"].time, ts_dpsim_ode_tpf_emt[\"v1_1_shift\"].values\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"v1_2_shift\"].time, ts_dpsim_ode_tpf_emt[\"v1_2_shift\"].values\n", + ")\n", "plt.show()" ] }, @@ -504,12 +608,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_0_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_0_shift'].values)\n", - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_1_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_1_shift'].values)\n", - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_2_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_2_shift'].values)\n", - "plt.plot(ts_dpsim_emt_ode_tpf['i_gen_0'].time, ts_dpsim_emt_ode_tpf['i_gen_0'].values)\n", - "plt.plot(ts_dpsim_emt_ode_tpf['i_gen_1'].time, ts_dpsim_emt_ode_tpf['i_gen_1'].values)\n", - "plt.plot(ts_dpsim_emt_ode_tpf['i_gen_2'].time, ts_dpsim_emt_ode_tpf['i_gen_2'].values)\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_0_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_0_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_1_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_1_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_2_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_2_shift\"].values,\n", + ")\n", + "plt.plot(ts_dpsim_emt_ode_tpf[\"i_gen_0\"].time, ts_dpsim_emt_ode_tpf[\"i_gen_0\"].values)\n", + "plt.plot(ts_dpsim_emt_ode_tpf[\"i_gen_1\"].time, ts_dpsim_emt_ode_tpf[\"i_gen_1\"].values)\n", + "plt.plot(ts_dpsim_emt_ode_tpf[\"i_gen_2\"].time, ts_dpsim_emt_ode_tpf[\"i_gen_2\"].values)\n", "plt.show()" ] }, @@ -527,10 +640,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/DP_SynGenDq7odTrapez_ThreePhFault/'\n", - "log_name = 'DP_SynGenDq7odTrapez_ThreePhFault'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_trapez_tpf = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/DP_SynGenDq7odTrapez_ThreePhFault/\"\n", + "log_name = \"DP_SynGenDq7odTrapez_ThreePhFault\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_trapez_tpf = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_trapez_tpf_emt = ts.frequency_shift_list(ts_dpsim_trapez_tpf, 60)" ] }, @@ -540,10 +653,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/EMT_SynGenDq7odTrapez_ThreePhFault/'\n", - "log_name = 'EMT_SynGenDq7odTrapez_ThreePhFault'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_emt_trapez_tpf = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/EMT_SynGenDq7odTrapez_ThreePhFault/\"\n", + "log_name = \"EMT_SynGenDq7odTrapez_ThreePhFault\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_emt_trapez_tpf = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -552,12 +665,27 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_trapez_tpf_emt['i_gen_0_shift'].time, ts_dpsim_trapez_tpf_emt['i_gen_0_shift'].values)\n", - "plt.plot(ts_dpsim_trapez_tpf_emt['i_gen_1_shift'].time, ts_dpsim_trapez_tpf_emt['i_gen_1_shift'].values)\n", - "plt.plot(ts_dpsim_trapez_tpf_emt['i_gen_2_shift'].time, ts_dpsim_trapez_tpf_emt['i_gen_2_shift'].values)\n", - "plt.plot(ts_dpsim_emt_trapez_tpf['i_gen_0'].time, ts_dpsim_emt_trapez_tpf['i_gen_0'].values)\n", - "plt.plot(ts_dpsim_emt_trapez_tpf['i_gen_1'].time, ts_dpsim_emt_trapez_tpf['i_gen_1'].values)\n", - "plt.plot(ts_dpsim_emt_trapez_tpf['i_gen_2'].time, ts_dpsim_emt_trapez_tpf['i_gen_2'].values)\n", + "plt.plot(\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_0_shift\"].time,\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_0_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_1_shift\"].time,\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_1_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_2_shift\"].time,\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_2_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_trapez_tpf[\"i_gen_0\"].time, ts_dpsim_emt_trapez_tpf[\"i_gen_0\"].values\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_trapez_tpf[\"i_gen_1\"].time, ts_dpsim_emt_trapez_tpf[\"i_gen_1\"].values\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_trapez_tpf[\"i_gen_2\"].time, ts_dpsim_emt_trapez_tpf[\"i_gen_2\"].values\n", + ")\n", "plt.show()" ] }, @@ -579,15 +707,16 @@ "import os\n", "import urllib.request\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Simulink/SynchronousGenerator/SynGen_dq_7th_ThreePhFault/SL_SynGenDq7od_ThreePhFault_v_i.csv'\n", - "local_file = 'reference-results/SL_SynGenDq7od_ThreePhFault_v_i.csv'\n", - "urllib.request.urlretrieve(url, local_file) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Simulink/SynchronousGenerator/SynGen_dq_7th_ThreePhFault/SL_SynGenDq7od_ThreePhFault_v_i.csv\"\n", + "local_file = \"reference-results/SL_SynGenDq7od_ThreePhFault_v_i.csv\"\n", + "urllib.request.urlretrieve(url, local_file)\n", "\n", "import villas.dataprocessing.readtools as rt\n", - "import matplotlib.pyplot as plt \n", + "import matplotlib.pyplot as plt\n", + "\n", "ts_sl_tpf = rt.read_timeseries_simulink(local_file)" ] }, @@ -597,16 +726,16 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_sl_tpf['v1'].time, ts_sl_tpf['v1'].values)\n", - "plt.plot(ts_sl_tpf['v2'].time, ts_sl_tpf['v2'].values)\n", - "plt.plot(ts_sl_tpf['v3'].time, ts_sl_tpf['v3'].values)\n", - "plt.xlim(0,0.3)\n", + "plt.plot(ts_sl_tpf[\"v1\"].time, ts_sl_tpf[\"v1\"].values)\n", + "plt.plot(ts_sl_tpf[\"v2\"].time, ts_sl_tpf[\"v2\"].values)\n", + "plt.plot(ts_sl_tpf[\"v3\"].time, ts_sl_tpf[\"v3\"].values)\n", + "plt.xlim(0, 0.3)\n", "\n", "plt.figure()\n", - "plt.plot(ts_sl_tpf['i1'].time, ts_sl_tpf['i1'].values)\n", - "plt.plot(ts_sl_tpf['i2'].time, ts_sl_tpf['i2'].values)\n", - "plt.plot(ts_sl_tpf['i3'].time, ts_sl_tpf['i3'].values)\n", - "plt.xlim(0,0.3)" + "plt.plot(ts_sl_tpf[\"i1\"].time, ts_sl_tpf[\"i1\"].values)\n", + "plt.plot(ts_sl_tpf[\"i2\"].time, ts_sl_tpf[\"i2\"].values)\n", + "plt.plot(ts_sl_tpf[\"i3\"].time, ts_sl_tpf[\"i3\"].values)\n", + "plt.xlim(0, 0.3)" ] }, { @@ -623,24 +752,43 @@ "metadata": {}, "outputs": [], "source": [ - "#%matplotlib qt\n", + "# %matplotlib qt\n", "import matplotlib.pyplot as plt\n", - "ts_sl_tpf_i1 = ts('i1', ts_sl_tpf['i1'].time, -ts_sl_tpf['i1'].values)\n", - "ts_sl_tpf_i2 = ts('i2', ts_sl_tpf['i2'].time, -ts_sl_tpf['i2'].values)\n", - "ts_sl_tpf_i3 = ts('i3', ts_sl_tpf['i3'].time, -ts_sl_tpf['i3'].values)\n", - "\n", - "#plt.figure(figsize=(20,10))\n", - "plt.plot(ts_sl_tpf_i1.time, ts_sl_tpf_i1.values, color = '#939393ff', label = 'ia_sl')\n", - "plt.plot(ts_sl_tpf_i2.time, ts_sl_tpf_i2.values, color = '#939393ff', label = 'ib_sl')\n", - "plt.plot(ts_sl_tpf_i3.time, ts_sl_tpf_i3.values, color = '#939393ff', label = 'ic_sl')\n", - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_0_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_0_shift'].values, linestyle='-.', color = '#d62728ff', label = 'ia_dpsim')\n", - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_1_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_1_shift'].values, linestyle='-.', color = '#0055ffff', label = 'ib_dpsim')\n", - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_2_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_2_shift'].values, linestyle='-.', color = '#00aa7fff', label = 'ic_dpsim')\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (V)')\n", - "plt.xlim(0.05,0.25)\n", - "#plt.ylim(-1.6e5,1.6e5)\n", - "#plt.savefig('syngen_fault_ode.pdf')" + "\n", + "ts_sl_tpf_i1 = ts(\"i1\", ts_sl_tpf[\"i1\"].time, -ts_sl_tpf[\"i1\"].values)\n", + "ts_sl_tpf_i2 = ts(\"i2\", ts_sl_tpf[\"i2\"].time, -ts_sl_tpf[\"i2\"].values)\n", + "ts_sl_tpf_i3 = ts(\"i3\", ts_sl_tpf[\"i3\"].time, -ts_sl_tpf[\"i3\"].values)\n", + "\n", + "# plt.figure(figsize=(20,10))\n", + "plt.plot(ts_sl_tpf_i1.time, ts_sl_tpf_i1.values, color=\"#939393ff\", label=\"ia_sl\")\n", + "plt.plot(ts_sl_tpf_i2.time, ts_sl_tpf_i2.values, color=\"#939393ff\", label=\"ib_sl\")\n", + "plt.plot(ts_sl_tpf_i3.time, ts_sl_tpf_i3.values, color=\"#939393ff\", label=\"ic_sl\")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_0_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_0_shift\"].values,\n", + " linestyle=\"-.\",\n", + " color=\"#d62728ff\",\n", + " label=\"ia_dpsim\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_1_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_1_shift\"].values,\n", + " linestyle=\"-.\",\n", + " color=\"#0055ffff\",\n", + " label=\"ib_dpsim\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_2_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_2_shift\"].values,\n", + " linestyle=\"-.\",\n", + " color=\"#00aa7fff\",\n", + " label=\"ic_dpsim\",\n", + ")\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (V)\")\n", + "plt.xlim(0.05, 0.25)\n", + "# plt.ylim(-1.6e5,1.6e5)\n", + "# plt.savefig('syngen_fault_ode.pdf')" ] }, { @@ -649,12 +797,15 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_ode_tpf_phasors['i_gen_0']['phase'].time, ts_dpsim_ode_tpf_phasors['i_gen_0']['phase'].values)\n", - "plt.xlim([0.09,0.21])\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_phasors[\"i_gen_0\"][\"phase\"].time,\n", + " ts_dpsim_ode_tpf_phasors[\"i_gen_0\"][\"phase\"].values,\n", + ")\n", + "plt.xlim([0.09, 0.21])\n", "\n", "plt.figure()\n", - "plt.plot(ts_dpsim_ode_tpf['wr_gen'].time, ts_dpsim_ode_tpf['wr_gen'].values * 60)\n", - "plt.xlim([0.09,0.21])" + "plt.plot(ts_dpsim_ode_tpf[\"wr_gen\"].time, ts_dpsim_ode_tpf[\"wr_gen\"].values * 60)\n", + "plt.xlim([0.09, 0.21])" ] }, { @@ -664,7 +815,8 @@ "outputs": [], "source": [ "import numpy as np\n", - "diff = ts_sl_tpf_i1.values - ts_dpsim_ode_tpf_emt['i_gen_0_shift'].values\n", + "\n", + "diff = ts_sl_tpf_i1.values - ts_dpsim_ode_tpf_emt[\"i_gen_0_shift\"].values\n", "print(np.max(diff[:4000]))\n", "assert np.max(diff[:4000]) < 28.5" ] @@ -683,17 +835,26 @@ "metadata": {}, "outputs": [], "source": [ - "ts_sl_tpf_i1 = ts('i1', ts_sl_tpf['i1'].time, -ts_sl_tpf['i1'].values)\n", - "ts_sl_tpf_i2 = ts('i2', ts_sl_tpf['i2'].time, -ts_sl_tpf['i2'].values)\n", - "ts_sl_tpf_i3 = ts('i3', ts_sl_tpf['i3'].time, -ts_sl_tpf['i3'].values)\n", + "ts_sl_tpf_i1 = ts(\"i1\", ts_sl_tpf[\"i1\"].time, -ts_sl_tpf[\"i1\"].values)\n", + "ts_sl_tpf_i2 = ts(\"i2\", ts_sl_tpf[\"i2\"].time, -ts_sl_tpf[\"i2\"].values)\n", + "ts_sl_tpf_i3 = ts(\"i3\", ts_sl_tpf[\"i3\"].time, -ts_sl_tpf[\"i3\"].values)\n", "\n", - "#plt.figure(figsize=(20,10))\n", + "# plt.figure(figsize=(20,10))\n", "plt.plot(ts_sl_tpf_i1.time, ts_sl_tpf_i1.values)\n", "plt.plot(ts_sl_tpf_i2.time, ts_sl_tpf_i2.values)\n", "plt.plot(ts_sl_tpf_i3.time, ts_sl_tpf_i3.values)\n", - "plt.plot(ts_dpsim_trapez_tpf_emt['i_gen_0_shift'].time, ts_dpsim_trapez_tpf_emt['i_gen_0_shift'].values)\n", - "plt.plot(ts_dpsim_trapez_tpf_emt['i_gen_1_shift'].time, ts_dpsim_trapez_tpf_emt['i_gen_1_shift'].values)\n", - "plt.plot(ts_dpsim_trapez_tpf_emt['i_gen_2_shift'].time, ts_dpsim_trapez_tpf_emt['i_gen_2_shift'].values)\n", + "plt.plot(\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_0_shift\"].time,\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_0_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_1_shift\"].time,\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_1_shift\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_2_shift\"].time,\n", + " ts_dpsim_trapez_tpf_emt[\"i_gen_2_shift\"].values,\n", + ")\n", "plt.show()" ] }, @@ -704,7 +865,8 @@ "outputs": [], "source": [ "import numpy as np\n", - "diff = ts_sl_tpf_i1.values - ts_dpsim_trapez_tpf_emt['i_gen_0_shift'].values\n", + "\n", + "diff = ts_sl_tpf_i1.values - ts_dpsim_trapez_tpf_emt[\"i_gen_0_shift\"].values\n", "print(np.max(diff[:4000]))\n", "assert np.max(diff[:4000]) < 30.6" ] diff --git a/examples/Notebooks/Components/SynGen_trStab.ipynb b/examples/Notebooks/Components/SynGen_trStab.ipynb index 4ec8b63b7e..5c78602171 100644 --- a/examples/Notebooks/Components/SynGen_trStab.ipynb +++ b/examples/Notebooks/Components/SynGen_trStab.ipynb @@ -39,8 +39,8 @@ " # Define simulation parameters\n", " time_step = 0.0005\n", " final_time = 0.03\n", - " sim_name = 'DP_SynGen_TrStab_SteadyState'\n", - " dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + " sim_name = \"DP_SynGen_TrStab_SteadyState\"\n", + " dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", " # Define machine parameters in per unit\n", " nom_power = 555e6\n", @@ -62,15 +62,17 @@ " R_load = 1.92\n", "\n", " # Nodes\n", - " n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [init_voltage])\n", + " n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.Single, [init_voltage])\n", "\n", " # Components\n", - " gen = dpsimpy.dp.ph1.SynchronGeneratorTrStab('SynGen', dpsimpy.LogLevel.debug)\n", - " gen.set_fundamental_parameters_PU(nom_power, nom_ph_ph_volt_rms, nom_freq, Ll, Lmd, Llfd, H)\n", + " gen = dpsimpy.dp.ph1.SynchronGeneratorTrStab(\"SynGen\", dpsimpy.LogLevel.debug)\n", + " gen.set_fundamental_parameters_PU(\n", + " nom_power, nom_ph_ph_volt_rms, nom_freq, Ll, Lmd, Llfd, H\n", + " )\n", " gen.connect([n1])\n", " gen.set_initial_values(init_elec_power, mech_power)\n", "\n", - " res = dpsimpy.dp.ph1.Resistor('Rl', dpsimpy.LogLevel.debug)\n", + " res = dpsimpy.dp.ph1.Resistor(\"Rl\", dpsimpy.LogLevel.debug)\n", " res.set_parameters(R_load)\n", " res.connect([dpsimpy.dp.SimNode.gnd, n1])\n", "\n", @@ -79,10 +81,10 @@ "\n", " # Logging\n", " logger = dpsimpy.Logger(sim_name)\n", - " logger.log_attribute('v1', 'v', n1)\n", - " logger.log_attribute('i_gen', 'i_intf', gen)\n", - " logger.log_attribute('i_load', 'i_intf', res)\n", - " logger.log_attribute('wr_gen', 'w_r', gen)\n", + " logger.log_attribute(\"v1\", \"v\", n1)\n", + " logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", + " logger.log_attribute(\"i_load\", \"i_intf\", res)\n", + " logger.log_attribute(\"wr_gen\", \"w_r\", gen)\n", "\n", " # Simulation\n", " sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.trace)\n", @@ -92,7 +94,7 @@ " sim.set_final_time(final_time)\n", " sim.set_domain(dpsimpy.Domain.DP)\n", " sim.add_logger(logger)\n", - " sim.run()\n" + " sim.run()" ] }, { @@ -111,10 +113,10 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = 'logs/DP_SynGen_TrStab_SteadyState/'\n", - "logName_ststate = 'DP_SynGen_TrStab_SteadyState_LeftVector'\n", - "print(work_dir + logName_ststate + '.csv')\n", - "ts_dpsim_ststate = rt.read_timeseries_dpsim(work_dir + logName_ststate + '.csv')\n", + "work_dir = \"logs/DP_SynGen_TrStab_SteadyState/\"\n", + "logName_ststate = \"DP_SynGen_TrStab_SteadyState_LeftVector\"\n", + "print(work_dir + logName_ststate + \".csv\")\n", + "ts_dpsim_ststate = rt.read_timeseries_dpsim(work_dir + logName_ststate + \".csv\")\n", "ts_dpsim_ststate_emt = ts.frequency_shift_list(ts_dpsim_ststate, 60)\n", "phasors_ststate = ts.phasors(ts_dpsim_ststate)" ] @@ -126,7 +128,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_ststate.items():\n", - " print(node + ': ' + str(phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[0])\n", + " )" ] }, { @@ -135,8 +143,8 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(1, ts_dpsim_ststate_emt['n00000f00_shift'])\n", - "pt.plot_timeseries(1, ts_dpsim_ststate_emt['n00001f00_shift'])" + "pt.plot_timeseries(1, ts_dpsim_ststate_emt[\"n00000f00_shift\"])\n", + "pt.plot_timeseries(1, ts_dpsim_ststate_emt[\"n00001f00_shift\"])" ] }, { @@ -146,10 +154,10 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = './logs/DP_SynGen_TrStab_SteadyState/'\n", - "logName_ststate = 'DP_SynGen_TrStab_SteadyState'\n", - "print(work_dir + logName_ststate + '.csv')\n", - "ts_dpsim_ststate = rt.read_timeseries_dpsim(work_dir + logName_ststate + '.csv')\n", + "work_dir = \"./logs/DP_SynGen_TrStab_SteadyState/\"\n", + "logName_ststate = \"DP_SynGen_TrStab_SteadyState\"\n", + "print(work_dir + logName_ststate + \".csv\")\n", + "ts_dpsim_ststate = rt.read_timeseries_dpsim(work_dir + logName_ststate + \".csv\")\n", "ts_dpsim_ststate_emt = ts.frequency_shift_list(ts_dpsim_ststate, 60)\n", "phasors_ststate = ts.phasors(ts_dpsim_ststate)" ] @@ -160,7 +168,13 @@ "metadata": {}, "outputs": [], "source": [ - "print('v1' + ': ' + str(phasors_ststate['v1']['abs'].values[0]) + '<' + str(phasors_ststate['v1']['phase'].values[0]))" + "print(\n", + " \"v1\"\n", + " + \": \"\n", + " + str(phasors_ststate[\"v1\"][\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasors_ststate[\"v1\"][\"phase\"].values[0])\n", + ")" ] }, { @@ -169,8 +183,8 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(1, ts_dpsim_ststate['wr_gen'])\n", - "plt.ylim([375,380])" + "pt.plot_timeseries(1, ts_dpsim_ststate[\"wr_gen\"])\n", + "plt.ylim([375, 380])" ] }, { @@ -180,7 +194,11 @@ "outputs": [], "source": [ "import numpy as np\n", - "assert np.max(ts_dpsim_ststate['wr_gen'].values[0] - ts_dpsim_ststate['wr_gen'].values[-1]) < 0.001" + "\n", + "assert (\n", + " np.max(ts_dpsim_ststate[\"wr_gen\"].values[0] - ts_dpsim_ststate[\"wr_gen\"].values[-1])\n", + " < 0.001\n", + ")" ] }, { @@ -199,8 +217,8 @@ "# Define simulation parameters\n", "time_step = 0.0005\n", "final_time = 0.1\n", - "sim_name = 'DP_SynGen_TrStab_LoadStep'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"DP_SynGen_TrStab_LoadStep\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -223,15 +241,17 @@ "R_load_step = 0.7\n", "\n", "# Nodes\n", - "n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [init_voltage])\n", + "n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.Single, [init_voltage])\n", "\n", "# Components\n", - "gen = dpsimpy.dp.ph1.SynchronGeneratorTrStab('SynGen', dpsimpy.LogLevel.debug)\n", - "gen.set_fundamental_parameters_PU(nom_power, nom_ph_ph_volt_rms, nom_freq, Ll, Lmd, Llfd, H)\n", + "gen = dpsimpy.dp.ph1.SynchronGeneratorTrStab(\"SynGen\", dpsimpy.LogLevel.debug)\n", + "gen.set_fundamental_parameters_PU(\n", + " nom_power, nom_ph_ph_volt_rms, nom_freq, Ll, Lmd, Llfd, H\n", + ")\n", "gen.connect([n1])\n", "gen.set_initial_values(init_elec_power, mech_power)\n", "\n", - "load = dpsimpy.dp.ph1.Switch('StepLoad', dpsimpy.LogLevel.debug)\n", + "load = dpsimpy.dp.ph1.Switch(\"StepLoad\", dpsimpy.LogLevel.debug)\n", "load.set_parameters(R_load, R_load_step)\n", "load.connect([dpsimpy.dp.SimNode.gnd, n1])\n", "load.open()\n", @@ -241,10 +261,10 @@ "\n", "# Logging\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('i_gen', 'i_intf', gen)\n", - "logger.log_attribute('i_load', 'i_intf', load)\n", - "logger.log_attribute('wr_gen', 'w_r', gen)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_gen\", \"i_intf\", gen)\n", + "logger.log_attribute(\"i_load\", \"i_intf\", load)\n", + "logger.log_attribute(\"wr_gen\", \"w_r\", gen)\n", "\n", "# Simulation\n", "sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.info)\n", @@ -259,7 +279,7 @@ "sw1 = dpsimpy.event.SwitchEvent(0.05, load, True)\n", "sim.add_event(sw1)\n", "\n", - "sim.run()\n" + "sim.run()" ] }, { @@ -269,10 +289,10 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = 'logs/DP_SynGen_TrStab_LoadStep/'\n", - "logName = 'DP_SynGen_TrStab_LoadStep'\n", - "print(work_dir + logName + '.csv')\n", - "ts_dpsim_loadstep= rt.read_timeseries_dpsim(work_dir + logName + '.csv')\n", + "work_dir = \"logs/DP_SynGen_TrStab_LoadStep/\"\n", + "logName = \"DP_SynGen_TrStab_LoadStep\"\n", + "print(work_dir + logName + \".csv\")\n", + "ts_dpsim_loadstep = rt.read_timeseries_dpsim(work_dir + logName + \".csv\")\n", "ts_dpsim_loadstep_emt = ts.frequency_shift_list(ts_dpsim_loadstep, 60)\n", "phasors_loadstep = ts.phasors(ts_dpsim_loadstep)" ] @@ -283,7 +303,13 @@ "metadata": {}, "outputs": [], "source": [ - "print('v1' + ': ' + str(phasors_loadstep['v1']['abs'].values[0]) + '<' + str(phasors_loadstep['v1']['phase'].values[0]))" + "print(\n", + " \"v1\"\n", + " + \": \"\n", + " + str(phasors_loadstep[\"v1\"][\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasors_loadstep[\"v1\"][\"phase\"].values[0])\n", + ")" ] }, { @@ -292,8 +318,8 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(2, ts_dpsim_loadstep_emt['v1_shift'])\n", - "plt.xlim(0.03, 0.07) " + "pt.plot_timeseries(2, ts_dpsim_loadstep_emt[\"v1_shift\"])\n", + "plt.xlim(0.03, 0.07)" ] }, { @@ -302,7 +328,7 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(3, ts_dpsim_loadstep['wr_gen'])" + "pt.plot_timeseries(3, ts_dpsim_loadstep[\"wr_gen\"])" ] }, { @@ -311,7 +337,12 @@ "metadata": {}, "outputs": [], "source": [ - "assert np.max(ts_dpsim_loadstep['wr_gen'].values[0] - ts_dpsim_loadstep['wr_gen'].values[-1]) < 5" + "assert (\n", + " np.max(\n", + " ts_dpsim_loadstep[\"wr_gen\"].values[0] - ts_dpsim_loadstep[\"wr_gen\"].values[-1]\n", + " )\n", + " < 5\n", + ")" ] } ], diff --git a/examples/Notebooks/Components/SynGen_trStab_logger_test.ipynb b/examples/Notebooks/Components/SynGen_trStab_logger_test.ipynb index 1a1d341bb5..85b4b8fbc4 100644 --- a/examples/Notebooks/Components/SynGen_trStab_logger_test.ipynb +++ b/examples/Notebooks/Components/SynGen_trStab_logger_test.ipynb @@ -32,8 +32,8 @@ " # Define simulation parameters\n", " time_step = 0.0005\n", " final_time = 0.03\n", - " sim_name = 'DP_SynGen_TrStab_SteadyState'\n", - " dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + " sim_name = \"DP_SynGen_TrStab_SteadyState\"\n", + " dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", " # Define machine parameters in per unit\n", " nom_power = 555e6\n", @@ -55,21 +55,23 @@ " R_load = 1.92\n", "\n", " # Nodes\n", - " n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [init_voltage])\n", + " n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.Single, [init_voltage])\n", "\n", " # Components\n", - " gen = dpsimpy.dp.ph1.SynchronGeneratorTrStab('SynGen', dpsimpy.LogLevel.debug)\n", - " gen.set_fundamental_parameters_PU(nom_power, nom_ph_ph_volt_rms, nom_freq, Ll, Lmd, Llfd, H)\n", + " gen = dpsimpy.dp.ph1.SynchronGeneratorTrStab(\"SynGen\", dpsimpy.LogLevel.debug)\n", + " gen.set_fundamental_parameters_PU(\n", + " nom_power, nom_ph_ph_volt_rms, nom_freq, Ll, Lmd, Llfd, H\n", + " )\n", " gen.connect([n1])\n", " gen.set_initial_values(init_elec_power, mech_power)\n", "\n", - " res = dpsimpy.dp.ph1.Resistor('Rl', dpsimpy.LogLevel.debug)\n", + " res = dpsimpy.dp.ph1.Resistor(\"Rl\", dpsimpy.LogLevel.debug)\n", " res.set_parameters(R_load)\n", " res.connect([dpsimpy.dp.SimNode.gnd, n1])\n", "\n", " # System\n", " sys = dpsimpy.SystemTopology(60, [n1], [gen, res])\n", - " \n", + "\n", " # Simulation\n", " sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.trace)\n", " sim.set_time_step(time_step)\n", @@ -87,11 +89,14 @@ "outputs": [], "source": [ "def printTrStabLeftVector():\n", - " f = open('logs/DP_SynGen_TrStab_SteadyState/DP_SynGen_TrStab_SteadyState_LeftVector.csv', 'r')\n", + " f = open(\n", + " \"logs/DP_SynGen_TrStab_SteadyState/DP_SynGen_TrStab_SteadyState_LeftVector.csv\",\n", + " \"r\",\n", + " )\n", " content = f.read()\n", - " print('----- Start of LeftVector-File -----')\n", + " print(\"----- Start of LeftVector-File -----\")\n", " print(content)\n", - " print('----- End of LeftVector-File -----\\n')\n", + " print(\"----- End of LeftVector-File -----\\n\")\n", " f.close()" ] }, @@ -101,11 +106,11 @@ "metadata": {}, "outputs": [], "source": [ - " # Define simulation parameters\n", + "# Define simulation parameters\n", "time_step = 0.0005\n", "final_time = 0.03\n", - "sim_name = 'DP_SynGen_TrStab_SteadyState'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"DP_SynGen_TrStab_SteadyState\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "# Define machine parameters in per unit\n", "nom_power = 555e6\n", @@ -127,15 +132,17 @@ "R_load = 1.92\n", "\n", "# Nodes\n", - "n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [init_voltage])\n", + "n1 = dpsimpy.dp.SimNode(\"n1\", dpsimpy.PhaseType.Single, [init_voltage])\n", "\n", "# Components\n", - "gen = dpsimpy.dp.ph1.SynchronGeneratorTrStab('SynGen', dpsimpy.LogLevel.debug)\n", - "gen.set_fundamental_parameters_PU(nom_power, nom_ph_ph_volt_rms, nom_freq, Ll, Lmd, Llfd, H)\n", + "gen = dpsimpy.dp.ph1.SynchronGeneratorTrStab(\"SynGen\", dpsimpy.LogLevel.debug)\n", + "gen.set_fundamental_parameters_PU(\n", + " nom_power, nom_ph_ph_volt_rms, nom_freq, Ll, Lmd, Llfd, H\n", + ")\n", "gen.connect([n1])\n", "gen.set_initial_values(init_elec_power, mech_power)\n", "\n", - "res = dpsimpy.dp.ph1.Resistor('Rl', dpsimpy.LogLevel.debug)\n", + "res = dpsimpy.dp.ph1.Resistor(\"Rl\", dpsimpy.LogLevel.debug)\n", "res.set_parameters(R_load)\n", "res.connect([dpsimpy.dp.SimNode.gnd, n1])\n", "\n", @@ -151,11 +158,11 @@ "sim1.set_system(sys)\n", "sim1.run()\n", "\n", - "print('LeftVector-File after running simulation in the same cell')\n", + "print(\"LeftVector-File after running simulation in the same cell\")\n", "printTrStabLeftVector()\n", "\n", "SimTrStab()\n", - "print('LeftVector-File after running simulation in a function')\n", + "print(\"LeftVector-File after running simulation in a function\")\n", "printTrStabLeftVector()" ] } diff --git a/examples/Notebooks/Components/Syngen_9Order_DCIM_VBR_Governor_Exciter.ipynb b/examples/Notebooks/Components/Syngen_9Order_DCIM_VBR_Governor_Exciter.ipynb index c0205c180a..e2068ff37a 100644 --- a/examples/Notebooks/Components/Syngen_9Order_DCIM_VBR_Governor_Exciter.ipynb +++ b/examples/Notebooks/Components/Syngen_9Order_DCIM_VBR_Governor_Exciter.ipynb @@ -22,13 +22,18 @@ "import os\n", "import subprocess\n", "\n", - "#%matplotlib widget\n", + "# %matplotlib widget\n", "\n", - "PEAK1PH_TO_RMS3PH=np.sqrt(3./2.)\n", + "PEAK1PH_TO_RMS3PH = np.sqrt(3.0 / 2.0)\n", "\n", - "root_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", + "root_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", "\n", - "path_exec = root_path + '/build/dpsim/examples/cxx/'\n", + "path_exec = root_path + \"/build/dpsim/examples/cxx/\"\n", "\n", "finalTime = 30.0\n", "\n", @@ -52,15 +57,31 @@ "metadata": {}, "outputs": [], "source": [ - "name_exec = 'EMT_SynchronGenerator9OrderDCIM_LoadStep_TurbineGovernor_Exciter'\n", + "name_exec = \"EMT_SynchronGenerator9OrderDCIM_LoadStep_TurbineGovernor_Exciter\"\n", "\n", "model_name = name_exec\n", "\n", - "sim = subprocess.Popen([path_exec+name_exec, '--name', model_name, '--timestep', str(timeStepDCIM), '--duration', str(finalTime), '--option', 'TIMESTEPEVENT='+str(loadStepEventTime), '--option', 'LOADFACTOR='+str(loadFactor)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_exec,\n", + " \"--name\",\n", + " model_name,\n", + " \"--timestep\",\n", + " str(timeStepDCIM),\n", + " \"--duration\",\n", + " str(finalTime),\n", + " \"--option\",\n", + " \"TIMESTEPEVENT=\" + str(loadStepEventTime),\n", + " \"--option\",\n", + " \"LOADFACTOR=\" + str(loadFactor),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_emt_dcim = read_timeseries_csv(dpsim_result_file)" ] }, @@ -77,15 +98,31 @@ "metadata": {}, "outputs": [], "source": [ - "name_exec = 'EMT_SynchronGenerator9OrderVBR_LoadStep_TurbineGovernor_Exciter'\n", + "name_exec = \"EMT_SynchronGenerator9OrderVBR_LoadStep_TurbineGovernor_Exciter\"\n", "\n", "model_name = name_exec\n", "\n", - "sim = subprocess.Popen([path_exec+name_exec, '--name', model_name, '--timestep', str(timeStepVBR), '--duration', str(finalTime), '--option', 'TIMESTEPEVENT='+str(loadStepEventTime), '--option', 'LOADFACTOR='+str(loadFactor)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_exec,\n", + " \"--name\",\n", + " model_name,\n", + " \"--timestep\",\n", + " str(timeStepVBR),\n", + " \"--duration\",\n", + " str(finalTime),\n", + " \"--option\",\n", + " \"TIMESTEPEVENT=\" + str(loadStepEventTime),\n", + " \"--option\",\n", + " \"LOADFACTOR=\" + str(loadFactor),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_emt_vbr = read_timeseries_csv(dpsim_result_file)" ] }, @@ -102,10 +139,19 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'v1_0'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt_dcim[name].values, label='dcim')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt_vbr[name].values, label='vbr', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"v1_0\"\n", + "plt.plot(\n", + " ts_dpsim_emt_dcim[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt_dcim[name].values,\n", + " label=\"dcim\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -123,10 +169,15 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'i_gen_0'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, ts_dpsim_emt_dcim[name].values, label='dcim')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, ts_dpsim_emt_vbr[name].values, label='vbr', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"i_gen_0\"\n", + "plt.plot(ts_dpsim_emt_dcim[name].time, ts_dpsim_emt_dcim[name].values, label=\"dcim\")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -144,10 +195,15 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'wr_gen'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, ts_dpsim_emt_dcim[name].values, label='dcim')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, ts_dpsim_emt_vbr[name].values, label='vbr', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"wr_gen\"\n", + "plt.plot(ts_dpsim_emt_dcim[name].time, ts_dpsim_emt_dcim[name].values, label=\"dcim\")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -165,10 +221,12 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'wr_gen'\n", - "rmse = ts_dpsim_emt_dcim[name].rmse(ts_dpsim_emt_dcim[name], ts_dpsim_emt_vbr[name].interpolate(timeStepDCIM))\n", + "name = \"wr_gen\"\n", + "rmse = ts_dpsim_emt_dcim[name].rmse(\n", + " ts_dpsim_emt_dcim[name], ts_dpsim_emt_vbr[name].interpolate(timeStepDCIM)\n", + ")\n", "print(rmse)\n", - "assert(rmse < 4e-4)" + "assert rmse < 4e-4" ] }, { @@ -186,15 +244,33 @@ "metadata": {}, "outputs": [], "source": [ - "name_exec = 'EMT_SynchronGenerator9OrderDCIM_LoadStep_TurbineGovernor_Exciter'\n", + "name_exec = \"EMT_SynchronGenerator9OrderDCIM_LoadStep_TurbineGovernor_Exciter\"\n", "\n", "model_name = name_exec\n", "\n", - "sim = subprocess.Popen([path_exec+name_exec, '--name', model_name, '--timestep', str(timeStepDCIM), '--duration', str(finalTime), '--option', 'WITHGOVERNOR=true', '--option', 'TIMESTEPEVENT='+str(loadStepEventTime), '--option', 'LOADFACTOR='+str(loadFactor)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_exec,\n", + " \"--name\",\n", + " model_name,\n", + " \"--timestep\",\n", + " str(timeStepDCIM),\n", + " \"--duration\",\n", + " str(finalTime),\n", + " \"--option\",\n", + " \"WITHGOVERNOR=true\",\n", + " \"--option\",\n", + " \"TIMESTEPEVENT=\" + str(loadStepEventTime),\n", + " \"--option\",\n", + " \"LOADFACTOR=\" + str(loadFactor),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_emt_dcim = read_timeseries_csv(dpsim_result_file)" ] }, @@ -211,15 +287,33 @@ "metadata": {}, "outputs": [], "source": [ - "name_exec = 'EMT_SynchronGenerator9OrderVBR_LoadStep_TurbineGovernor_Exciter'\n", + "name_exec = \"EMT_SynchronGenerator9OrderVBR_LoadStep_TurbineGovernor_Exciter\"\n", "\n", "model_name = name_exec\n", "\n", - "sim = subprocess.Popen([path_exec+name_exec, '--name', model_name, '--timestep', str(timeStepVBR), '--duration', str(finalTime), '--option', 'WITHGOVERNOR=true', '--option', 'TIMESTEPEVENT='+str(loadStepEventTime), '--option', 'LOADFACTOR='+str(loadFactor)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_exec,\n", + " \"--name\",\n", + " model_name,\n", + " \"--timestep\",\n", + " str(timeStepVBR),\n", + " \"--duration\",\n", + " str(finalTime),\n", + " \"--option\",\n", + " \"WITHGOVERNOR=true\",\n", + " \"--option\",\n", + " \"TIMESTEPEVENT=\" + str(loadStepEventTime),\n", + " \"--option\",\n", + " \"LOADFACTOR=\" + str(loadFactor),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_emt_vbr = read_timeseries_csv(dpsim_result_file)" ] }, @@ -236,10 +330,19 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'v1_0'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt_dcim[name].values, label='dcim - with governor')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt_vbr[name].values, label='vbr - with governor', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"v1_0\"\n", + "plt.plot(\n", + " ts_dpsim_emt_dcim[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt_dcim[name].values,\n", + " label=\"dcim - with governor\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr - with governor\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -257,10 +360,19 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'i_gen_0'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, ts_dpsim_emt_dcim[name].values, label='dcim - with governor')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, ts_dpsim_emt_vbr[name].values, label='vbr - with governor', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"i_gen_0\"\n", + "plt.plot(\n", + " ts_dpsim_emt_dcim[name].time,\n", + " ts_dpsim_emt_dcim[name].values,\n", + " label=\"dcim - with governor\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr - with governor\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -278,10 +390,19 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'wr_gen'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, ts_dpsim_emt_dcim[name].values, label='dcim - with governor')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, ts_dpsim_emt_vbr[name].values, label='vbr - with governor', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"wr_gen\"\n", + "plt.plot(\n", + " ts_dpsim_emt_dcim[name].time,\n", + " ts_dpsim_emt_dcim[name].values,\n", + " label=\"dcim - with governor\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr - with governor\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -299,10 +420,12 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'wr_gen'\n", - "rmse = ts_dpsim_emt_dcim[name].rmse(ts_dpsim_emt_dcim[name], ts_dpsim_emt_vbr[name].interpolate(timeStepDCIM))\n", + "name = \"wr_gen\"\n", + "rmse = ts_dpsim_emt_dcim[name].rmse(\n", + " ts_dpsim_emt_dcim[name], ts_dpsim_emt_vbr[name].interpolate(timeStepDCIM)\n", + ")\n", "print(rmse)\n", - "assert(rmse < 2.1e-5)" + "assert rmse < 2.1e-5" ] }, { @@ -320,15 +443,35 @@ "metadata": {}, "outputs": [], "source": [ - "name_exec = 'EMT_SynchronGenerator9OrderDCIM_LoadStep_TurbineGovernor_Exciter'\n", + "name_exec = \"EMT_SynchronGenerator9OrderDCIM_LoadStep_TurbineGovernor_Exciter\"\n", "\n", "model_name = name_exec\n", "\n", - "sim = subprocess.Popen([path_exec+name_exec, '--name', model_name, '--timestep', str(timeStepDCIM), '--duration', str(finalTime), '--option', 'WITHGOVERNOR=true', '--option', 'WITHEXCITER=true', '--option', 'TIMESTEPEVENT='+str(loadStepEventTime), '--option', 'LOADFACTOR='+str(loadFactor)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_exec,\n", + " \"--name\",\n", + " model_name,\n", + " \"--timestep\",\n", + " str(timeStepDCIM),\n", + " \"--duration\",\n", + " str(finalTime),\n", + " \"--option\",\n", + " \"WITHGOVERNOR=true\",\n", + " \"--option\",\n", + " \"WITHEXCITER=true\",\n", + " \"--option\",\n", + " \"TIMESTEPEVENT=\" + str(loadStepEventTime),\n", + " \"--option\",\n", + " \"LOADFACTOR=\" + str(loadFactor),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_emt_dcim = read_timeseries_csv(dpsim_result_file)" ] }, @@ -345,15 +488,35 @@ "metadata": {}, "outputs": [], "source": [ - "name_exec = 'EMT_SynchronGenerator9OrderVBR_LoadStep_TurbineGovernor_Exciter'\n", + "name_exec = \"EMT_SynchronGenerator9OrderVBR_LoadStep_TurbineGovernor_Exciter\"\n", "\n", "model_name = name_exec\n", "\n", - "sim = subprocess.Popen([path_exec+name_exec, '--name', model_name, '--timestep', str(timeStepVBR), '--duration', str(finalTime), '--option', 'WITHGOVERNOR=true', '--option', 'WITHEXCITER=true', '--option', 'TIMESTEPEVENT='+str(loadStepEventTime), '--option', 'LOADFACTOR='+str(loadFactor)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_exec,\n", + " \"--name\",\n", + " model_name,\n", + " \"--timestep\",\n", + " str(timeStepVBR),\n", + " \"--duration\",\n", + " str(finalTime),\n", + " \"--option\",\n", + " \"WITHGOVERNOR=true\",\n", + " \"--option\",\n", + " \"WITHEXCITER=true\",\n", + " \"--option\",\n", + " \"TIMESTEPEVENT=\" + str(loadStepEventTime),\n", + " \"--option\",\n", + " \"LOADFACTOR=\" + str(loadFactor),\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())\n", "\n", - "path = 'logs/' + model_name + '/'\n", - "dpsim_result_file = path + model_name + '.csv'\n", + "path = \"logs/\" + model_name + \"/\"\n", + "dpsim_result_file = path + model_name + \".csv\"\n", "ts_dpsim_emt_vbr = read_timeseries_csv(dpsim_result_file)" ] }, @@ -370,10 +533,19 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'v1_0'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt_dcim[name].values, label='dcim - with governor and exciter')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, PEAK1PH_TO_RMS3PH*ts_dpsim_emt_vbr[name].values, label='vbr - with governor and exciter', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"v1_0\"\n", + "plt.plot(\n", + " ts_dpsim_emt_dcim[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt_dcim[name].values,\n", + " label=\"dcim - with governor and exciter\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " PEAK1PH_TO_RMS3PH * ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr - with governor and exciter\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -391,10 +563,19 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'i_gen_0'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, ts_dpsim_emt_dcim[name].values, label='dcim - with governor and exciter')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, ts_dpsim_emt_vbr[name].values, label='vbr - with governor and exciter', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"i_gen_0\"\n", + "plt.plot(\n", + " ts_dpsim_emt_dcim[name].time,\n", + " ts_dpsim_emt_dcim[name].values,\n", + " label=\"dcim - with governor and exciter\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr - with governor and exciter\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -412,10 +593,19 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "name = 'wr_gen'\n", - "plt.plot(ts_dpsim_emt_dcim[name].time, ts_dpsim_emt_dcim[name].values, label='dcim - with governor and exciter')\n", - "plt.plot(ts_dpsim_emt_vbr[name].time, ts_dpsim_emt_vbr[name].values, label='vbr - with governor and exciter', linestyle='--')\n", + "plt.figure(figsize=(12, 8))\n", + "name = \"wr_gen\"\n", + "plt.plot(\n", + " ts_dpsim_emt_dcim[name].time,\n", + " ts_dpsim_emt_dcim[name].values,\n", + " label=\"dcim - with governor and exciter\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_vbr[name].time,\n", + " ts_dpsim_emt_vbr[name].values,\n", + " label=\"vbr - with governor and exciter\",\n", + " linestyle=\"--\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -433,10 +623,12 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'wr_gen'\n", - "rmse = ts_dpsim_emt_dcim[name].rmse(ts_dpsim_emt_dcim[name], ts_dpsim_emt_vbr[name].interpolate(timeStepDCIM))\n", + "name = \"wr_gen\"\n", + "rmse = ts_dpsim_emt_dcim[name].rmse(\n", + " ts_dpsim_emt_dcim[name], ts_dpsim_emt_vbr[name].interpolate(timeStepDCIM)\n", + ")\n", "print(rmse)\n", - "assert(rmse < 8e-6)" + "assert rmse < 8e-6" ] } ], diff --git a/examples/Notebooks/Components/Trafo.ipynb b/examples/Notebooks/Components/Trafo.ipynb index e54a49a58c..68fb87e486 100644 --- a/examples/Notebooks/Components/Trafo.ipynb +++ b/examples/Notebooks/Components/Trafo.ipynb @@ -23,7 +23,7 @@ "\n", "epsilon = 1e-12\n", "\n", - "PEAK1PH_TO_RMS3PH = np.sqrt(3/2)" + "PEAK1PH_TO_RMS3PH = np.sqrt(3 / 2)" ] }, { @@ -41,10 +41,10 @@ "source": [ "time_step = 0.00005\n", "final_time = 1\n", - "sim_name = 'SP_Trafo_Elements'\n", + "sim_name = \"SP_Trafo_Elements\"\n", "frequency = 50\n", "omega = 2 * np.pi * frequency\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "voltage_hv_side = 100000\n", "voltage_mv_side = 10000\n", @@ -55,22 +55,28 @@ "q_snub = dpsimpy.Q_SNUB_TRANSFORMER * trafo_power\n", "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", - "snubber_resistance_hv_side = np.abs(voltage_hv_side)**2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side)**2 / p_snub\n", - "snubber_capacitance_mv_side_to_hv_side = 1/(omega * ratio**2 * np.abs(voltage_mv_side)**2 / q_snub) \n", + "snubber_resistance_hv_side = np.abs(voltage_hv_side) ** 2 / p_snub\n", + "snubber_resistance_mv_side_to_hv_side = (\n", + " ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", + ")\n", + "snubber_capacitance_mv_side_to_hv_side = 1 / (\n", + " omega * ratio**2 * np.abs(voltage_mv_side) ** 2 / q_snub\n", + ")\n", "\n", - "n1 = dpsimpy.sp.SimNode('n1')\n", - "n2 = dpsimpy.sp.SimNode('n2')\n", - "vn1 = dpsimpy.sp.SimNode('vn1')\n", + "n1 = dpsimpy.sp.SimNode(\"n1\")\n", + "n2 = dpsimpy.sp.SimNode(\"n2\")\n", + "vn1 = dpsimpy.sp.SimNode(\"vn1\")\n", "gnd = dpsimpy.sp.SimNode.gnd\n", "\n", - "vs = dpsimpy.sp.ph1.VoltageSource('v_1')\n", - "trafo_res = dpsimpy.sp.ph1.Resistor('trafo_res')\n", - "trafo_snubber_res_hv_side = dpsimpy.sp.ph1.Resistor('trafo_snub_res_mv') ##FIXME: Is the naming correct here?\n", - "trafo_snubber_res_mv_side = dpsimpy.sp.ph1.Resistor('trafo_snub_res_hv')\n", - "trafo_snubber_cap_mv_side = dpsimpy.sp.ph1.Capacitor('trafo_snub_cap_mv')\n", - "trafo_ind = dpsimpy.sp.ph1.Inductor('trafo_ind')\n", - "load_res = dpsimpy.sp.ph1.Resistor('r_1')\n", + "vs = dpsimpy.sp.ph1.VoltageSource(\"v_1\")\n", + "trafo_res = dpsimpy.sp.ph1.Resistor(\"trafo_res\")\n", + "trafo_snubber_res_hv_side = dpsimpy.sp.ph1.Resistor(\n", + " \"trafo_snub_res_mv\"\n", + ") ##FIXME: Is the naming correct here?\n", + "trafo_snubber_res_mv_side = dpsimpy.sp.ph1.Resistor(\"trafo_snub_res_hv\")\n", + "trafo_snubber_cap_mv_side = dpsimpy.sp.ph1.Capacitor(\"trafo_snub_cap_mv\")\n", + "trafo_ind = dpsimpy.sp.ph1.Inductor(\"trafo_ind\")\n", + "load_res = dpsimpy.sp.ph1.Resistor(\"r_1\")\n", "\n", "vs.connect([gnd, n1])\n", "trafo_res.connect([n1, vn1])\n", @@ -88,12 +94,24 @@ "trafo_snubber_cap_mv_side.set_parameters(snubber_capacitance_mv_side_to_hv_side)\n", "load_res.set_parameters(load_resistance_hv_side)\n", "\n", - "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, trafo_snubber_res_hv_side, trafo_snubber_res_mv_side, trafo_snubber_cap_mv_side, load_res])\n", + "sys = dpsimpy.SystemTopology(\n", + " 50,\n", + " [n1, n2, vn1],\n", + " [\n", + " vs,\n", + " trafo_res,\n", + " trafo_ind,\n", + " trafo_snubber_res_hv_side,\n", + " trafo_snubber_res_mv_side,\n", + " trafo_snubber_cap_mv_side,\n", + " load_res,\n", + " ],\n", + ")\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('itrafo', 'i_intf', trafo_ind)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"v2\", \"v\", n2)\n", + "logger.log_attribute(\"itrafo\", \"i_intf\", trafo_ind)\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", "sim.set_system(sys)\n", @@ -120,8 +138,8 @@ "source": [ "time_step = 0.00005\n", "final_time = 1\n", - "sim_name = 'SP_Trafo_Component'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"SP_Trafo_Component\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "voltage_hv_side = 100000\n", "voltage_mv_side = 10000\n", @@ -131,29 +149,38 @@ "ratio = voltage_hv_side / voltage_mv_side\n", "load_resistance_mv_side = load_resistance_hv_side / ratio**2\n", "\n", - "n1 = dpsimpy.sp.SimNode('n1')\n", - "n2 = dpsimpy.sp.SimNode('n2')\n", + "n1 = dpsimpy.sp.SimNode(\"n1\")\n", + "n2 = dpsimpy.sp.SimNode(\"n2\")\n", "gnd = dpsimpy.sp.SimNode.gnd\n", "\n", - "vs = dpsimpy.sp.ph1.VoltageSource('v_1', dpsimpy.LogLevel.debug)\n", - "trafo = dpsimpy.sp.ph1.Transformer('trafo', 'trafo', dpsimpy.LogLevel.debug, with_resistive_losses=True)\n", - "load_res = dpsimpy.sp.ph1.Resistor('r_1', dpsimpy.LogLevel.debug)\n", + "vs = dpsimpy.sp.ph1.VoltageSource(\"v_1\", dpsimpy.LogLevel.debug)\n", + "trafo = dpsimpy.sp.ph1.Transformer(\n", + " \"trafo\", \"trafo\", dpsimpy.LogLevel.debug, with_resistive_losses=True\n", + ")\n", + "load_res = dpsimpy.sp.ph1.Resistor(\"r_1\", dpsimpy.LogLevel.debug)\n", "\n", "vs.connect([gnd, n1])\n", "trafo.connect([n1, n2])\n", "load_res.connect([n2, gnd])\n", "\n", "vs.set_parameters(complex(voltage_hv_side, 0))\n", - "trafo.set_parameters(voltage_hv_side, voltage_mv_side, trafo_power, ratio, 0,\n", - " trafo_resistance, trafo_inductance)\n", + "trafo.set_parameters(\n", + " voltage_hv_side,\n", + " voltage_mv_side,\n", + " trafo_power,\n", + " ratio,\n", + " 0,\n", + " trafo_resistance,\n", + " trafo_inductance,\n", + ")\n", "load_res.set_parameters(load_resistance_mv_side)\n", "\n", "sys = dpsimpy.SystemTopology(50, [n1, n2], [vs, trafo, load_res])\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('itrafo', 'i_intf', trafo)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"v2\", \"v\", n2)\n", + "logger.log_attribute(\"itrafo\", \"i_intf\", trafo)\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", "sim.set_system(sys)\n", @@ -180,10 +207,10 @@ "source": [ "time_step = 0.00005\n", "final_time = 1\n", - "sim_name = 'DP_Trafo_Elements'\n", + "sim_name = \"DP_Trafo_Elements\"\n", "frequency = 50\n", "omega = 2 * np.pi * frequency\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "voltage_hv_side = 100000\n", "voltage_mv_side = 10000\n", @@ -194,22 +221,28 @@ "q_snub = dpsimpy.Q_SNUB_TRANSFORMER * trafo_power\n", "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", - "snubber_resistance_hv_side = np.abs(voltage_hv_side)**2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side)**2 / p_snub\n", - "snubber_capacitance_mv_side_to_hv_side = 1/(omega * ratio**2 * np.abs(voltage_mv_side)**2 / q_snub) \n", + "snubber_resistance_hv_side = np.abs(voltage_hv_side) ** 2 / p_snub\n", + "snubber_resistance_mv_side_to_hv_side = (\n", + " ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", + ")\n", + "snubber_capacitance_mv_side_to_hv_side = 1 / (\n", + " omega * ratio**2 * np.abs(voltage_mv_side) ** 2 / q_snub\n", + ")\n", "\n", - "n1 = dpsimpy.dp.SimNode('n1')\n", - "n2 = dpsimpy.dp.SimNode('n2')\n", - "vn1 = dpsimpy.dp.SimNode('vn1')\n", + "n1 = dpsimpy.dp.SimNode(\"n1\")\n", + "n2 = dpsimpy.dp.SimNode(\"n2\")\n", + "vn1 = dpsimpy.dp.SimNode(\"vn1\")\n", "gnd = dpsimpy.dp.SimNode.gnd\n", "\n", - "vs = dpsimpy.dp.ph1.VoltageSource('v_1')\n", - "trafo_res = dpsimpy.dp.ph1.Resistor('trafo_res')\n", - "trafo_snubber_res_hv_side = dpsimpy.dp.ph1.Resistor('trafo_snub_res_mv') ##FIXME: Is the naming correct here?\n", - "trafo_snubber_res_mv_side = dpsimpy.dp.ph1.Resistor('trafo_snub_res_hv')\n", - "trafo_snubber_cap_mv_side = dpsimpy.dp.ph1.Capacitor('trafo_snub_cap_mv')\n", - "trafo_ind = dpsimpy.dp.ph1.Inductor('trafo_ind')\n", - "load_res = dpsimpy.dp.ph1.Resistor('r_1')\n", + "vs = dpsimpy.dp.ph1.VoltageSource(\"v_1\")\n", + "trafo_res = dpsimpy.dp.ph1.Resistor(\"trafo_res\")\n", + "trafo_snubber_res_hv_side = dpsimpy.dp.ph1.Resistor(\n", + " \"trafo_snub_res_mv\"\n", + ") ##FIXME: Is the naming correct here?\n", + "trafo_snubber_res_mv_side = dpsimpy.dp.ph1.Resistor(\"trafo_snub_res_hv\")\n", + "trafo_snubber_cap_mv_side = dpsimpy.dp.ph1.Capacitor(\"trafo_snub_cap_mv\")\n", + "trafo_ind = dpsimpy.dp.ph1.Inductor(\"trafo_ind\")\n", + "load_res = dpsimpy.dp.ph1.Resistor(\"r_1\")\n", "\n", "vs.connect([gnd, n1])\n", "trafo_res.connect([n1, vn1])\n", @@ -227,12 +260,24 @@ "trafo_snubber_cap_mv_side.set_parameters(snubber_capacitance_mv_side_to_hv_side)\n", "load_res.set_parameters(load_resistance_hv_side)\n", "\n", - "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, trafo_snubber_res_hv_side, trafo_snubber_res_mv_side, trafo_snubber_cap_mv_side, load_res])\n", + "sys = dpsimpy.SystemTopology(\n", + " 50,\n", + " [n1, n2, vn1],\n", + " [\n", + " vs,\n", + " trafo_res,\n", + " trafo_ind,\n", + " trafo_snubber_res_hv_side,\n", + " trafo_snubber_res_mv_side,\n", + " trafo_snubber_cap_mv_side,\n", + " load_res,\n", + " ],\n", + ")\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('itrafo', 'i_intf', trafo_ind)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"v2\", \"v\", n2)\n", + "logger.log_attribute(\"itrafo\", \"i_intf\", trafo_ind)\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", "sim.set_system(sys)\n", @@ -259,8 +304,8 @@ "source": [ "time_step = 0.00005\n", "final_time = 1\n", - "sim_name = 'DP_Trafo_Component'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"DP_Trafo_Component\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "voltage_hv_side = 100000\n", "voltage_mv_side = 10000\n", @@ -270,29 +315,38 @@ "ratio = voltage_hv_side / voltage_mv_side\n", "load_resistance_mv_side = load_resistance_hv_side / ratio**2\n", "\n", - "n1 = dpsimpy.dp.SimNode('n1')\n", - "n2 = dpsimpy.dp.SimNode('n2')\n", + "n1 = dpsimpy.dp.SimNode(\"n1\")\n", + "n2 = dpsimpy.dp.SimNode(\"n2\")\n", "gnd = dpsimpy.dp.SimNode.gnd\n", "\n", - "vs = dpsimpy.dp.ph1.VoltageSource('v_1', dpsimpy.LogLevel.debug)\n", - "trafo = dpsimpy.dp.ph1.Transformer('trafo', 'trafo', dpsimpy.LogLevel.debug, with_resistive_losses=True)\n", - "load_res = dpsimpy.dp.ph1.Resistor('r_1', dpsimpy.LogLevel.debug)\n", + "vs = dpsimpy.dp.ph1.VoltageSource(\"v_1\", dpsimpy.LogLevel.debug)\n", + "trafo = dpsimpy.dp.ph1.Transformer(\n", + " \"trafo\", \"trafo\", dpsimpy.LogLevel.debug, with_resistive_losses=True\n", + ")\n", + "load_res = dpsimpy.dp.ph1.Resistor(\"r_1\", dpsimpy.LogLevel.debug)\n", "\n", "vs.connect([gnd, n1])\n", "trafo.connect([n1, n2])\n", "load_res.connect([n2, gnd])\n", "\n", "vs.set_parameters(complex(voltage_hv_side, 0))\n", - "trafo.set_parameters(voltage_hv_side, voltage_mv_side, trafo_power, ratio, 0,\n", - " trafo_resistance, trafo_inductance)\n", + "trafo.set_parameters(\n", + " voltage_hv_side,\n", + " voltage_mv_side,\n", + " trafo_power,\n", + " ratio,\n", + " 0,\n", + " trafo_resistance,\n", + " trafo_inductance,\n", + ")\n", "load_res.set_parameters(load_resistance_mv_side)\n", "\n", "sys = dpsimpy.SystemTopology(50, [n1, n2], [vs, trafo, load_res])\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('itrafo', 'i_intf', trafo)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"v2\", \"v\", n2)\n", + "logger.log_attribute(\"itrafo\", \"i_intf\", trafo)\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", "sim.set_system(sys)\n", @@ -319,10 +373,10 @@ "source": [ "time_step = 0.00005\n", "final_time = 1\n", - "sim_name = 'EMT_Trafo_Elements'\n", + "sim_name = \"EMT_Trafo_Elements\"\n", "frequency = 50\n", "omega = 2 * np.pi * frequency\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "voltage_hv_side = 100000\n", "voltage_mv_side = 10000\n", @@ -333,23 +387,29 @@ "q_snub = dpsimpy.Q_SNUB_TRANSFORMER * trafo_power\n", "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", - "snubber_resistance_hv_side = np.abs(voltage_hv_side)**2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side)**2 / p_snub\n", - "snubber_capacitance_mv_side_to_hv_side = 1/(omega * ratio**2 * np.abs(voltage_mv_side)**2 / q_snub) \n", + "snubber_resistance_hv_side = np.abs(voltage_hv_side) ** 2 / p_snub\n", + "snubber_resistance_mv_side_to_hv_side = (\n", + " ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", + ")\n", + "snubber_capacitance_mv_side_to_hv_side = 1 / (\n", + " omega * ratio**2 * np.abs(voltage_mv_side) ** 2 / q_snub\n", + ")\n", "\n", "\n", - "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", - "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", - "vn1 = dpsimpy.emt.SimNode('vn1', dpsimpy.PhaseType.ABC)\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.ABC)\n", + "n2 = dpsimpy.emt.SimNode(\"n2\", dpsimpy.PhaseType.ABC)\n", + "vn1 = dpsimpy.emt.SimNode(\"vn1\", dpsimpy.PhaseType.ABC)\n", "gnd = dpsimpy.emt.SimNode.gnd\n", "\n", - "vs = dpsimpy.emt.ph3.VoltageSource('v_1')\n", - "trafo_res = dpsimpy.emt.ph3.Resistor('trafo_res')\n", - "trafo_snubber_res_hv_side = dpsimpy.emt.ph3.Resistor('trafo_snub_res_mv') ##FIXME: Is the naming correct here?\n", - "trafo_snubber_res_mv_side = dpsimpy.emt.ph3.Resistor('trafo_snub_res_hv')\n", - "trafo_snubber_cap_mv_side = dpsimpy.emt.ph3.Capacitor('trafo_snub_cap_mv')\n", - "trafo_ind = dpsimpy.emt.ph3.Inductor('trafo_ind')\n", - "load_res = dpsimpy.emt.ph3.Resistor('r_1')\n", + "vs = dpsimpy.emt.ph3.VoltageSource(\"v_1\")\n", + "trafo_res = dpsimpy.emt.ph3.Resistor(\"trafo_res\")\n", + "trafo_snubber_res_hv_side = dpsimpy.emt.ph3.Resistor(\n", + " \"trafo_snub_res_mv\"\n", + ") ##FIXME: Is the naming correct here?\n", + "trafo_snubber_res_mv_side = dpsimpy.emt.ph3.Resistor(\"trafo_snub_res_hv\")\n", + "trafo_snubber_cap_mv_side = dpsimpy.emt.ph3.Capacitor(\"trafo_snub_cap_mv\")\n", + "trafo_ind = dpsimpy.emt.ph3.Inductor(\"trafo_ind\")\n", + "load_res = dpsimpy.emt.ph3.Resistor(\"r_1\")\n", "\n", "vs.connect([gnd, n1])\n", "trafo_res.connect([n1, vn1])\n", @@ -359,20 +419,50 @@ "trafo_snubber_cap_mv_side.connect([n2, gnd])\n", "load_res.connect([n2, gnd])\n", "\n", - "vs.set_parameters(dpsimpy.Math.single_phase_variable_to_three_phase(complex(voltage_hv_side, 0)), 50)\n", - "trafo_res.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_resistance))\n", - "trafo_ind.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_inductance))\n", - "trafo_snubber_res_hv_side.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(snubber_resistance_hv_side))\n", - "trafo_snubber_res_mv_side.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(snubber_resistance_mv_side_to_hv_side))\n", - "trafo_snubber_cap_mv_side.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(snubber_capacitance_mv_side_to_hv_side))\n", - "load_res.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(load_resistance_hv_side))\n", + "vs.set_parameters(\n", + " dpsimpy.Math.single_phase_variable_to_three_phase(complex(voltage_hv_side, 0)), 50\n", + ")\n", + "trafo_res.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_resistance)\n", + ")\n", + "trafo_ind.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_inductance)\n", + ")\n", + "trafo_snubber_res_hv_side.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(snubber_resistance_hv_side)\n", + ")\n", + "trafo_snubber_res_mv_side.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(\n", + " snubber_resistance_mv_side_to_hv_side\n", + " )\n", + ")\n", + "trafo_snubber_cap_mv_side.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(\n", + " snubber_capacitance_mv_side_to_hv_side\n", + " )\n", + ")\n", + "load_res.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(load_resistance_hv_side)\n", + ")\n", "\n", - "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, trafo_snubber_res_hv_side, trafo_snubber_res_mv_side, trafo_snubber_cap_mv_side, load_res])\n", + "sys = dpsimpy.SystemTopology(\n", + " 50,\n", + " [n1, n2, vn1],\n", + " [\n", + " vs,\n", + " trafo_res,\n", + " trafo_ind,\n", + " trafo_snubber_res_hv_side,\n", + " trafo_snubber_res_mv_side,\n", + " trafo_snubber_cap_mv_side,\n", + " load_res,\n", + " ],\n", + ")\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('itrafo', 'i_intf', trafo_ind)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"v2\", \"v\", n2)\n", + "logger.log_attribute(\"itrafo\", \"i_intf\", trafo_ind)\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", "sim.set_system(sys)\n", @@ -399,8 +489,8 @@ "source": [ "time_step = 0.00005\n", "final_time = 1\n", - "sim_name = 'EMT_Trafo_Component'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"EMT_Trafo_Component\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", "voltage_hv_side = 100000\n", "voltage_mv_side = 10000\n", @@ -410,30 +500,42 @@ "ratio = voltage_hv_side / voltage_mv_side\n", "load_resistance_mv_side = load_resistance_hv_side / ratio**2\n", "\n", - "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", - "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.ABC)\n", + "n2 = dpsimpy.emt.SimNode(\"n2\", dpsimpy.PhaseType.ABC)\n", "gnd = dpsimpy.emt.SimNode.gnd\n", "\n", - "vs = dpsimpy.emt.ph3.VoltageSource('v_1', dpsimpy.LogLevel.debug)\n", - "trafo = dpsimpy.emt.ph3.Transformer('trafo', 'trafo', dpsimpy.LogLevel.debug, with_resistive_losses=True)\n", - "load_res = dpsimpy.emt.ph3.Resistor('r_1', dpsimpy.LogLevel.debug)\n", + "vs = dpsimpy.emt.ph3.VoltageSource(\"v_1\", dpsimpy.LogLevel.debug)\n", + "trafo = dpsimpy.emt.ph3.Transformer(\n", + " \"trafo\", \"trafo\", dpsimpy.LogLevel.debug, with_resistive_losses=True\n", + ")\n", + "load_res = dpsimpy.emt.ph3.Resistor(\"r_1\", dpsimpy.LogLevel.debug)\n", "\n", "vs.connect([gnd, n1])\n", "trafo.connect([n1, n2])\n", "load_res.connect([n2, gnd])\n", "\n", - "vs.set_parameters(dpsimpy.Math.single_phase_variable_to_three_phase(complex(voltage_hv_side, 0)), 50)\n", - "trafo.set_parameters(voltage_hv_side, voltage_mv_side, trafo_power, ratio, 0,\n", + "vs.set_parameters(\n", + " dpsimpy.Math.single_phase_variable_to_three_phase(complex(voltage_hv_side, 0)), 50\n", + ")\n", + "trafo.set_parameters(\n", + " voltage_hv_side,\n", + " voltage_mv_side,\n", + " trafo_power,\n", + " ratio,\n", + " 0,\n", " dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_resistance),\n", - " dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_inductance))\n", - "load_res.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(load_resistance_mv_side))\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_inductance),\n", + ")\n", + "load_res.set_parameters(\n", + " dpsimpy.Math.single_phase_parameter_to_three_phase(load_resistance_mv_side)\n", + ")\n", "\n", "sys = dpsimpy.SystemTopology(50, [n1, n2], [vs, trafo, load_res])\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('itrafo', 'i_intf', trafo)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"v2\", \"v\", n2)\n", + "logger.log_attribute(\"itrafo\", \"i_intf\", trafo)\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", "sim.set_system(sys)\n", @@ -451,10 +553,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/SP_Trafo_Elements/'\n", - "log_name = 'SP_Trafo_Elements'\n", - "print(work_dir + log_name + '.csv')\n", - "trafo_elements = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/SP_Trafo_Elements/\"\n", + "log_name = \"SP_Trafo_Elements\"\n", + "print(work_dir + log_name + \".csv\")\n", + "trafo_elements = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "trafo_elements_sp_shifted = ts.frequency_shift_list(trafo_elements, 50)" ] }, @@ -465,7 +567,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_elements_sp_shifted['v1_shift'].time, trafo_elements_sp_shifted['v1_shift'].values, label='v1_shift')\n", + "plt.plot(\n", + " trafo_elements_sp_shifted[\"v1_shift\"].time,\n", + " trafo_elements_sp_shifted[\"v1_shift\"].values,\n", + " label=\"v1_shift\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -477,7 +583,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_elements_sp_shifted['itrafo_shift'].time, trafo_elements_sp_shifted['itrafo_shift'].values, label='itrafo_shift')\n", + "plt.plot(\n", + " trafo_elements_sp_shifted[\"itrafo_shift\"].time,\n", + " trafo_elements_sp_shifted[\"itrafo_shift\"].values,\n", + " label=\"itrafo_shift\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -495,10 +605,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/SP_Trafo_Component/'\n", - "log_name = 'SP_Trafo_Component'\n", - "print(work_dir + log_name + '.csv')\n", - "trafo_component = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/SP_Trafo_Component/\"\n", + "log_name = \"SP_Trafo_Component\"\n", + "print(work_dir + log_name + \".csv\")\n", + "trafo_component = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "trafo_component_sp_shifted = ts.frequency_shift_list(trafo_component, 50)" ] }, @@ -509,7 +619,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_component_sp_shifted['v1_shift'].time, trafo_component_sp_shifted['v1_shift'].values, label='v1_shift')\n", + "plt.plot(\n", + " trafo_component_sp_shifted[\"v1_shift\"].time,\n", + " trafo_component_sp_shifted[\"v1_shift\"].values,\n", + " label=\"v1_shift\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -521,7 +635,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_component_sp_shifted['itrafo_shift'].time, trafo_component_sp_shifted['itrafo_shift'].values, label='itrafo_shift')\n", + "plt.plot(\n", + " trafo_component_sp_shifted[\"itrafo_shift\"].time,\n", + " trafo_component_sp_shifted[\"itrafo_shift\"].values,\n", + " label=\"itrafo_shift\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -540,8 +658,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in ['v1_shift', 'itrafo_shift']:\n", - " plt.plot(trafo_elements_sp_shifted[name].time, trafo_elements_sp_shifted[name].values - trafo_component_sp_shifted[name].values, label=name+'_error')\n", + "for name in [\"v1_shift\", \"itrafo_shift\"]:\n", + " plt.plot(\n", + " trafo_elements_sp_shifted[name].time,\n", + " trafo_elements_sp_shifted[name].values\n", + " - trafo_component_sp_shifted[name].values,\n", + " label=name + \"_error\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -560,9 +683,14 @@ "outputs": [], "source": [ "errors_sp_shifted = []\n", - "for name in ['v1_shift', 'itrafo_shift']:\n", - " errors_sp_shifted.append(np.absolute(trafo_elements_sp_shifted[name].values - trafo_component_sp_shifted[name].values).max())\n", - " print(name + ': ' + str(errors_sp_shifted[-1]))\n", + "for name in [\"v1_shift\", \"itrafo_shift\"]:\n", + " errors_sp_shifted.append(\n", + " np.absolute(\n", + " trafo_elements_sp_shifted[name].values\n", + " - trafo_component_sp_shifted[name].values\n", + " ).max()\n", + " )\n", + " print(name + \": \" + str(errors_sp_shifted[-1]))\n", "assert np.max(errors_sp_shifted) < epsilon" ] }, @@ -579,10 +707,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/DP_Trafo_Elements/'\n", - "log_name = 'DP_Trafo_Elements'\n", - "print(work_dir + log_name + '.csv')\n", - "trafo_elements = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/DP_Trafo_Elements/\"\n", + "log_name = \"DP_Trafo_Elements\"\n", + "print(work_dir + log_name + \".csv\")\n", + "trafo_elements = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "trafo_elements_dp_shifted = ts.frequency_shift_list(trafo_elements, 50)" ] }, @@ -593,7 +721,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_elements_dp_shifted['v1_shift'].time, trafo_elements_dp_shifted['v1_shift'].values, label='v1_shift')\n", + "plt.plot(\n", + " trafo_elements_dp_shifted[\"v1_shift\"].time,\n", + " trafo_elements_dp_shifted[\"v1_shift\"].values,\n", + " label=\"v1_shift\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -605,7 +737,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_elements_dp_shifted['itrafo_shift'].time, trafo_elements_dp_shifted['itrafo_shift'].values, label='itrafo_shift')\n", + "plt.plot(\n", + " trafo_elements_dp_shifted[\"itrafo_shift\"].time,\n", + " trafo_elements_dp_shifted[\"itrafo_shift\"].values,\n", + " label=\"itrafo_shift\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -623,10 +759,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/DP_Trafo_Component/'\n", - "log_name = 'DP_Trafo_Component'\n", - "print(work_dir + log_name + '.csv')\n", - "trafo_component = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"logs/DP_Trafo_Component/\"\n", + "log_name = \"DP_Trafo_Component\"\n", + "print(work_dir + log_name + \".csv\")\n", + "trafo_component = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "trafo_component_dp_shifted = ts.frequency_shift_list(trafo_component, 50)" ] }, @@ -637,7 +773,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_component_dp_shifted['v1_shift'].time, trafo_component_dp_shifted['v1_shift'].values, label='v1_shift')\n", + "plt.plot(\n", + " trafo_component_dp_shifted[\"v1_shift\"].time,\n", + " trafo_component_dp_shifted[\"v1_shift\"].values,\n", + " label=\"v1_shift\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -649,7 +789,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_component_dp_shifted['itrafo_shift'].time, trafo_component_dp_shifted['itrafo_shift'].values, label='itrafo_shift')\n", + "plt.plot(\n", + " trafo_component_dp_shifted[\"itrafo_shift\"].time,\n", + " trafo_component_dp_shifted[\"itrafo_shift\"].values,\n", + " label=\"itrafo_shift\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -668,8 +812,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in ['v1_shift', 'itrafo_shift']:\n", - " plt.plot(trafo_elements_dp_shifted[name].time, trafo_elements_dp_shifted[name].values - trafo_component_dp_shifted[name].values, label=name+'_error')\n", + "for name in [\"v1_shift\", \"itrafo_shift\"]:\n", + " plt.plot(\n", + " trafo_elements_dp_shifted[name].time,\n", + " trafo_elements_dp_shifted[name].values\n", + " - trafo_component_dp_shifted[name].values,\n", + " label=name + \"_error\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -688,9 +837,14 @@ "outputs": [], "source": [ "errors_dp_shifted = []\n", - "for name in ['v1_shift', 'itrafo_shift']:\n", - " errors_dp_shifted.append(np.absolute(trafo_elements_dp_shifted[name].values - trafo_component_dp_shifted[name].values).max())\n", - " print(name + ': ' + str(errors_dp_shifted[-1]))\n", + "for name in [\"v1_shift\", \"itrafo_shift\"]:\n", + " errors_dp_shifted.append(\n", + " np.absolute(\n", + " trafo_elements_dp_shifted[name].values\n", + " - trafo_component_dp_shifted[name].values\n", + " ).max()\n", + " )\n", + " print(name + \": \" + str(errors_dp_shifted[-1]))\n", "assert np.max(errors_dp_shifted) < epsilon" ] }, @@ -707,10 +861,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/EMT_Trafo_Elements/'\n", - "log_name = 'EMT_Trafo_Elements'\n", - "print(work_dir + log_name + '.csv')\n", - "trafo_elements_emt = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/EMT_Trafo_Elements/\"\n", + "log_name = \"EMT_Trafo_Elements\"\n", + "print(work_dir + log_name + \".csv\")\n", + "trafo_elements_emt = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -720,7 +874,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_elements_emt['v1_0'].time, PEAK1PH_TO_RMS3PH*trafo_elements_emt['v1_0'].values, label='v1_0')\n", + "plt.plot(\n", + " trafo_elements_emt[\"v1_0\"].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_elements_emt[\"v1_0\"].values,\n", + " label=\"v1_0\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -732,7 +890,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_elements_emt['itrafo_0'].time, PEAK1PH_TO_RMS3PH*trafo_elements_emt['itrafo_0'].values, label='itrafo_0')\n", + "plt.plot(\n", + " trafo_elements_emt[\"itrafo_0\"].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_elements_emt[\"itrafo_0\"].values,\n", + " label=\"itrafo_0\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -750,10 +912,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/EMT_Trafo_Component/'\n", - "log_name = 'EMT_Trafo_Component'\n", - "print(work_dir + log_name + '.csv')\n", - "trafo_component_emt = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/EMT_Trafo_Component/\"\n", + "log_name = \"EMT_Trafo_Component\"\n", + "print(work_dir + log_name + \".csv\")\n", + "trafo_component_emt = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -763,9 +925,21 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_component_emt['v1_0'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_0'].values, label='v1_0')\n", - "plt.plot(trafo_component_emt['v1_1'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_1'].values, label='v1_1')\n", - "plt.plot(trafo_component_emt['v1_2'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_2'].values, label='v1_2')\n", + "plt.plot(\n", + " trafo_component_emt[\"v1_0\"].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[\"v1_0\"].values,\n", + " label=\"v1_0\",\n", + ")\n", + "plt.plot(\n", + " trafo_component_emt[\"v1_1\"].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[\"v1_1\"].values,\n", + " label=\"v1_1\",\n", + ")\n", + "plt.plot(\n", + " trafo_component_emt[\"v1_2\"].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[\"v1_2\"].values,\n", + " label=\"v1_2\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -777,9 +951,21 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_component_emt['itrafo_0'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_0'].values, label='itrafo_0')\n", - "plt.plot(trafo_component_emt['itrafo_1'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_1'].values, label='itrafo_1')\n", - "plt.plot(trafo_component_emt['itrafo_2'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_2'].values, label='itrafo_2')\n", + "plt.plot(\n", + " trafo_component_emt[\"itrafo_0\"].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[\"itrafo_0\"].values,\n", + " label=\"itrafo_0\",\n", + ")\n", + "plt.plot(\n", + " trafo_component_emt[\"itrafo_1\"].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[\"itrafo_1\"].values,\n", + " label=\"itrafo_1\",\n", + ")\n", + "plt.plot(\n", + " trafo_component_emt[\"itrafo_2\"].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[\"itrafo_2\"].values,\n", + " label=\"itrafo_2\",\n", + ")\n", "plt.legend()\n", "plt.show()" ] @@ -798,8 +984,12 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in ['v1_0', 'v1_1', 'v1_1', 'itrafo_0', 'itrafo_1', 'itrafo_2']:\n", - " plt.plot(trafo_elements_emt[name].time, trafo_elements_emt[name].values - trafo_component_emt[name].values, label=name+'_error')\n", + "for name in [\"v1_0\", \"v1_1\", \"v1_1\", \"itrafo_0\", \"itrafo_1\", \"itrafo_2\"]:\n", + " plt.plot(\n", + " trafo_elements_emt[name].time,\n", + " trafo_elements_emt[name].values - trafo_component_emt[name].values,\n", + " label=name + \"_error\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -818,9 +1008,13 @@ "outputs": [], "source": [ "errors_emt = []\n", - "for name in ['v1_0', 'v1_1', 'v1_1', 'itrafo_0', 'itrafo_1', 'itrafo_2']:\n", - " errors_emt.append(np.absolute(trafo_elements_emt[name].values - trafo_component_emt[name].values).max())\n", - " print(name + ': ' + str(errors_emt[-1]))\n", + "for name in [\"v1_0\", \"v1_1\", \"v1_1\", \"itrafo_0\", \"itrafo_1\", \"itrafo_2\"]:\n", + " errors_emt.append(\n", + " np.absolute(\n", + " trafo_elements_emt[name].values - trafo_component_emt[name].values\n", + " ).max()\n", + " )\n", + " print(name + \": \" + str(errors_emt[-1]))\n", "assert np.max(errors_emt) < epsilon" ] }, @@ -838,8 +1032,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in [('v1_shift', 'v1_shift')]:\n", - " plt.plot(trafo_component_sp_shifted[name[0]].time, trafo_component_sp_shifted[name[0]].values - trafo_component_dp_shifted[name[1]].values, label=name[0]+' (SP) vs. '+name[1]+' (DP)')\n", + "for name in [(\"v1_shift\", \"v1_shift\")]:\n", + " plt.plot(\n", + " trafo_component_sp_shifted[name[0]].time,\n", + " trafo_component_sp_shifted[name[0]].values\n", + " - trafo_component_dp_shifted[name[1]].values,\n", + " label=name[0] + \" (SP) vs. \" + name[1] + \" (DP)\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -851,8 +1050,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in [('itrafo_shift', 'itrafo_shift')]:\n", - " plt.plot(trafo_component_sp_shifted[name[0]].time, trafo_component_sp_shifted[name[0]].values - trafo_component_dp_shifted[name[1]].values, label=name[0]+' (SP) vs. '+name[1]+' (DP)')\n", + "for name in [(\"itrafo_shift\", \"itrafo_shift\")]:\n", + " plt.plot(\n", + " trafo_component_sp_shifted[name[0]].time,\n", + " trafo_component_sp_shifted[name[0]].values\n", + " - trafo_component_dp_shifted[name[1]].values,\n", + " label=name[0] + \" (SP) vs. \" + name[1] + \" (DP)\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -872,12 +1076,23 @@ "source": [ "compare_errors_abs = []\n", "compare_errors_rel = []\n", - "for name in [('v1_shift', 'v1_shift'), ('itrafo_shift', 'itrafo_shift')]:\n", - " compare_errors_abs.append(np.absolute(trafo_component_sp_shifted[name[0]].values - trafo_component_dp_shifted[name[1]].values).max())\n", - " compare_errors_rel.append(np.absolute(trafo_component_sp_shifted[name[0]].values - trafo_component_dp_shifted[name[1]].values).max()/trafo_component_dp_shifted[name[1]].values.max())\n", - " print(name[0]+' vs. '+name[1] + ' (abs): ' + str(compare_errors_abs[-1]))\n", - " print(name[0]+' vs. '+name[1] + ' (rel): ' + str(compare_errors_rel[-1]))\n", - "print('Max rel error: '+ '{:.2}'.format(np.max(compare_errors_rel)*100) +'%')\n", + "for name in [(\"v1_shift\", \"v1_shift\"), (\"itrafo_shift\", \"itrafo_shift\")]:\n", + " compare_errors_abs.append(\n", + " np.absolute(\n", + " trafo_component_sp_shifted[name[0]].values\n", + " - trafo_component_dp_shifted[name[1]].values\n", + " ).max()\n", + " )\n", + " compare_errors_rel.append(\n", + " np.absolute(\n", + " trafo_component_sp_shifted[name[0]].values\n", + " - trafo_component_dp_shifted[name[1]].values\n", + " ).max()\n", + " / trafo_component_dp_shifted[name[1]].values.max()\n", + " )\n", + " print(name[0] + \" vs. \" + name[1] + \" (abs): \" + str(compare_errors_abs[-1]))\n", + " print(name[0] + \" vs. \" + name[1] + \" (rel): \" + str(compare_errors_rel[-1]))\n", + "print(\"Max rel error: \" + \"{:.2}\".format(np.max(compare_errors_rel) * 100) + \"%\")\n", "assert np.max(compare_errors_rel) < 3e-1" ] }, @@ -895,8 +1110,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in [('v1_0', 'v1_shift')]:\n", - " plt.plot(trafo_component_emt[name[0]].time, PEAK1PH_TO_RMS3PH*trafo_component_emt[name[0]].values - trafo_component_dp_shifted[name[1]].values, label=name[0]+' vs. '+name[1])\n", + "for name in [(\"v1_0\", \"v1_shift\")]:\n", + " plt.plot(\n", + " trafo_component_emt[name[0]].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[name[0]].values\n", + " - trafo_component_dp_shifted[name[1]].values,\n", + " label=name[0] + \" vs. \" + name[1],\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -908,8 +1128,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in [('itrafo_0', 'itrafo_shift')]:\n", - " plt.plot(trafo_component_emt[name[0]].time, PEAK1PH_TO_RMS3PH*trafo_component_emt[name[0]].values - trafo_component_dp_shifted[name[1]].values, label=name[0]+' vs. '+name[1])\n", + "for name in [(\"itrafo_0\", \"itrafo_shift\")]:\n", + " plt.plot(\n", + " trafo_component_emt[name[0]].time,\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[name[0]].values\n", + " - trafo_component_dp_shifted[name[1]].values,\n", + " label=name[0] + \" vs. \" + name[1],\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -929,12 +1154,23 @@ "source": [ "compare_errors_abs = []\n", "compare_errors_rel = []\n", - "for name in [('v1_0', 'v1_shift'), ('itrafo_0', 'itrafo_shift')]:\n", - " compare_errors_abs.append(np.absolute(PEAK1PH_TO_RMS3PH*trafo_component_emt[name[0]].values - trafo_component_dp_shifted[name[1]].values).max())\n", - " compare_errors_rel.append(np.absolute(PEAK1PH_TO_RMS3PH*trafo_component_emt[name[0]].values - trafo_component_dp_shifted[name[1]].values).max()/trafo_component_dp_shifted[name[1]].values.max())\n", - " print(name[0]+' vs. '+name[1] + ' (abs): ' + str(compare_errors_abs[-1]))\n", - " print(name[0]+' vs. '+name[1] + ' (rel): ' + str(compare_errors_rel[-1]))\n", - "print('Max rel error: '+ '{:.2}'.format(np.max(compare_errors_rel)*100) +'%')\n", + "for name in [(\"v1_0\", \"v1_shift\"), (\"itrafo_0\", \"itrafo_shift\")]:\n", + " compare_errors_abs.append(\n", + " np.absolute(\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[name[0]].values\n", + " - trafo_component_dp_shifted[name[1]].values\n", + " ).max()\n", + " )\n", + " compare_errors_rel.append(\n", + " np.absolute(\n", + " PEAK1PH_TO_RMS3PH * trafo_component_emt[name[0]].values\n", + " - trafo_component_dp_shifted[name[1]].values\n", + " ).max()\n", + " / trafo_component_dp_shifted[name[1]].values.max()\n", + " )\n", + " print(name[0] + \" vs. \" + name[1] + \" (abs): \" + str(compare_errors_abs[-1]))\n", + " print(name[0] + \" vs. \" + name[1] + \" (rel): \" + str(compare_errors_rel[-1]))\n", + "print(\"Max rel error: \" + \"{:.2}\".format(np.max(compare_errors_rel) * 100) + \"%\")\n", "assert np.max(compare_errors_rel) < 1e-4" ] } diff --git a/examples/Notebooks/Features/AsynchronousIO.ipynb b/examples/Notebooks/Features/AsynchronousIO.ipynb index 3fa5bca8b6..ea200e7f75 100644 --- a/examples/Notebooks/Features/AsynchronousIO.ipynb +++ b/examples/Notebooks/Features/AsynchronousIO.ipynb @@ -46,7 +46,7 @@ "n1 = dpsim.dp.Node(\"n1\")\n", "\n", "# Components\n", - "v1 = dpsim.dp.ph1.VoltageSource(\"v_1\", [gnd, n1], V_ref=complex(345,0))\n", + "v1 = dpsim.dp.ph1.VoltageSource(\"v_1\", [gnd, n1], V_ref=complex(345, 0))\n", "\n", "sys = dpsim.SystemTopology(50, [gnd, n1], [v1])" ] @@ -67,16 +67,18 @@ "source": [ "sims = []\n", "for i in range(1, 4):\n", - " sim = dpsim.RealTimeSimulation(\"async_demo_%d\" % i, sys, timestep=i*1e-3, duration=3*i+5, pbar=True)\n", + " sim = dpsim.RealTimeSimulation(\n", + " \"async_demo_%d\" % i, sys, timestep=i * 1e-3, duration=3 * i + 5, pbar=True\n", + " )\n", " sim.start()\n", - " \n", + "\n", " sims += [sim]\n", "\n", "for i in range(1, 6):\n", " print(\"Doing something different: %d\" % i)\n", " await asyncio.sleep(1)\n", - " \n", - "_ = await asyncio.wait([ s.wait(Event.done) for s in sims ])" + "\n", + "_ = await asyncio.wait([s.wait(Event.done) for s in sims])" ] } ], diff --git a/examples/Notebooks/Features/Graphviz.ipynb b/examples/Notebooks/Features/Graphviz.ipynb index ba068be3e3..1a15617761 100644 --- a/examples/Notebooks/Features/Graphviz.ipynb +++ b/examples/Notebooks/Features/Graphviz.ipynb @@ -48,18 +48,18 @@ "source": [ "# Nodes\n", "gnd = dpsim.dp.Node.GND()\n", - "n1 = dpsim.dp.Node(\"n1\")\n", - "n2 = dpsim.dp.Node(\"n2\")\n", - "n3 = dpsim.dp.Node(\"n3\")\n", - "n4 = dpsim.dp.Node(\"n4\")\n", + "n1 = dpsim.dp.Node(\"n1\")\n", + "n2 = dpsim.dp.Node(\"n2\")\n", + "n3 = dpsim.dp.Node(\"n3\")\n", + "n4 = dpsim.dp.Node(\"n4\")\n", "\n", "# Components\n", - "v1 = dpsim.dp.ph1.VoltageSource(\"v_1\", [gnd, n1], V_ref=complex(345,0))\n", - "r1 = dpsim.dp.ph1.Resistor(\"r1\", [n1, n2], R=5)\n", - "c1 = dpsim.dp.ph1.Capacitor(\"c_1\", [n2, gnd], C=0.002)\n", + "v1 = dpsim.dp.ph1.VoltageSource(\"v_1\", [gnd, n1], V_ref=complex(345, 0))\n", + "r1 = dpsim.dp.ph1.Resistor(\"r1\", [n1, n2], R=5)\n", + "c1 = dpsim.dp.ph1.Capacitor(\"c_1\", [n2, gnd], C=0.002)\n", "rL1 = dpsim.dp.ph1.Resistor(\"r_load1\", [n2, n4], R=6.4)\n", - "l1 = dpsim.dp.ph1.Inductor(\"l_1\", [n4, n3], L=0.186)\n", - "c2 = dpsim.dp.ph1.Capacitor(\"c_2\", [n3, gnd], C=0.002)\n", + "l1 = dpsim.dp.ph1.Inductor(\"l_1\", [n4, n3], L=0.186)\n", + "c2 = dpsim.dp.ph1.Capacitor(\"c_2\", [n3, gnd], C=0.002)\n", "rL2 = dpsim.dp.ph1.Resistor(\"r_load2\", [n3, gnd], R=150)\n", "\n", "sys = dpsim.SystemTopology(50, [gnd, n1, n2, n3, n4], [v1, r1, c1, rL1, l1, c2, rL2])" @@ -79,7 +79,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim = dpsim.Simulation('IdealVS_PiLine_RLC_1', sys, duration=20, timestep=0.0005)\n", + "sim = dpsim.Simulation(\"IdealVS_PiLine_RLC_1\", sys, duration=20, timestep=0.0005)\n", "await sim.simulate()" ] }, @@ -151,9 +151,9 @@ "from glob import glob\n", "\n", "# Adjust this path to the root of the DPsim repo\n", - "files = glob('../../CIM/WSCC-09_RX/*.xml')\n", + "files = glob(\"../../CIM/WSCC-09_RX/*.xml\")\n", "\n", - "dpsim.load_cim('WSCC_9bus', files)" + "dpsim.load_cim(\"WSCC_9bus\", files)" ] }, { diff --git a/examples/Notebooks/Features/Progressbars.ipynb b/examples/Notebooks/Features/Progressbars.ipynb index 41cddb9a27..ff762f6135 100644 --- a/examples/Notebooks/Features/Progressbars.ipynb +++ b/examples/Notebooks/Features/Progressbars.ipynb @@ -33,18 +33,18 @@ "\n", "# Nodes\n", "gnd = dpsim.dp.Node.GND()\n", - "n1 = dpsim.dp.Node(\"n1\")\n", - "n2 = dpsim.dp.Node(\"n2\")\n", - "n3 = dpsim.dp.Node(\"n3\")\n", - "n4 = dpsim.dp.Node(\"n4\")\n", + "n1 = dpsim.dp.Node(\"n1\")\n", + "n2 = dpsim.dp.Node(\"n2\")\n", + "n3 = dpsim.dp.Node(\"n3\")\n", + "n4 = dpsim.dp.Node(\"n4\")\n", "\n", "# Components\n", - "v1 = dpsim.dp.ph1.VoltageSource(\"v_1\", [gnd, n1], V_ref=complex(345,0))\n", - "r1 = dpsim.dp.ph1.Resistor(\"r1\", [n1, n2], R=5)\n", - "c1 = dpsim.dp.ph1.Capacitor(\"c_1\", [n2, gnd], C=0.002)\n", + "v1 = dpsim.dp.ph1.VoltageSource(\"v_1\", [gnd, n1], V_ref=complex(345, 0))\n", + "r1 = dpsim.dp.ph1.Resistor(\"r1\", [n1, n2], R=5)\n", + "c1 = dpsim.dp.ph1.Capacitor(\"c_1\", [n2, gnd], C=0.002)\n", "rL1 = dpsim.dp.ph1.Resistor(\"r_load1\", [n2, n4], R=6.4)\n", - "l1 = dpsim.dp.ph1.Inductor(\"l_1\", [n4, n3], L=0.186)\n", - "c2 = dpsim.dp.ph1.Capacitor(\"c_2\", [n3, gnd], C=0.002)\n", + "l1 = dpsim.dp.ph1.Inductor(\"l_1\", [n4, n3], L=0.186)\n", + "c2 = dpsim.dp.ph1.Capacitor(\"c_2\", [n3, gnd], C=0.002)\n", "rL2 = dpsim.dp.ph1.Resistor(\"r_load2\", [n3, gnd], R=150)\n", "\n", "sys = dpsim.SystemTopology(50, [gnd, n1, n2, n3, n4], [v1, r1, c1, rL1, l1, c2, rL2])\n", @@ -91,10 +91,12 @@ "source": [ "import asyncio\n", "\n", + "\n", "async def dummy():\n", - " for i in range(1,10):\n", + " for i in range(1, 10):\n", " await asyncio.sleep(1)\n", - " print('Doing something different:', i)\n", + " print(\"Doing something different:\", i)\n", + "\n", "\n", "sim2 = dpsim.Simulation(\"progress_demo2\", sys, duration=20, timestep=0.00005)\n", "sim2.show_progressbar()\n", diff --git a/examples/Notebooks/Features/Widgets.ipynb b/examples/Notebooks/Features/Widgets.ipynb index 406e292a88..8f4ad91ca3 100644 --- a/examples/Notebooks/Features/Widgets.ipynb +++ b/examples/Notebooks/Features/Widgets.ipynb @@ -45,8 +45,8 @@ "outputs": [], "source": [ "gnd = dpsim.dp.Node.GND()\n", - "n1 = dpsim.dp.Node(\"n1\")\n", - "n2 = dpsim.dp.Node(\"n2\")\n", + "n1 = dpsim.dp.Node(\"n1\")\n", + "n2 = dpsim.dp.Node(\"n2\")\n", "\n", "cs = dpsim.dp.ph1.CurrentSource(\"cs\", [gnd, n1])\n", "r1 = dpsim.dp.ph1.Resistor(\"r_1\", [n1, gnd])\n", @@ -56,12 +56,12 @@ "\n", "sys = dpsim.SystemTopology(50, [gnd, n1, n2], [cs, r1, c1, l1, r2])\n", "sim = dpsim.Simulation(\"Widgets\", sys, duration=0.1)\n", - " \n", + "\n", "logger = dpsim.Logger(\"Widgets\")\n", - "logger.log_attribute(n1, \"v\") # v1\n", - "logger.log_attribute(n2, \"v\") # v2\n", - "logger.log_attribute(cs, \"i_intf\") # i12\n", - "logger.log_attribute(c1, \"i_intf\") # i34\n", + "logger.log_attribute(n1, \"v\") # v1\n", + "logger.log_attribute(n2, \"v\") # v2\n", + "logger.log_attribute(cs, \"i_intf\") # i12\n", + "logger.log_attribute(c1, \"i_intf\") # i34\n", "sim.add_logger(logger)" ] }, @@ -81,7 +81,7 @@ "source": [ "def simulate(dt, dur, pha, mag, r1_val, r2_val, l_val, c_val):\n", " sim.reset()\n", - " \n", + "\n", " sim.timestep = dt\n", " sim.final_time = dur\n", " cs.I_ref = cmath.rect(mag, pha)\n", @@ -89,13 +89,13 @@ " c1.C = c_val\n", " l1.L = l_val * 1e-3\n", " r2.R = r2_val * 1e-3\n", - " \n", + "\n", " sim.start()\n", " while sim.state != 9:\n", " time.sleep(0.001)\n", - " \n", - " results = rt.read_timeseries_dpsim('logs/Widgets.csv')\n", - " for l in [ 'n1.v', 'n2.v', 'cs.i_intf', 'c_1.i_intf' ]:\n", + "\n", + " results = rt.read_timeseries_dpsim(\"logs/Widgets.csv\")\n", + " for l in [\"n1.v\", \"n2.v\", \"cs.i_intf\", \"c_1.i_intf\"]:\n", " emt = results[l].frequency_shift(50)\n", " pt.plot_timeseries(1, emt)" ] @@ -125,19 +125,32 @@ "from ipywidgets import interact, interactive, fixed, interact_manual\n", "import ipywidgets as widgets\n", "\n", - "output = interactive(simulate,\n", - " dt = widgets.FloatText(description=\"Timestep [s]\", value=1e-3, min=1e-3, max=1),\n", - " dur = widgets.FloatText(description=\"Duration [s]\", value=0.5, min=0.001, max=4),\n", - " pha = widgets.FloatSlider(description=\"Phase [rad]\", min=-math.pi, max=math.pi, continuous_update=cu),\n", - " mag = widgets.FloatSlider(description=\"Magnitude [V]\", value=10, min=0, max=100, continuous_update=cu),\n", - " r1_val = widgets.FloatSlider(description=\"Resistance [Ohm]\", value=1, min=0.1, max=10, continuous_update=cu),\n", - " r2_val = widgets.FloatSlider(description=\"Resistance [Ohm]\", value=1, min=0.1, max=10, continuous_update=cu),\n", - " l_val = widgets.FloatSlider(description=\"Inductance [H]\", value=1, min=1, max=10, continuous_update=cu),\n", - " c_val = widgets.FloatSlider(description=\"Capactance [F]\", value=1, min=1, max=10, continuous_update=cu)\n", + "output = interactive(\n", + " simulate,\n", + " dt=widgets.FloatText(description=\"Timestep [s]\", value=1e-3, min=1e-3, max=1),\n", + " dur=widgets.FloatText(description=\"Duration [s]\", value=0.5, min=0.001, max=4),\n", + " pha=widgets.FloatSlider(\n", + " description=\"Phase [rad]\", min=-math.pi, max=math.pi, continuous_update=cu\n", + " ),\n", + " mag=widgets.FloatSlider(\n", + " description=\"Magnitude [V]\", value=10, min=0, max=100, continuous_update=cu\n", + " ),\n", + " r1_val=widgets.FloatSlider(\n", + " description=\"Resistance [Ohm]\", value=1, min=0.1, max=10, continuous_update=cu\n", + " ),\n", + " r2_val=widgets.FloatSlider(\n", + " description=\"Resistance [Ohm]\", value=1, min=0.1, max=10, continuous_update=cu\n", + " ),\n", + " l_val=widgets.FloatSlider(\n", + " description=\"Inductance [H]\", value=1, min=1, max=10, continuous_update=cu\n", + " ),\n", + " c_val=widgets.FloatSlider(\n", + " description=\"Capactance [F]\", value=1, min=1, max=10, continuous_update=cu\n", + " ),\n", ")\n", "\n", "last = output.children[-1]\n", - "last.layout.height = '400px'\n", + "last.layout.height = \"400px\"\n", "output" ] }, diff --git a/examples/Notebooks/Grids/CIGRE_MV_pf-interactive-dpsimpy.ipynb b/examples/Notebooks/Grids/CIGRE_MV_pf-interactive-dpsimpy.ipynb index d57879f5d2..2d19b22812 100644 --- a/examples/Notebooks/Grids/CIGRE_MV_pf-interactive-dpsimpy.ipynb +++ b/examples/Notebooks/Grids/CIGRE_MV_pf-interactive-dpsimpy.ipynb @@ -23,18 +23,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/Rootnet_FULL_NE_06J16h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/Rootnet_FULL_NE_06J16h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -53,9 +55,11 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'CIGRE_MV'\n", + "name = \"CIGRE_MV\"\n", "reader = dpsimpy.CIMReader(name)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)" + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")" ] }, { @@ -64,7 +68,7 @@ "metadata": {}, "outputs": [], "source": [ - "#system.render_to_file('CIGRE_MV.svg')\n", + "# system.render_to_file('CIGRE_MV.svg')\n", "system" ] }, @@ -83,7 +87,7 @@ "\n", "logger = dpsimpy.Logger(name)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node)\n", + " logger.log_attribute(node.name() + \".V\", \"v\", node)\n", "sim.add_logger(logger)" ] }, @@ -111,7 +115,9 @@ "metadata": {}, "outputs": [], "source": [ - "sim.get_idobj_attr('LOAD-I-10', 'P_pu').get() # The get method provides a reference to the underlying value" + "sim.get_idobj_attr(\n", + " \"LOAD-I-10\", \"P_pu\"\n", + ").get() # The get method provides a reference to the underlying value" ] }, { @@ -120,7 +126,9 @@ "metadata": {}, "outputs": [], "source": [ - "sim.get_idobj_attr('N10', 'v') # This also works because the Attribute returned by get_idobj_attr is printable" + "sim.get_idobj_attr(\n", + " \"N10\", \"v\"\n", + ") # This also works because the Attribute returned by get_idobj_attr is printable" ] }, { @@ -129,7 +137,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim.get_idobj_attr('L1-2', 'i_intf')" + "sim.get_idobj_attr(\"L1-2\", \"i_intf\")" ] }, { @@ -138,7 +146,9 @@ "metadata": {}, "outputs": [], "source": [ - "sim.get_idobj_attr('LOAD-I-10', 'P_pu').set(0.00128) # Setting values can be done using an attribute's set function" + "sim.get_idobj_attr(\"LOAD-I-10\", \"P_pu\").set(\n", + " 0.00128\n", + ") # Setting values can be done using an attribute's set function" ] }, { diff --git a/examples/Notebooks/Grids/CIGRE_MV_powerflow-dpsimpy.ipynb b/examples/Notebooks/Grids/CIGRE_MV_powerflow-dpsimpy.ipynb index 8f24793c3f..c52f3986d8 100644 --- a/examples/Notebooks/Grids/CIGRE_MV_powerflow-dpsimpy.ipynb +++ b/examples/Notebooks/Grids/CIGRE_MV_powerflow-dpsimpy.ipynb @@ -23,18 +23,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/Rootnet_FULL_NE_06J16h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/Rootnet_FULL_NE_06J16h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -56,9 +58,11 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'CIGRE_MV'\n", + "name = \"CIGRE_MV\"\n", "reader = dpsimpy.CIMReader(name)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "system" ] }, @@ -75,7 +79,7 @@ "\n", "logger = dpsimpy.Logger(name)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node);\n", + " logger.log_attribute(node.name() + \".V\", \"v\", node)\n", "sim.add_logger(logger)" ] }, @@ -101,14 +105,14 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/'\n", - "logName = 'CIGRE_MV'\n", - "dpsim_result_file = path + logName + '.csv'\n", + "path = \"logs/\"\n", + "logName = \"CIGRE_MV\"\n", + "dpsim_result_file = path + logName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)\n", "\n", "# Fix for dpsim naming - TODO: unify dpsim notation in log file and update villas-dataprocessing accordingly\n", - "for ts,values in ts_dpsim.items():\n", + "for ts, values in ts_dpsim.items():\n", " values.name = values.name[:-2]" ] }, @@ -125,16 +129,16 @@ "metadata": {}, "outputs": [], "source": [ - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Neplan/ReferenceGrids/CIGRE_MV.rlf'\n", - "neplan_result_file = 'reference-results/CIGRE_MV.rlf'\n", - "urllib.request.urlretrieve(url, neplan_result_file) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Neplan/ReferenceGrids/CIGRE_MV.rlf\"\n", + "neplan_result_file = \"reference-results/CIGRE_MV.rlf\"\n", + "urllib.request.urlretrieve(url, neplan_result_file)\n", "print(neplan_result_file)\n", "\n", "ts_NEPLAN = read_timeseries_NEPLAN_loadflow(neplan_result_file)\n", - "#print([ts_NEPLAN[i].name for i in range(len(ts_NEPLAN))])" + "# print([ts_NEPLAN[i].name for i in range(len(ts_NEPLAN))])" ] }, { @@ -150,15 +154,19 @@ "metadata": {}, "outputs": [], "source": [ - "net_name='CIGRE_MV_NoTap'\n", - "threshold=0.5\n", + "net_name = \"CIGRE_MV_NoTap\"\n", + "threshold = 0.5\n", "\n", - "ts_NEPLAN_standardized=validationtools.convert_neplan_to_standard_timeseries(ts_NEPLAN)\n", - "#print([ts_NEPLAN_standardized[i].name for i in range(len(ts_NEPLAN_standardized))])\n", - "ts_dpsim_standardized=validationtools.convert_dpsim_to_standard_timeseries(ts_dpsim)\n", - "#print([ts_dpsim_standardized[i].name for i in range(len(ts_dpsim_standardized))])\n", - "res_err=validationtools.compare_timeseries(ts_NEPLAN_standardized,ts_dpsim_standardized)\n", - "validationtools.assert_modelica_results(net_name,res_err,threshold)" + "ts_NEPLAN_standardized = validationtools.convert_neplan_to_standard_timeseries(\n", + " ts_NEPLAN\n", + ")\n", + "# print([ts_NEPLAN_standardized[i].name for i in range(len(ts_NEPLAN_standardized))])\n", + "ts_dpsim_standardized = validationtools.convert_dpsim_to_standard_timeseries(ts_dpsim)\n", + "# print([ts_dpsim_standardized[i].name for i in range(len(ts_dpsim_standardized))])\n", + "res_err = validationtools.compare_timeseries(\n", + " ts_NEPLAN_standardized, ts_dpsim_standardized\n", + ")\n", + "validationtools.assert_modelica_results(net_name, res_err, threshold)" ] } ], diff --git a/examples/Notebooks/Grids/CIGRE_MV_powerflow_profiles-dpsimpy.ipynb b/examples/Notebooks/Grids/CIGRE_MV_powerflow_profiles-dpsimpy.ipynb index 12f8040b25..913abd2db3 100644 --- a/examples/Notebooks/Grids/CIGRE_MV_powerflow_profiles-dpsimpy.ipynb +++ b/examples/Notebooks/Grids/CIGRE_MV_powerflow_profiles-dpsimpy.ipynb @@ -23,18 +23,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/Rootnet_FULL_NE_06J16h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/Rootnet_FULL_NE_06J16h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -46,13 +48,37 @@ "source": [ "import os\n", "\n", - "profiles = ['Load_H_1','Load_H_3','Load_H_4','Load_H_5','Load_H_6','Load_H_8','Load_H_10','Load_H_11','Load_H_12','Load_H_14','Load_I_1','Load_I_3','Load_I_7','Load_I_9','Load_I_10','Load_I_12','Load_I_13','Load_I_14']\n", + "profiles = [\n", + " \"Load_H_1\",\n", + " \"Load_H_3\",\n", + " \"Load_H_4\",\n", + " \"Load_H_5\",\n", + " \"Load_H_6\",\n", + " \"Load_H_8\",\n", + " \"Load_H_10\",\n", + " \"Load_H_11\",\n", + " \"Load_H_12\",\n", + " \"Load_H_14\",\n", + " \"Load_I_1\",\n", + " \"Load_I_3\",\n", + " \"Load_I_7\",\n", + " \"Load_I_9\",\n", + " \"Load_I_10\",\n", + " \"Load_I_12\",\n", + " \"Load_I_13\",\n", + " \"Load_I_14\",\n", + "]\n", "for profile in profiles:\n", - " filename = './profiles/'+profile+'.csv'\n", + " filename = \"./profiles/\" + profile + \".csv\"\n", " os.makedirs(os.path.dirname(filename), exist_ok=True)\n", - " download_grid_data(filename, 'https://raw.githubusercontent.com/dpsim-simulator/example-profile-data/master/CIGRE_MV_NoTap/load_profiles/'+profile+'.csv')\n", - " \n", - "profile_files = glob.glob('profiles/Load*.csv')\n", + " download_grid_data(\n", + " filename,\n", + " \"https://raw.githubusercontent.com/dpsim-simulator/example-profile-data/master/CIGRE_MV_NoTap/load_profiles/\"\n", + " + profile\n", + " + \".csv\",\n", + " )\n", + "\n", + "profile_files = glob.glob(\"profiles/Load*.csv\")\n", "print(profile_files)" ] }, @@ -64,7 +90,7 @@ "source": [ "import pathlib\n", "\n", - "profile_path = str(pathlib.Path().resolve())+'/profiles/'\n", + "profile_path = str(pathlib.Path().resolve()) + \"/profiles/\"\n", "print(profile_path)" ] }, @@ -86,9 +112,11 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'CIGRE-MV-Profiles'\n", + "name = \"CIGRE-MV-Profiles\"\n", "reader = dpsimpy.CIMReader(name)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)" + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")" ] }, { @@ -97,25 +125,25 @@ "metadata": {}, "outputs": [], "source": [ - "assignList = { }\n", - "assignList['LOAD-H-1'] = 'Load_H_1'\n", - "assignList['LOAD-H-3'] = 'Load_H_3'\n", - "assignList['LOAD-H-4'] = 'Load_H_4'\n", - "assignList['LOAD-H-5'] = 'Load_H_5'\n", - "assignList['LOAD-H-6'] = 'Load_H_6'\n", - "assignList['LOAD-H-8'] = 'Load_H_8'\n", - "assignList['LOAD-H-10'] = 'Load_H_10'\n", - "assignList['LOAD-H-11'] = 'Load_H_11'\n", - "assignList['LOAD-H-12'] = 'Load_H_12'\n", - "assignList['LOAD-H-14'] = 'Load_H_14'\n", - "assignList['LOAD-I-1'] = 'Load_I_1'\n", - "assignList['LOAD-I-3'] = 'Load_I_3'\n", - "assignList['LOAD-I-7'] = 'Load_I_7'\n", - "assignList['LOAD-I-9'] = 'Load_I_9'\n", - "assignList['LOAD-I-10'] = 'Load_I_10'\n", - "assignList['LOAD-I-12'] = 'Load_I_12'\n", - "assignList['LOAD-I-13'] = 'Load_I_13'\n", - "assignList['LOAD-I-14'] = 'Load_I_14'" + "assignList = {}\n", + "assignList[\"LOAD-H-1\"] = \"Load_H_1\"\n", + "assignList[\"LOAD-H-3\"] = \"Load_H_3\"\n", + "assignList[\"LOAD-H-4\"] = \"Load_H_4\"\n", + "assignList[\"LOAD-H-5\"] = \"Load_H_5\"\n", + "assignList[\"LOAD-H-6\"] = \"Load_H_6\"\n", + "assignList[\"LOAD-H-8\"] = \"Load_H_8\"\n", + "assignList[\"LOAD-H-10\"] = \"Load_H_10\"\n", + "assignList[\"LOAD-H-11\"] = \"Load_H_11\"\n", + "assignList[\"LOAD-H-12\"] = \"Load_H_12\"\n", + "assignList[\"LOAD-H-14\"] = \"Load_H_14\"\n", + "assignList[\"LOAD-I-1\"] = \"Load_I_1\"\n", + "assignList[\"LOAD-I-3\"] = \"Load_I_3\"\n", + "assignList[\"LOAD-I-7\"] = \"Load_I_7\"\n", + "assignList[\"LOAD-I-9\"] = \"Load_I_9\"\n", + "assignList[\"LOAD-I-10\"] = \"Load_I_10\"\n", + "assignList[\"LOAD-I-12\"] = \"Load_I_12\"\n", + "assignList[\"LOAD-I-13\"] = \"Load_I_13\"\n", + "assignList[\"LOAD-I-14\"] = \"Load_I_14\"" ] }, { @@ -125,7 +153,9 @@ "outputs": [], "source": [ "csvreader = dpsimpy.CSVReader(name, profile_path, assignList, dpsimpy.LogLevel.info)\n", - "csvreader.assignLoadProfile(system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS)" + "csvreader.assignLoadProfile(\n", + " system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS\n", + ")" ] }, { @@ -152,7 +182,7 @@ "\n", "logger = dpsimpy.Logger(name)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node);\n", + " logger.log_attribute(node.name() + \".V\", \"v\", node)\n", "sim.add_logger(logger)" ] }, diff --git a/examples/Notebooks/Grids/DP_CIGRE_MV_withDG.ipynb b/examples/Notebooks/Grids/DP_CIGRE_MV_withDG.ipynb index 6b8b94907c..accb1eac8e 100644 --- a/examples/Notebooks/Grids/DP_CIGRE_MV_withDG.ipynb +++ b/examples/Notebooks/Grids/DP_CIGRE_MV_withDG.ipynb @@ -23,18 +23,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -59,7 +61,7 @@ "time_step = 1e-3\n", "final_time = 3.0\n", "steady_state_init = False\n", - "sim_name = 'DP_CIGRE_MV_withDG'\n", + "sim_name = \"DP_CIGRE_MV_withDG\"\n", "sim_name_pf = sim_name + \"_Powerflow\"" ] }, @@ -76,30 +78,64 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system_pf = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_pf = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "pv_active_power = 50e3 * int(int(4319.1e3 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system_pf.node('N' + str(n))\n", - " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power = 5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0, resistance=0, inductance=0.928e-3)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system_pf.node(\"N\" + str(n))\n", + " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system_pf.add(pv)\n", " system_pf.connect_component(pv, [connection_node])\n", "\n", "\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", - " logger_pf.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_pf.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", "sim_pf.set_system(system_pf)\n", @@ -111,7 +147,7 @@ "sim_pf.do_init_from_nodes_and_terminals(True)\n", "\n", "sim_pf.add_logger(logger_pf)\n", - "sim_pf.run()\n" + "sim_pf.run()" ] }, { @@ -127,67 +163,107 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader2 = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.info, dpsimpy.LogLevel.debug)\n", - "system_dp = reader2.loadCIM(50, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_dp = reader2.loadCIM(\n", + " 50, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "\n", "pv_active_power = 50e3 * int(int(4319.1e3 * 1 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system_dp.node('N' + str(n))\n", - " pv = dpsimpy.dp.ph1.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power = 5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system_dp.node(\"N\" + str(n))\n", + " pv = dpsimpy.dp.ph1.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system_dp.add(pv)\n", " system_dp.connect_component(pv, [connection_node])\n", "\n", "system_dp.init_with_powerflow(system_pf, dpsimpy.Domain.DP)\n", "\n", "# log node voltages\n", - "logger_dp= dpsimpy.Logger(sim_name)\n", + "logger_dp = dpsimpy.Logger(sim_name)\n", "for node in system_dp.nodes:\n", - " logger_dp.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_dp.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "# log line and load currents\n", "for comp in system_dp.components:\n", " if isinstance(comp, dpsimpy.dp.ph1.PiLine):\n", - " logger_dp.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_dp.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", " if isinstance(comp, dpsimpy.dp.ph1.RXLoad):\n", - " logger_dp.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_dp.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", "\n", "# log output of PV connected at N11\n", - "pv_name = 'pv_N11'\n", + "pv_name = \"pv_N11\"\n", "pv = system_dp.component(pv_name)\n", "input_names = [\n", - " \"pv_powerctrl_input_pref\", \"pv_powerctrl_input_qref\", \"pv_powerctrl_input_vcd\",\n", - " \"pv_powerctrl_input_vcq\", \"pv_powerctrl_input_ircd\", \"pv_powerctrl_input_ircq\"\n", + " \"pv_powerctrl_input_pref\",\n", + " \"pv_powerctrl_input_qref\",\n", + " \"pv_powerctrl_input_vcd\",\n", + " \"pv_powerctrl_input_vcq\",\n", + " \"pv_powerctrl_input_ircd\",\n", + " \"pv_powerctrl_input_ircq\",\n", "]\n", - "logger_dp.log_attribute(input_names, 'powerctrl_inputs', pv)\n", + "logger_dp.log_attribute(input_names, \"powerctrl_inputs\", pv)\n", "\n", "state_names = [\n", - " \"pv_powerctrl_state_p\", \"pv_powerctrl_state_q\", \"pv_powerctrl_state_phid\",\n", - " \"pv_powerctrl_state_phiq\", \"pv_powerctrl_state_gammad\", \"pv_powerctrl_state_gammaq\"\n", + " \"pv_powerctrl_state_p\",\n", + " \"pv_powerctrl_state_q\",\n", + " \"pv_powerctrl_state_phid\",\n", + " \"pv_powerctrl_state_phiq\",\n", + " \"pv_powerctrl_state_gammad\",\n", + " \"pv_powerctrl_state_gammaq\",\n", "]\n", - "logger_dp.log_attribute(state_names, 'powerctrl_states', pv)\n", + "logger_dp.log_attribute(state_names, \"powerctrl_states\", pv)\n", "\n", - "output_names = [\n", - " \"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"\n", - "]\n", + "output_names = [\"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"]\n", "\n", - "logger_dp.log_attribute(output_names, 'powerctrl_outputs', pv)\n", + "logger_dp.log_attribute(output_names, \"powerctrl_outputs\", pv)\n", "\n", - "logger_dp.log_attribute(pv_name + '_v_intf', 'v_intf', pv)\n", - "logger_dp.log_attribute(pv_name + '_i_intf', 'i_intf', pv)\n", - "logger_dp.log_attribute(pv_name + '_pll_output', 'pll_output', pv)\n", - "logger_dp.log_attribute(pv_name + '_vsref', 'Vsref', pv)\n", - "logger_dp.log_attribute(pv_name + '_vs', 'Vs', pv)\n", + "logger_dp.log_attribute(pv_name + \"_v_intf\", \"v_intf\", pv)\n", + "logger_dp.log_attribute(pv_name + \"_i_intf\", \"i_intf\", pv)\n", + "logger_dp.log_attribute(pv_name + \"_pll_output\", \"pll_output\", pv)\n", + "logger_dp.log_attribute(pv_name + \"_vsref\", \"Vsref\", pv)\n", + "logger_dp.log_attribute(pv_name + \"_vs\", \"Vs\", pv)\n", "\n", "sim_dp = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", "sim_dp.set_system(system_dp)\n", @@ -222,10 +298,9 @@ "metadata": {}, "outputs": [], "source": [ - "\n", - "modelName = 'DP_CIGRE_MV_withDG_Powerflow'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"DP_CIGRE_MV_withDG_Powerflow\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim_powerflow = read_timeseries_csv(dpsim_result_file)" ] @@ -243,9 +318,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", - " if ts_name != 'N0.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", + " if ts_name != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -264,8 +339,14 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -281,9 +362,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'DP_CIGRE_MV_withDG'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"DP_CIGRE_MV_withDG\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -301,9 +382,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name != 'N0.V' and ts_name[-2:] == '.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name != \"N0.V\" and ts_name[-2:] == \".V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -322,9 +403,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.V':\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".V\":\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -340,9 +427,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.V':\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".V\":\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -365,9 +458,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-7:]=='state_p' or ts_name[-7:]=='state_q':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-7:] == \"state_p\" or ts_name[-7:] == \"state_q\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -386,9 +479,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-7:]!='state_p' and ts_name[-7:]!='state_q' and 'state' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-7:] != \"state_p\" and ts_name[-7:] != \"state_q\" and \"state\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -407,9 +500,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'state' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"state\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -425,9 +524,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'state' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"state\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -443,9 +548,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -464,9 +569,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -482,9 +593,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -500,9 +617,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -521,9 +638,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -539,9 +662,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -557,9 +686,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -578,12 +707,14 @@ "metadata": {}, "outputs": [], "source": [ - "pv_N11_s_intf = ts_dpsim['pv_N11_v_intf'].values*np.conj(ts_dpsim['pv_N11_i_intf'].values)\n", - "plt.figure(figsize=(12,6))\n", - "plt.plot(ts_dpsim['pv_N11_v_intf'].time, np.real(pv_N11_s_intf), label='pv_N11_P_intf')\n", - "plt.plot(ts_dpsim['pv_N11_v_intf'].time, np.imag(pv_N11_s_intf), label='pv_N11_Q_intf')\n", + "pv_N11_s_intf = ts_dpsim[\"pv_N11_v_intf\"].values * np.conj(\n", + " ts_dpsim[\"pv_N11_i_intf\"].values\n", + ")\n", + "plt.figure(figsize=(12, 6))\n", + "plt.plot(ts_dpsim[\"pv_N11_v_intf\"].time, np.real(pv_N11_s_intf), label=\"pv_N11_P_intf\")\n", + "plt.plot(ts_dpsim[\"pv_N11_v_intf\"].time, np.imag(pv_N11_s_intf), label=\"pv_N11_Q_intf\")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { @@ -599,10 +730,22 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))\n", - "print('pv_N11_s_intf' + ': ' + str(np.real(pv_N11_s_intf[0])) + ', ' + str(np.imag(pv_N11_s_intf[0])))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )\n", + "print(\n", + " \"pv_N11_s_intf\"\n", + " + \": \"\n", + " + str(np.real(pv_N11_s_intf[0]))\n", + " + \", \"\n", + " + str(np.imag(pv_N11_s_intf[0]))\n", + ")" ] }, { @@ -618,10 +761,22 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))\n", - "print('pv_N11_s_intf' + ': ' + str(np.real(pv_N11_s_intf[-1])) + ', ' + str(np.imag(pv_N11_s_intf[-1])))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )\n", + "print(\n", + " \"pv_N11_s_intf\"\n", + " + \": \"\n", + " + str(np.real(pv_N11_s_intf[-1]))\n", + " + \", \"\n", + " + str(np.imag(pv_N11_s_intf[-1]))\n", + ")" ] } ], diff --git a/examples/Notebooks/Grids/DP_CIGRE_MV_withDG_withLoadStep.ipynb b/examples/Notebooks/Grids/DP_CIGRE_MV_withDG_withLoadStep.ipynb index 4a52e83914..a0e8df8bfd 100644 --- a/examples/Notebooks/Grids/DP_CIGRE_MV_withDG_withLoadStep.ipynb +++ b/examples/Notebooks/Grids/DP_CIGRE_MV_withDG_withLoadStep.ipynb @@ -16,18 +16,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -51,7 +53,7 @@ "source": [ "time_step = 1e-3\n", "final_time = 3.0\n", - "sim_name = 'DP_CIGRE_MV_withDG_withLoadStep'\n", + "sim_name = \"DP_CIGRE_MV_withDG_withLoadStep\"\n", "sim_name_pf = sim_name + \"_Powerflow\"" ] }, @@ -68,30 +70,64 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system_pf = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_pf = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "pv_active_power = 50e3 * int(int(4319.1e3 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system_pf.node('N' + str(n))\n", - " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power = 5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system_pf.node(\"N\" + str(n))\n", + " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system_pf.add(pv)\n", " system_pf.connect_component(pv, [connection_node])\n", "\n", "\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", - " logger_pf.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_pf.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", "sim_pf.set_system(system_pf)\n", @@ -103,7 +139,7 @@ "sim_pf.do_init_from_nodes_and_terminals(True)\n", "\n", "sim_pf.add_logger(logger_pf)\n", - "sim_pf.run()\n" + "sim_pf.run()" ] }, { @@ -119,78 +155,120 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader2 = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.info, dpsimpy.LogLevel.debug)\n", - "system_dp = reader2.loadCIM(50, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_dp = reader2.loadCIM(\n", + " 50, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "\n", "pv_active_power = 50e3 * int(int(4319.1e3 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system_dp.node('N' + str(n))\n", - " pv = dpsimpy.dp.ph1.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power = 5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system_dp.node(\"N\" + str(n))\n", + " pv = dpsimpy.dp.ph1.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system_dp.add(pv)\n", " system_dp.connect_component(pv, [connection_node])\n", "\n", "system_dp.init_with_powerflow(system_pf, dpsimpy.Domain.DP)\n", "\n", "# log node voltages\n", - "logger_dp= dpsimpy.Logger(sim_name)\n", + "logger_dp = dpsimpy.Logger(sim_name)\n", "for node in system_dp.nodes:\n", - " logger_dp.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_dp.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "# log line and load currents\n", "for comp in system_dp.components:\n", " if isinstance(comp, dpsimpy.dp.ph1.PiLine):\n", - " logger_dp.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_dp.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", " if isinstance(comp, dpsimpy.dp.ph1.RXLoad):\n", - " logger_dp.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_dp.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", "\n", "# log output of PV connected at N11\n", - "pv_name = 'pv_N11'\n", + "pv_name = \"pv_N11\"\n", "pv = system_dp.component(pv_name)\n", "input_names = [\n", - " \"pv_powerctrl_input_pref\", \"pv_powerctrl_input_qref\", \"pv_powerctrl_input_vcd\",\n", - " \"pv_powerctrl_input_vcq\", \"pv_powerctrl_input_ircd\", \"pv_powerctrl_input_ircq\"\n", + " \"pv_powerctrl_input_pref\",\n", + " \"pv_powerctrl_input_qref\",\n", + " \"pv_powerctrl_input_vcd\",\n", + " \"pv_powerctrl_input_vcq\",\n", + " \"pv_powerctrl_input_ircd\",\n", + " \"pv_powerctrl_input_ircq\",\n", "]\n", - "logger_dp.log_attribute(input_names, 'powerctrl_inputs', pv)\n", + "logger_dp.log_attribute(input_names, \"powerctrl_inputs\", pv)\n", "\n", "state_names = [\n", - " \"pv_powerctrl_state_p\", \"pv_powerctrl_state_q\", \"pv_powerctrl_state_phid\",\n", - " \"pv_powerctrl_state_phiq\", \"pv_powerctrl_state_gammad\", \"pv_powerctrl_state_gammaq\"\n", + " \"pv_powerctrl_state_p\",\n", + " \"pv_powerctrl_state_q\",\n", + " \"pv_powerctrl_state_phid\",\n", + " \"pv_powerctrl_state_phiq\",\n", + " \"pv_powerctrl_state_gammad\",\n", + " \"pv_powerctrl_state_gammaq\",\n", "]\n", - "logger_dp.log_attribute(state_names, 'powerctrl_states', pv)\n", + "logger_dp.log_attribute(state_names, \"powerctrl_states\", pv)\n", "\n", - "output_names = [\n", - " \"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"\n", - "]\n", + "output_names = [\"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"]\n", "\n", - "logger_dp.log_attribute(output_names, 'powerctrl_outputs', pv)\n", + "logger_dp.log_attribute(output_names, \"powerctrl_outputs\", pv)\n", "\n", - "logger_dp.log_attribute(pv_name + '_v_intf', 'v_intf', pv)\n", - "logger_dp.log_attribute(pv_name + '_i_intf', 'i_intf', pv)\n", - "logger_dp.log_attribute(pv_name + '_pll_output', 'pll_output', pv)\n", - "logger_dp.log_attribute(pv_name + '_vsref', 'Vsref', pv)\n", - "logger_dp.log_attribute(pv_name + '_vs', 'Vs', pv)\n", + "logger_dp.log_attribute(pv_name + \"_v_intf\", \"v_intf\", pv)\n", + "logger_dp.log_attribute(pv_name + \"_i_intf\", \"i_intf\", pv)\n", + "logger_dp.log_attribute(pv_name + \"_pll_output\", \"pll_output\", pv)\n", + "logger_dp.log_attribute(pv_name + \"_vsref\", \"Vsref\", pv)\n", + "logger_dp.log_attribute(pv_name + \"_vs\", \"Vs\", pv)\n", "\n", "# load step sized in absolute terms\n", "load_switch = dpsimpy.dp.ph1.Switch(\"Load_Add_Switch_N11\", dpsimpy.LogLevel.debug)\n", - "connection_node = system_dp.node('N11')\n", - "resistance = np.abs(connection_node.initial_single_voltage())**2 / 1500.0e3\n", + "connection_node = system_dp.node(\"N11\")\n", + "resistance = np.abs(connection_node.initial_single_voltage()) ** 2 / 1500.0e3\n", "load_switch.set_parameters(1e9, resistance)\n", "load_switch.open()\n", "system_dp.add(load_switch)\n", - "system_dp.connect_component(load_switch, [dpsimpy.dp.SimNode.gnd, system_dp.node('N11')])\n", - "logger_dp.log_attribute('switchedload_i', 'i_intf', load_switch)\n", - "load_step_event = dpsimpy.event.SwitchEvent(2 - time_step, load_switch, True)\n", + "system_dp.connect_component(\n", + " load_switch, [dpsimpy.dp.SimNode.gnd, system_dp.node(\"N11\")]\n", + ")\n", + "logger_dp.log_attribute(\"switchedload_i\", \"i_intf\", load_switch)\n", + "load_step_event = dpsimpy.event.SwitchEvent(2 - time_step, load_switch, True)\n", "\n", "\n", "sim_dp = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", @@ -227,9 +305,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'DP_CIGRE_MV_withDG_withLoadStep_Powerflow'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"DP_CIGRE_MV_withDG_withLoadStep_Powerflow\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -247,9 +325,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name != 'N0.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -268,9 +346,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'DP_CIGRE_MV_withDG_withLoadStep'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"DP_CIGRE_MV_withDG_withLoadStep\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -288,9 +366,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name != 'N0.V' and ts_name[-2:] == '.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name != \"N0.V\" and ts_name[-2:] == \".V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -309,9 +387,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.V':\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".V\":\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -327,12 +411,12 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name != 'N0.V' and ts_name[-2:] == '.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name != \"N0.V\" and ts_name[-2:] == \".V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", - "#plt.ylim([19000,21000])\n", - "plt.xlim([1.9,3])\n", + "# plt.ylim([19000,21000])\n", + "plt.xlim([1.9, 3])\n", "plt.legend()\n", "plt.show()" ] @@ -350,16 +434,20 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,12))\n", + "plt.figure(figsize=(12, 12))\n", "subplot_number = 1\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.V' and ts_name[:-2] != 'N0.V':\n", - " plt.subplot(4,3,subplot_number)\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".V\" and ts_name[:-2] != \"N0.V\":\n", + " plt.subplot(4, 3, subplot_number)\n", " subplot_number += 1\n", - " plt.plot(ts_dpsim[ts_name].interpolate(50e-6).time, ts_dpsim[ts_name].interpolate(50e-6).frequency_shift(50).values, label=ts_name)\n", - " plt.legend(loc='upper right')\n", - " plt.xlim([1.8,3])\n", - " plt.ylim([18500,20000])\n", + " plt.plot(\n", + " ts_dpsim[ts_name].interpolate(50e-6).time,\n", + " ts_dpsim[ts_name].interpolate(50e-6).frequency_shift(50).values,\n", + " label=ts_name,\n", + " )\n", + " plt.legend(loc=\"upper right\")\n", + " plt.xlim([1.8, 3])\n", + " plt.ylim([18500, 20000])\n", "plt.show()" ] }, @@ -376,12 +464,12 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[:4]=='LOAD': \n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[:4] == \"LOAD\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", - "#plt.xlim([0,0.1])\n", - "plt.legend(loc='upper right')\n", + "# plt.xlim([0,0.1])\n", + "plt.legend(loc=\"upper right\")\n", "plt.show()" ] }, @@ -398,15 +486,15 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", + "plt.figure(figsize=(12, 6))\n", "subplot_number = 1\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.I' and ts_name[:4] != 'LOAD':\n", - " plt.subplot(4,3,subplot_number)\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".I\" and ts_name[:4] != \"LOAD\":\n", + " plt.subplot(4, 3, subplot_number)\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", " subplot_number += 1\n", - " plt.legend(loc='upper right')\n", - "#plt.xlim([0,0.1])\n", + " plt.legend(loc=\"upper right\")\n", + "# plt.xlim([0,0.1])\n", "plt.show()" ] }, @@ -430,9 +518,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-7:]=='state_p' or ts_name[-7:]=='state_q':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-7:] == \"state_p\" or ts_name[-7:] == \"state_q\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -451,9 +539,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-7:]!='state_p' and ts_name[-7:]!='state_q' and 'state' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-7:] != \"state_p\" and ts_name[-7:] != \"state_q\" and \"state\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -472,9 +560,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'state' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"state\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -490,9 +584,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'state' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"state\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -508,9 +608,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -529,9 +629,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -547,9 +653,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -565,9 +677,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -586,9 +698,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -604,9 +722,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -622,9 +746,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -643,12 +767,14 @@ "metadata": {}, "outputs": [], "source": [ - "pv_N11_s_intf = ts_dpsim['pv_N11_v_intf'].values*np.conj(ts_dpsim['pv_N11_i_intf'].values)\n", - "plt.figure(figsize=(12,6))\n", - "plt.plot(ts_dpsim['pv_N11_v_intf'].time, np.real(pv_N11_s_intf), label='pv_N11_P_intf')\n", - "plt.plot(ts_dpsim['pv_N11_v_intf'].time, np.imag(pv_N11_s_intf), label='pv_N11_Q_intf')\n", + "pv_N11_s_intf = ts_dpsim[\"pv_N11_v_intf\"].values * np.conj(\n", + " ts_dpsim[\"pv_N11_i_intf\"].values\n", + ")\n", + "plt.figure(figsize=(12, 6))\n", + "plt.plot(ts_dpsim[\"pv_N11_v_intf\"].time, np.real(pv_N11_s_intf), label=\"pv_N11_P_intf\")\n", + "plt.plot(ts_dpsim[\"pv_N11_v_intf\"].time, np.imag(pv_N11_s_intf), label=\"pv_N11_Q_intf\")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { @@ -664,10 +790,22 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))\n", - "print('pv_N11_s_intf' + ': ' + str(np.real(pv_N11_s_intf[0])) + ', ' + str(np.imag(pv_N11_s_intf[0])))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )\n", + "print(\n", + " \"pv_N11_s_intf\"\n", + " + \": \"\n", + " + str(np.real(pv_N11_s_intf[0]))\n", + " + \", \"\n", + " + str(np.imag(pv_N11_s_intf[0]))\n", + ")" ] }, { @@ -683,10 +821,22 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))\n", - "print('pv_N11_s_intf' + ': ' + str(np.real(pv_N11_s_intf[-1])) + ', ' + str(np.imag(pv_N11_s_intf[-1])))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )\n", + "print(\n", + " \"pv_N11_s_intf\"\n", + " + \": \"\n", + " + str(np.real(pv_N11_s_intf[-1]))\n", + " + \", \"\n", + " + str(np.imag(pv_N11_s_intf[-1]))\n", + ")" ] }, { diff --git a/examples/Notebooks/Grids/DP_CIGRE_MV_withoutDG.ipynb b/examples/Notebooks/Grids/DP_CIGRE_MV_withoutDG.ipynb index afc9f6cb9c..0d6a2af4ae 100644 --- a/examples/Notebooks/Grids/DP_CIGRE_MV_withoutDG.ipynb +++ b/examples/Notebooks/Grids/DP_CIGRE_MV_withoutDG.ipynb @@ -23,18 +23,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -67,7 +69,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'DP_CIGRE_MV_withoutDG'\n", + "sim_name = \"DP_CIGRE_MV_withoutDG\"\n", "sim_name_pf = sim_name + \"_Powerflow\"" ] }, @@ -84,13 +86,15 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system_pf = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_pf = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", - " logger_pf.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_pf.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", "sim_pf.set_system(system_pf)\n", @@ -102,7 +106,7 @@ "sim_pf.do_init_from_nodes_and_terminals(True)\n", "\n", "sim_pf.add_logger(logger_pf)\n", - "sim_pf.run()\n" + "sim_pf.run()" ] }, { @@ -118,22 +122,24 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader2 = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.info, dpsimpy.LogLevel.debug)\n", - "system_dp = reader2.loadCIM(50, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_dp = reader2.loadCIM(\n", + " 50, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "system_dp.init_with_powerflow(system_pf, dpsimpy.Domain.DP)\n", "\n", "# log node voltages\n", - "logger_dp= dpsimpy.Logger(sim_name)\n", + "logger_dp = dpsimpy.Logger(sim_name)\n", "for node in system_dp.nodes:\n", - " logger_dp.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_dp.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "# log line and load currents\n", "for comp in system_dp.components:\n", " if isinstance(comp, dpsimpy.dp.ph1.PiLine):\n", - " logger_dp.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_dp.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", " if isinstance(comp, dpsimpy.dp.ph1.RXLoad):\n", - " logger_dp.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_dp.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", "\n", "sim_dp = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", "sim_dp.set_system(system_dp)\n", @@ -168,9 +174,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'DP_CIGRE_MV_withoutDG_Powerflow'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"DP_CIGRE_MV_withoutDG_Powerflow\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim_powerflow = read_timeseries_csv(dpsim_result_file)" ] @@ -188,9 +194,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", - " if ts_name != 'N0.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", + " if ts_name != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -209,8 +215,14 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -233,9 +245,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'DP_CIGRE_MV_withoutDG'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"DP_CIGRE_MV_withoutDG\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -260,11 +272,11 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name != 'N0.V' and ts_name[-2:] == '.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name != \"N0.V\" and ts_name[-2:] == \".V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", - "plt.legend(loc='upper right')\n", + "plt.legend(loc=\"upper right\")\n", "plt.show()" ] }, @@ -281,9 +293,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.V':\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".V\":\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -299,9 +317,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.V':\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1:]) + ', ' + str(ts_obj.phase().values[-1:]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".V\":\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1:])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1:])\n", + " )" ] }, { @@ -317,12 +341,12 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.I' and ts_name[:4] == 'LOAD':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".I\" and ts_name[:4] == \"LOAD\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", - "plt.xlim([0,0.01])\n", - "plt.legend(loc='upper right')\n", + "plt.xlim([0, 0.01])\n", + "plt.legend(loc=\"upper right\")\n", "plt.show()" ] }, @@ -339,9 +363,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.I' and ts_name[:4] == 'LOAD':\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".I\" and ts_name[:4] == \"LOAD\":\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -357,9 +387,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-2:] == '.I' and ts_name[:4] == 'LOAD':\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1:]) + ', ' + str(ts_obj.phase().values[-1:]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-2:] == \".I\" and ts_name[:4] == \"LOAD\":\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1:])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1:])\n", + " )" ] }, { @@ -375,8 +411,12 @@ "metadata": {}, "outputs": [], "source": [ - "load_I_3_s = ts_dpsim['N3.V'].values*np.conj(ts_dpsim['LOAD-I-3.I'].values) # ref from CIM: P=225250, Q=139597\n", - "load_H_11_s = ts_dpsim['N11.V'].values*np.conj(ts_dpsim['LOAD-H-11.I'].values) # ref from CIM: P=329800, Q=82656" + "load_I_3_s = ts_dpsim[\"N3.V\"].values * np.conj(\n", + " ts_dpsim[\"LOAD-I-3.I\"].values\n", + ") # ref from CIM: P=225250, Q=139597\n", + "load_H_11_s = ts_dpsim[\"N11.V\"].values * np.conj(\n", + " ts_dpsim[\"LOAD-H-11.I\"].values\n", + ") # ref from CIM: P=329800, Q=82656" ] }, { @@ -392,8 +432,8 @@ "metadata": {}, "outputs": [], "source": [ - "print('Load-I-3.S' + ': ' + str(load_I_3_s[0]))\n", - "print('Load-H-11.S' + ': ' + str(load_H_11_s[0]))" + "print(\"Load-I-3.S\" + \": \" + str(load_I_3_s[0]))\n", + "print(\"Load-H-11.S\" + \": \" + str(load_H_11_s[0]))" ] }, { @@ -409,8 +449,8 @@ "metadata": {}, "outputs": [], "source": [ - "print('Load-I-3.S' + ': ' + str(load_I_3_s[-1]))\n", - "print('Load-H-11.S' + ': ' + str(load_H_11_s[-1]))" + "print(\"Load-I-3.S\" + \": \" + str(load_I_3_s[-1]))\n", + "print(\"Load-H-11.S\" + \": \" + str(load_H_11_s[-1]))" ] } ], diff --git a/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab.ipynb b/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab.ipynb index 204e721545..e679c42d78 100644 --- a/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab.ipynb +++ b/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab.ipynb @@ -16,18 +16,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX_Dyn/WSCC-09_RX'\n", - "filename = 'WSCC-09'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX_Dyn/WSCC-09_RX\"\n", + "filename = \"WSCC-09\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -51,7 +53,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'WSCC-9bus_dyn'" + "sim_name = \"WSCC-9bus_dyn\"" ] }, { @@ -67,17 +69,23 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system = reader.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.TransientStability)\n", + "system = reader.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.TransientStability,\n", + ")\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "\n", "for i in range(1, 10):\n", - " logger.log_attribute('v' + str(i), 'v', system.node('BUS' + str(i)))\n", + " logger.log_attribute(\"v\" + str(i), \"v\", system.node(\"BUS\" + str(i)))\n", "\n", "for i in range(1, 4):\n", - " logger.log_attribute('wr_' + str(i), 'w_r', system.component('GEN' + str(i)))\n", + " logger.log_attribute(\"wr_\" + str(i), \"w_r\", system.component(\"GEN\" + str(i)))\n", "\n", "sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.info)\n", "sim.set_system(system)\n", @@ -87,7 +95,7 @@ "sim.do_steady_state_init(True)\n", "\n", "sim.add_logger(logger)\n", - "sim.run()\n" + "sim.run()" ] }, { @@ -103,9 +111,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC-9bus_dyn/'\n", - "logName = 'WSCC-9bus_dyn_InitLeftVector'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC-9bus_dyn/\"\n", + "logName = \"WSCC-9bus_dyn_InitLeftVector\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_dpsim_init = rt.read_timeseries_dpsim(logFilename)" @@ -127,7 +135,13 @@ "phasors_init = ts.phasors(ts_dpsim_init)\n", "\n", "for node, phasor in phasors_init.items():\n", - " print(node + ': ' + str(phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[0])\n", + " )" ] }, { @@ -144,7 +158,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_init.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1])\n", + " )" ] }, { @@ -161,7 +181,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_init.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1] - phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[-1] - phasor['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1] - phasor[\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1] - phasor[\"phase\"].values[0])\n", + " )" ] }, { @@ -177,9 +203,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC-9bus_dyn/'\n", - "logName = 'WSCC-9bus_dyn'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC-9bus_dyn/\"\n", + "logName = \"WSCC-9bus_dyn\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_dpsim = rt.read_timeseries_dpsim(logFilename)\n", @@ -199,11 +225,25 @@ "metadata": {}, "outputs": [], "source": [ - "nominal_voltages = {'v1': 16500, 'v2': 18000, 'v3': 13800, \n", - " 'v4': 230000, 'v5': 230000, 'v6': 230000, \n", - " 'v7': 230000, 'v8': 230000, 'v9': 230000} \n", + "nominal_voltages = {\n", + " \"v1\": 16500,\n", + " \"v2\": 18000,\n", + " \"v3\": 13800,\n", + " \"v4\": 230000,\n", + " \"v5\": 230000,\n", + " \"v6\": 230000,\n", + " \"v7\": 230000,\n", + " \"v8\": 230000,\n", + " \"v9\": 230000,\n", + "}\n", "for node, nom_voltage in nominal_voltages.items():\n", - " print(node + ': ' + str(phasors[node]['abs'].values[0] / nom_voltage) + '<' + str(phasors[node]['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasors[node][\"abs\"].values[0] / nom_voltage)\n", + " + \"<\"\n", + " + str(phasors[node][\"phase\"].values[0])\n", + " )" ] }, { @@ -219,8 +259,8 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(1, phasors['v9']['phase'])\n", - "#plt.xlim(0,0.2)" + "pt.plot_timeseries(1, phasors[\"v9\"][\"phase\"])\n", + "# plt.xlim(0,0.2)" ] }, { @@ -237,7 +277,13 @@ "outputs": [], "source": [ "for node, phasor in phasors.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1])\n", + " )" ] }, { @@ -246,18 +292,18 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(1, phasors['v1']['abs'])\n", - "pt.plot_timeseries(1, phasors['v2']['abs'])\n", - "pt.plot_timeseries(1, phasors['v3']['abs'])\n", + "pt.plot_timeseries(1, phasors[\"v1\"][\"abs\"])\n", + "pt.plot_timeseries(1, phasors[\"v2\"][\"abs\"])\n", + "pt.plot_timeseries(1, phasors[\"v3\"][\"abs\"])\n", "\n", - "pt.plot_timeseries(2, phasors['v4']['abs'])\n", - "pt.plot_timeseries(2, phasors['v5']['abs'])\n", - "pt.plot_timeseries(2, phasors['v6']['abs'])\n", - "pt.plot_timeseries(2, phasors['v7']['abs'])\n", - "pt.plot_timeseries(2, phasors['v8']['abs'])\n", - "pt.plot_timeseries(2, phasors['v9']['abs'])\n", - "plt.ylim([200000,240000])\n", - "plt.xlim([0,0.1])" + "pt.plot_timeseries(2, phasors[\"v4\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v5\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v6\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v7\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v8\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v9\"][\"abs\"])\n", + "plt.ylim([200000, 240000])\n", + "plt.xlim([0, 0.1])" ] }, { @@ -267,11 +313,11 @@ "outputs": [], "source": [ "for node, phasor in phasors.items():\n", - " abs_diff = phasor['abs'].values[-1] - phasor['abs'].values[0]\n", + " abs_diff = phasor[\"abs\"].values[-1] - phasor[\"abs\"].values[0]\n", " assert abs_diff < 27\n", - " phase_diff = phasor['phase'].values[-1] - phasor['phase'].values[0]\n", + " phase_diff = phasor[\"phase\"].values[-1] - phasor[\"phase\"].values[0]\n", " assert phase_diff < 0.001\n", - " print(node + ': ' + str(abs_diff) + '<' + str(phase_diff))" + " print(node + \": \" + str(abs_diff) + \"<\" + str(phase_diff))" ] }, { @@ -280,13 +326,13 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(1, ts_dpsim['wr_1'])\n", - "pt.plot_timeseries(1, ts_dpsim['wr_2'])\n", - "pt.plot_timeseries(1, ts_dpsim['wr_3'])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('mechanical speed (rad/s)')\n", - "#plt.ylim([370,380])\n", - "#plt.xlim([0,0.06])" + "pt.plot_timeseries(1, ts_dpsim[\"wr_1\"])\n", + "pt.plot_timeseries(1, ts_dpsim[\"wr_2\"])\n", + "pt.plot_timeseries(1, ts_dpsim[\"wr_3\"])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"mechanical speed (rad/s)\")\n", + "# plt.ylim([370,380])\n", + "# plt.xlim([0,0.06])" ] } ], diff --git a/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab_Switch.ipynb b/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab_Switch.ipynb index 9fc74088e8..6fd9b4c88f 100644 --- a/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab_Switch.ipynb +++ b/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab_Switch.ipynb @@ -16,18 +16,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX_Dyn/WSCC-09_RX'\n", - "filename = 'WSCC-09'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX_Dyn/WSCC-09_RX\"\n", + "filename = \"WSCC-09\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -51,7 +53,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'WSCC-9bus_dyn_switch'" + "sim_name = \"WSCC-9bus_dyn_switch\"" ] }, { @@ -67,32 +69,40 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system = reader.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.TransientStability)\n", + "system = reader.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.TransientStability,\n", + ")\n", "\n", "# Extend topology with switch\n", - "sw = dpsimpy.dp.ph1.Switch('Fault', dpsimpy.LogLevel.info)\n", + "sw = dpsimpy.dp.ph1.Switch(\"Fault\", dpsimpy.LogLevel.info)\n", "sw.set_parameters(1e9, 0.1)\n", - "sw.connect([dpsimpy.dp.SimNode.gnd, system.node('BUS6')])\n", + "sw.connect([dpsimpy.dp.SimNode.gnd, system.node(\"BUS6\")])\n", "sw.open()\n", "system.add(sw)\n", "\n", "# Use omegNom for torque conversion in SG models for validation with PSAT\n", - "system.component('GEN1').set_model_flags(False)\n", - "system.component('GEN2').set_model_flags(False)\n", - "system.component('GEN3').set_model_flags(False)\n", + "system.component(\"GEN1\").set_model_flags(False)\n", + "system.component(\"GEN2\").set_model_flags(False)\n", + "system.component(\"GEN3\").set_model_flags(False)\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "\n", "for i in range(1, 10):\n", - " logger.log_attribute('v' + str(i), 'v', system.node('BUS' + str(i)))\n", + " logger.log_attribute(\"v\" + str(i), \"v\", system.node(\"BUS\" + str(i)))\n", "\n", "for i in range(1, 4):\n", - " logger.log_attribute('wr_' + str(i), 'w_r', system.component('GEN' + str(i)))\n", - " logger.log_attribute('delta_r_' + str(i), 'delta_r', system.component('GEN' + str(i)))\n", - " logger.log_attribute('P_elec_' + str(i), 'P_elec', system.component('GEN' + str(i)))\n", - " logger.log_attribute('P_mech_' + str(i), 'P_mech', system.component('GEN' + str(i)))\n", + " logger.log_attribute(\"wr_\" + str(i), \"w_r\", system.component(\"GEN\" + str(i)))\n", + " logger.log_attribute(\n", + " \"delta_r_\" + str(i), \"delta_r\", system.component(\"GEN\" + str(i))\n", + " )\n", + " logger.log_attribute(\"P_elec_\" + str(i), \"P_elec\", system.component(\"GEN\" + str(i)))\n", + " logger.log_attribute(\"P_mech_\" + str(i), \"P_mech\", system.component(\"GEN\" + str(i)))\n", "\n", "\n", "sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", @@ -107,7 +117,7 @@ "sim.add_event(sw_event_1)\n", "\n", "sim.add_logger(logger)\n", - "sim.run()\n" + "sim.run()" ] }, { @@ -123,9 +133,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC-9bus_dyn_switch/'\n", - "logName = 'WSCC-9bus_dyn_switch'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC-9bus_dyn_switch/\"\n", + "logName = \"WSCC-9bus_dyn_switch\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_dpsim = rt.read_timeseries_dpsim(logFilename)\n", @@ -145,11 +155,25 @@ "metadata": {}, "outputs": [], "source": [ - "nominal_voltages = {'v1': 16500, 'v2': 18000, 'v3': 13800, \n", - " 'v4': 230000, 'v5': 230000, 'v6': 230000, \n", - " 'v7': 230000, 'v8': 230000, 'v9': 230000} \n", + "nominal_voltages = {\n", + " \"v1\": 16500,\n", + " \"v2\": 18000,\n", + " \"v3\": 13800,\n", + " \"v4\": 230000,\n", + " \"v5\": 230000,\n", + " \"v6\": 230000,\n", + " \"v7\": 230000,\n", + " \"v8\": 230000,\n", + " \"v9\": 230000,\n", + "}\n", "for node, nom_voltage in nominal_voltages.items():\n", - " print(node + ': ' + str(phasors[node]['abs'].values[0] / nom_voltage) + '<' + str(phasors[node]['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasors[node][\"abs\"].values[0] / nom_voltage)\n", + " + \"<\"\n", + " + str(phasors[node][\"phase\"].values[0])\n", + " )" ] }, { @@ -166,21 +190,21 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(phasors['v1']['abs'].time, phasors['v1']['abs'].values, label='v1.abs')\n", - "plt.plot(phasors['v2']['abs'].time, phasors['v2']['abs'].values, label='v2.abs')\n", - "plt.plot(phasors['v3']['abs'].time, phasors['v3']['abs'].values, label='v3.abs')\n", + "plt.plot(phasors[\"v1\"][\"abs\"].time, phasors[\"v1\"][\"abs\"].values, label=\"v1.abs\")\n", + "plt.plot(phasors[\"v2\"][\"abs\"].time, phasors[\"v2\"][\"abs\"].values, label=\"v2.abs\")\n", + "plt.plot(phasors[\"v3\"][\"abs\"].time, phasors[\"v3\"][\"abs\"].values, label=\"v3.abs\")\n", "plt.legend()\n", - "plt.ylim([0,20000])\n", + "plt.ylim([0, 20000])\n", "\n", "plt.figure()\n", - "plt.plot(phasors['v4']['abs'].time, phasors['v4']['abs'].values, label='v4.abs')\n", - "plt.plot(phasors['v5']['abs'].time, phasors['v5']['abs'].values, label='v5.abs')\n", - "plt.plot(phasors['v6']['abs'].time, phasors['v6']['abs'].values, label='v6.abs')\n", - "plt.plot(phasors['v7']['abs'].time, phasors['v7']['abs'].values, label='v7.abs')\n", - "plt.plot(phasors['v8']['abs'].time, phasors['v8']['abs'].values, label='v8.abs')\n", - "plt.plot(phasors['v9']['abs'].time, phasors['v9']['abs'].values, label='v9.abs')\n", + "plt.plot(phasors[\"v4\"][\"abs\"].time, phasors[\"v4\"][\"abs\"].values, label=\"v4.abs\")\n", + "plt.plot(phasors[\"v5\"][\"abs\"].time, phasors[\"v5\"][\"abs\"].values, label=\"v5.abs\")\n", + "plt.plot(phasors[\"v6\"][\"abs\"].time, phasors[\"v6\"][\"abs\"].values, label=\"v6.abs\")\n", + "plt.plot(phasors[\"v7\"][\"abs\"].time, phasors[\"v7\"][\"abs\"].values, label=\"v7.abs\")\n", + "plt.plot(phasors[\"v8\"][\"abs\"].time, phasors[\"v8\"][\"abs\"].values, label=\"v8.abs\")\n", + "plt.plot(phasors[\"v9\"][\"abs\"].time, phasors[\"v9\"][\"abs\"].values, label=\"v9.abs\")\n", "plt.legend()\n", - "plt.ylim([0,240000])" + "plt.ylim([0, 240000])" ] }, { @@ -197,12 +221,12 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(ts_dpsim['wr_1'].time, ts_dpsim['wr_1'].values)\n", - "plt.plot(ts_dpsim['wr_2'].time, ts_dpsim['wr_2'].values)\n", - "plt.plot(ts_dpsim['wr_3'].time, ts_dpsim['wr_3'].values)\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('mechanical speed (rad/s)')\n", - "#plt.savefig('wscc_9bus_fault_gen_speed.pdf')" + "plt.plot(ts_dpsim[\"wr_1\"].time, ts_dpsim[\"wr_1\"].values)\n", + "plt.plot(ts_dpsim[\"wr_2\"].time, ts_dpsim[\"wr_2\"].values)\n", + "plt.plot(ts_dpsim[\"wr_3\"].time, ts_dpsim[\"wr_3\"].values)\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"mechanical speed (rad/s)\")\n", + "# plt.savefig('wscc_9bus_fault_gen_speed.pdf')" ] }, { @@ -222,12 +246,12 @@ "import os\n", "import urllib.request\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://git.rwth-aachen.de/acs/public/simulation/dpsim/dpsim-results/raw/master/WSCC-9bus/WSCC-9bus_dyn_switch_mod_inertia.csv'\n", - "local_file = 'reference-results/WSCC-9bus_dyn_switch.csv'\n", - "urllib.request.urlretrieve(url, local_file) \n", + "url = \"https://git.rwth-aachen.de/acs/public/simulation/dpsim/dpsim-results/raw/master/WSCC-9bus/WSCC-9bus_dyn_switch_mod_inertia.csv\"\n", + "local_file = \"reference-results/WSCC-9bus_dyn_switch.csv\"\n", + "urllib.request.urlretrieve(url, local_file)\n", "\n", "ts_sl = rt.read_timeseries_simulink(local_file)\n", "phasors_sl = ts.phasors(ts_sl)" @@ -240,21 +264,21 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(phasors_sl['v1']['abs'].time, phasors_sl['v1']['abs'].values, label='v1.abs')\n", - "plt.plot(phasors_sl['v2']['abs'].time, phasors_sl['v2']['abs'].values, label='v2.abs')\n", - "plt.plot(phasors_sl['v3']['abs'].time, phasors_sl['v3']['abs'].values, label='v3.abs')\n", + "plt.plot(phasors_sl[\"v1\"][\"abs\"].time, phasors_sl[\"v1\"][\"abs\"].values, label=\"v1.abs\")\n", + "plt.plot(phasors_sl[\"v2\"][\"abs\"].time, phasors_sl[\"v2\"][\"abs\"].values, label=\"v2.abs\")\n", + "plt.plot(phasors_sl[\"v3\"][\"abs\"].time, phasors_sl[\"v3\"][\"abs\"].values, label=\"v3.abs\")\n", "plt.legend()\n", - "plt.ylim([0,20000])\n", + "plt.ylim([0, 20000])\n", "\n", "plt.figure()\n", - "plt.plot(phasors_sl['v4']['abs'].time, phasors_sl['v4']['abs'].values, label='v4.abs')\n", - "plt.plot(phasors_sl['v5']['abs'].time, phasors_sl['v5']['abs'].values, label='v5.abs')\n", - "plt.plot(phasors_sl['v6']['abs'].time, phasors_sl['v6']['abs'].values, label='v6.abs')\n", - "plt.plot(phasors_sl['v7']['abs'].time, phasors_sl['v7']['abs'].values, label='v7.abs')\n", - "plt.plot(phasors_sl['v8']['abs'].time, phasors_sl['v8']['abs'].values, label='v8.abs')\n", - "plt.plot(phasors_sl['v9']['abs'].time, phasors_sl['v9']['abs'].values, label='v9.abs')\n", + "plt.plot(phasors_sl[\"v4\"][\"abs\"].time, phasors_sl[\"v4\"][\"abs\"].values, label=\"v4.abs\")\n", + "plt.plot(phasors_sl[\"v5\"][\"abs\"].time, phasors_sl[\"v5\"][\"abs\"].values, label=\"v5.abs\")\n", + "plt.plot(phasors_sl[\"v6\"][\"abs\"].time, phasors_sl[\"v6\"][\"abs\"].values, label=\"v6.abs\")\n", + "plt.plot(phasors_sl[\"v7\"][\"abs\"].time, phasors_sl[\"v7\"][\"abs\"].values, label=\"v7.abs\")\n", + "plt.plot(phasors_sl[\"v8\"][\"abs\"].time, phasors_sl[\"v8\"][\"abs\"].values, label=\"v8.abs\")\n", + "plt.plot(phasors_sl[\"v9\"][\"abs\"].time, phasors_sl[\"v9\"][\"abs\"].values, label=\"v9.abs\")\n", "plt.legend()\n", - "plt.ylim([0,240000])" + "plt.ylim([0, 240000])" ] }, { @@ -264,11 +288,11 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(ts_sl['wr_1'].time, ts_sl['wr_1'].values)\n", - "plt.plot(ts_sl['wr_2'].time, ts_sl['wr_2'].values)\n", - "plt.plot(ts_sl['wr_3'].time, ts_sl['wr_3'].values)\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('mechanical speed (rad/s)')" + "plt.plot(ts_sl[\"wr_1\"].time, ts_sl[\"wr_1\"].values)\n", + "plt.plot(ts_sl[\"wr_2\"].time, ts_sl[\"wr_2\"].values)\n", + "plt.plot(ts_sl[\"wr_3\"].time, ts_sl[\"wr_3\"].values)\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"mechanical speed (rad/s)\")" ] }, { @@ -278,6 +302,7 @@ "outputs": [], "source": [ "import numpy as np\n", + "\n", "# assert np.all(ts_sl['wr_1'].values - ts_dpsim['wr_1'].values < 0.01)" ] } diff --git a/examples/Notebooks/Grids/DP_WSCC9bus_SGVoltageSource.ipynb b/examples/Notebooks/Grids/DP_WSCC9bus_SGVoltageSource.ipynb index 6747701970..5310a7165f 100644 --- a/examples/Notebooks/Grids/DP_WSCC9bus_SGVoltageSource.ipynb +++ b/examples/Notebooks/Grids/DP_WSCC9bus_SGVoltageSource.ipynb @@ -16,18 +16,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX/WSCC-09_RX'\n", - "filename = 'WSCC-09_RX_WithoutSyngenParams'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX/WSCC-09_RX\"\n", + "filename = \"WSCC-09_RX_WithoutSyngenParams\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -51,7 +53,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'WSCC-9bus'" + "sim_name = \"WSCC-9bus\"" ] }, { @@ -74,14 +76,20 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system = reader.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.IdealVoltageSource)\n", + "system = reader.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.IdealVoltageSource,\n", + ")\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "\n", "for i in range(1, 10):\n", - " logger.log_attribute('v' + str(i), 'v', system.node('BUS' + str(i)))\n", + " logger.log_attribute(\"v\" + str(i), \"v\", system.node(\"BUS\" + str(i)))\n", "\n", "sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.info)\n", "sim.set_system(system)\n", @@ -91,7 +99,7 @@ "sim.do_steady_state_init(True)\n", "\n", "sim.add_logger(logger)\n", - "sim.run()\n" + "sim.run()" ] }, { @@ -100,9 +108,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC-9bus/'\n", - "logName = 'WSCC-9bus_InitLeftVector'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC-9bus/\"\n", + "logName = \"WSCC-9bus_InitLeftVector\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_dpsim_init = rt.read_timeseries_dpsim(logFilename)" @@ -124,7 +132,13 @@ "phasors_init = ts.phasors(ts_dpsim_init)\n", "\n", "for node, phasor in phasors_init.items():\n", - " print(node + ': ' + str(phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[0])\n", + " )" ] }, { @@ -141,7 +155,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_init.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1])\n", + " )" ] }, { @@ -158,7 +178,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_init.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1] - phasor['abs'].values[0]) + '<' + str(phasor['phase'].values[-1] - phasor['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1] - phasor[\"abs\"].values[0])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1] - phasor[\"phase\"].values[0])\n", + " )" ] }, { @@ -174,9 +200,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC-9bus/'\n", - "logName = 'WSCC-9bus'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC-9bus/\"\n", + "logName = \"WSCC-9bus\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_dpsim = rt.read_timeseries_dpsim(logFilename)\n", @@ -196,11 +222,25 @@ "metadata": {}, "outputs": [], "source": [ - "nominal_voltages = {'v1': 16500, 'v2': 18000, 'v3': 13800, \n", - " 'v4': 230000, 'v5': 230000, 'v6': 230000, \n", - " 'v7': 230000, 'v8': 230000, 'v9': 230000} \n", + "nominal_voltages = {\n", + " \"v1\": 16500,\n", + " \"v2\": 18000,\n", + " \"v3\": 13800,\n", + " \"v4\": 230000,\n", + " \"v5\": 230000,\n", + " \"v6\": 230000,\n", + " \"v7\": 230000,\n", + " \"v8\": 230000,\n", + " \"v9\": 230000,\n", + "}\n", "for node, nom_voltage in nominal_voltages.items():\n", - " print(node + ': ' + str(phasors[node]['abs'].values[0] / nom_voltage) + '<' + str(phasors[node]['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasors[node][\"abs\"].values[0] / nom_voltage)\n", + " + \"<\"\n", + " + str(phasors[node][\"phase\"].values[0])\n", + " )" ] }, { @@ -218,7 +258,7 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(1, phasors['v9']['phase'])\n", + "pt.plot_timeseries(1, phasors[\"v9\"][\"phase\"])\n", "plt.ylim([2.10405, 2.1042])" ] }, @@ -235,7 +275,7 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(1, phasors_init['n00007f00']['phase'])\n", + "pt.plot_timeseries(1, phasors_init[\"n00007f00\"][\"phase\"])\n", "plt.ylim([2.10405, 2.1042])" ] }, @@ -253,7 +293,13 @@ "outputs": [], "source": [ "for node, phasor in phasors.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1])\n", + " )" ] }, { @@ -262,17 +308,17 @@ "metadata": {}, "outputs": [], "source": [ - "pt.plot_timeseries(1, phasors['v1']['abs'])\n", - "pt.plot_timeseries(1, phasors['v2']['abs'])\n", - "pt.plot_timeseries(1, phasors['v3']['abs'])\n", + "pt.plot_timeseries(1, phasors[\"v1\"][\"abs\"])\n", + "pt.plot_timeseries(1, phasors[\"v2\"][\"abs\"])\n", + "pt.plot_timeseries(1, phasors[\"v3\"][\"abs\"])\n", "\n", - "pt.plot_timeseries(2, phasors['v4']['abs'])\n", - "pt.plot_timeseries(2, phasors['v5']['abs'])\n", - "pt.plot_timeseries(2, phasors['v6']['abs'])\n", - "pt.plot_timeseries(2, phasors['v7']['abs'])\n", - "pt.plot_timeseries(2, phasors['v8']['abs'])\n", - "pt.plot_timeseries(2, phasors['v9']['abs'])\n", - "plt.gca().axes.set_ylim([200000,240000])" + "pt.plot_timeseries(2, phasors[\"v4\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v5\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v6\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v7\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v8\"][\"abs\"])\n", + "pt.plot_timeseries(2, phasors[\"v9\"][\"abs\"])\n", + "plt.gca().axes.set_ylim([200000, 240000])" ] }, { @@ -289,11 +335,11 @@ "outputs": [], "source": [ "for node, phasor in phasors.items():\n", - " abs_diff = phasor['abs'].values[-1] - phasor['abs'].values[0]\n", + " abs_diff = phasor[\"abs\"].values[-1] - phasor[\"abs\"].values[0]\n", " assert abs_diff < 20\n", - " phase_diff = phasor['phase'].values[-1] - phasor['phase'].values[0]\n", + " phase_diff = phasor[\"phase\"].values[-1] - phasor[\"phase\"].values[0]\n", " assert phase_diff < 0.001\n", - " print(node + ': ' + str(abs_diff) + '<' + str(phase_diff))" + " print(node + \": \" + str(abs_diff) + \"<\" + str(phase_diff))" ] } ], diff --git a/examples/Notebooks/Grids/EMT_CIGRE_MV_withDG.ipynb b/examples/Notebooks/Grids/EMT_CIGRE_MV_withDG.ipynb index b80d326ebe..404f27a6c1 100644 --- a/examples/Notebooks/Grids/EMT_CIGRE_MV_withDG.ipynb +++ b/examples/Notebooks/Grids/EMT_CIGRE_MV_withDG.ipynb @@ -25,18 +25,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -68,7 +70,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'EMT_CIGRE_MV_withDG'\n", + "sim_name = \"EMT_CIGRE_MV_withDG\"\n", "sim_name_pf = sim_name + \"_Powerflow\"" ] }, @@ -86,30 +88,64 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system_pf = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_pf = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "pv_active_power = 50e3 * int(int(4319.1e3 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system_pf.node('N' + str(n))\n", - " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power = 5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system_pf.node(\"N\" + str(n))\n", + " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system_pf.add(pv)\n", " system_pf.connect_component(pv, [connection_node])\n", "\n", "\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", - " logger_pf.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_pf.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", "sim_pf.set_system(system_pf)\n", @@ -121,7 +157,7 @@ "sim_pf.do_init_from_nodes_and_terminals(True)\n", "\n", "sim_pf.add_logger(logger_pf)\n", - "sim_pf.run()\n" + "sim_pf.run()" ] }, { @@ -138,67 +174,108 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader2 = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.info, dpsimpy.LogLevel.debug)\n", - "system_emt = reader2.loadCIM(50, files, dpsimpy.Domain.EMT, dpsimpy.PhaseType.ABC, dpsimpy.GeneratorType.NONE)\n", + "system_emt = reader2.loadCIM(\n", + " 50, files, dpsimpy.Domain.EMT, dpsimpy.PhaseType.ABC, dpsimpy.GeneratorType.NONE\n", + ")\n", "\n", "pv_active_power = 50e3 * int(int(4319.1e3 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system_emt.node('N' + str(n))\n", - " pv = dpsimpy.emt.ph3.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power=5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3, omega = 2 * np.pi * 50)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system_emt.node(\"N\" + str(n))\n", + " pv = dpsimpy.emt.ph3.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " omega=2 * np.pi * 50,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system_emt.add(pv)\n", " system_emt.connect_component(pv, [connection_node])\n", "\n", "system_emt.init_with_powerflow(system_pf, dpsimpy.Domain.EMT)\n", "\n", "# log node voltages\n", - "logger_emt= dpsimpy.Logger(sim_name)\n", + "logger_emt = dpsimpy.Logger(sim_name)\n", "for node in system_emt.nodes:\n", - " logger_emt.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_emt.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "# log line and load currents\n", "for comp in system_emt.components:\n", " if isinstance(comp, dpsimpy.emt.ph3.PiLine):\n", - " logger_emt.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_emt.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", " if isinstance(comp, dpsimpy.emt.ph3.RXLoad):\n", - " logger_emt.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_emt.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", "\n", "# log output of PV connected at N11\n", - "pv_name = 'pv_N11'\n", + "pv_name = \"pv_N11\"\n", "pv = system_emt.component(pv_name)\n", "input_names = [\n", - " \"pv_powerctrl_input_pref\", \"pv_powerctrl_input_qref\", \"pv_powerctrl_input_vcd\",\n", - " \"pv_powerctrl_input_vcq\", \"pv_powerctrl_input_ircd\", \"pv_powerctrl_input_ircq\"\n", + " \"pv_powerctrl_input_pref\",\n", + " \"pv_powerctrl_input_qref\",\n", + " \"pv_powerctrl_input_vcd\",\n", + " \"pv_powerctrl_input_vcq\",\n", + " \"pv_powerctrl_input_ircd\",\n", + " \"pv_powerctrl_input_ircq\",\n", "]\n", - "logger_emt.log_attribute(input_names, 'powerctrl_inputs', pv)\n", + "logger_emt.log_attribute(input_names, \"powerctrl_inputs\", pv)\n", "\n", "state_names = [\n", - " \"pv_powerctrl_state_p\", \"pv_powerctrl_state_q\", \"pv_powerctrl_state_phid\",\n", - " \"pv_powerctrl_state_phiq\", \"pv_powerctrl_state_gammad\", \"pv_powerctrl_state_gammaq\"\n", + " \"pv_powerctrl_state_p\",\n", + " \"pv_powerctrl_state_q\",\n", + " \"pv_powerctrl_state_phid\",\n", + " \"pv_powerctrl_state_phiq\",\n", + " \"pv_powerctrl_state_gammad\",\n", + " \"pv_powerctrl_state_gammaq\",\n", "]\n", - "logger_emt.log_attribute(state_names, 'powerctrl_states', pv)\n", + "logger_emt.log_attribute(state_names, \"powerctrl_states\", pv)\n", "\n", - "output_names = [\n", - " \"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"\n", - "]\n", + "output_names = [\"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"]\n", "\n", - "logger_emt.log_attribute(output_names, 'powerctrl_outputs', pv)\n", + "logger_emt.log_attribute(output_names, \"powerctrl_outputs\", pv)\n", "\n", - "logger_emt.log_attribute(pv_name + '_v_intf', 'v_intf', pv)\n", - "logger_emt.log_attribute(pv_name + '_i_intf', 'i_intf', pv)\n", - "logger_emt.log_attribute(pv_name + '_pll_output', 'pll_output', pv)\n", - "logger_emt.log_attribute(pv_name + '_vsref', 'Vsref', pv)\n", - "logger_emt.log_attribute(pv_name + '_vs', 'Vs', pv)\n", + "logger_emt.log_attribute(pv_name + \"_v_intf\", \"v_intf\", pv)\n", + "logger_emt.log_attribute(pv_name + \"_i_intf\", \"i_intf\", pv)\n", + "logger_emt.log_attribute(pv_name + \"_pll_output\", \"pll_output\", pv)\n", + "logger_emt.log_attribute(pv_name + \"_vsref\", \"Vsref\", pv)\n", + "logger_emt.log_attribute(pv_name + \"_vs\", \"Vs\", pv)\n", "\n", "sim_emt = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", "sim_emt.set_system(system_emt)\n", @@ -236,11 +313,11 @@ "outputs": [], "source": [ "time_step = 0.001\n", - "num_steps_window = int(0.02/time_step)\n", + "num_steps_window = int(0.02 / time_step)\n", "\n", - "modelName = 'EMT_CIGRE_MV_withDG_Powerflow'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"EMT_CIGRE_MV_withDG_Powerflow\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim_powerflow = read_timeseries_csv(dpsim_result_file)" ] @@ -259,9 +336,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", - " if ts_name != 'N0.V':\n", + "plt.figure(figsize=(12, 8))\n", + "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", + " if ts_name != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -281,8 +358,14 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -307,9 +390,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'EMT_CIGRE_MV_withDG'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"EMT_CIGRE_MV_withDG\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -336,15 +419,15 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,12))\n", + "plt.figure(figsize=(12, 12))\n", "subplot_number = 1\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-3:] == 'V_0' and ts_name[:-2] != 'N0.V':\n", - " plt.subplot(4,3,subplot_number)\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-3:] == \"V_0\" and ts_name[:-2] != \"N0.V\":\n", + " plt.subplot(4, 3, subplot_number)\n", " subplot_number += 1\n", " plt.plot(ts_obj.time, ts_obj.values, label=ts_name)\n", - " plt.legend(loc='upper right')\n", - " plt.xlim([-0.03,1])\n", + " plt.legend(loc=\"upper right\")\n", + " plt.xlim([-0.03, 1])\n", "plt.show()" ] }, @@ -362,9 +445,9 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-3:] == 'V_0':\n", - " print(ts_name + ': ' + str(ts_obj.values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-3:] == \"V_0\":\n", + " print(ts_name + \": \" + str(ts_obj.values[0]))" ] }, { @@ -381,9 +464,9 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-3:] == 'V_0':\n", - " print(ts_name + ': ' + str(max(ts_obj.values[-num_steps_window:])))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-3:] == \"V_0\":\n", + " print(ts_name + \": \" + str(max(ts_obj.values[-num_steps_window:])))" ] }, { @@ -408,9 +491,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-7:]=='state_p' or ts_name[-7:]=='state_q':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-7:] == \"state_p\" or ts_name[-7:] == \"state_q\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -430,9 +513,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-7:]!='state_p' and ts_name[-7:]!='state_q' and 'state' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-7:] != \"state_p\" and ts_name[-7:] != \"state_q\" and \"state\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -452,9 +535,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'state' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"state\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -471,9 +560,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'state' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"state\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -490,9 +585,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -512,9 +607,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -531,9 +632,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'input' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"input\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -550,9 +657,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -572,9 +679,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[0]) + ', ' + str(ts_obj.phase().values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[0])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[0])\n", + " )" ] }, { @@ -591,9 +704,15 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'output' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.abs().values[-1]) + ', ' + str(ts_obj.phase().values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"output\" in ts_name:\n", + " print(\n", + " ts_name\n", + " + \": \"\n", + " + str(ts_obj.abs().values[-1])\n", + " + \", \"\n", + " + str(ts_obj.phase().values[-1])\n", + " )" ] }, { @@ -610,14 +729,14 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "subplot_number = 1 \n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", - " plt.subplot(2,3,subplot_number)\n", + "plt.figure(figsize=(12, 6))\n", + "subplot_number = 1\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", + " plt.subplot(2, 3, subplot_number)\n", " subplot_number += 1\n", " plt.plot(ts_obj.time, ts_obj.values, label=ts_name)\n", - " plt.legend(loc='upper right')\n", + " plt.legend(loc=\"upper right\")\n", "plt.show()" ] }, @@ -635,11 +754,17 @@ "metadata": {}, "outputs": [], "source": [ - "pv_N11_p_inst_intf = ts_dpsim['pv_N11_v_intf_0'].values*ts_dpsim['pv_N11_i_intf_0'].values+ts_dpsim['pv_N11_v_intf_1'].values*ts_dpsim['pv_N11_i_intf_1'].values+ts_dpsim['pv_N11_v_intf_2'].values*ts_dpsim['pv_N11_i_intf_2'].values\n", - "plt.figure(figsize=(12,6))\n", - "plt.plot(ts_dpsim['pv_N11_v_intf_0'].time, pv_N11_p_inst_intf, label='pv_N11_p_inst_intf')\n", + "pv_N11_p_inst_intf = (\n", + " ts_dpsim[\"pv_N11_v_intf_0\"].values * ts_dpsim[\"pv_N11_i_intf_0\"].values\n", + " + ts_dpsim[\"pv_N11_v_intf_1\"].values * ts_dpsim[\"pv_N11_i_intf_1\"].values\n", + " + ts_dpsim[\"pv_N11_v_intf_2\"].values * ts_dpsim[\"pv_N11_i_intf_2\"].values\n", + ")\n", + "plt.figure(figsize=(12, 6))\n", + "plt.plot(\n", + " ts_dpsim[\"pv_N11_v_intf_0\"].time, pv_N11_p_inst_intf, label=\"pv_N11_p_inst_intf\"\n", + ")\n", "plt.legend()\n", - "plt.show()\n" + "plt.show()" ] }, { @@ -656,10 +781,10 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.values[0]))\n", - "print('pv_N11_p_inst_intf' + ': ' + str(pv_N11_p_inst_intf[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", + " print(ts_name + \": \" + str(ts_obj.values[0]))\n", + "print(\"pv_N11_p_inst_intf\" + \": \" + str(pv_N11_p_inst_intf[0]))" ] }, { @@ -676,10 +801,10 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if 'intf' in ts_name:\n", - " print(ts_name + ': ' + str(ts_obj.values[-1]))\n", - "print('pv_N11_p_inst_intf' + ': ' + str(pv_N11_p_inst_intf[-1:]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if \"intf\" in ts_name:\n", + " print(ts_name + \": \" + str(ts_obj.values[-1]))\n", + "print(\"pv_N11_p_inst_intf\" + \": \" + str(pv_N11_p_inst_intf[-1:]))" ] } ], diff --git a/examples/Notebooks/Grids/EMT_CIGRE_MV_withDG_withLoadStep.ipynb b/examples/Notebooks/Grids/EMT_CIGRE_MV_withDG_withLoadStep.ipynb index a6d8d10faa..738496a6a9 100644 --- a/examples/Notebooks/Grids/EMT_CIGRE_MV_withDG_withLoadStep.ipynb +++ b/examples/Notebooks/Grids/EMT_CIGRE_MV_withDG_withLoadStep.ipynb @@ -25,18 +25,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -68,7 +70,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'EMT_CIGRE_MV_withDG_withLoadStep'\n", + "sim_name = \"EMT_CIGRE_MV_withDG_withLoadStep\"\n", "sim_name_pf = sim_name + \"_Powerflow\"" ] }, @@ -86,30 +88,64 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system_pf = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_pf = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "pv_active_power = 50e3 * int(int(4319.1e3 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system_pf.node('N' + str(n))\n", - " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power = 5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system_pf.node(\"N\" + str(n))\n", + " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system_pf.add(pv)\n", " system_pf.connect_component(pv, [connection_node])\n", "\n", "\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", - " logger_pf.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_pf.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", "sim_pf.set_system(system_pf)\n", @@ -121,7 +157,7 @@ "sim_pf.do_init_from_nodes_and_terminals(True)\n", "\n", "sim_pf.add_logger(logger_pf)\n", - "sim_pf.run()\n" + "sim_pf.run()" ] }, { @@ -138,78 +174,121 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader2 = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.info, dpsimpy.LogLevel.debug)\n", - "system_emt = reader2.loadCIM(50, files, dpsimpy.Domain.EMT, dpsimpy.PhaseType.ABC, dpsimpy.GeneratorType.NONE)\n", + "system_emt = reader2.loadCIM(\n", + " 50, files, dpsimpy.Domain.EMT, dpsimpy.PhaseType.ABC, dpsimpy.GeneratorType.NONE\n", + ")\n", "\n", "pv_active_power = 50e3 * int(int(4319.1e3 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system_emt.node('N' + str(n))\n", - " pv = dpsimpy.emt.ph3.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power=5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3, omega = 2 * np.pi * 50)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system_emt.node(\"N\" + str(n))\n", + " pv = dpsimpy.emt.ph3.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " omega=2 * np.pi * 50,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system_emt.add(pv)\n", " system_emt.connect_component(pv, [connection_node])\n", "\n", "system_emt.init_with_powerflow(system_pf, dpsimpy.Domain.EMT)\n", "\n", "# log node voltages\n", - "logger_emt= dpsimpy.Logger(sim_name)\n", + "logger_emt = dpsimpy.Logger(sim_name)\n", "for node in system_emt.nodes:\n", - " logger_emt.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_emt.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "# log line and load currents\n", "for comp in system_emt.components:\n", " if isinstance(comp, dpsimpy.emt.ph3.PiLine):\n", - " logger_emt.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_emt.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", " if isinstance(comp, dpsimpy.emt.ph3.RXLoad):\n", - " logger_emt.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_emt.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", "\n", "# log output of PV connected at N11\n", - "pv_name = 'pv_N11'\n", + "pv_name = \"pv_N11\"\n", "pv = system_emt.component(pv_name)\n", "input_names = [\n", - " \"pv_powerctrl_input_pref\", \"pv_powerctrl_input_qref\", \"pv_powerctrl_input_vcd\",\n", - " \"pv_powerctrl_input_vcq\", \"pv_powerctrl_input_ircd\", \"pv_powerctrl_input_ircq\"\n", + " \"pv_powerctrl_input_pref\",\n", + " \"pv_powerctrl_input_qref\",\n", + " \"pv_powerctrl_input_vcd\",\n", + " \"pv_powerctrl_input_vcq\",\n", + " \"pv_powerctrl_input_ircd\",\n", + " \"pv_powerctrl_input_ircq\",\n", "]\n", - "logger_emt.log_attribute(input_names, 'powerctrl_inputs', pv)\n", + "logger_emt.log_attribute(input_names, \"powerctrl_inputs\", pv)\n", "\n", "state_names = [\n", - " \"pv_powerctrl_state_p\", \"pv_powerctrl_state_q\", \"pv_powerctrl_state_phid\",\n", - " \"pv_powerctrl_state_phiq\", \"pv_powerctrl_state_gammad\", \"pv_powerctrl_state_gammaq\"\n", + " \"pv_powerctrl_state_p\",\n", + " \"pv_powerctrl_state_q\",\n", + " \"pv_powerctrl_state_phid\",\n", + " \"pv_powerctrl_state_phiq\",\n", + " \"pv_powerctrl_state_gammad\",\n", + " \"pv_powerctrl_state_gammaq\",\n", "]\n", - "logger_emt.log_attribute(state_names, 'powerctrl_states', pv)\n", + "logger_emt.log_attribute(state_names, \"powerctrl_states\", pv)\n", "\n", - "output_names = [\n", - " \"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"\n", - "]\n", + "output_names = [\"pv_powerctrl_output_vsd\", \"pv_powerctrl_output_vsq\"]\n", "\n", - "logger_emt.log_attribute(output_names, 'powerctrl_outputs', pv)\n", + "logger_emt.log_attribute(output_names, \"powerctrl_outputs\", pv)\n", "\n", - "logger_emt.log_attribute(pv_name + '_v_intf', 'v_intf', pv)\n", - "logger_emt.log_attribute(pv_name + '_i_intf', 'i_intf', pv)\n", - "logger_emt.log_attribute(pv_name + '_pll_output', 'pll_output', pv)\n", - "logger_emt.log_attribute(pv_name + '_vsref', 'Vsref', pv)\n", - "logger_emt.log_attribute(pv_name + '_vs', 'Vs', pv)\n", + "logger_emt.log_attribute(pv_name + \"_v_intf\", \"v_intf\", pv)\n", + "logger_emt.log_attribute(pv_name + \"_i_intf\", \"i_intf\", pv)\n", + "logger_emt.log_attribute(pv_name + \"_pll_output\", \"pll_output\", pv)\n", + "logger_emt.log_attribute(pv_name + \"_vsref\", \"Vsref\", pv)\n", + "logger_emt.log_attribute(pv_name + \"_vs\", \"Vs\", pv)\n", "\n", "# load step sized in absolute terms\n", "load_switch = dpsimpy.emt.ph3.Switch(\"Load_Add_Switch_N11\", dpsimpy.LogLevel.debug)\n", - "connection_node = system_emt.node('N11')\n", - "resistance = np.abs(connection_node.initial_single_voltage())**2 / 1500.0e3\n", + "connection_node = system_emt.node(\"N11\")\n", + "resistance = np.abs(connection_node.initial_single_voltage()) ** 2 / 1500.0e3\n", "load_switch.set_parameters(np.identity(3) * 1e9, np.identity(3) * resistance)\n", "load_switch.open()\n", "system_emt.add(load_switch)\n", - "system_emt.connect_component(load_switch, [dpsimpy.emt.SimNode.gnd, system_emt.node('N11')])\n", - "logger_emt.log_attribute('switchedload_i', 'i_intf', load_switch)\n", - "load_step_event = dpsimpy.event.SwitchEvent3Ph(2 - time_step, load_switch, True)\n", + "system_emt.connect_component(\n", + " load_switch, [dpsimpy.emt.SimNode.gnd, system_emt.node(\"N11\")]\n", + ")\n", + "logger_emt.log_attribute(\"switchedload_i\", \"i_intf\", load_switch)\n", + "load_step_event = dpsimpy.event.SwitchEvent3Ph(2 - time_step, load_switch, True)\n", "\n", "\n", "sim_emt = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", @@ -248,9 +327,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'EMT_CIGRE_MV_withDG_withLoadStep_Powerflow'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"EMT_CIGRE_MV_withDG_withLoadStep_Powerflow\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -269,9 +348,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name != 'N0.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -291,9 +370,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'EMT_CIGRE_MV_withDG_withLoadStep'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"EMT_CIGRE_MV_withDG_withLoadStep\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -320,9 +399,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-3:] == 'V_0' and ts_name[:-2] != 'N0.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-3:] == \"V_0\" and ts_name[:-2] != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -342,9 +421,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-3:] == 'I_0':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-3:] == \"I_0\":\n", " plt.plot(ts_obj.time, ts_obj.values, label=ts_name)\n", "plt.legend()\n", "plt.show()" diff --git a/examples/Notebooks/Grids/EMT_CIGRE_MV_withoutDG.ipynb b/examples/Notebooks/Grids/EMT_CIGRE_MV_withoutDG.ipynb index 7dfbf10b54..d26a8b2b1a 100644 --- a/examples/Notebooks/Grids/EMT_CIGRE_MV_withoutDG.ipynb +++ b/examples/Notebooks/Grids/EMT_CIGRE_MV_withoutDG.ipynb @@ -25,18 +25,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -68,7 +70,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'EMT_CIGRE_MV_withoutDG'\n", + "sim_name = \"EMT_CIGRE_MV_withoutDG\"\n", "sim_name_pf = sim_name + \"_Powerflow\"" ] }, @@ -86,13 +88,15 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system_pf = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system_pf = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", - " logger_pf.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_pf.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", "sim_pf.set_system(system_pf)\n", @@ -104,7 +108,7 @@ "sim_pf.do_init_from_nodes_and_terminals(True)\n", "\n", "sim_pf.add_logger(logger_pf)\n", - "sim_pf.run()\n" + "sim_pf.run()" ] }, { @@ -121,23 +125,25 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader2 = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.info, dpsimpy.LogLevel.debug)\n", - "system_emt = reader2.loadCIM(50, files, dpsimpy.Domain.EMT, dpsimpy.PhaseType.ABC, dpsimpy.GeneratorType.NONE)\n", + "system_emt = reader2.loadCIM(\n", + " 50, files, dpsimpy.Domain.EMT, dpsimpy.PhaseType.ABC, dpsimpy.GeneratorType.NONE\n", + ")\n", "\n", "system_emt.init_with_powerflow(system_pf, dpsimpy.Domain.EMT)\n", "\n", "# log node voltages\n", - "logger_emt= dpsimpy.Logger(sim_name)\n", + "logger_emt = dpsimpy.Logger(sim_name)\n", "for node in system_emt.nodes:\n", - " logger_emt.log_attribute(node.name() + '.V', 'v', node)\n", + " logger_emt.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "# log line and load currents\n", "for comp in system_emt.components:\n", " if isinstance(comp, dpsimpy.emt.ph3.PiLine):\n", - " logger_emt.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_emt.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", " if isinstance(comp, dpsimpy.emt.ph3.RXLoad):\n", - " logger_emt.log_attribute(comp.name() + '.I', 'i_intf', comp)\n", + " logger_emt.log_attribute(comp.name() + \".I\", \"i_intf\", comp)\n", "\n", "sim_emt = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", "sim_emt.set_system(system_emt)\n", @@ -174,9 +180,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'EMT_CIGRE_MV_withoutDG'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"EMT_CIGRE_MV_withoutDG\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim_powerflow = read_timeseries_csv(dpsim_result_file)" ] @@ -195,9 +201,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", - " if ts_name != 'N0.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim_powerflow.items():\n", + " if ts_name != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" @@ -225,9 +231,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'EMT_CIGRE_MV_withoutDG'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"EMT_CIGRE_MV_withoutDG\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -246,12 +252,16 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-3:] == 'V_0' and ts_name[:-2] != 'N0.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-3:] == \"V_0\" and ts_name[:-2] != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.values, label=ts_name)\n", - " plt.plot(ts_dpsim_powerflow[ts_name].time, np.sqrt(2/3)*ts_dpsim_powerflow[ts_name].abs().values, label=ts_name)\n", - "plt.xlim([0,0.1])\n", + " plt.plot(\n", + " ts_dpsim_powerflow[ts_name].time,\n", + " np.sqrt(2 / 3) * ts_dpsim_powerflow[ts_name].abs().values,\n", + " label=ts_name,\n", + " )\n", + "plt.xlim([0, 0.1])\n", "plt.legend()\n", "plt.show()" ] @@ -270,9 +280,9 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-4:] == '.V_0':\n", - " print(ts_name + ': ' + str(ts_obj.values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-4:] == \".V_0\":\n", + " print(ts_name + \": \" + str(ts_obj.values[0]))" ] }, { @@ -289,9 +299,9 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-4:] == '.V_0':\n", - " print(ts_name + ': ' + str(ts_obj.values[-1:]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-4:] == \".V_0\":\n", + " print(ts_name + \": \" + str(ts_obj.values[-1:]))" ] }, { @@ -308,12 +318,12 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-4:] == '.I_0' and ts_name[:4]=='LOAD':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-4:] == \".I_0\" and ts_name[:4] == \"LOAD\":\n", " plt.plot(ts_obj.time, ts_obj.values, label=ts_name)\n", - "#plt.xlim([0,0.1])\n", - "plt.legend(loc='upper right')\n", + "# plt.xlim([0,0.1])\n", + "plt.legend(loc=\"upper right\")\n", "plt.show()" ] }, @@ -331,9 +341,9 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-4:] == '.I_0' and ts_name[:4]=='LOAD':\n", - " print(ts_name + ': ' + str(ts_obj.values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-4:] == \".I_0\" and ts_name[:4] == \"LOAD\":\n", + " print(ts_name + \": \" + str(ts_obj.values[0]))" ] }, { @@ -350,9 +360,9 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-4:] == '.I_0' and ts_name[:4]=='LOAD':\n", - " print(ts_name + ': ' + str(ts_obj.values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-4:] == \".I_0\" and ts_name[:4] == \"LOAD\":\n", + " print(ts_name + \": \" + str(ts_obj.values[-1]))" ] }, { @@ -372,8 +382,16 @@ "# load_I_3_p ref from CIM: P=225250, Q=139597\n", "# load_H_11_p ref from CIM: P=329800, Q=82656\n", "\n", - "load_I_3_p = ts_dpsim['N3.V_0'].values*ts_dpsim['LOAD-I-3.I_0'].values+ts_dpsim['N3.V_1'].values*ts_dpsim['LOAD-I-3.I_1'].values+ts_dpsim['N3.V_2'].values*ts_dpsim['LOAD-I-3.I_2'].values\n", - "load_H_11_p = ts_dpsim['N11.V_0'].values*ts_dpsim['LOAD-H-11.I_0'].values+ts_dpsim['N11.V_1'].values*ts_dpsim['LOAD-H-11.I_1'].values+ts_dpsim['N11.V_2'].values*ts_dpsim['LOAD-H-11.I_2'].values" + "load_I_3_p = (\n", + " ts_dpsim[\"N3.V_0\"].values * ts_dpsim[\"LOAD-I-3.I_0\"].values\n", + " + ts_dpsim[\"N3.V_1\"].values * ts_dpsim[\"LOAD-I-3.I_1\"].values\n", + " + ts_dpsim[\"N3.V_2\"].values * ts_dpsim[\"LOAD-I-3.I_2\"].values\n", + ")\n", + "load_H_11_p = (\n", + " ts_dpsim[\"N11.V_0\"].values * ts_dpsim[\"LOAD-H-11.I_0\"].values\n", + " + ts_dpsim[\"N11.V_1\"].values * ts_dpsim[\"LOAD-H-11.I_1\"].values\n", + " + ts_dpsim[\"N11.V_2\"].values * ts_dpsim[\"LOAD-H-11.I_2\"].values\n", + ")" ] }, { @@ -382,11 +400,11 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "plt.plot(ts_dpsim['N3.V_0'].time, load_I_3_p, label='load_I_3_p')\n", - "plt.plot(ts_dpsim['N11.V_0'].time, load_H_11_p, label='load_H_11_p')\n", - "#plt.xlim([0,0.01])\n", - "plt.legend(loc='upper right')\n", + "plt.figure(figsize=(12, 6))\n", + "plt.plot(ts_dpsim[\"N3.V_0\"].time, load_I_3_p, label=\"load_I_3_p\")\n", + "plt.plot(ts_dpsim[\"N11.V_0\"].time, load_H_11_p, label=\"load_H_11_p\")\n", + "# plt.xlim([0,0.01])\n", + "plt.legend(loc=\"upper right\")\n", "plt.show()" ] }, @@ -404,8 +422,8 @@ "metadata": {}, "outputs": [], "source": [ - "print('Load-I-3.p' + ': ' + str(load_I_3_p[0]))\n", - "print('Load-H-11.p' + ': ' + str(load_H_11_p[0]))" + "print(\"Load-I-3.p\" + \": \" + str(load_I_3_p[0]))\n", + "print(\"Load-H-11.p\" + \": \" + str(load_H_11_p[0]))" ] }, { @@ -422,8 +440,8 @@ "metadata": {}, "outputs": [], "source": [ - "print('Load-I-3.p' + ': ' + str(load_I_3_p[-1]))\n", - "print('Load-H-11.p' + ': ' + str(load_H_11_p[-1]))" + "print(\"Load-I-3.p\" + \": \" + str(load_I_3_p[-1]))\n", + "print(\"Load-H-11.p\" + \": \" + str(load_H_11_p[-1]))" ] }, { @@ -440,12 +458,12 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-4:] == '.I_0' and ts_name[:4]!='LOAD':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-4:] == \".I_0\" and ts_name[:4] != \"LOAD\":\n", " plt.plot(ts_obj.time, ts_obj.values, label=ts_name)\n", - "#plt.xlim([0,0.1])\n", - "plt.legend(loc='upper right')\n", + "# plt.xlim([0,0.1])\n", + "plt.legend(loc=\"upper right\")\n", "plt.show()" ] }, @@ -463,9 +481,9 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-4:] == '.I_0' and ts_name[:4]!='LOAD':\n", - " print(ts_name + ': ' + str(ts_obj.values[0]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-4:] == \".I_0\" and ts_name[:4] != \"LOAD\":\n", + " print(ts_name + \": \" + str(ts_obj.values[0]))" ] }, { @@ -482,9 +500,9 @@ "metadata": {}, "outputs": [], "source": [ - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name[-4:] == '.I_0' and ts_name[:4]!='LOAD':\n", - " print(ts_name + ': ' + str(ts_obj.values[-1]))" + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name[-4:] == \".I_0\" and ts_name[:4] != \"LOAD\":\n", + " print(ts_name + \": \" + str(ts_obj.values[-1]))" ] } ], diff --git a/examples/Notebooks/Grids/IEEE_LV_powerflow.ipynb b/examples/Notebooks/Grids/IEEE_LV_powerflow.ipynb index 556dfcf315..891f000f96 100644 --- a/examples/Notebooks/Grids/IEEE_LV_powerflow.ipynb +++ b/examples/Notebooks/Grids/IEEE_LV_powerflow.ipynb @@ -23,18 +23,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/IEEE_EU_LV/IEEE_EU_LV_reduced/'\n", - "filename = 'IEEE_EU_LV'\n", - "download_grid_data(filename+'_EQ.xml', url+'Rootnet_FULL_NE_13J16h_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'Rootnet_FULL_NE_13J16h_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'Rootnet_FULL_NE_13J16h_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/IEEE_EU_LV/IEEE_EU_LV_reduced/\"\n", + "filename = \"IEEE_EU_LV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"Rootnet_FULL_NE_13J16h_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"Rootnet_FULL_NE_13J16h_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"Rootnet_FULL_NE_13J16h_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -63,7 +65,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'IEEE_EU_LV_reduced'" + "sim_name = \"IEEE_EU_LV_reduced\"" ] }, { @@ -73,11 +75,13 @@ "outputs": [], "source": [ "reader = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.info, dpsimpy.LogLevel.off)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.NONE)\n", + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.NONE\n", + ")\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name() + '.V', 'v', node)\n", + " logger.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", "sim.set_system(system)\n", @@ -88,7 +92,7 @@ "sim.do_init_from_nodes_and_terminals(True)\n", "\n", "sim.add_logger(logger)\n", - "sim.run()\n" + "sim.run()" ] }, { @@ -104,14 +108,14 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/'\n", - "logName = 'IEEE_EU_LV_reduced'\n", - "dpsim_result_file = path + logName + '.csv'\n", + "path = \"logs/\"\n", + "logName = \"IEEE_EU_LV_reduced\"\n", + "dpsim_result_file = path + logName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)\n", "\n", "# Fix for dpsim naming - TODO: unify dpsim notation in log file and update villas-dataprocessing accordingly\n", - "for ts,values in ts_dpsim.items():\n", + "for ts, values in ts_dpsim.items():\n", " values.name = values.name[:-2]" ] }, @@ -131,12 +135,12 @@ "import os\n", "import urllib\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Neplan/ReferenceGrids/IEEE_EU_LV.rlf'\n", - "neplan_result_file = 'reference-results/IEEE_EU_LV.rlf'\n", - "urllib.request.urlretrieve(url, neplan_result_file) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Neplan/ReferenceGrids/IEEE_EU_LV.rlf\"\n", + "neplan_result_file = \"reference-results/IEEE_EU_LV.rlf\"\n", + "urllib.request.urlretrieve(url, neplan_result_file)\n", "print(neplan_result_file)\n", "\n", "ts_NEPLAN = read_timeseries_NEPLAN_loadflow(neplan_result_file)\n", @@ -156,15 +160,19 @@ "metadata": {}, "outputs": [], "source": [ - "net_name='IEEE_EU_LV_reduced'\n", - "threshold=0.5\n", + "net_name = \"IEEE_EU_LV_reduced\"\n", + "threshold = 0.5\n", "\n", - "ts_NEPLAN_standardized=validationtools.convert_neplan_to_standard_timeseries(ts_NEPLAN)\n", - "#print([[ts_NEPLAN_standardized[i].name, ts_NEPLAN_standardized[i].values] for i in range(len(ts_NEPLAN_standardized))])\n", - "ts_dpsim_standardized=validationtools.convert_dpsim_to_standard_timeseries(ts_dpsim)\n", - "#print([[ts_dpsim_standardized[i].name, ts_dpsim_standardized[i].values] for i in range(len(ts_dpsim_standardized))])\n", - "res_err=validationtools.compare_timeseries(ts_NEPLAN_standardized,ts_dpsim_standardized)\n", - "validationtools.assert_modelica_results(net_name,res_err,threshold)" + "ts_NEPLAN_standardized = validationtools.convert_neplan_to_standard_timeseries(\n", + " ts_NEPLAN\n", + ")\n", + "# print([[ts_NEPLAN_standardized[i].name, ts_NEPLAN_standardized[i].values] for i in range(len(ts_NEPLAN_standardized))])\n", + "ts_dpsim_standardized = validationtools.convert_dpsim_to_standard_timeseries(ts_dpsim)\n", + "# print([[ts_dpsim_standardized[i].name, ts_dpsim_standardized[i].values] for i in range(len(ts_dpsim_standardized))])\n", + "res_err = validationtools.compare_timeseries(\n", + " ts_NEPLAN_standardized, ts_dpsim_standardized\n", + ")\n", + "validationtools.assert_modelica_results(net_name, res_err, threshold)" ] } ], diff --git a/examples/Notebooks/Grids/PF_CIGRE_MV_withDG.ipynb b/examples/Notebooks/Grids/PF_CIGRE_MV_withDG.ipynb index 895c85570c..8b093a85c0 100644 --- a/examples/Notebooks/Grids/PF_CIGRE_MV_withDG.ipynb +++ b/examples/Notebooks/Grids/PF_CIGRE_MV_withDG.ipynb @@ -30,18 +30,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_noLoad1_LeftFeeder_With_LoadFlow_Results/Rootnet_FULL_NE_28J17h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -63,7 +65,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'PF_CIGRE_MV_withDG'" + "sim_name = \"PF_CIGRE_MV_withDG\"" ] }, { @@ -79,30 +81,64 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "pv_active_power = 50e3 * int(int(4319.1e3 / 50e3) / 9)\n", - "pv_reactive_power = np.sqrt(np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2))\n", + "pv_reactive_power = np.sqrt(\n", + " np.power(pv_active_power / 1, 2) - np.power(pv_active_power, 2)\n", + ")\n", "\n", "for n in range(3, 12):\n", - " connection_node = system.node('N' + str(n))\n", - " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ('pv_' + connection_node.name(), 'pv_' + connection_node.name(), dpsimpy.LogLevel.debug, True)\n", - " pv.set_parameters(sys_omega=2 * np.pi * 50, sys_volt_nom=1500, p_ref=pv_active_power, q_ref=pv_reactive_power)\n", - " pv.set_controller_parameters(Kp_pll=0.25 / 10, Ki_pll=2 / 1000,\n", - " Kp_power_ctrl=0.001 / 10, Ki_power_ctrl=0.08 / 1000 ,\n", - " Kp_curr_ctrl=0.3 / 10, Ki_curr_ctrl=10 / 1000, omega_cutoff=2*np.pi*50)\n", - " pv.set_filter_parameters(Lf=0.002,Cf=789.3e-6,Rf=0.1,Rc=0.1)\n", - " pv.set_transformer_parameters(nom_voltage_end_1=20e3, nom_voltage_end_2=1500, rated_power = 5e6,\n", - " ratio_abs=20e3 / 1500, ratio_phase=0,resistance=0, inductance=0.928e-3)\n", - " pv.set_initial_state_values(p_init=450000.716605, q_init=-0.577218, phi_d_init=3854.197405 * 1000, phi_q_init=-0.003737 * 1000, gamma_d_init=128.892668 * 1000, gamma_q_init=23.068682 * 1000)\n", + " connection_node = system.node(\"N\" + str(n))\n", + " pv = dpsimpy.sp.ph1.AvVoltageSourceInverterDQ(\n", + " \"pv_\" + connection_node.name(),\n", + " \"pv_\" + connection_node.name(),\n", + " dpsimpy.LogLevel.debug,\n", + " True,\n", + " )\n", + " pv.set_parameters(\n", + " sys_omega=2 * np.pi * 50,\n", + " sys_volt_nom=1500,\n", + " p_ref=pv_active_power,\n", + " q_ref=pv_reactive_power,\n", + " )\n", + " pv.set_controller_parameters(\n", + " Kp_pll=0.25 / 10,\n", + " Ki_pll=2 / 1000,\n", + " Kp_power_ctrl=0.001 / 10,\n", + " Ki_power_ctrl=0.08 / 1000,\n", + " Kp_curr_ctrl=0.3 / 10,\n", + " Ki_curr_ctrl=10 / 1000,\n", + " omega_cutoff=2 * np.pi * 50,\n", + " )\n", + " pv.set_filter_parameters(Lf=0.002, Cf=789.3e-6, Rf=0.1, Rc=0.1)\n", + " pv.set_transformer_parameters(\n", + " nom_voltage_end_1=20e3,\n", + " nom_voltage_end_2=1500,\n", + " rated_power=5e6,\n", + " ratio_abs=20e3 / 1500,\n", + " ratio_phase=0,\n", + " resistance=0,\n", + " inductance=0.928e-3,\n", + " )\n", + " pv.set_initial_state_values(\n", + " p_init=450000.716605,\n", + " q_init=-0.577218,\n", + " phi_d_init=3854.197405 * 1000,\n", + " phi_q_init=-0.003737 * 1000,\n", + " gamma_d_init=128.892668 * 1000,\n", + " gamma_q_init=23.068682 * 1000,\n", + " )\n", " system.add(pv)\n", " system.connect_component(pv, [connection_node])\n", "\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name() + '.V', 'v', node)\n", + " logger.log_attribute(node.name() + \".V\", \"v\", node)\n", "\n", "sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", "sim.set_system(system)\n", @@ -113,7 +149,7 @@ "sim.do_init_from_nodes_and_terminals(True)\n", "\n", "sim.add_logger(logger)\n", - "sim.run()\n" + "sim.run()" ] }, { @@ -129,9 +165,9 @@ "metadata": {}, "outputs": [], "source": [ - "modelName = 'PF_CIGRE_MV_withDG'\n", - "path = 'logs/' + modelName + '/'\n", - "dpsim_result_file = path + modelName + '.csv'\n", + "modelName = \"PF_CIGRE_MV_withDG\"\n", + "path = \"logs/\" + modelName + \"/\"\n", + "dpsim_result_file = path + modelName + \".csv\"\n", "\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] @@ -149,9 +185,9 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,6))\n", - "for ts_name, ts_obj in ts_dpsim.items():\n", - " if ts_name != 'N0.V':\n", + "plt.figure(figsize=(12, 6))\n", + "for ts_name, ts_obj in ts_dpsim.items():\n", + " if ts_name != \"N0.V\":\n", " plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)\n", "plt.legend()\n", "plt.show()" diff --git a/examples/Notebooks/Grids/SP_SMIB_SynGenTrStab_KundurExample1.ipynb b/examples/Notebooks/Grids/SP_SMIB_SynGenTrStab_KundurExample1.ipynb index 2e3a54927e..5b0df15b4c 100644 --- a/examples/Notebooks/Grids/SP_SMIB_SynGenTrStab_KundurExample1.ipynb +++ b/examples/Notebooks/Grids/SP_SMIB_SynGenTrStab_KundurExample1.ipynb @@ -29,13 +29,18 @@ "import os\n", "import subprocess\n", "\n", - "#%matplotlib widget\n", + "# %matplotlib widget\n", "\n", - "name = 'SP_SynGenTrStab_SMIB_Fault_KundurExample1'\n", + "name = \"SP_SynGenTrStab_SMIB_Fault_KundurExample1\"\n", "\n", - "dpsim_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", + "dpsim_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", "\n", - "path_exec = dpsim_path + '/build/dpsim/examples/cxx/'\n", + "path_exec = dpsim_path + \"/build/dpsim/examples/cxx/\"\n", "\n", "timestep = 100e-6" ] @@ -53,7 +58,11 @@ "metadata": {}, "outputs": [], "source": [ - "sim = subprocess.Popen([path_exec+name, '--name', name, '--timestep', str(timestep)], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + "sim = subprocess.Popen(\n", + " [path_exec + name, \"--name\", name, \"--timestep\", str(timestep)],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + ")\n", "print(sim.communicate()[0].decode())" ] }, @@ -70,9 +79,9 @@ "metadata": {}, "outputs": [], "source": [ - "model_name = 'SynGenTrStab_SMIB_Fault_KundurExample1'\n", - "path_ref = 'logs/' + 'SP_' + model_name + '_SP/'\n", - "dpsim_result_file_ref = path_ref + 'SP_' + model_name + '_SP.csv'\n", + "model_name = \"SynGenTrStab_SMIB_Fault_KundurExample1\"\n", + "path_ref = \"logs/\" + \"SP_\" + model_name + \"_SP/\"\n", + "dpsim_result_file_ref = path_ref + \"SP_\" + model_name + \"_SP.csv\"\n", "ts_dpsim_ref = read_timeseries_csv(dpsim_result_file_ref)" ] }, @@ -92,14 +101,27 @@ "import os\n", "import urllib.request\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/Kundur2-Example1/d_kundur2_example1_dpsim.out'\n", - "local_file = 'reference-results/d_kundur2_example1_dpsim.out'\n", - "urllib.request.urlretrieve(url, local_file) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/Kundur2-Example1/d_kundur2_example1_dpsim.out\"\n", + "local_file = \"reference-results/d_kundur2_example1_dpsim.out\"\n", + "urllib.request.urlretrieve(url, local_file)\n", "\n", - "timeseries_names_psat = ['delta_Syn_1', 'omega_Syn_1', 'theta_Bus1', 'theta_Bus2', 'theta_Bus3', 'V_Bus1', 'V_Bus2', 'V_Bus3', 'pm_Syn_1', 'vf_Syn_1', 'p_Syn_1', 'q_Syn_1']\n", + "timeseries_names_psat = [\n", + " \"delta_Syn_1\",\n", + " \"omega_Syn_1\",\n", + " \"theta_Bus1\",\n", + " \"theta_Bus2\",\n", + " \"theta_Bus3\",\n", + " \"V_Bus1\",\n", + " \"V_Bus2\",\n", + " \"V_Bus3\",\n", + " \"pm_Syn_1\",\n", + " \"vf_Syn_1\",\n", + " \"p_Syn_1\",\n", + " \"q_Syn_1\",\n", + "]\n", "\n", "ts_psat = read_timeseries_PSAT(local_file, timeseries_names_psat)" ] @@ -117,10 +139,10 @@ "metadata": {}, "outputs": [], "source": [ - "vbase = 400e3 # for p.u. conversion\n", - "deg_to_rad = np.pi/180\n", + "vbase = 400e3 # for p.u. conversion\n", + "deg_to_rad = np.pi / 180\n", "sbase = 100e6\n", - "omega_base = 2*np.pi*60\n", + "omega_base = 2 * np.pi * 60\n", "sgen = 2220e6" ] }, @@ -139,11 +161,11 @@ "source": [ "timestep_common = 100e-6\n", "\n", - "t_begin=0\n", - "t_end=10\n", + "t_begin = 0\n", + "t_end = 10\n", "\n", - "begin_idx = int(t_begin/timestep_common)\n", - "end_idx= int(t_end/timestep_common)" + "begin_idx = int(t_begin / timestep_common)\n", + "end_idx = int(t_end / timestep_common)" ] }, { @@ -159,12 +181,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['v1', 'v2', 'v3']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).abs().values[begin_idx:end_idx], label=name + ' SP DPsim')\n", - "for name in ['V_Bus1', 'V_Bus2', 'V_Bus3']:\n", - " plt.plot(ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx]*vbase, label=name + ' SP PSAT', linestyle='--')\n", + "for name in [\"v1\", \"v2\", \"v3\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).abs().values[begin_idx:end_idx],\n", + " label=name + \" SP DPsim\",\n", + " )\n", + "for name in [\"V_Bus1\", \"V_Bus2\", \"V_Bus3\"]:\n", + " plt.plot(\n", + " ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx] * vbase,\n", + " label=name + \" SP PSAT\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -182,12 +213,25 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['v1', 'v2', 'v3']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).phase().values[begin_idx:end_idx]*deg_to_rad, label=name + ' phase SP DPsim')\n", - "for name in ['theta_Bus1', 'theta_Bus2', 'theta_Bus3']:\n", - " plt.plot(ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx], label=name + ' SP PSAT', linestyle='--')\n", + "for name in [\"v1\", \"v2\", \"v3\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name]\n", + " .interpolate(timestep_common)\n", + " .phase()\n", + " .values[begin_idx:end_idx]\n", + " * deg_to_rad,\n", + " label=name + \" phase SP DPsim\",\n", + " )\n", + "for name in [\"theta_Bus1\", \"theta_Bus2\", \"theta_Bus3\"]:\n", + " plt.plot(\n", + " ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=name + \" SP PSAT\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -205,13 +249,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['Ep']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).abs().values[begin_idx:end_idx], label=name + ' SP DPsim')\n", - "for name in ['vf_Syn_1']:\n", - " plt.plot(ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx]*vbase, label=name + ' SP PSAT', linestyle='--')\n", - "plt.ylim([0.5*vbase,1.5*vbase])\n", + "for name in [\"Ep\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).abs().values[begin_idx:end_idx],\n", + " label=name + \" SP DPsim\",\n", + " )\n", + "for name in [\"vf_Syn_1\"]:\n", + " plt.plot(\n", + " ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx] * vbase,\n", + " label=name + \" SP PSAT\",\n", + " linestyle=\"--\",\n", + " )\n", + "plt.ylim([0.5 * vbase, 1.5 * vbase])\n", "plt.legend()\n", "plt.show()" ] @@ -229,13 +282,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", - "for name in ['v_fault']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).abs().values[begin_idx:end_idx], label=name + 'SP DPsim')\n", - "for name in ['i_fault']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).abs().values[begin_idx:end_idx], label=name + 'SP DPsim')\n", + "plt.figure(figsize=(12, 8))\n", + "for name in [\"v_fault\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).abs().values[begin_idx:end_idx],\n", + " label=name + \"SP DPsim\",\n", + " )\n", + "for name in [\"i_fault\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).abs().values[begin_idx:end_idx],\n", + " label=name + \"SP DPsim\",\n", + " )\n", "\n", - "plt.xlim([0.4,0.6])\n", + "plt.xlim([0.4, 0.6])\n", "plt.legend()\n", "plt.show()" ] @@ -253,12 +314,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['P_mech']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx], label=name + ' SP DPsim')\n", - "for name in ['pm_Syn_1']:\n", - " plt.plot(ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx]*sbase, label=name + ' SP PSAT', linestyle='--')\n", + "for name in [\"P_mech\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=name + \" SP DPsim\",\n", + " )\n", + "for name in [\"pm_Syn_1\"]:\n", + " plt.plot(\n", + " ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx] * sbase,\n", + " label=name + \" SP PSAT\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -276,13 +346,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['P_elec']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx], label=name + ' SP DPsim')\n", - "for name in ['p_Syn_1']:\n", - " ts_psat[name].values = ts_psat[name].values*sbase\n", - " plt.plot(ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx], label=name + ' SP PSAT', linestyle='--')\n", + "for name in [\"P_elec\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=name + \" SP DPsim\",\n", + " )\n", + "for name in [\"p_Syn_1\"]:\n", + " ts_psat[name].values = ts_psat[name].values * sbase\n", + " plt.plot(\n", + " ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=name + \" SP PSAT\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -300,13 +379,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['Q_elec']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx], label=name + ' SP DPsim')\n", - "for name in ['q_Syn_1']:\n", - " ts_psat[name].values = ts_psat[name].values*sbase\n", - " plt.plot(ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx], label=name + ' SP PSAT', linestyle='--')\n", + "for name in [\"Q_elec\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=name + \" SP DPsim\",\n", + " )\n", + "for name in [\"q_Syn_1\"]:\n", + " ts_psat[name].values = ts_psat[name].values * sbase\n", + " plt.plot(\n", + " ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=name + \" SP PSAT\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -324,13 +412,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['wr_gen']:\n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx], label='$\\omega _r$' + ' SP DPsim')\n", - "for name in ['omega_Syn_1']:\n", - " ts_psat[name].values = ts_psat[name].values*omega_base\n", - " plt.plot(ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx], label='$\\omega _r$' + ' SP PSAT', linestyle='--')\n", + "for name in [\"wr_gen\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=\"$\\omega _r$\" + \" SP DPsim\",\n", + " )\n", + "for name in [\"omega_Syn_1\"]:\n", + " ts_psat[name].values = ts_psat[name].values * omega_base\n", + " plt.plot(\n", + " ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=\"$\\omega _r$\" + \" SP PSAT\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -348,12 +445,21 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,8))\n", + "plt.figure(figsize=(12, 8))\n", "\n", - "for name in ['delta_r_gen']: \n", - " plt.plot(ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx], label='$\\delta _r$' + ' SP DPsim')\n", - "for name in ['delta_Syn_1']:\n", - " plt.plot(ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx], ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx], label='$\\delta _r$' + ' SP PSAT', linestyle='--')\n", + "for name in [\"delta_r_gen\"]:\n", + " plt.plot(\n", + " ts_dpsim_ref[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_dpsim_ref[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=\"$\\delta _r$\" + \" SP DPsim\",\n", + " )\n", + "for name in [\"delta_Syn_1\"]:\n", + " plt.plot(\n", + " ts_psat[name].interpolate(timestep_common).time[begin_idx:end_idx],\n", + " ts_psat[name].interpolate(timestep_common).values[begin_idx:end_idx],\n", + " label=\"$\\delta _r$\" + \" SP PSAT\",\n", + " linestyle=\"--\",\n", + " )\n", "plt.legend()\n", "plt.show()" ] @@ -371,14 +477,38 @@ "metadata": {}, "outputs": [], "source": [ - "p_elec_diff = ts_dpsim_ref['P_elec'].rmse(ts_dpsim_ref['P_elec'].interpolate(timestep_common), ts_psat['p_Syn_1'].interpolate(timestep_common))\n", - "print('{:.3f} MVA, which is {:.3f}% of nominal Sgen = {:.2f} MVA'.format(p_elec_diff/1e6, p_elec_diff/sgen*100, sgen/1e6))\n", - "q_elec_diff = ts_dpsim_ref['Q_elec'].rmse(ts_dpsim_ref['Q_elec'].interpolate(timestep_common), ts_psat['q_Syn_1'].interpolate(timestep_common))\n", - "print('{:.3f} MVA, which is {:.3}% of nominal Sgen = {:.2f} MVA'.format(q_elec_diff/1e6, q_elec_diff/sgen*100,sgen/1e6))\n", - "omega_r_diff = ts_dpsim_ref['wr_gen'].rmse(ts_dpsim_ref['wr_gen'].interpolate(timestep_common), ts_psat['omega_Syn_1'].interpolate(timestep_common))\n", - "print('{:.3f} 1/s, which is {:.3}% of nominal omega {:.2f} 1/s'.format(omega_r_diff, omega_r_diff/omega_base*100, omega_base))\n", - "delta_r_gen_diff = ts_dpsim_ref['delta_r_gen'].rmse(ts_dpsim_ref['delta_r_gen'].interpolate(timestep_common), ts_psat['delta_Syn_1'].interpolate(timestep_common))\n", - "print('{:.3} rad'.format(delta_r_gen_diff))" + "p_elec_diff = ts_dpsim_ref[\"P_elec\"].rmse(\n", + " ts_dpsim_ref[\"P_elec\"].interpolate(timestep_common),\n", + " ts_psat[\"p_Syn_1\"].interpolate(timestep_common),\n", + ")\n", + "print(\n", + " \"{:.3f} MVA, which is {:.3f}% of nominal Sgen = {:.2f} MVA\".format(\n", + " p_elec_diff / 1e6, p_elec_diff / sgen * 100, sgen / 1e6\n", + " )\n", + ")\n", + "q_elec_diff = ts_dpsim_ref[\"Q_elec\"].rmse(\n", + " ts_dpsim_ref[\"Q_elec\"].interpolate(timestep_common),\n", + " ts_psat[\"q_Syn_1\"].interpolate(timestep_common),\n", + ")\n", + "print(\n", + " \"{:.3f} MVA, which is {:.3}% of nominal Sgen = {:.2f} MVA\".format(\n", + " q_elec_diff / 1e6, q_elec_diff / sgen * 100, sgen / 1e6\n", + " )\n", + ")\n", + "omega_r_diff = ts_dpsim_ref[\"wr_gen\"].rmse(\n", + " ts_dpsim_ref[\"wr_gen\"].interpolate(timestep_common),\n", + " ts_psat[\"omega_Syn_1\"].interpolate(timestep_common),\n", + ")\n", + "print(\n", + " \"{:.3f} 1/s, which is {:.3}% of nominal omega {:.2f} 1/s\".format(\n", + " omega_r_diff, omega_r_diff / omega_base * 100, omega_base\n", + " )\n", + ")\n", + "delta_r_gen_diff = ts_dpsim_ref[\"delta_r_gen\"].rmse(\n", + " ts_dpsim_ref[\"delta_r_gen\"].interpolate(timestep_common),\n", + " ts_psat[\"delta_Syn_1\"].interpolate(timestep_common),\n", + ")\n", + "print(\"{:.3} rad\".format(delta_r_gen_diff))" ] }, { @@ -394,10 +524,10 @@ "metadata": {}, "outputs": [], "source": [ - "assert(p_elec_diff/1e6<0.6)\n", - "assert(q_elec_diff/1e6<4)\n", - "assert(omega_r_diff<0.002)\n", - "assert(delta_r_gen_diff<2e-4)" + "assert p_elec_diff / 1e6 < 0.6\n", + "assert q_elec_diff / 1e6 < 4\n", + "assert omega_r_diff < 0.002\n", + "assert delta_r_gen_diff < 2e-4" ] }, { diff --git a/examples/Notebooks/Grids/SP_WSCC9bus_SG4thOrder_Fault_PSAT_Validation.ipynb b/examples/Notebooks/Grids/SP_WSCC9bus_SG4thOrder_Fault_PSAT_Validation.ipynb index 3c506a702d..c62d95a086 100644 --- a/examples/Notebooks/Grids/SP_WSCC9bus_SG4thOrder_Fault_PSAT_Validation.ipynb +++ b/examples/Notebooks/Grids/SP_WSCC9bus_SG4thOrder_Fault_PSAT_Validation.ipynb @@ -27,42 +27,49 @@ "import requests\n", "import urllib.request\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "#%matplotlib widget\n", "\n", - "PEAK1PH_TO_RMS3PH=np.sqrt(3./2.)\n", + "# %matplotlib widget\n", + "\n", + "PEAK1PH_TO_RMS3PH = np.sqrt(3.0 / 2.0)\n", "\n", - "name_exec = 'SP_WSCC9bus_SGReducedOrderVBR'\n", + "name_exec = \"SP_WSCC9bus_SGReducedOrderVBR\"\n", "\n", - "order_names_list = ['4th'] # ['3rd', '4th', '6th']\n", - "order_options_list = ['sgType=4'] # ['sgType=3', 'sgType=4', 'sgType=6b']\n", - "sim_names_list = [name_exec + '_' + order_name for order_name in order_names_list]\n", + "order_names_list = [\"4th\"] # ['3rd', '4th', '6th']\n", + "order_options_list = [\"sgType=4\"] # ['sgType=3', 'sgType=4', 'sgType=6b']\n", + "sim_names_list = [name_exec + \"_\" + order_name for order_name in order_names_list]\n", "num_orders = len(order_names_list)\n", "\n", "timestep = 1e-3\n", "duration = 30\n", "\n", - "view_time_interval = [0.1,1.0]\n", + "view_time_interval = [0.1, 1.0]\n", "\n", - "root_path = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')\n", + "root_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", "\n", - "path_exec = root_path + '/build/dpsim/examples/cxx/'\n", + "path_exec = root_path + \"/build/dpsim/examples/cxx/\"\n", "\n", - "cim_file = 'WSCC-09_Dyn_Fourth'\n", + "cim_file = \"WSCC-09_Dyn_Fourth\"\n", "\n", - "cim_url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_Dyn_Fourth/WSCC-09_Dyn_Fourth'\n", - "download_grid_data(cim_file+'_EQ.xml', cim_url+'_EQ.xml')\n", - "download_grid_data(cim_file+'_TP.xml', cim_url+'_TP.xml')\n", - "download_grid_data(cim_file+'_SV.xml', cim_url+'_SV.xml')\n", - "download_grid_data(cim_file+'_DI.xml', cim_url+'_DI.xml')\n", + "cim_url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_Dyn_Fourth/WSCC-09_Dyn_Fourth\"\n", + "download_grid_data(cim_file + \"_EQ.xml\", cim_url + \"_EQ.xml\")\n", + "download_grid_data(cim_file + \"_TP.xml\", cim_url + \"_TP.xml\")\n", + "download_grid_data(cim_file + \"_SV.xml\", cim_url + \"_SV.xml\")\n", + "download_grid_data(cim_file + \"_DI.xml\", cim_url + \"_DI.xml\")\n", "\n", - "psat_results_url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/WSCC-9bus/d_009_fault_dpsim_4th_order.out'\n", - "psat_results_file = 'd_009_fault_dpsim_4th_order.out'\n", - "urllib.request.urlretrieve(psat_results_url, psat_results_file) " + "psat_results_url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/WSCC-9bus/d_009_fault_dpsim_4th_order.out\"\n", + "psat_results_file = \"d_009_fault_dpsim_4th_order.out\"\n", + "urllib.request.urlretrieve(psat_results_url, psat_results_file)" ] }, { @@ -80,7 +87,25 @@ "outputs": [], "source": [ "for order_idx in range(num_orders):\n", - " sim = subprocess.Popen([path_exec+name_exec, '--name', sim_names_list[order_idx], '--timestep', str(timestep), '--duration', str(duration), cim_file +'_DI.xml', cim_file +'_EQ.xml', cim_file +'_SV.xml', cim_file +'_TP.xml', '--option', order_options_list[order_idx]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + " sim = subprocess.Popen(\n", + " [\n", + " path_exec + name_exec,\n", + " \"--name\",\n", + " sim_names_list[order_idx],\n", + " \"--timestep\",\n", + " str(timestep),\n", + " \"--duration\",\n", + " str(duration),\n", + " cim_file + \"_DI.xml\",\n", + " cim_file + \"_EQ.xml\",\n", + " cim_file + \"_SV.xml\",\n", + " cim_file + \"_TP.xml\",\n", + " \"--option\",\n", + " order_options_list[order_idx],\n", + " ],\n", + " stdout=subprocess.PIPE,\n", + " stderr=subprocess.STDOUT,\n", + " )\n", " print(sim.communicate()[0].decode())" ] }, @@ -100,9 +125,9 @@ "source": [ "ts_dpsim = []\n", "for order_idx in range(num_orders):\n", - " path = 'logs/' + sim_names_list[order_idx] + '/'\n", + " path = \"logs/\" + sim_names_list[order_idx] + \"/\"\n", " logName = sim_names_list[order_idx]\n", - " logFilename = path + logName + '.csv'\n", + " logFilename = path + logName + \".csv\"\n", " print(logFilename)\n", " ts_dpsim.append(rt.read_timeseries_dpsim(logFilename))" ] @@ -121,20 +146,56 @@ "metadata": {}, "outputs": [], "source": [ - "syngen_power_name_dpsim_list = ['GEN1.Te', 'GEN2.Te', 'GEN3.Te']\n", - "syngen_power_name_psat_list = ['p_Syn_1', 'p_Syn_2', 'p_Syn_3']\n", + "syngen_power_name_dpsim_list = [\"GEN1.Te\", \"GEN2.Te\", \"GEN3.Te\"]\n", + "syngen_power_name_psat_list = [\"p_Syn_1\", \"p_Syn_2\", \"p_Syn_3\"]\n", "\n", - "syngen_omega_name_dpsim_list = ['GEN1.omega', 'GEN2.omega', 'GEN3.omega']\n", - "syngen_omega_name_psat_list = ['omega_Syn_1', 'omega_Syn_2', 'omega_Syn_3']\n", + "syngen_omega_name_dpsim_list = [\"GEN1.omega\", \"GEN2.omega\", \"GEN3.omega\"]\n", + "syngen_omega_name_psat_list = [\"omega_Syn_1\", \"omega_Syn_2\", \"omega_Syn_3\"]\n", "\n", - "syngen_delta_name_dpsim_list = ['GEN1.delta', 'GEN2.delta', 'GEN3.delta']\n", - "syngen_delta_name_psat_list = ['delta_Syn_1', 'delta_Syn_2', 'delta_Syn_3']\n", + "syngen_delta_name_dpsim_list = [\"GEN1.delta\", \"GEN2.delta\", \"GEN3.delta\"]\n", + "syngen_delta_name_psat_list = [\"delta_Syn_1\", \"delta_Syn_2\", \"delta_Syn_3\"]\n", "\n", - "bus_volt_name_dpsim_list = ['BUS1.V', 'BUS2.V', 'BUS3.V', 'BUS4.V', 'BUS5.V', 'BUS6.V', 'BUS7.V', 'BUS8.V', 'BUS9.V']\n", - "bus_volt_name_psat_list = ['V_Bus 1', 'V_Bus 2', 'V_Bus 3', 'V_Bus 4', 'V_Bus 5', 'V_Bus 6', 'V_Bus 7', 'V_Bus 8', 'V_Bus 9']\n", - "bus_angle_name_psat_list = ['theta_Bus 1', 'theta_Bus 2', 'theta_Bus 3', 'theta_Bus 4', 'theta_Bus 5', 'theta_Bus 6', 'theta_Bus 7', 'theta_Bus 8', 'theta_Bus 9']\n", + "bus_volt_name_dpsim_list = [\n", + " \"BUS1.V\",\n", + " \"BUS2.V\",\n", + " \"BUS3.V\",\n", + " \"BUS4.V\",\n", + " \"BUS5.V\",\n", + " \"BUS6.V\",\n", + " \"BUS7.V\",\n", + " \"BUS8.V\",\n", + " \"BUS9.V\",\n", + "]\n", + "bus_volt_name_psat_list = [\n", + " \"V_Bus 1\",\n", + " \"V_Bus 2\",\n", + " \"V_Bus 3\",\n", + " \"V_Bus 4\",\n", + " \"V_Bus 5\",\n", + " \"V_Bus 6\",\n", + " \"V_Bus 7\",\n", + " \"V_Bus 8\",\n", + " \"V_Bus 9\",\n", + "]\n", + "bus_angle_name_psat_list = [\n", + " \"theta_Bus 1\",\n", + " \"theta_Bus 2\",\n", + " \"theta_Bus 3\",\n", + " \"theta_Bus 4\",\n", + " \"theta_Bus 5\",\n", + " \"theta_Bus 6\",\n", + " \"theta_Bus 7\",\n", + " \"theta_Bus 8\",\n", + " \"theta_Bus 9\",\n", + "]\n", "\n", - "timeseries_names_psat = syngen_power_name_psat_list+syngen_omega_name_psat_list+syngen_delta_name_psat_list+bus_volt_name_psat_list+bus_angle_name_psat_list\n", + "timeseries_names_psat = (\n", + " syngen_power_name_psat_list\n", + " + syngen_omega_name_psat_list\n", + " + syngen_delta_name_psat_list\n", + " + bus_volt_name_psat_list\n", + " + bus_angle_name_psat_list\n", + ")\n", "\n", "ts_psat = []\n", "for order_idx in range(num_orders):\n", @@ -156,18 +217,33 @@ "outputs": [], "source": [ "for order_idx in range(num_orders):\n", - " plt.figure(figsize=(12,9))\n", - " #plt.subplot(num_orders,1,order_idx+1)\n", + " plt.figure(figsize=(12, 9))\n", + " # plt.subplot(num_orders,1,order_idx+1)\n", " for syngen_omega_name_dpsim in syngen_omega_name_dpsim_list:\n", - " plt.plot(ts_dpsim[order_idx][syngen_omega_name_dpsim].time, ts_dpsim[order_idx][syngen_omega_name_dpsim].values, label=syngen_omega_name_dpsim+', '+order_names_list[order_idx]+' (dpsim)')\n", + " plt.plot(\n", + " ts_dpsim[order_idx][syngen_omega_name_dpsim].time,\n", + " ts_dpsim[order_idx][syngen_omega_name_dpsim].values,\n", + " label=syngen_omega_name_dpsim\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (dpsim)\",\n", + " )\n", " for syngen_omega_name_psat in syngen_omega_name_psat_list:\n", - " plt.plot(ts_psat[order_idx][syngen_omega_name_psat].time, ts_psat[order_idx][syngen_omega_name_psat].values, label=syngen_omega_name_psat+', '+order_names_list[order_idx]+' (psat)', linestyle='--')\n", - " \n", - " #plt.ylim([0.99,1.02])\n", + " plt.plot(\n", + " ts_psat[order_idx][syngen_omega_name_psat].time,\n", + " ts_psat[order_idx][syngen_omega_name_psat].values,\n", + " label=syngen_omega_name_psat\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (psat)\",\n", + " linestyle=\"--\",\n", + " )\n", + "\n", + " # plt.ylim([0.99,1.02])\n", " plt.xlim(view_time_interval)\n", - " \n", - " plt.xlabel('time (s)')\n", - " plt.ylabel('mechanical speed (p.u)')\n", + "\n", + " plt.xlabel(\"time (s)\")\n", + " plt.ylabel(\"mechanical speed (p.u)\")\n", " plt.legend()" ] }, @@ -185,17 +261,32 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,9))\n", + "plt.figure(figsize=(12, 9))\n", "for order_idx in range(num_orders):\n", - " plt.subplot(num_orders,1,order_idx+1)\n", + " plt.subplot(num_orders, 1, order_idx + 1)\n", " for syngen_delta_name_dpsim in syngen_delta_name_dpsim_list:\n", - " plt.plot(ts_dpsim[order_idx][syngen_delta_name_dpsim].time, ts_dpsim[order_idx][syngen_delta_name_dpsim].values/np.pi*180, label=syngen_delta_name_dpsim+', '+order_names_list[order_idx]+' (dpsim)')\n", + " plt.plot(\n", + " ts_dpsim[order_idx][syngen_delta_name_dpsim].time,\n", + " ts_dpsim[order_idx][syngen_delta_name_dpsim].values / np.pi * 180,\n", + " label=syngen_delta_name_dpsim\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (dpsim)\",\n", + " )\n", " for syngen_delta_name_psat in syngen_delta_name_psat_list:\n", - " plt.plot(ts_psat[order_idx][syngen_delta_name_psat].time, ts_psat[order_idx][syngen_delta_name_psat].values/np.pi*180, label=syngen_delta_name_psat+', '+order_names_list[order_idx]+' (psat)', linestyle='--')\n", - " \n", + " plt.plot(\n", + " ts_psat[order_idx][syngen_delta_name_psat].time,\n", + " ts_psat[order_idx][syngen_delta_name_psat].values / np.pi * 180,\n", + " label=syngen_delta_name_psat\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (psat)\",\n", + " linestyle=\"--\",\n", + " )\n", + "\n", " plt.xlim(view_time_interval)\n", - " plt.xlabel('time (s)')\n", - " plt.ylabel('rotor angle (rad)')\n", + " plt.xlabel(\"time (s)\")\n", + " plt.ylabel(\"rotor angle (rad)\")\n", " plt.legend()" ] }, @@ -214,16 +305,43 @@ "outputs": [], "source": [ "for order_idx in range(num_orders):\n", - " plt.figure(figsize=(12,9))\n", - " #plt.subplot(num_orders,1,order_idx+1)\n", + " plt.figure(figsize=(12, 9))\n", + " # plt.subplot(num_orders,1,order_idx+1)\n", " for syngen_delta_name_dpsim in syngen_delta_name_dpsim_list:\n", - " plt.plot(ts_dpsim[order_idx][syngen_delta_name_dpsim].time, (ts_dpsim[order_idx][syngen_delta_name_dpsim].values-ts_dpsim[order_idx]['GEN1.delta'].values+ts_dpsim[order_idx]['GEN1.delta'].values[0])/np.pi*180, label=syngen_delta_name_dpsim+', '+order_names_list[order_idx]+' (dpsim)')\n", + " plt.plot(\n", + " ts_dpsim[order_idx][syngen_delta_name_dpsim].time,\n", + " (\n", + " ts_dpsim[order_idx][syngen_delta_name_dpsim].values\n", + " - ts_dpsim[order_idx][\"GEN1.delta\"].values\n", + " + ts_dpsim[order_idx][\"GEN1.delta\"].values[0]\n", + " )\n", + " / np.pi\n", + " * 180,\n", + " label=syngen_delta_name_dpsim\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (dpsim)\",\n", + " )\n", " for syngen_delta_name_psat in syngen_delta_name_psat_list:\n", - " plt.plot(ts_psat[order_idx][syngen_delta_name_psat].time, (ts_psat[order_idx][syngen_delta_name_psat].values-ts_psat[order_idx]['delta_Syn_3'].values+ts_psat[order_idx]['delta_Syn_3'].values[0])/np.pi*180, label=syngen_delta_name_psat+', '+order_names_list[order_idx]+' (psat)', linestyle='--')\n", - " \n", + " plt.plot(\n", + " ts_psat[order_idx][syngen_delta_name_psat].time,\n", + " (\n", + " ts_psat[order_idx][syngen_delta_name_psat].values\n", + " - ts_psat[order_idx][\"delta_Syn_3\"].values\n", + " + ts_psat[order_idx][\"delta_Syn_3\"].values[0]\n", + " )\n", + " / np.pi\n", + " * 180,\n", + " label=syngen_delta_name_psat\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (psat)\",\n", + " linestyle=\"--\",\n", + " )\n", + "\n", " plt.xlim(view_time_interval)\n", - " plt.xlabel('time (s)')\n", - " plt.ylabel('rotor angle (rad)')\n", + " plt.xlabel(\"time (s)\")\n", + " plt.ylabel(\"rotor angle (rad)\")\n", " plt.legend()" ] }, @@ -241,24 +359,62 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,12))\n", + "plt.figure(figsize=(12, 12))\n", "for order_idx in range(num_orders):\n", - " plt.subplot(num_orders,1,order_idx+1)\n", + " plt.subplot(num_orders, 1, order_idx + 1)\n", " for bus_volt_name_dpsim in bus_volt_name_dpsim_list:\n", - " if bus_volt_name_dpsim == 'BUS1.V':\n", - " plt.plot(ts_dpsim[order_idx][bus_volt_name_dpsim].time, ts_dpsim[order_idx][bus_volt_name_dpsim].abs().values/16.5e3, label=bus_volt_name_dpsim +', '+order_names_list[order_idx]+' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", - " elif bus_volt_name_dpsim == 'BUS2.V':\n", - " plt.plot(ts_dpsim[order_idx][bus_volt_name_dpsim].time, ts_dpsim[order_idx][bus_volt_name_dpsim].abs().values/18e3, label=bus_volt_name_dpsim +', '+order_names_list[order_idx]+' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", - " elif bus_volt_name_dpsim == 'BUS3.V':\n", - " plt.plot(ts_dpsim[order_idx][bus_volt_name_dpsim].time, ts_dpsim[order_idx][bus_volt_name_dpsim].abs().values/13.8e3, label=bus_volt_name_dpsim +', '+order_names_list[order_idx]+' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", + " if bus_volt_name_dpsim == \"BUS1.V\":\n", + " plt.plot(\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].time,\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].abs().values / 16.5e3,\n", + " label=bus_volt_name_dpsim\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", + " elif bus_volt_name_dpsim == \"BUS2.V\":\n", + " plt.plot(\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].time,\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].abs().values / 18e3,\n", + " label=bus_volt_name_dpsim\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", + " elif bus_volt_name_dpsim == \"BUS3.V\":\n", + " plt.plot(\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].time,\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].abs().values / 13.8e3,\n", + " label=bus_volt_name_dpsim\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", " else:\n", - " plt.plot(ts_dpsim[order_idx][bus_volt_name_dpsim].time, ts_dpsim[order_idx][bus_volt_name_dpsim].abs().values/230e3, label=bus_volt_name_dpsim +', '+order_names_list[order_idx]+' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", + " plt.plot(\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].time,\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].abs().values / 230e3,\n", + " label=bus_volt_name_dpsim\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", " for bus_volt_name_psat in bus_volt_name_psat_list:\n", - " plt.plot(ts_psat[order_idx][bus_volt_name_psat].time, ts_psat[order_idx][bus_volt_name_psat].values, label=bus_volt_name_psat +', '+order_names_list[order_idx]+' (psat)', linestyle='--', color='C'+str(bus_volt_name_psat_list.index(bus_volt_name_psat)))\n", - " \n", + " plt.plot(\n", + " ts_psat[order_idx][bus_volt_name_psat].time,\n", + " ts_psat[order_idx][bus_volt_name_psat].values,\n", + " label=bus_volt_name_psat + \", \" + order_names_list[order_idx] + \" (psat)\",\n", + " linestyle=\"--\",\n", + " color=\"C\" + str(bus_volt_name_psat_list.index(bus_volt_name_psat)),\n", + " )\n", + "\n", " plt.xlim(view_time_interval)\n", - " plt.xlabel('time (s)')\n", - " plt.ylabel('voltage (p.u.)')\n", + " plt.xlabel(\"time (s)\")\n", + " plt.ylabel(\"voltage (p.u.)\")\n", " plt.legend()" ] }, @@ -276,17 +432,29 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,12))\n", + "plt.figure(figsize=(12, 12))\n", "for order_idx in range(num_orders):\n", - " plt.subplot(num_orders,1,order_idx+1)\n", + " plt.subplot(num_orders, 1, order_idx + 1)\n", " for bus_volt_name_dpsim in bus_volt_name_dpsim_list:\n", - " plt.plot(ts_dpsim[order_idx][bus_volt_name_dpsim].time, ts_dpsim[order_idx][bus_volt_name_dpsim].phase().values/180*np.pi-ts_dpsim[order_idx]['BUS1.V'].phase().values/180*np.pi, label=bus_volt_name_dpsim +', '+order_names_list[order_idx]+' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", + " plt.plot(\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].time,\n", + " ts_dpsim[order_idx][bus_volt_name_dpsim].phase().values / 180 * np.pi\n", + " - ts_dpsim[order_idx][\"BUS1.V\"].phase().values / 180 * np.pi,\n", + " label=bus_volt_name_dpsim + \", \" + order_names_list[order_idx] + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", " for bus_angle_name_psat in bus_angle_name_psat_list:\n", - " plt.plot(ts_psat[order_idx][bus_angle_name_psat].time, ts_psat[order_idx][bus_angle_name_psat].values, label=bus_angle_name_psat +', '+order_names_list[order_idx]+' (psat)', linestyle='--', color='C'+str(bus_angle_name_psat_list.index(bus_angle_name_psat)))\n", - " \n", + " plt.plot(\n", + " ts_psat[order_idx][bus_angle_name_psat].time,\n", + " ts_psat[order_idx][bus_angle_name_psat].values,\n", + " label=bus_angle_name_psat + \", \" + order_names_list[order_idx] + \" (psat)\",\n", + " linestyle=\"--\",\n", + " color=\"C\" + str(bus_angle_name_psat_list.index(bus_angle_name_psat)),\n", + " )\n", + "\n", " plt.xlim(view_time_interval)\n", - " plt.xlabel('time (s)')\n", - " plt.ylabel('angle (rad)')\n", + " plt.xlabel(\"time (s)\")\n", + " plt.ylabel(\"angle (rad)\")\n", " plt.legend()" ] }, @@ -305,16 +473,31 @@ "outputs": [], "source": [ "for order_idx in range(num_orders):\n", - " plt.figure(figsize=(12,9))\n", - " #plt.subplot(num_orders,1,order_idx+1)\n", + " plt.figure(figsize=(12, 9))\n", + " # plt.subplot(num_orders,1,order_idx+1)\n", " for syngen_power_name_dpsim in syngen_power_name_dpsim_list:\n", - " plt.plot(ts_dpsim[order_idx][syngen_power_name_dpsim].time, ts_dpsim[order_idx][syngen_power_name_dpsim].values, label=syngen_power_name_dpsim+', '+order_names_list[order_idx]+' (dpsim)')\n", + " plt.plot(\n", + " ts_dpsim[order_idx][syngen_power_name_dpsim].time,\n", + " ts_dpsim[order_idx][syngen_power_name_dpsim].values,\n", + " label=syngen_power_name_dpsim\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (dpsim)\",\n", + " )\n", " for syngen_power_name_psat in syngen_power_name_psat_list:\n", - " plt.plot(ts_psat[order_idx][syngen_power_name_psat].time, ts_psat[order_idx][syngen_power_name_psat].values, label=syngen_power_name_psat+', '+order_names_list[order_idx]+' (psat)', linestyle='--')\n", - " \n", + " plt.plot(\n", + " ts_psat[order_idx][syngen_power_name_psat].time,\n", + " ts_psat[order_idx][syngen_power_name_psat].values,\n", + " label=syngen_power_name_psat\n", + " + \", \"\n", + " + order_names_list[order_idx]\n", + " + \" (psat)\",\n", + " linestyle=\"--\",\n", + " )\n", + "\n", " plt.xlim(view_time_interval)\n", - " plt.xlabel('time (s)')\n", - " plt.ylabel('torque (p.u)')\n", + " plt.xlabel(\"time (s)\")\n", + " plt.ylabel(\"torque (p.u)\")\n", " plt.legend()" ] }, @@ -333,19 +516,25 @@ "outputs": [], "source": [ "for order_idx in range(num_orders):\n", - " print('{} order:'.format(order_names_list[order_idx]))\n", - " \n", - " rmse_gen_1 = ts_psat[order_idx]['p_Syn_3'].rmse(ts_psat[order_idx]['p_Syn_3'],ts_dpsim[order_idx]['GEN1.Te'])\n", - " print('{}: {}'.format('GEN1',rmse_gen_1))\n", - " assert(rmse_gen_1 < 1e-2)\n", - " \n", - " rmse_gen_2 = ts_psat[order_idx]['p_Syn_1'].rmse(ts_psat[order_idx]['p_Syn_1'],ts_dpsim[order_idx]['GEN2.Te'])\n", - " print('{}: {}'.format('GEN2',rmse_gen_2))\n", - " assert(rmse_gen_2 < 1e-2)\n", - " \n", - " rmse_gen_3 = ts_psat[order_idx]['p_Syn_2'].rmse(ts_psat[order_idx]['p_Syn_2'],ts_dpsim[order_idx]['GEN3.Te'])\n", - " print('{}: {}'.format('GEN3',rmse_gen_3))\n", - " assert(rmse_gen_3 < 1e-2)" + " print(\"{} order:\".format(order_names_list[order_idx]))\n", + "\n", + " rmse_gen_1 = ts_psat[order_idx][\"p_Syn_3\"].rmse(\n", + " ts_psat[order_idx][\"p_Syn_3\"], ts_dpsim[order_idx][\"GEN1.Te\"]\n", + " )\n", + " print(\"{}: {}\".format(\"GEN1\", rmse_gen_1))\n", + " assert rmse_gen_1 < 1e-2\n", + "\n", + " rmse_gen_2 = ts_psat[order_idx][\"p_Syn_1\"].rmse(\n", + " ts_psat[order_idx][\"p_Syn_1\"], ts_dpsim[order_idx][\"GEN2.Te\"]\n", + " )\n", + " print(\"{}: {}\".format(\"GEN2\", rmse_gen_2))\n", + " assert rmse_gen_2 < 1e-2\n", + "\n", + " rmse_gen_3 = ts_psat[order_idx][\"p_Syn_2\"].rmse(\n", + " ts_psat[order_idx][\"p_Syn_2\"], ts_dpsim[order_idx][\"GEN3.Te\"]\n", + " )\n", + " print(\"{}: {}\".format(\"GEN3\", rmse_gen_3))\n", + " assert rmse_gen_3 < 1e-2" ] }, { diff --git a/examples/Notebooks/Grids/SP_WSCC9bus_SGTrStab_Switch_PSAT_Validation.ipynb b/examples/Notebooks/Grids/SP_WSCC9bus_SGTrStab_Switch_PSAT_Validation.ipynb index 16099921b3..2e0f27c648 100644 --- a/examples/Notebooks/Grids/SP_WSCC9bus_SGTrStab_Switch_PSAT_Validation.ipynb +++ b/examples/Notebooks/Grids/SP_WSCC9bus_SGTrStab_Switch_PSAT_Validation.ipynb @@ -16,18 +16,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX_Dyn/WSCC-09_RX'\n", - "filename = 'WSCC-09_RX_Dyn_Second'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX_Dyn/WSCC-09_RX\"\n", + "filename = \"WSCC-09_RX_Dyn_Second\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -51,7 +53,7 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'SP_WSCC-9bus_dyn_switch'" + "sim_name = \"SP_WSCC-9bus_dyn_switch\"" ] }, { @@ -67,32 +69,40 @@ "metadata": {}, "outputs": [], "source": [ - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "reader = dpsimpy.CIMReader(sim_name, dpsimpy.LogLevel.debug, dpsimpy.LogLevel.debug)\n", - "system = reader.loadCIM(60, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.TransientStability)\n", + "system = reader.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.SP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.TransientStability,\n", + ")\n", "\n", "# Extend topology with switch\n", - "sw = dpsimpy.sp.ph1.Switch('Fault', dpsimpy.LogLevel.info)\n", - "sw.set_parameters(1e12, 0.1*529)\n", - "sw.connect([dpsimpy.sp.SimNode.gnd, system.node('BUS7')])\n", + "sw = dpsimpy.sp.ph1.Switch(\"Fault\", dpsimpy.LogLevel.info)\n", + "sw.set_parameters(1e12, 0.1 * 529)\n", + "sw.connect([dpsimpy.sp.SimNode.gnd, system.node(\"BUS7\")])\n", "sw.open()\n", "system.add(sw)\n", "\n", "# Use omegNom for torque conversion in SG models for validation with PSAT\n", - "system.component('GEN1').set_model_flags(False)\n", - "system.component('GEN2').set_model_flags(False)\n", - "system.component('GEN3').set_model_flags(False)\n", + "system.component(\"GEN1\").set_model_flags(False)\n", + "system.component(\"GEN2\").set_model_flags(False)\n", + "system.component(\"GEN3\").set_model_flags(False)\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "\n", "for i in range(1, 10):\n", - " logger.log_attribute('v' + str(i), 'v', system.node('BUS' + str(i)))\n", + " logger.log_attribute(\"v\" + str(i), \"v\", system.node(\"BUS\" + str(i)))\n", "\n", "for i in range(1, 4):\n", - " logger.log_attribute('wr_' + str(i), 'w_r', system.component('GEN' + str(i)))\n", - " logger.log_attribute('delta_r_' + str(i), 'delta_r', system.component('GEN' + str(i)))\n", - " logger.log_attribute('P_elec_' + str(i), 'P_elec', system.component('GEN' + str(i)))\n", - " logger.log_attribute('P_mech_' + str(i), 'P_mech', system.component('GEN' + str(i)))\n", + " logger.log_attribute(\"wr_\" + str(i), \"w_r\", system.component(\"GEN\" + str(i)))\n", + " logger.log_attribute(\n", + " \"delta_r_\" + str(i), \"delta_r\", system.component(\"GEN\" + str(i))\n", + " )\n", + " logger.log_attribute(\"P_elec_\" + str(i), \"P_elec\", system.component(\"GEN\" + str(i)))\n", + " logger.log_attribute(\"P_mech_\" + str(i), \"P_mech\", system.component(\"GEN\" + str(i)))\n", "\n", "\n", "sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", @@ -107,7 +117,7 @@ "sim.add_event(sw_event_1)\n", "\n", "sim.add_logger(logger)\n", - "sim.run()\n" + "sim.run()" ] }, { @@ -123,9 +133,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/SP_WSCC-9bus_dyn_switch/'\n", - "logName = 'SP_WSCC-9bus_dyn_switch'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/SP_WSCC-9bus_dyn_switch/\"\n", + "logName = \"SP_WSCC-9bus_dyn_switch\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_dpsim = rt.read_timeseries_dpsim(logFilename)\n", @@ -145,11 +155,25 @@ "metadata": {}, "outputs": [], "source": [ - "nominal_voltages = {'v1': 16500, 'v2': 18000, 'v3': 13800, \n", - " 'v4': 230000, 'v5': 230000, 'v6': 230000, \n", - " 'v7': 230000, 'v8': 230000, 'v9': 230000} \n", + "nominal_voltages = {\n", + " \"v1\": 16500,\n", + " \"v2\": 18000,\n", + " \"v3\": 13800,\n", + " \"v4\": 230000,\n", + " \"v5\": 230000,\n", + " \"v6\": 230000,\n", + " \"v7\": 230000,\n", + " \"v8\": 230000,\n", + " \"v9\": 230000,\n", + "}\n", "for node, nom_voltage in nominal_voltages.items():\n", - " print(node + ': ' + str(phasors[node]['abs'].values[0] / nom_voltage) + '<' + str(phasors[node]['phase'].values[0]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasors[node][\"abs\"].values[0] / nom_voltage)\n", + " + \"<\"\n", + " + str(phasors[node][\"phase\"].values[0])\n", + " )" ] }, { @@ -166,21 +190,21 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(phasors['v1']['abs'].time, phasors['v1']['abs'].values, label='v1.abs')\n", - "plt.plot(phasors['v2']['abs'].time, phasors['v2']['abs'].values, label='v2.abs')\n", - "plt.plot(phasors['v3']['abs'].time, phasors['v3']['abs'].values, label='v3.abs')\n", + "plt.plot(phasors[\"v1\"][\"abs\"].time, phasors[\"v1\"][\"abs\"].values, label=\"v1.abs\")\n", + "plt.plot(phasors[\"v2\"][\"abs\"].time, phasors[\"v2\"][\"abs\"].values, label=\"v2.abs\")\n", + "plt.plot(phasors[\"v3\"][\"abs\"].time, phasors[\"v3\"][\"abs\"].values, label=\"v3.abs\")\n", "plt.legend()\n", - "plt.ylim([0,20000])\n", + "plt.ylim([0, 20000])\n", "\n", "plt.figure()\n", - "plt.plot(phasors['v4']['abs'].time, phasors['v4']['abs'].values, label='v4.abs')\n", - "plt.plot(phasors['v5']['abs'].time, phasors['v5']['abs'].values, label='v5.abs')\n", - "plt.plot(phasors['v6']['abs'].time, phasors['v6']['abs'].values, label='v6.abs')\n", - "plt.plot(phasors['v7']['abs'].time, phasors['v7']['abs'].values, label='v7.abs')\n", - "plt.plot(phasors['v8']['abs'].time, phasors['v8']['abs'].values, label='v8.abs')\n", - "plt.plot(phasors['v9']['abs'].time, phasors['v9']['abs'].values, label='v9.abs')\n", + "plt.plot(phasors[\"v4\"][\"abs\"].time, phasors[\"v4\"][\"abs\"].values, label=\"v4.abs\")\n", + "plt.plot(phasors[\"v5\"][\"abs\"].time, phasors[\"v5\"][\"abs\"].values, label=\"v5.abs\")\n", + "plt.plot(phasors[\"v6\"][\"abs\"].time, phasors[\"v6\"][\"abs\"].values, label=\"v6.abs\")\n", + "plt.plot(phasors[\"v7\"][\"abs\"].time, phasors[\"v7\"][\"abs\"].values, label=\"v7.abs\")\n", + "plt.plot(phasors[\"v8\"][\"abs\"].time, phasors[\"v8\"][\"abs\"].values, label=\"v8.abs\")\n", + "plt.plot(phasors[\"v9\"][\"abs\"].time, phasors[\"v9\"][\"abs\"].values, label=\"v9.abs\")\n", "plt.legend()\n", - "plt.ylim([0,240000])" + "plt.ylim([0, 240000])" ] }, { @@ -197,14 +221,14 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(ts_dpsim['wr_1'].time, ts_dpsim['wr_1'].values, label='wr_1')\n", - "plt.plot(ts_dpsim['wr_2'].time, ts_dpsim['wr_2'].values, label='wr_2')\n", - "plt.plot(ts_dpsim['wr_3'].time, ts_dpsim['wr_3'].values, label='wr_3')\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('mechanical speed (rad/s)')\n", + "plt.plot(ts_dpsim[\"wr_1\"].time, ts_dpsim[\"wr_1\"].values, label=\"wr_1\")\n", + "plt.plot(ts_dpsim[\"wr_2\"].time, ts_dpsim[\"wr_2\"].values, label=\"wr_2\")\n", + "plt.plot(ts_dpsim[\"wr_3\"].time, ts_dpsim[\"wr_3\"].values, label=\"wr_3\")\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"mechanical speed (rad/s)\")\n", "plt.legend()\n", "plt.show()\n", - "#plt.savefig('wscc_9bus_fault_gen_speed.pdf')" + "# plt.savefig('wscc_9bus_fault_gen_speed.pdf')" ] }, { @@ -223,27 +247,53 @@ "import os\n", "import urllib.request\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/WSCC-9bus/d_009_fault_dpsim_2nd_order.out'\n", - "local_file = 'reference-results/d_009_fault_dpsim_2nd_order.out'\n", - "urllib.request.urlretrieve(url, local_file) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/PSAT/WSCC-9bus/d_009_fault_dpsim_2nd_order.out\"\n", + "local_file = \"reference-results/d_009_fault_dpsim_2nd_order.out\"\n", + "urllib.request.urlretrieve(url, local_file)\n", "\n", - "syngen_power_name_dpsim_list = ['P_elec_1', 'P_elec_2', 'P_elec_3']\n", - "syngen_power_name_psat_list = ['p_Syn_1', 'p_Syn_2', 'p_Syn_3']\n", + "syngen_power_name_dpsim_list = [\"P_elec_1\", \"P_elec_2\", \"P_elec_3\"]\n", + "syngen_power_name_psat_list = [\"p_Syn_1\", \"p_Syn_2\", \"p_Syn_3\"]\n", "\n", - "syngen_omega_name_dpsim_list = ['wr_1', 'wr_2', 'wr_3']\n", - "syngen_omega_name_psat_list = ['omega_Syn_1', 'omega_Syn_2', 'omega_Syn_3']\n", + "syngen_omega_name_dpsim_list = [\"wr_1\", \"wr_2\", \"wr_3\"]\n", + "syngen_omega_name_psat_list = [\"omega_Syn_1\", \"omega_Syn_2\", \"omega_Syn_3\"]\n", "\n", - "syngen_delta_name_dpsim_list = ['delta_r_1', 'delta_r_2', 'delta_r_3']\n", - "syngen_delta_name_psat_list = ['delta_Syn_1', 'delta_Syn_2', 'delta_Syn_3']\n", + "syngen_delta_name_dpsim_list = [\"delta_r_1\", \"delta_r_2\", \"delta_r_3\"]\n", + "syngen_delta_name_psat_list = [\"delta_Syn_1\", \"delta_Syn_2\", \"delta_Syn_3\"]\n", "\n", - "bus_volt_name_dpsim_list = ['v1', 'v2', 'v3', 'v4', 'v5', 'v6', 'v7', 'v8', 'v9']\n", - "bus_volt_name_psat_list = ['V_Bus 1', 'V_Bus 2', 'V_Bus 3', 'V_Bus 4', 'V_Bus 5', 'V_Bus 6', 'V_Bus 7', 'V_Bus 8', 'V_Bus 9']\n", - "bus_angle_name_psat_list = ['theta_Bus 1', 'theta_Bus 2', 'theta_Bus 3', 'theta_Bus 4', 'theta_Bus 5', 'theta_Bus 6', 'theta_Bus 7', 'theta_Bus 8', 'theta_Bus 9']\n", + "bus_volt_name_dpsim_list = [\"v1\", \"v2\", \"v3\", \"v4\", \"v5\", \"v6\", \"v7\", \"v8\", \"v9\"]\n", + "bus_volt_name_psat_list = [\n", + " \"V_Bus 1\",\n", + " \"V_Bus 2\",\n", + " \"V_Bus 3\",\n", + " \"V_Bus 4\",\n", + " \"V_Bus 5\",\n", + " \"V_Bus 6\",\n", + " \"V_Bus 7\",\n", + " \"V_Bus 8\",\n", + " \"V_Bus 9\",\n", + "]\n", + "bus_angle_name_psat_list = [\n", + " \"theta_Bus 1\",\n", + " \"theta_Bus 2\",\n", + " \"theta_Bus 3\",\n", + " \"theta_Bus 4\",\n", + " \"theta_Bus 5\",\n", + " \"theta_Bus 6\",\n", + " \"theta_Bus 7\",\n", + " \"theta_Bus 8\",\n", + " \"theta_Bus 9\",\n", + "]\n", "\n", - "timeseries_names_psat = syngen_power_name_psat_list+syngen_omega_name_psat_list+syngen_delta_name_psat_list+bus_volt_name_psat_list+bus_angle_name_psat_list\n", + "timeseries_names_psat = (\n", + " syngen_power_name_psat_list\n", + " + syngen_omega_name_psat_list\n", + " + syngen_delta_name_psat_list\n", + " + bus_volt_name_psat_list\n", + " + bus_angle_name_psat_list\n", + ")\n", "\n", "ts_psat = rt.read_timeseries_PSAT(local_file, timeseries_names_psat)" ] @@ -261,14 +311,25 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,9))\n", + "plt.figure(figsize=(12, 9))\n", "for syngen_omega_name_dpsim in syngen_omega_name_dpsim_list:\n", - " ts_dpsim[syngen_omega_name_dpsim].values = ts_dpsim[syngen_omega_name_dpsim].values/(2*np.pi*60)\n", - " plt.plot(ts_dpsim[syngen_omega_name_dpsim].time, ts_dpsim[syngen_omega_name_dpsim].values, label=syngen_omega_name_dpsim+' (dpsim)')\n", + " ts_dpsim[syngen_omega_name_dpsim].values = ts_dpsim[\n", + " syngen_omega_name_dpsim\n", + " ].values / (2 * np.pi * 60)\n", + " plt.plot(\n", + " ts_dpsim[syngen_omega_name_dpsim].time,\n", + " ts_dpsim[syngen_omega_name_dpsim].values,\n", + " label=syngen_omega_name_dpsim + \" (dpsim)\",\n", + " )\n", "for syngen_omega_name_psat in syngen_omega_name_psat_list:\n", - " plt.plot(ts_psat[syngen_omega_name_psat].time, ts_psat[syngen_omega_name_psat].values, label=syngen_omega_name_psat+' (psat)', linestyle='--')\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('mechanical speed (p.u)')\n", + " plt.plot(\n", + " ts_psat[syngen_omega_name_psat].time,\n", + " ts_psat[syngen_omega_name_psat].values,\n", + " label=syngen_omega_name_psat + \" (psat)\",\n", + " linestyle=\"--\",\n", + " )\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"mechanical speed (p.u)\")\n", "plt.legend()\n", "plt.show()" ] @@ -286,9 +347,27 @@ "metadata": {}, "outputs": [], "source": [ - "assert(ts_dpsim[syngen_omega_name_dpsim_list[0]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[0]], ts_psat[syngen_omega_name_psat_list[2]]) < 2e-4)\n", - "assert(ts_dpsim[syngen_omega_name_dpsim_list[1]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[1]], ts_psat[syngen_omega_name_psat_list[0]]) < 2e-4)\n", - "assert(ts_dpsim[syngen_omega_name_dpsim_list[2]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[2]], ts_psat[syngen_omega_name_psat_list[1]]) < 2e-4)" + "assert (\n", + " ts_dpsim[syngen_omega_name_dpsim_list[0]].rmse(\n", + " ts_dpsim[syngen_omega_name_dpsim_list[0]],\n", + " ts_psat[syngen_omega_name_psat_list[2]],\n", + " )\n", + " < 2e-4\n", + ")\n", + "assert (\n", + " ts_dpsim[syngen_omega_name_dpsim_list[1]].rmse(\n", + " ts_dpsim[syngen_omega_name_dpsim_list[1]],\n", + " ts_psat[syngen_omega_name_psat_list[0]],\n", + " )\n", + " < 2e-4\n", + ")\n", + "assert (\n", + " ts_dpsim[syngen_omega_name_dpsim_list[2]].rmse(\n", + " ts_dpsim[syngen_omega_name_dpsim_list[2]],\n", + " ts_psat[syngen_omega_name_psat_list[1]],\n", + " )\n", + " < 2e-4\n", + ")" ] }, { @@ -304,13 +383,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,9))\n", + "plt.figure(figsize=(12, 9))\n", "for syngen_delta_name_dpsim in syngen_delta_name_dpsim_list:\n", - " plt.plot(ts_dpsim[syngen_delta_name_dpsim].time, ts_dpsim[syngen_delta_name_dpsim].values, label=syngen_delta_name_dpsim+' (dpsim)')\n", + " plt.plot(\n", + " ts_dpsim[syngen_delta_name_dpsim].time,\n", + " ts_dpsim[syngen_delta_name_dpsim].values,\n", + " label=syngen_delta_name_dpsim + \" (dpsim)\",\n", + " )\n", "for syngen_delta_name_psat in syngen_delta_name_psat_list:\n", - " plt.plot(ts_psat[syngen_delta_name_psat].time, ts_psat[syngen_delta_name_psat].values, label=syngen_delta_name_psat+' (psat)', linestyle='--')\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('rotor angle (deg)')\n", + " plt.plot(\n", + " ts_psat[syngen_delta_name_psat].time,\n", + " ts_psat[syngen_delta_name_psat].values,\n", + " label=syngen_delta_name_psat + \" (psat)\",\n", + " linestyle=\"--\",\n", + " )\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"rotor angle (deg)\")\n", "plt.legend()\n", "plt.show()" ] @@ -328,20 +416,46 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,9))\n", + "plt.figure(figsize=(12, 9))\n", "for bus_volt_name_dpsim in bus_volt_name_dpsim_list:\n", - " if bus_volt_name_dpsim == 'v1':\n", - " plt.plot(ts_dpsim[bus_volt_name_dpsim].time, ts_dpsim[bus_volt_name_dpsim].abs().values/16.5e3, label=bus_volt_name_dpsim + ' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", - " elif bus_volt_name_dpsim == 'v2':\n", - " plt.plot(ts_dpsim[bus_volt_name_dpsim].time, ts_dpsim[bus_volt_name_dpsim].abs().values/18e3, label=bus_volt_name_dpsim + ' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", - " elif bus_volt_name_dpsim == 'v3':\n", - " plt.plot(ts_dpsim[bus_volt_name_dpsim].time, ts_dpsim[bus_volt_name_dpsim].abs().values/13.8e3, label=bus_volt_name_dpsim + ' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", + " if bus_volt_name_dpsim == \"v1\":\n", + " plt.plot(\n", + " ts_dpsim[bus_volt_name_dpsim].time,\n", + " ts_dpsim[bus_volt_name_dpsim].abs().values / 16.5e3,\n", + " label=bus_volt_name_dpsim + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", + " elif bus_volt_name_dpsim == \"v2\":\n", + " plt.plot(\n", + " ts_dpsim[bus_volt_name_dpsim].time,\n", + " ts_dpsim[bus_volt_name_dpsim].abs().values / 18e3,\n", + " label=bus_volt_name_dpsim + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", + " elif bus_volt_name_dpsim == \"v3\":\n", + " plt.plot(\n", + " ts_dpsim[bus_volt_name_dpsim].time,\n", + " ts_dpsim[bus_volt_name_dpsim].abs().values / 13.8e3,\n", + " label=bus_volt_name_dpsim + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", " else:\n", - " plt.plot(ts_dpsim[bus_volt_name_dpsim].time, ts_dpsim[bus_volt_name_dpsim].abs().values/230e3, label=bus_volt_name_dpsim + ' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", + " plt.plot(\n", + " ts_dpsim[bus_volt_name_dpsim].time,\n", + " ts_dpsim[bus_volt_name_dpsim].abs().values / 230e3,\n", + " label=bus_volt_name_dpsim + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", "for bus_volt_name_psat in bus_volt_name_psat_list:\n", - " plt.plot(ts_psat[bus_volt_name_psat].time, ts_psat[bus_volt_name_psat].values, label=bus_volt_name_psat + ' (psat)', linestyle='--', color='C'+str(bus_volt_name_psat_list.index(bus_volt_name_psat)))\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (p.u.)')\n", + " plt.plot(\n", + " ts_psat[bus_volt_name_psat].time,\n", + " ts_psat[bus_volt_name_psat].values,\n", + " label=bus_volt_name_psat + \" (psat)\",\n", + " linestyle=\"--\",\n", + " color=\"C\" + str(bus_volt_name_psat_list.index(bus_volt_name_psat)),\n", + " )\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (p.u.)\")\n", "plt.legend()\n", "plt.show()" ] @@ -359,13 +473,24 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,9))\n", + "plt.figure(figsize=(12, 9))\n", "for bus_volt_name_dpsim in bus_volt_name_dpsim_list:\n", - " plt.plot(ts_dpsim[bus_volt_name_dpsim].time, ts_dpsim[bus_volt_name_dpsim].phase().values/180*np.pi, label=bus_volt_name_dpsim + ' (dpsim)', color='C'+str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)))\n", + " plt.plot(\n", + " ts_dpsim[bus_volt_name_dpsim].time,\n", + " ts_dpsim[bus_volt_name_dpsim].phase().values / 180 * np.pi,\n", + " label=bus_volt_name_dpsim + \" (dpsim)\",\n", + " color=\"C\" + str(bus_volt_name_dpsim_list.index(bus_volt_name_dpsim)),\n", + " )\n", "for bus_angle_name_psat in bus_angle_name_psat_list:\n", - " plt.plot(ts_psat[bus_angle_name_psat].time, ts_psat[bus_angle_name_psat].values, label=bus_angle_name_psat + ' (psat)', linestyle='--', color='C'+str(bus_angle_name_psat_list.index(bus_angle_name_psat)))\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('angle (rad)')\n", + " plt.plot(\n", + " ts_psat[bus_angle_name_psat].time,\n", + " ts_psat[bus_angle_name_psat].values,\n", + " label=bus_angle_name_psat + \" (psat)\",\n", + " linestyle=\"--\",\n", + " color=\"C\" + str(bus_angle_name_psat_list.index(bus_angle_name_psat)),\n", + " )\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"angle (rad)\")\n", "plt.legend()\n", "plt.show()" ] @@ -383,13 +508,22 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12,9))\n", + "plt.figure(figsize=(12, 9))\n", "for syngen_power_name_dpsim in syngen_power_name_dpsim_list:\n", - " plt.plot(ts_dpsim[syngen_power_name_dpsim].time, ts_dpsim[syngen_power_name_dpsim].values/100e6, label=syngen_power_name_dpsim+' (dpsim)')\n", + " plt.plot(\n", + " ts_dpsim[syngen_power_name_dpsim].time,\n", + " ts_dpsim[syngen_power_name_dpsim].values / 100e6,\n", + " label=syngen_power_name_dpsim + \" (dpsim)\",\n", + " )\n", "for syngen_power_name_psat in syngen_power_name_psat_list:\n", - " plt.plot(ts_psat[syngen_power_name_psat].time, ts_psat[syngen_power_name_psat].values, label=syngen_power_name_psat+' (psat)', linestyle='--')\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('power (W)')\n", + " plt.plot(\n", + " ts_psat[syngen_power_name_psat].time,\n", + " ts_psat[syngen_power_name_psat].values,\n", + " label=syngen_power_name_psat + \" (psat)\",\n", + " linestyle=\"--\",\n", + " )\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"power (W)\")\n", "plt.legend()\n", "plt.show()" ] diff --git a/examples/Notebooks/Grids/case14.ipynb b/examples/Notebooks/Grids/case14.ipynb index 092d845a38..93efbdb5ef 100644 --- a/examples/Notebooks/Grids/case14.ipynb +++ b/examples/Notebooks/Grids/case14.ipynb @@ -21,9 +21,10 @@ "outputs": [], "source": [ "import requests\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/Matpower_cases/case14.xml'\n", - "filename = 'case14.xml'\n", - "with open(filename, 'wb') as out_file:\n", + "\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/Matpower_cases/case14.xml\"\n", + "filename = \"case14.xml\"\n", + "with open(filename, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", @@ -46,9 +47,11 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'case14'\n", + "name = \"case14\"\n", "reader = dpsimpy.CIMReader(name)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "system" ] }, @@ -66,7 +69,7 @@ "logger = dpsimpy.Logger(name)\n", "sim.add_logger(logger)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node);" + " logger.log_attribute(node.name() + \".V\", \"v\", node);" ] }, { @@ -91,7 +94,7 @@ "metadata": {}, "outputs": [], "source": [ - "dpsim_result_file = 'logs/' + name + '.csv'\n", + "dpsim_result_file = \"logs/\" + name + \".csv\"\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] }, @@ -101,8 +104,8 @@ "metadata": {}, "outputs": [], "source": [ - "for k,v in ts_dpsim.items():\n", - " print(v.name + ':' + str(v.values[0]))" + "for k, v in ts_dpsim.items():\n", + " print(v.name + \":\" + str(v.values[0]))" ] } ], diff --git a/examples/Notebooks/Grids/case145.ipynb b/examples/Notebooks/Grids/case145.ipynb index 74418ce8a1..5508b1b9f7 100644 --- a/examples/Notebooks/Grids/case145.ipynb +++ b/examples/Notebooks/Grids/case145.ipynb @@ -21,9 +21,10 @@ "outputs": [], "source": [ "import requests\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/Matpower_cases/case145.xml'\n", - "filename = 'case145.xml'\n", - "with open(filename, 'wb') as out_file:\n", + "\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/Matpower_cases/case145.xml\"\n", + "filename = \"case145.xml\"\n", + "with open(filename, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", @@ -46,9 +47,11 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'case145'\n", + "name = \"case145\"\n", "reader = dpsimpy.CIMReader(name)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "system" ] }, @@ -66,7 +69,7 @@ "logger = dpsimpy.Logger(name)\n", "sim.add_logger(logger)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node);" + " logger.log_attribute(node.name() + \".V\", \"v\", node);" ] }, { @@ -91,7 +94,7 @@ "metadata": {}, "outputs": [], "source": [ - "dpsim_result_file = 'logs/' + name + '.csv'\n", + "dpsim_result_file = \"logs/\" + name + \".csv\"\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] }, @@ -101,8 +104,8 @@ "metadata": {}, "outputs": [], "source": [ - "for k,v in ts_dpsim.items():\n", - " print(v.name + ':' + str(v.values[0]))" + "for k, v in ts_dpsim.items():\n", + " print(v.name + \":\" + str(v.values[0]))" ] }, { diff --git a/examples/Notebooks/Grids/case300.ipynb b/examples/Notebooks/Grids/case300.ipynb index cc804f3420..015fe65d1f 100644 --- a/examples/Notebooks/Grids/case300.ipynb +++ b/examples/Notebooks/Grids/case300.ipynb @@ -21,9 +21,10 @@ "outputs": [], "source": [ "import requests\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/Matpower_cases/case300.xml'\n", - "filename = 'case300.xml'\n", - "with open(filename, 'wb') as out_file:\n", + "\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/Matpower_cases/case300.xml\"\n", + "filename = \"case300.xml\"\n", + "with open(filename, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", @@ -46,9 +47,11 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'case300'\n", + "name = \"case300\"\n", "reader = dpsimpy.CIMReader(name)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "system" ] }, @@ -66,7 +69,7 @@ "logger = dpsimpy.Logger(name)\n", "sim.add_logger(logger)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node);" + " logger.log_attribute(node.name() + \".V\", \"v\", node);" ] }, { @@ -91,7 +94,7 @@ "metadata": {}, "outputs": [], "source": [ - "dpsim_result_file = 'logs/' + name + '.csv'\n", + "dpsim_result_file = \"logs/\" + name + \".csv\"\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] }, @@ -101,8 +104,8 @@ "metadata": {}, "outputs": [], "source": [ - "for k,v in ts_dpsim.items():\n", - " print(v.name + ':' + str(v.values[0]))" + "for k, v in ts_dpsim.items():\n", + " print(v.name + \":\" + str(v.values[0]))" ] }, { diff --git a/examples/Notebooks/Grids/case9.ipynb b/examples/Notebooks/Grids/case9.ipynb index 1c35295f4a..fb9f023efd 100644 --- a/examples/Notebooks/Grids/case9.ipynb +++ b/examples/Notebooks/Grids/case9.ipynb @@ -21,9 +21,10 @@ "outputs": [], "source": [ "import requests\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/Matpower_cases/case9.xml'\n", - "filename = 'case9.xml'\n", - "with open(filename, 'wb') as out_file:\n", + "\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/Matpower_cases/case9.xml\"\n", + "filename = \"case9.xml\"\n", + "with open(filename, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", @@ -46,9 +47,11 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'case9'\n", + "name = \"case9\"\n", "reader = dpsimpy.CIMReader(name)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", "system" ] }, @@ -66,7 +69,7 @@ "logger = dpsimpy.Logger(name)\n", "sim.add_logger(logger)\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node);" + " logger.log_attribute(node.name() + \".V\", \"v\", node);" ] }, { @@ -91,7 +94,7 @@ "metadata": {}, "outputs": [], "source": [ - "dpsim_result_file = 'logs/' + name + '.csv'\n", + "dpsim_result_file = \"logs/\" + name + \".csv\"\n", "ts_dpsim = read_timeseries_csv(dpsim_result_file)" ] }, @@ -101,8 +104,8 @@ "metadata": {}, "outputs": [], "source": [ - "for k,v in ts_dpsim.items():\n", - " print(v.name + ':' + str(v.values[0]))" + "for k, v in ts_dpsim.items():\n", + " print(v.name + \":\" + str(v.values[0]))" ] } ], diff --git a/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_SparseLU_KLU_fault_comparison.ipynb b/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_SparseLU_KLU_fault_comparison.ipynb index 61092ce9da..ca79ef4616 100644 --- a/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_SparseLU_KLU_fault_comparison.ipynb +++ b/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_SparseLU_KLU_fault_comparison.ipynb @@ -58,20 +58,22 @@ "\n", "log_level = dpsimpy.LogLevel.trace\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "filename = 'WSCC-09_Dyn_Fourth'\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_Dyn_Fourth/WSCC-09_Dyn_Fourth'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", - "download_grid_data(filename+'_DI.xml', url+'_DI.xml')\n", - " \n", - "files = glob.glob(filename+'_*.xml')" + "filename = \"WSCC-09_Dyn_Fourth\"\n", + "\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_Dyn_Fourth/WSCC-09_Dyn_Fourth\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "download_grid_data(filename + \"_DI.xml\", url + \"_DI.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")" ] }, { @@ -91,19 +93,21 @@ "source": [ "sim_name_pf = example_name + \"_PF\"\n", "\n", - "dpsimpy.Logger.set_log_dir(log_dir+\"/\"+sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(log_dir + \"/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, log_level, log_level)\n", "\n", - "system_pf = reader.loadCIM(60, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", - "system_pf.component('GEN1').modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", + "system_pf = reader.loadCIM(\n", + " 60, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", + "system_pf.component(\"GEN1\").modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", " logger_pf.log_attribute(node.name() + \".V\", node.attr(\"v\"))\n", - " \n", + "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, log_level)\n", "sim_pf.set_system(system_pf)\n", "sim_pf.set_time_step(final_time)\n", - "sim_pf.set_final_time(2*final_time)\n", + "sim_pf.set_final_time(2 * final_time)\n", "sim_pf.set_domain(dpsimpy.Domain.SP)\n", "sim_pf.set_solver(dpsimpy.Solver.NRP)\n", "sim_pf.set_solver_component_behaviour(dpsimpy.SolverBehaviour.Initialization)\n", @@ -127,16 +131,38 @@ "metadata": {}, "outputs": [], "source": [ - "def run_simulation(sim_name, implementation, model_syngens_as_norton, config = dpsimpy.DirectLinearSolverConfiguration()):\n", - " \n", - " dpsimpy.Logger.set_log_dir(log_dir+\"/\"+sim_name)\n", + "def run_simulation(\n", + " sim_name,\n", + " implementation,\n", + " model_syngens_as_norton,\n", + " config=dpsimpy.DirectLinearSolverConfiguration(),\n", + "):\n", + " dpsimpy.Logger.set_log_dir(log_dir + \"/\" + sim_name)\n", " reader2 = dpsimpy.CIMReader(sim_name, log_level, log_level)\n", " if sg_type == \"3\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG3OrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG3OrderVBR,\n", + " )\n", " elif sg_type == \"4\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG4OrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG4OrderVBR,\n", + " )\n", " elif sg_type == \"6b\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG6bOrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG6bOrderVBR,\n", + " )\n", " else:\n", " raise Exception(\"Unsupported reduced-order SG type!\")\n", "\n", @@ -144,18 +170,18 @@ "\n", " if with_fault == True:\n", " n1_dp = dpsimpy.dp.SimNode(fault_bus_name, dpsimpy.PhaseType.Single)\n", - " fault_dp.set_parameters(1e12, 0.02*529)\n", + " fault_dp.set_parameters(1e12, 0.02 * 529)\n", " fault_dp.connect([dpsimpy.dp.SimNode.gnd, n1_dp])\n", " fault_dp.open()\n", " sys.add(fault_dp)\n", "\n", " sys.init_with_powerflow(system_pf, dpsimpy.Domain.DP)\n", - " \n", + "\n", " for comp in sys.components:\n", - " if comp.__class__ == dpsimpy.dp.ph1.SynchronGenerator4OrderVBR:\n", - " gen_pf = system_pf.component(comp.name())\n", - " comp.get_terminal(index=0).set_power(- gen_pf.get_apparent_power())\n", - " comp.set_model_as_norton_source(model_syngens_as_norton)\n", + " if comp.__class__ == dpsimpy.dp.ph1.SynchronGenerator4OrderVBR:\n", + " gen_pf = system_pf.component(comp.name())\n", + " comp.get_terminal(index=0).set_power(-gen_pf.get_apparent_power())\n", + " comp.set_model_as_norton_source(model_syngens_as_norton)\n", "\n", " logger = dpsimpy.Logger(sim_name)\n", " for node in sys.nodes:\n", @@ -218,11 +244,17 @@ "outputs": [], "source": [ "%%capture\n", - "sim_name_lu_thevenin = example_name+'_SparseLU_thevenin'\n", - "run_simulation(sim_name_lu_thevenin,dpsimpy.DirectLinearSolverImpl.SparseLU,False)\n", - "ts_dpsim_sparse_thevenin = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_lu_thevenin+\".csv\")\n", - "ts_dpsim_sparse_thevenin_rhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_lu_thevenin+\"_RightVector.csv\")\n", - "ts_dpsim_sparse_thevenin_lhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_lu_thevenin+\"_LeftVector.csv\")" + "sim_name_lu_thevenin = example_name + \"_SparseLU_thevenin\"\n", + "run_simulation(sim_name_lu_thevenin, dpsimpy.DirectLinearSolverImpl.SparseLU, False)\n", + "ts_dpsim_sparse_thevenin = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_lu_thevenin + \".csv\"\n", + ")\n", + "ts_dpsim_sparse_thevenin_rhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_lu_thevenin + \"_RightVector.csv\"\n", + ")\n", + "ts_dpsim_sparse_thevenin_lhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_lu_thevenin + \"_LeftVector.csv\"\n", + ")" ] }, { @@ -245,11 +277,17 @@ "outputs": [], "source": [ "%%capture\n", - "sim_name_lu_norton = example_name+'_SparseLU_norton'\n", - "run_simulation(sim_name_lu_norton,dpsimpy.DirectLinearSolverImpl.SparseLU,True)\n", - "ts_dpsim_sparse_norton = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_lu_norton+\".csv\")\n", - "ts_dpsim_sparse_norton_rhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_lu_norton+\"_RightVector.csv\")\n", - "ts_dpsim_sparse_norton_lhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_lu_norton+\"_LeftVector.csv\")" + "sim_name_lu_norton = example_name + \"_SparseLU_norton\"\n", + "run_simulation(sim_name_lu_norton, dpsimpy.DirectLinearSolverImpl.SparseLU, True)\n", + "ts_dpsim_sparse_norton = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_lu_norton + \".csv\"\n", + ")\n", + "ts_dpsim_sparse_norton_rhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_lu_norton + \"_RightVector.csv\"\n", + ")\n", + "ts_dpsim_sparse_norton_lhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_lu_norton + \"_LeftVector.csv\"\n", + ")" ] }, { @@ -270,11 +308,17 @@ "outputs": [], "source": [ "%%capture\n", - "sim_name_klu_pf_thevenin = example_name+'_KLU_pf_thevenin'\n", - "run_simulation(sim_name_klu_pf_thevenin,dpsimpy.DirectLinearSolverImpl.KLU,False)\n", - "ts_dpsim_klu_pf_thevenin = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_pf_thevenin+\".csv\")\n", - "ts_dpsim_klu_pf_thevenin_rhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_pf_thevenin+\"_RightVector.csv\")\n", - "ts_dpsim_klu_pf_thevenin_lhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_pf_thevenin+\"_LeftVector.csv\")" + "sim_name_klu_pf_thevenin = example_name + \"_KLU_pf_thevenin\"\n", + "run_simulation(sim_name_klu_pf_thevenin, dpsimpy.DirectLinearSolverImpl.KLU, False)\n", + "ts_dpsim_klu_pf_thevenin = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_pf_thevenin + \".csv\"\n", + ")\n", + "ts_dpsim_klu_pf_thevenin_rhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_pf_thevenin + \"_RightVector.csv\"\n", + ")\n", + "ts_dpsim_klu_pf_thevenin_lhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_pf_thevenin + \"_LeftVector.csv\"\n", + ")" ] }, { @@ -293,11 +337,17 @@ "outputs": [], "source": [ "%%capture\n", - "sim_name_klu_pf_norton = example_name+'_KLU_pf_norton'\n", - "run_simulation(sim_name_klu_pf_norton,dpsimpy.DirectLinearSolverImpl.KLU,True)\n", - "ts_dpsim_klu_pf_norton = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_pf_norton+\".csv\")\n", - "ts_dpsim_klu_pf_norton_rhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_pf_norton+\"_RightVector.csv\")\n", - "ts_dpsim_klu_pf_norton_lhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_pf_norton+\"_LeftVector.csv\")" + "sim_name_klu_pf_norton = example_name + \"_KLU_pf_norton\"\n", + "run_simulation(sim_name_klu_pf_norton, dpsimpy.DirectLinearSolverImpl.KLU, True)\n", + "ts_dpsim_klu_pf_norton = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_pf_norton + \".csv\"\n", + ")\n", + "ts_dpsim_klu_pf_norton_rhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_pf_norton + \"_RightVector.csv\"\n", + ")\n", + "ts_dpsim_klu_pf_norton_lhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_pf_norton + \"_LeftVector.csv\"\n", + ")" ] }, { @@ -323,12 +373,22 @@ "source": [ "%%capture\n", "config = dpsimpy.DirectLinearSolverConfiguration()\n", - "config.set_partial_refactorization_method(dpsimpy.partial_refactorization_method.no_partial_refactorization)\n", - "sim_name_klu_cf_thevenin = example_name+'_KLU_cf_thevenin'\n", - "run_simulation(sim_name_klu_cf_thevenin, dpsimpy.DirectLinearSolverImpl.KLU, False, config)\n", - "ts_dpsim_klu_cf_thevenin = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_cf_thevenin+\".csv\")\n", - "ts_dpsim_klu_cf_thevenin_rhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_cf_thevenin+\"_RightVector.csv\")\n", - "ts_dpsim_klu_cf_thevenin_lhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_cf_thevenin+\"_LeftVector.csv\")" + "config.set_partial_refactorization_method(\n", + " dpsimpy.partial_refactorization_method.no_partial_refactorization\n", + ")\n", + "sim_name_klu_cf_thevenin = example_name + \"_KLU_cf_thevenin\"\n", + "run_simulation(\n", + " sim_name_klu_cf_thevenin, dpsimpy.DirectLinearSolverImpl.KLU, False, config\n", + ")\n", + "ts_dpsim_klu_cf_thevenin = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_cf_thevenin + \".csv\"\n", + ")\n", + "ts_dpsim_klu_cf_thevenin_rhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_cf_thevenin + \"_RightVector.csv\"\n", + ")\n", + "ts_dpsim_klu_cf_thevenin_lhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_cf_thevenin + \"_LeftVector.csv\"\n", + ")" ] }, { @@ -352,12 +412,20 @@ "source": [ "%%capture\n", "config = dpsimpy.DirectLinearSolverConfiguration()\n", - "config.set_partial_refactorization_method(dpsimpy.partial_refactorization_method.no_partial_refactorization)\n", - "sim_name_klu_cf_norton = example_name+'_KLU_cf_norton'\n", + "config.set_partial_refactorization_method(\n", + " dpsimpy.partial_refactorization_method.no_partial_refactorization\n", + ")\n", + "sim_name_klu_cf_norton = example_name + \"_KLU_cf_norton\"\n", "run_simulation(sim_name_klu_cf_norton, dpsimpy.DirectLinearSolverImpl.KLU, True, config)\n", - "ts_dpsim_klu_cf_norton = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_cf_norton+\".csv\")\n", - "ts_dpsim_klu_cf_norton_rhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_cf_norton+\"_RightVector.csv\")\n", - "ts_dpsim_klu_cf_norton_lhs = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name_klu_cf_norton+\"_LeftVector.csv\")" + "ts_dpsim_klu_cf_norton = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_cf_norton + \".csv\"\n", + ")\n", + "ts_dpsim_klu_cf_norton_rhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_cf_norton + \"_RightVector.csv\"\n", + ")\n", + "ts_dpsim_klu_cf_norton_lhs = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name_klu_cf_norton + \"_LeftVector.csv\"\n", + ")" ] }, { @@ -401,8 +469,11 @@ "# Constants\n", "close_to_zero_tolerance = 1e-12\n", "\n", + "\n", "# Helper function relative error (relative to vector1)\n", - "def relative_error(vector1: np.ndarray, vector2: np.ndarray) -> (np.ndarray, float, int):\n", + "def relative_error(\n", + " vector1: np.ndarray, vector2: np.ndarray\n", + ") -> (np.ndarray, float, int):\n", " N = len(vector1)\n", " rel_error = np.zeros(N, dtype=float)\n", " for i in range(0, N - 1):\n", @@ -415,47 +486,71 @@ " # [RV, LV]\n", " maxerror = [0.0, 0.0]\n", " maxerror_timestamp = [0, 0]\n", - " maxerror_entry = ['', '']\n", - "\n", + " maxerror_entry = [\"\", \"\"]\n", "\n", " # Relative error in right vector\n", - " print('Maximum relative error in right vector for each entry (when > 0)')\n", + " print(\"Maximum relative error in right vector for each entry (when > 0)\")\n", " for entry in sparse_r_vec:\n", " sparse_values = sparse_r_vec[entry].values\n", " klu_values = klu_r_vec[entry].values\n", "\n", - " relative_error_klu_sparse, max_error_rv, max_error_rv_timestamp = relative_error(sparse_values, klu_values)\n", + " (\n", + " relative_error_klu_sparse,\n", + " max_error_rv,\n", + " max_error_rv_timestamp,\n", + " ) = relative_error(sparse_values, klu_values)\n", " if max_error_rv > maxerror[0]:\n", " maxerror[0] = max_error_rv\n", " maxerror_timestamp[0] = max_error_rv_timestamp\n", " maxerror_entry[0] = entry\n", " if max_error_rv > close_to_zero_tolerance:\n", - " print('Entry {}: {:.3e} at {}s'.format(entry, max_error_rv, max_error_rv_timestamp / 1000.0))\n", - " print('Maximum relative error in right vector: {} {:.3e} {}s'.format(maxerror_entry[0], maxerror[0], maxerror_timestamp[0] / 1000.0))\n", - "\n", + " print(\n", + " \"Entry {}: {:.3e} at {}s\".format(\n", + " entry, max_error_rv, max_error_rv_timestamp / 1000.0\n", + " )\n", + " )\n", + " print(\n", + " \"Maximum relative error in right vector: {} {:.3e} {}s\".format(\n", + " maxerror_entry[0], maxerror[0], maxerror_timestamp[0] / 1000.0\n", + " )\n", + " )\n", "\n", " # Relative error in left vector\n", - " print('\\nMaximum relative error in left vector for each entry (when > 0)')\n", + " print(\"\\nMaximum relative error in left vector for each entry (when > 0)\")\n", " for entry in sparse_l_vec:\n", " sparse_values = sparse_l_vec[entry].values\n", " klu_values = klu_l_vec[entry].values\n", "\n", - " relative_error_klu_sparse, max_error_lv, max_error_lv_timestamp = relative_error(sparse_values, klu_values)\n", + " (\n", + " relative_error_klu_sparse,\n", + " max_error_lv,\n", + " max_error_lv_timestamp,\n", + " ) = relative_error(sparse_values, klu_values)\n", " if max_error_lv > maxerror[1]:\n", " maxerror[1] = max_error_lv\n", " maxerror_timestamp[1] = max_error_lv_timestamp\n", " maxerror_entry[1] = entry\n", " if max_error_lv > close_to_zero_tolerance:\n", - " print('Entry {}: {:.3e} at {}s'.format(entry, max_error_lv, max_error_lv_timestamp / 1000.0))\n", - " print('Maximum relative error in left vector: {} {:.3e} {}s'.format(maxerror_entry[1], maxerror[1], maxerror_timestamp[1] / 1000.0))\n", - "\n", - " _rvlv = ['right', 'left']\n", - " print('\\nMaximum relative error in all values: {:.3e} at {}s at entry {} in {} vector'.format(\n", - " max(maxerror),\n", - " maxerror_timestamp[np.argmax(maxerror)] / 1000.0,\n", - " maxerror_entry[np.argmax(maxerror)],\n", - " _rvlv[np.argmax(maxerror)])\n", - " )\n", + " print(\n", + " \"Entry {}: {:.3e} at {}s\".format(\n", + " entry, max_error_lv, max_error_lv_timestamp / 1000.0\n", + " )\n", + " )\n", + " print(\n", + " \"Maximum relative error in left vector: {} {:.3e} {}s\".format(\n", + " maxerror_entry[1], maxerror[1], maxerror_timestamp[1] / 1000.0\n", + " )\n", + " )\n", + "\n", + " _rvlv = [\"right\", \"left\"]\n", + " print(\n", + " \"\\nMaximum relative error in all values: {:.3e} at {}s at entry {} in {} vector\".format(\n", + " max(maxerror),\n", + " maxerror_timestamp[np.argmax(maxerror)] / 1000.0,\n", + " maxerror_entry[np.argmax(maxerror)],\n", + " _rvlv[np.argmax(maxerror)],\n", + " )\n", + " )\n", " return max(maxerror)" ] }, @@ -488,11 +583,13 @@ "source": [ "# KLU partial refactorization / SparseLU, thevenin equivalent\n", "max_error = evaluation_func(\n", - " ts_dpsim_sparse_thevenin_rhs, ts_dpsim_sparse_thevenin_lhs,\n", - " ts_dpsim_klu_pf_thevenin_rhs, ts_dpsim_klu_pf_thevenin_lhs\n", + " ts_dpsim_sparse_thevenin_rhs,\n", + " ts_dpsim_sparse_thevenin_lhs,\n", + " ts_dpsim_klu_pf_thevenin_rhs,\n", + " ts_dpsim_klu_pf_thevenin_lhs,\n", ")\n", "\n", - "assert(max_error < max_rel_error)" + "assert max_error < max_rel_error" ] }, { @@ -504,11 +601,13 @@ "source": [ "# KLU partial refactorization / SparseLU, norton equivalent\n", "max_error = evaluation_func(\n", - " ts_dpsim_sparse_norton_rhs, ts_dpsim_sparse_norton_lhs,\n", - " ts_dpsim_klu_pf_norton_rhs, ts_dpsim_klu_pf_norton_lhs\n", + " ts_dpsim_sparse_norton_rhs,\n", + " ts_dpsim_sparse_norton_lhs,\n", + " ts_dpsim_klu_pf_norton_rhs,\n", + " ts_dpsim_klu_pf_norton_lhs,\n", ")\n", "\n", - "assert(max_error < max_rel_error)" + "assert max_error < max_rel_error" ] }, { @@ -520,11 +619,13 @@ "source": [ "# KLU complete refactorization / SparseLU, thevenin equivalent\n", "max_error = evaluation_func(\n", - " ts_dpsim_sparse_thevenin_rhs, ts_dpsim_sparse_thevenin_lhs,\n", - " ts_dpsim_klu_cf_thevenin_rhs, ts_dpsim_klu_cf_thevenin_lhs\n", + " ts_dpsim_sparse_thevenin_rhs,\n", + " ts_dpsim_sparse_thevenin_lhs,\n", + " ts_dpsim_klu_cf_thevenin_rhs,\n", + " ts_dpsim_klu_cf_thevenin_lhs,\n", ")\n", "\n", - "assert(max_error < max_rel_error)" + "assert max_error < max_rel_error" ] }, { @@ -536,11 +637,13 @@ "source": [ "# KLU complete refactorization / SparseLU, norton equivalent\n", "max_error = evaluation_func(\n", - " ts_dpsim_sparse_norton_rhs, ts_dpsim_sparse_norton_lhs,\n", - " ts_dpsim_klu_cf_norton_rhs, ts_dpsim_klu_cf_norton_lhs\n", + " ts_dpsim_sparse_norton_rhs,\n", + " ts_dpsim_sparse_norton_lhs,\n", + " ts_dpsim_klu_cf_norton_rhs,\n", + " ts_dpsim_klu_cf_norton_lhs,\n", ")\n", "\n", - "assert(max_error < max_rel_error)" + "assert max_error < max_rel_error" ] }, { @@ -552,11 +655,13 @@ "source": [ "# KLU complete refactorization / KLU partial refactorization, thevenin equivalent\n", "max_error = evaluation_func(\n", - " ts_dpsim_klu_pf_thevenin_rhs, ts_dpsim_klu_pf_thevenin_lhs,\n", - " ts_dpsim_klu_cf_thevenin_rhs, ts_dpsim_klu_cf_thevenin_lhs\n", + " ts_dpsim_klu_pf_thevenin_rhs,\n", + " ts_dpsim_klu_pf_thevenin_lhs,\n", + " ts_dpsim_klu_cf_thevenin_rhs,\n", + " ts_dpsim_klu_cf_thevenin_lhs,\n", ")\n", "\n", - "assert(max_error < max_rel_error)" + "assert max_error < max_rel_error" ] }, { @@ -568,11 +673,13 @@ "source": [ "# KLU complete refactorization / KLU partial refactorization, norton equivalent\n", "max_error = evaluation_func(\n", - " ts_dpsim_klu_pf_norton_rhs, ts_dpsim_klu_pf_norton_lhs,\n", - " ts_dpsim_klu_cf_norton_rhs, ts_dpsim_klu_cf_norton_lhs\n", + " ts_dpsim_klu_pf_norton_rhs,\n", + " ts_dpsim_klu_pf_norton_lhs,\n", + " ts_dpsim_klu_cf_norton_rhs,\n", + " ts_dpsim_klu_cf_norton_lhs,\n", ")\n", "\n", - "assert(max_error < max_rel_error)" + "assert max_error < max_rel_error" ] } ], diff --git a/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_validate_KLU_using_different_settings.ipynb b/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_validate_KLU_using_different_settings.ipynb index 466439e420..0106c50191 100644 --- a/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_validate_KLU_using_different_settings.ipynb +++ b/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_validate_KLU_using_different_settings.ipynb @@ -44,34 +44,38 @@ "else:\n", " log_down_sampling = 1.0\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "filename = 'WSCC-09_Dyn_Fourth'\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_Dyn_Fourth/WSCC-09_Dyn_Fourth'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", - "download_grid_data(filename+'_DI.xml', url+'_DI.xml')\n", - " \n", - "files = glob.glob(filename+'_*.xml')\n", + "filename = \"WSCC-09_Dyn_Fourth\"\n", + "\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_Dyn_Fourth/WSCC-09_Dyn_Fourth\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "download_grid_data(filename + \"_DI.xml\", url + \"_DI.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "\n", - "dpsimpy.Logger.set_log_dir(log_dir+\"/\"+sim_name_pf)\n", + "dpsimpy.Logger.set_log_dir(log_dir + \"/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, log_level, log_level)\n", "\n", - "system_pf = reader.loadCIM(60, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", - "system_pf.component('GEN1').modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", + "system_pf = reader.loadCIM(\n", + " 60, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", + "system_pf.component(\"GEN1\").modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", " logger_pf.log_attribute(node.name() + \".V\", node.attr(\"v\"))\n", - " \n", + "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, log_level)\n", "sim_pf.set_system(system_pf)\n", "sim_pf.set_time_step(final_time)\n", - "sim_pf.set_final_time(2*final_time)\n", + "sim_pf.set_final_time(2 * final_time)\n", "sim_pf.set_domain(dpsimpy.Domain.SP)\n", "sim_pf.set_solver(dpsimpy.Solver.NRP)\n", "sim_pf.set_solver_component_behaviour(dpsimpy.SolverBehaviour.Initialization)\n", @@ -89,14 +93,32 @@ "source": [ "## Dynamic Simulation\n", "def run_simulation(fillin, btf, partial):\n", - " dpsimpy.Logger.set_log_dir(log_dir+\"/\"+sim_name)\n", + " dpsimpy.Logger.set_log_dir(log_dir + \"/\" + sim_name)\n", " reader2 = dpsimpy.CIMReader(sim_name, log_level, log_level)\n", " if sg_type == \"3\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG3OrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG3OrderVBR,\n", + " )\n", " elif sg_type == \"4\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG4OrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG4OrderVBR,\n", + " )\n", " elif sg_type == \"6b\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG6bOrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG6bOrderVBR,\n", + " )\n", " else:\n", " raise Exception(\"Unsupported reduced-order SG type!\")\n", "\n", @@ -104,19 +126,19 @@ "\n", " if with_fault == True:\n", " n1_dp = dpsimpy.dp.SimNode(fault_bus_name, dpsimpy.PhaseType.Single)\n", - " fault_dp.set_parameters(1e12, 0.02*529)\n", + " fault_dp.set_parameters(1e12, 0.02 * 529)\n", " fault_dp.connect([dpsimpy.dp.SimNode.gnd, n1_dp])\n", " fault_dp.open()\n", " sys.add(fault_dp)\n", "\n", " sys.init_with_powerflow(system_pf, dpsimpy.Domain.DP)\n", " for comp in sys.components:\n", - " # I assume this is how you access the generators\n", - " if \"GEN\" in comp.name():\n", - " comp.scale_inertia_constant(intertia_scaling_factor)\n", - " comp.set_model_as_norton_source(False)\n", + " # I assume this is how you access the generators\n", + " if \"GEN\" in comp.name():\n", + " comp.scale_inertia_constant(intertia_scaling_factor)\n", + " comp.set_model_as_norton_source(False)\n", "\n", - " logger = dpsimpy.Logger(sim_name)#, True, log_down_sampling)\n", + " logger = dpsimpy.Logger(sim_name) # , True, log_down_sampling)\n", " for node in sys.nodes:\n", " logger.log_attribute(node.name() + \".V\", node.attr(\"v\"))\n", "\n", @@ -126,7 +148,7 @@ " logger.log_attribute(comp.name() + \".Te\", comp.attr(\"Te\"))\n", " logger.log_attribute(comp.name() + \".omega\", comp.attr(\"w_r\"))\n", " logger.log_attribute(comp.name() + \".delta\", comp.attr(\"delta\"))\n", - " \n", + "\n", " config = dpsimpy.DirectLinearSolverConfiguration()\n", " config.set_btf(btf)\n", " config.set_fill_in_reduction_method(fillin)\n", @@ -167,8 +189,12 @@ "partial = dpsimpy.partial_refactorization_method.factorization_path\n", "\n", "run_simulation(fillin, btf, partial)\n", - "ts_dpsim_lv_amd = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_amd = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_amd = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_amd = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -184,8 +210,12 @@ "partial = dpsimpy.partial_refactorization_method.factorization_path\n", "\n", "run_simulation(fillin, btf, partial)\n", - "ts_dpsim_lv_amd_nv = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_amd_nv = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_amd_nv = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_amd_nv = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -201,8 +231,12 @@ "partial = dpsimpy.partial_refactorization_method.refactorization_restart\n", "\n", "run_simulation(fillin, btf, partial)\n", - "ts_dpsim_lv_amd_ra = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_amd_ra = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_amd_ra = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_amd_ra = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -219,24 +253,24 @@ " amd_nv_values = ts_dpsim_rv_amd_nv[entry].values\n", " amd_ra_values = ts_dpsim_rv_amd_ra[entry].values\n", " # 2-norm of errors\n", - " error_1 = np.linalg.norm(amd_values-amd_nv_values, ord=2)\n", - " error_2 = np.linalg.norm(amd_ra_values-amd_values, ord=2)\n", - " print('RV Error for {} for AMD vs NV: {}'.format(entry,error_1))\n", - " print('RV Error for {} for AMD vs RA: {}'.format(entry,error_2))\n", - " assert(error_1 < tolerance)\n", - " assert(error_2 < tolerance)\n", + " error_1 = np.linalg.norm(amd_values - amd_nv_values, ord=2)\n", + " error_2 = np.linalg.norm(amd_ra_values - amd_values, ord=2)\n", + " print(\"RV Error for {} for AMD vs NV: {}\".format(entry, error_1))\n", + " print(\"RV Error for {} for AMD vs RA: {}\".format(entry, error_2))\n", + " assert error_1 < tolerance\n", + " assert error_2 < tolerance\n", "\n", "for entry in ts_dpsim_lv_amd:\n", " amd_values = ts_dpsim_lv_amd[entry].values\n", " amd_nv_values = ts_dpsim_lv_amd_nv[entry].values\n", " amd_ra_values = ts_dpsim_lv_amd_ra[entry].values\n", " # 2-norm of errors\n", - " error_1 = np.linalg.norm(amd_values-amd_nv_values, ord=2)\n", - " error_2 = np.linalg.norm(amd_ra_values-amd_values, ord=2)\n", - " print('LV Error for {} for AMD vs NV: {}'.format(entry,error_1))\n", - " print('LV Error for {} for AMD vs RA: {}'.format(entry,error_2))\n", - " assert(error_1 < tolerance)\n", - " assert(error_2 < tolerance)" + " error_1 = np.linalg.norm(amd_values - amd_nv_values, ord=2)\n", + " error_2 = np.linalg.norm(amd_ra_values - amd_values, ord=2)\n", + " print(\"LV Error for {} for AMD vs NV: {}\".format(entry, error_1))\n", + " print(\"LV Error for {} for AMD vs RA: {}\".format(entry, error_2))\n", + " assert error_1 < tolerance\n", + " assert error_2 < tolerance" ] }, { diff --git a/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_validate_SparseLU_DenseLU_KLU_using_partial_refactorization.ipynb b/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_validate_SparseLU_DenseLU_KLU_using_partial_refactorization.ipynb index a50001c5db..3092c57af3 100644 --- a/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_validate_SparseLU_DenseLU_KLU_using_partial_refactorization.ipynb +++ b/examples/Notebooks/Performance/DP_WSCC9bus_SGReducedOrderVBR_validate_SparseLU_DenseLU_KLU_using_partial_refactorization.ipynb @@ -45,34 +45,38 @@ "else:\n", " log_down_sampling = 1.0\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "filename = 'WSCC-09_Dyn_Fourth'\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_Dyn_Fourth/WSCC-09_Dyn_Fourth'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", - "download_grid_data(filename+'_DI.xml', url+'_DI.xml')\n", - " \n", - "files = glob.glob(filename+'_*.xml')\n", + "filename = \"WSCC-09_Dyn_Fourth\"\n", + "\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_Dyn_Fourth/WSCC-09_Dyn_Fourth\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "download_grid_data(filename + \"_DI.xml\", url + \"_DI.xml\")\n", "\n", - "dpsimpy.Logger.set_log_dir(log_dir+\"/\"+sim_name_pf)\n", + "files = glob.glob(filename + \"_*.xml\")\n", + "\n", + "dpsimpy.Logger.set_log_dir(log_dir + \"/\" + sim_name_pf)\n", "reader = dpsimpy.CIMReader(sim_name_pf, log_level, log_level)\n", "\n", - "system_pf = reader.loadCIM(60, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)\n", - "system_pf.component('GEN1').modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", + "system_pf = reader.loadCIM(\n", + " 60, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")\n", + "system_pf.component(\"GEN1\").modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD)\n", "logger_pf = dpsimpy.Logger(sim_name_pf)\n", "for node in system_pf.nodes:\n", " logger_pf.log_attribute(node.name() + \".V\", node.attr(\"v\"))\n", - " \n", + "\n", "sim_pf = dpsimpy.Simulation(sim_name_pf, log_level)\n", "sim_pf.set_system(system_pf)\n", "sim_pf.set_time_step(final_time)\n", - "sim_pf.set_final_time(2*final_time)\n", + "sim_pf.set_final_time(2 * final_time)\n", "sim_pf.set_domain(dpsimpy.Domain.SP)\n", "sim_pf.set_solver(dpsimpy.Solver.NRP)\n", "sim_pf.set_solver_component_behaviour(dpsimpy.SolverBehaviour.Initialization)\n", @@ -90,14 +94,32 @@ "source": [ "## Dynamic Simulation\n", "def run_simulation(implementation):\n", - " dpsimpy.Logger.set_log_dir(log_dir+\"/\"+sim_name)\n", + " dpsimpy.Logger.set_log_dir(log_dir + \"/\" + sim_name)\n", " reader2 = dpsimpy.CIMReader(sim_name, log_level, log_level)\n", " if sg_type == \"3\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG3OrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG3OrderVBR,\n", + " )\n", " elif sg_type == \"4\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG4OrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG4OrderVBR,\n", + " )\n", " elif sg_type == \"6b\":\n", - " sys = reader2.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.SG6bOrderVBR)\n", + " sys = reader2.loadCIM(\n", + " 60,\n", + " files,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.SG6bOrderVBR,\n", + " )\n", " else:\n", " raise Exception(\"Unsupported reduced-order SG type!\")\n", "\n", @@ -105,19 +127,19 @@ "\n", " if with_fault == True:\n", " n1_dp = dpsimpy.dp.SimNode(fault_bus_name, dpsimpy.PhaseType.Single)\n", - " fault_dp.set_parameters(1e12, 0.02*529)\n", + " fault_dp.set_parameters(1e12, 0.02 * 529)\n", " fault_dp.connect([dpsimpy.dp.SimNode.gnd, n1_dp])\n", " fault_dp.open()\n", " sys.add(fault_dp)\n", "\n", " sys.init_with_powerflow(system_pf, dpsimpy.Domain.DP)\n", " for comp in sys.components:\n", - " # I assume this is how you access the generators\n", - " if \"GEN\" in comp.name():\n", - " comp.scale_inertia_constant(intertia_scaling_factor)\n", - " comp.set_model_as_norton_source(False)\n", + " # I assume this is how you access the generators\n", + " if \"GEN\" in comp.name():\n", + " comp.scale_inertia_constant(intertia_scaling_factor)\n", + " comp.set_model_as_norton_source(False)\n", "\n", - " logger = dpsimpy.Logger(sim_name)#, True, log_down_sampling)\n", + " logger = dpsimpy.Logger(sim_name) # , True, log_down_sampling)\n", " for node in sys.nodes:\n", " logger.log_attribute(node.name() + \".V\", node.attr(\"v\"))\n", "\n", @@ -156,8 +178,12 @@ "source": [ "%%capture\n", "run_simulation(dpsimpy.DirectLinearSolverImpl.SparseLU)\n", - "ts_dpsim_lv_sparse = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_sparse = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_sparse = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_sparse = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -169,8 +195,12 @@ "source": [ "%%capture\n", "run_simulation(dpsimpy.DirectLinearSolverImpl.KLU)\n", - "ts_dpsim_lv_klu = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_klu = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_klu = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_klu = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -182,8 +212,12 @@ "source": [ "%%capture\n", "run_simulation(dpsimpy.DirectLinearSolverImpl.DenseLU)\n", - "ts_dpsim_lv_denselu = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_denselu = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_denselu = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_denselu = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -203,25 +237,35 @@ " sparse_values = ts_dpsim_rv_sparse[entry].values\n", " klu_values = ts_dpsim_rv_klu[entry].values\n", " denselu_values = ts_dpsim_rv_denselu[entry].values\n", - " \n", + "\n", " N = len(klu_values)\n", - " \n", + "\n", " relativ_diff_sparse_klu = np.zeros(N, dtype=complex)\n", " relativ_diff_sparse_denselu = np.zeros(N, dtype=complex)\n", - " \n", - " for i in range(0, N-1):\n", + "\n", + " for i in range(0, N - 1):\n", " if abs(klu_values[i]) > close_to_zero_tolerance:\n", - " relativ_diff_sparse_klu[i] = (sparse_values[i]-klu_values[i])/klu_values[i]\n", - " relativ_diff_sparse_denselu[i] = (sparse_values[i]-denselu_values[i])/klu_values[i]\n", + " relativ_diff_sparse_klu[i] = (\n", + " sparse_values[i] - klu_values[i]\n", + " ) / klu_values[i]\n", + " relativ_diff_sparse_denselu[i] = (\n", + " sparse_values[i] - denselu_values[i]\n", + " ) / klu_values[i]\n", " if relativ_diff_sparse_klu[i] > maxerror:\n", " maxerror = relativ_diff_sparse_klu[i]\n", " if relativ_diff_sparse_denselu[i] > maxerror:\n", " maxerror = relativ_diff_sparse_denselu[i]\n", - " \n", + "\n", " error_1 = np.linalg.norm(relativ_diff_sparse_klu, ord=2)\n", " error_2 = np.linalg.norm(relativ_diff_sparse_denselu, ord=2)\n", - " print('RV Entry {} Maximum Difference of SparseLU vs. KLU: {}'.format(entry,error_1))\n", - " print('RV Entry {} Maximum Difference of DenseLU vs. SparseLU: {}'.format(entry,error_2))\n", + " print(\n", + " \"RV Entry {} Maximum Difference of SparseLU vs. KLU: {}\".format(entry, error_1)\n", + " )\n", + " print(\n", + " \"RV Entry {} Maximum Difference of DenseLU vs. SparseLU: {}\".format(\n", + " entry, error_2\n", + " )\n", + " )\n", " if error_1 > maxerrorn:\n", " maxerrorn = error_1\n", " if error_2 > maxerrorn:\n", @@ -231,32 +275,42 @@ " sparse_values = ts_dpsim_lv_sparse[entry].values\n", " klu_values = ts_dpsim_lv_klu[entry].values\n", " denselu_values = ts_dpsim_lv_denselu[entry].values\n", - " \n", + "\n", " N = len(klu_values)\n", - " \n", + "\n", " relativ_diff_sparse_klu = np.zeros(N, dtype=complex)\n", " relativ_diff_sparse_denselu = np.zeros(N, dtype=complex)\n", - " \n", - " for i in range(0, N-1):\n", + "\n", + " for i in range(0, N - 1):\n", " if abs(klu_values[i]) > close_to_zero_tolerance:\n", - " relativ_diff_sparse_klu[i] = (sparse_values[i]-klu_values[i])/klu_values[i]\n", - " relativ_diff_sparse_denselu[i] = (sparse_values[i]-denselu_values[i])/klu_values[i]\n", + " relativ_diff_sparse_klu[i] = (\n", + " sparse_values[i] - klu_values[i]\n", + " ) / klu_values[i]\n", + " relativ_diff_sparse_denselu[i] = (\n", + " sparse_values[i] - denselu_values[i]\n", + " ) / klu_values[i]\n", " if relativ_diff_sparse_klu[i] > maxerror:\n", " maxerror = relativ_diff_sparse_klu[i]\n", " if relativ_diff_sparse_denselu[i] > maxerror:\n", " maxerror = relativ_diff_sparse_denselu[i]\n", - " \n", + "\n", " error_1 = np.linalg.norm(relativ_diff_sparse_klu, ord=2)\n", " error_2 = np.linalg.norm(relativ_diff_sparse_denselu, ord=2)\n", - " print('LV Entry {} Maximum Difference of SparseLU vs. KLU: {}'.format(entry,error_1))\n", - " print('LV Entry {} Maximum Difference of DenseLU vs. SparseLU: {}'.format(entry,error_2))\n", + " print(\n", + " \"LV Entry {} Maximum Difference of SparseLU vs. KLU: {}\".format(entry, error_1)\n", + " )\n", + " print(\n", + " \"LV Entry {} Maximum Difference of DenseLU vs. SparseLU: {}\".format(\n", + " entry, error_2\n", + " )\n", + " )\n", " if error_1 > maxerrorn:\n", " maxerrorn = error_1\n", " if error_2 > maxerrorn:\n", " maxerrorn = error_2\n", - " \n", - "print('Maximum error in all values: {}'.format(maxerror))\n", - "print('Maximum norm of errors: {}'.format(maxerrorn))" + "\n", + "print(\"Maximum error in all values: {}\".format(maxerror))\n", + "print(\"Maximum norm of errors: {}\".format(maxerrorn))" ] }, { @@ -266,8 +320,8 @@ "metadata": {}, "outputs": [], "source": [ - "assert(maxerror < relative_solver_error_tolerance)\n", - "assert(maxerrorn < relative_solver_error_tolerance)" + "assert maxerror < relative_solver_error_tolerance\n", + "assert maxerrorn < relative_solver_error_tolerance" ] }, { diff --git a/examples/Notebooks/Performance/Inverter_Grid_Perf.ipynb b/examples/Notebooks/Performance/Inverter_Grid_Perf.ipynb index a9d461bb1a..ffa87654b1 100644 --- a/examples/Notebooks/Performance/Inverter_Grid_Perf.ipynb +++ b/examples/Notebooks/Performance/Inverter_Grid_Perf.ipynb @@ -13,7 +13,7 @@ "metadata": {}, "outputs": [], "source": [ - "from dpsim.MeasurementUtils import Measurement \n", + "from dpsim.MeasurementUtils import Measurement\n", "import matplotlib.pyplot as plt\n", "import pandas as pd\n", "import numpy as np" @@ -25,20 +25,31 @@ "metadata": {}, "outputs": [], "source": [ - "logs_dir = '../../../logs_inverter/'\n", + "logs_dir = \"../../../logs_inverter/\"\n", "seq_mean = []\n", "\n", - "for threads in range(0,13,2): \n", + "for threads in range(0, 13, 2):\n", " seq_meas = []\n", - " for seq in range(1,11):\n", - " log_path = logs_dir + 'DP_Inverter_Grid_Parallel_FreqSplit_t' + str(threads) + '_s' + str(seq) + '/' + \\\n", - " 'DP_Inverter_Grid_Parallel_FreqSplit_t' + str(threads) + '_s' + str(seq) + '_step_times.log' \n", - " #print(log_path)\n", - " meas = Measurement.read_timestep_csv(log_path)['step_time'].data\n", + " for seq in range(1, 11):\n", + " log_path = (\n", + " logs_dir\n", + " + \"DP_Inverter_Grid_Parallel_FreqSplit_t\"\n", + " + str(threads)\n", + " + \"_s\"\n", + " + str(seq)\n", + " + \"/\"\n", + " + \"DP_Inverter_Grid_Parallel_FreqSplit_t\"\n", + " + str(threads)\n", + " + \"_s\"\n", + " + str(seq)\n", + " + \"_step_times.log\"\n", + " )\n", + " # print(log_path)\n", + " meas = Measurement.read_timestep_csv(log_path)[\"step_time\"].data\n", " # aggregate the measurements from the different iterations\n", - " seq_meas = np.concatenate( (seq_meas, meas), axis=0 )\n", - " #print(seq_meas.shape)\n", - " seq_mean.append({'threads': threads, 'values': seq_meas.mean()}) \n", + " seq_meas = np.concatenate((seq_meas, meas), axis=0)\n", + " # print(seq_meas.shape)\n", + " seq_mean.append({\"threads\": threads, \"values\": seq_meas.mean()})\n", "\n", "pd_mean_freqsplit = pd.DataFrame(seq_mean)" ] @@ -58,20 +69,31 @@ "metadata": {}, "outputs": [], "source": [ - "logs_dir = '../../../logs_inverter/'\n", + "logs_dir = \"../../../logs_inverter/\"\n", "seq_mean = []\n", "\n", - "for threads in range(0,13,2): \n", + "for threads in range(0, 13, 2):\n", " seq_meas = []\n", - " for seq in range(1,11):\n", - " log_path = logs_dir + 'DP_Inverter_Grid_Parallel_t' + str(threads) + '_s' + str(seq) + '/' + \\\n", - " 'DP_Inverter_Grid_Parallel_t' + str(threads) + '_s' + str(seq) + '_step_times.log' \n", - " #print(log_path)\n", - " meas = Measurement.read_timestep_csv(log_path)['step_time'].data\n", + " for seq in range(1, 11):\n", + " log_path = (\n", + " logs_dir\n", + " + \"DP_Inverter_Grid_Parallel_t\"\n", + " + str(threads)\n", + " + \"_s\"\n", + " + str(seq)\n", + " + \"/\"\n", + " + \"DP_Inverter_Grid_Parallel_t\"\n", + " + str(threads)\n", + " + \"_s\"\n", + " + str(seq)\n", + " + \"_step_times.log\"\n", + " )\n", + " # print(log_path)\n", + " meas = Measurement.read_timestep_csv(log_path)[\"step_time\"].data\n", " # aggregate the measurements from the different iterations\n", - " seq_meas = np.concatenate( (seq_meas, meas), axis=0 )\n", - " #print(seq_meas.shape)\n", - " seq_mean.append({'threads': threads, 'values': seq_meas.mean()}) \n", + " seq_meas = np.concatenate((seq_meas, meas), axis=0)\n", + " # print(seq_meas.shape)\n", + " seq_mean.append({\"threads\": threads, \"values\": seq_meas.mean()})\n", "\n", "pd_mean_frequnit = pd.DataFrame(seq_mean)" ] @@ -91,19 +113,19 @@ "metadata": {}, "outputs": [], "source": [ - "threads = np.arange(0,13,2) \n", - "plt.plot(threads, pd_mean_freqsplit['values']*1e6, 'o-', label='freq. split')\n", - "plt.plot(threads, pd_mean_frequnit['values']*1e6, 'o-', label='no freq. split')\n", + "threads = np.arange(0, 13, 2)\n", + "plt.plot(threads, pd_mean_freqsplit[\"values\"] * 1e6, \"o-\", label=\"freq. split\")\n", + "plt.plot(threads, pd_mean_frequnit[\"values\"] * 1e6, \"o-\", label=\"no freq. split\")\n", "\n", - "plt.legend(loc='center right')\n", + "plt.legend(loc=\"center right\")\n", "plt.grid()\n", - "#plt.ylim([-0.01,0.2])\n", - "#plt.xlim([0,0.0009])\n", - "plt.xlabel('number of threads')\n", - "plt.ylabel('mean timestep duration (µs)')\n", + "# plt.ylim([-0.01,0.2])\n", + "# plt.xlim([0,0.0009])\n", + "plt.xlabel(\"number of threads\")\n", + "plt.ylabel(\"mean timestep duration (µs)\")\n", "plt.tight_layout()\n", - "plt.savefig('inverter_freq_split.pdf')\n", - "plt.savefig('inverter_freq_split.png', dpi=300)" + "plt.savefig(\"inverter_freq_split.pdf\")\n", + "plt.savefig(\"inverter_freq_split.png\", dpi=300)" ] }, { @@ -119,32 +141,34 @@ "metadata": {}, "outputs": [], "source": [ - "parallel = Measurement.read_timestep_csv('../../../logs/DP_Inverter_Grid_Parallel/DP_Inverter_Grid_Parallel_step_times.log')\n", - "data = parallel['step_time'].data\n", - "xaxis = parallel['step_time'].xaxis\n", + "parallel = Measurement.read_timestep_csv(\n", + " \"../../../logs/DP_Inverter_Grid_Parallel/DP_Inverter_Grid_Parallel_step_times.log\"\n", + ")\n", + "data = parallel[\"step_time\"].data\n", + "xaxis = parallel[\"step_time\"].xaxis\n", "\n", - "print('maximum timestep:')\n", + "print(\"maximum timestep:\")\n", "print(data.max())\n", - "print('standard deviation:')\n", + "print(\"standard deviation:\")\n", "print(data.std())\n", - "print('mean timestep:')\n", + "print(\"mean timestep:\")\n", "print(data.mean())\n", "\n", "plt.figure()\n", "plt.hist(data, 50)\n", - "plt.xlabel('timestep duration (s)')\n", - "plt.ylabel('number of timesteps')\n", - "#plt.xlim([0.0001,0.0005])\n", + "plt.xlabel(\"timestep duration (s)\")\n", + "plt.ylabel(\"number of timesteps\")\n", + "# plt.xlim([0.0001,0.0005])\n", "plt.grid()\n", - "#plt.savefig('parallel_rt_nolog_hist.png')\n", + "# plt.savefig('parallel_rt_nolog_hist.png')\n", "\n", "plt.figure()\n", "plt.plot(xaxis, data)\n", - "plt.xlabel('timestep index')\n", - "plt.ylabel('timestep duration (s)')\n", - "#plt.ylim([0.0001,0.0006])\n", + "plt.xlabel(\"timestep index\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", + "# plt.ylim([0.0001,0.0006])\n", "plt.grid()\n", - "#plt.savefig('parallel_rt_nolog_time.png')" + "# plt.savefig('parallel_rt_nolog_time.png')" ] }, { @@ -160,32 +184,34 @@ "metadata": {}, "outputs": [], "source": [ - "sequential = Measurement.read_timestep_csv('../../../logs/DP_Inverter_Grid_Sequential/DP_Inverter_Grid_Sequential_step_times.log')\n", - "data = sequential['step_time'].data\n", - "xaxis = sequential['step_time'].xaxis\n", + "sequential = Measurement.read_timestep_csv(\n", + " \"../../../logs/DP_Inverter_Grid_Sequential/DP_Inverter_Grid_Sequential_step_times.log\"\n", + ")\n", + "data = sequential[\"step_time\"].data\n", + "xaxis = sequential[\"step_time\"].xaxis\n", "\n", - "print('maximum timestep:')\n", + "print(\"maximum timestep:\")\n", "print(data.max())\n", - "print('standard deviation:')\n", + "print(\"standard deviation:\")\n", "print(data.std())\n", - "print('mean timestep:')\n", + "print(\"mean timestep:\")\n", "print(data.mean())\n", "\n", "plt.figure()\n", "plt.hist(data, 50)\n", - "plt.xlabel('timestep duration (s)')\n", - "plt.ylabel('number of timesteps')\n", - "#plt.xlim([0.0001,0.0005])\n", + "plt.xlabel(\"timestep duration (s)\")\n", + "plt.ylabel(\"number of timesteps\")\n", + "# plt.xlim([0.0001,0.0005])\n", "plt.grid()\n", - "#plt.savefig('parallel_rt_nolog_hist.png')\n", + "# plt.savefig('parallel_rt_nolog_hist.png')\n", "\n", "plt.figure()\n", "plt.plot(xaxis, data)\n", - "plt.xlabel('timestep index')\n", - "plt.ylabel('timestep duration (s)')\n", - "#plt.ylim([0.0001,0.0006])\n", + "plt.xlabel(\"timestep index\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", + "# plt.ylim([0.0001,0.0006])\n", "plt.grid()\n", - "#plt.savefig('parallel_rt_nolog_time.png')" + "# plt.savefig('parallel_rt_nolog_time.png')" ] }, { @@ -201,32 +227,34 @@ "metadata": {}, "outputs": [], "source": [ - "parallel_splitFreq = Measurement.read_timestep_csv('../../../logs/DP_Inverter_Grid_Parallel_FreqSplit/DP_Inverter_Grid_Parallel_FreqSplit_step_times.log')\n", - "data = parallel_splitFreq['step_time'].data\n", - "xaxis = parallel_splitFreq['step_time'].xaxis\n", + "parallel_splitFreq = Measurement.read_timestep_csv(\n", + " \"../../../logs/DP_Inverter_Grid_Parallel_FreqSplit/DP_Inverter_Grid_Parallel_FreqSplit_step_times.log\"\n", + ")\n", + "data = parallel_splitFreq[\"step_time\"].data\n", + "xaxis = parallel_splitFreq[\"step_time\"].xaxis\n", "\n", - "print('maximum timestep:')\n", + "print(\"maximum timestep:\")\n", "print(data.max())\n", - "print('standard deviation:')\n", + "print(\"standard deviation:\")\n", "print(data.std())\n", - "print('mean timestep:')\n", + "print(\"mean timestep:\")\n", "print(data.mean())\n", "\n", "plt.figure()\n", "plt.hist(data, 50)\n", - "plt.xlabel('timestep duration (s)')\n", - "plt.ylabel('number of timesteps')\n", - "#plt.xlim([0.0001,0.0005])\n", + "plt.xlabel(\"timestep duration (s)\")\n", + "plt.ylabel(\"number of timesteps\")\n", + "# plt.xlim([0.0001,0.0005])\n", "plt.grid()\n", - "#plt.savefig('parallel_rt_nolog_hist.png')\n", + "# plt.savefig('parallel_rt_nolog_hist.png')\n", "\n", "plt.figure()\n", "plt.plot(xaxis, data)\n", - "plt.xlabel('timestep index')\n", - "plt.ylabel('timestep duration (s)')\n", - "#plt.ylim([0.0001,0.0006])\n", + "plt.xlabel(\"timestep index\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", + "# plt.ylim([0.0001,0.0006])\n", "plt.grid()\n", - "#plt.savefig('parallel_rt_nolog_time.png')" + "# plt.savefig('parallel_rt_nolog_time.png')" ] }, { @@ -242,32 +270,34 @@ "metadata": {}, "outputs": [], "source": [ - "sequential_SplitFreq = Measurement.read_timestep_csv('../../../logs/DP_Inverter_Grid_Sequential_FreqSplit/DP_Inverter_Grid_Sequential_FreqSplit_step_times.log')\n", - "data = sequential_SplitFreq['step_time'].data\n", - "xaxis = sequential_SplitFreq['step_time'].xaxis\n", + "sequential_SplitFreq = Measurement.read_timestep_csv(\n", + " \"../../../logs/DP_Inverter_Grid_Sequential_FreqSplit/DP_Inverter_Grid_Sequential_FreqSplit_step_times.log\"\n", + ")\n", + "data = sequential_SplitFreq[\"step_time\"].data\n", + "xaxis = sequential_SplitFreq[\"step_time\"].xaxis\n", "\n", - "print('maximum timestep:')\n", + "print(\"maximum timestep:\")\n", "print(data.max())\n", - "print('standard deviation:')\n", + "print(\"standard deviation:\")\n", "print(data.std())\n", - "print('mean timestep:')\n", + "print(\"mean timestep:\")\n", "print(data.mean())\n", "\n", "plt.figure()\n", "plt.hist(data, 50)\n", - "plt.xlabel('timestep duration (s)')\n", - "plt.ylabel('number of timesteps')\n", - "#plt.xlim([0.0001,0.0005])\n", + "plt.xlabel(\"timestep duration (s)\")\n", + "plt.ylabel(\"number of timesteps\")\n", + "# plt.xlim([0.0001,0.0005])\n", "plt.grid()\n", - "#plt.savefig('parallel_rt_nolog_hist.png')\n", + "# plt.savefig('parallel_rt_nolog_hist.png')\n", "\n", "plt.figure()\n", "plt.plot(xaxis, data)\n", - "plt.xlabel('timestep index')\n", - "plt.ylabel('timestep duration (s)')\n", - "#plt.ylim([0.0001,0.0006])\n", + "plt.xlabel(\"timestep index\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", + "# plt.ylim([0.0001,0.0006])\n", "plt.grid()\n", - "#plt.savefig('parallel_rt_nolog_time.png')" + "# plt.savefig('parallel_rt_nolog_time.png')" ] }, { @@ -283,28 +313,28 @@ "metadata": {}, "outputs": [], "source": [ - "parallel_data = parallel['step_time'].data\n", - "parallel_xaxis = parallel['step_time'].xaxis\n", - "sequential_data = sequential['step_time'].data\n", - "sequential_xaxis = sequential['step_time'].xaxis\n", - "parallel_splitFreq_data = parallel_splitFreq['step_time'].data\n", - "parallel_splitFreq_xaxis = parallel_splitFreq['step_time'].xaxis\n", - "sequential_SplitFreq_data = sequential_SplitFreq['step_time'].data\n", - "sequential_SplitFreq_xaxis = sequential_SplitFreq['step_time'].xaxis\n", + "parallel_data = parallel[\"step_time\"].data\n", + "parallel_xaxis = parallel[\"step_time\"].xaxis\n", + "sequential_data = sequential[\"step_time\"].data\n", + "sequential_xaxis = sequential[\"step_time\"].xaxis\n", + "parallel_splitFreq_data = parallel_splitFreq[\"step_time\"].data\n", + "parallel_splitFreq_xaxis = parallel_splitFreq[\"step_time\"].xaxis\n", + "sequential_SplitFreq_data = sequential_SplitFreq[\"step_time\"].data\n", + "sequential_SplitFreq_xaxis = sequential_SplitFreq[\"step_time\"].xaxis\n", "\n", "plt.figure()\n", - "plt.hist(parallel_data, 50, label='parallel')\n", - "plt.hist(sequential_data, 50, label='sequential')\n", - "plt.hist(parallel_splitFreq_data, 50, label='parallel_freq_split')\n", - "plt.hist(sequential_SplitFreq_data, 50, label='sequential_freq_split')\n", - "plt.xlabel('timestep duration (s)')\n", - "plt.ylabel('number of timesteps')\n", + "plt.hist(parallel_data, 50, label=\"parallel\")\n", + "plt.hist(sequential_data, 50, label=\"sequential\")\n", + "plt.hist(parallel_splitFreq_data, 50, label=\"parallel_freq_split\")\n", + "plt.hist(sequential_SplitFreq_data, 50, label=\"sequential_freq_split\")\n", + "plt.xlabel(\"timestep duration (s)\")\n", + "plt.ylabel(\"number of timesteps\")\n", "plt.grid()\n", "ax = plt.gca()\n", "ax.xaxis.set_major_locator(plt.MaxNLocator(5))\n", "ax.legend()\n", - "#plt.xlim([0.0001,0.0005])\n", - "#plt.savefig('parallel_single_rt_nolog_hist.pdf')" + "# plt.xlim([0.0001,0.0005])\n", + "# plt.savefig('parallel_single_rt_nolog_hist.pdf')" ] }, { @@ -314,16 +344,18 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(parallel_xaxis, parallel_data, label='parallel')\n", - "plt.plot(sequential_xaxis, sequential_data, label='sequential')\n", - "plt.plot(parallel_splitFreq_xaxis, parallel_splitFreq_data, label='parallel_freq_split')\n", - "plt.plot(sequential_SplitFreq_xaxis, sequential_SplitFreq_data, label='sequential_freq_split')\n", - "plt.xlabel('timestep index')\n", - "plt.ylabel('timestep duration (s)')\n", - "plt.legend(loc='lower right')\n", + "plt.plot(parallel_xaxis, parallel_data, label=\"parallel\")\n", + "plt.plot(sequential_xaxis, sequential_data, label=\"sequential\")\n", + "plt.plot(parallel_splitFreq_xaxis, parallel_splitFreq_data, label=\"parallel_freq_split\")\n", + "plt.plot(\n", + " sequential_SplitFreq_xaxis, sequential_SplitFreq_data, label=\"sequential_freq_split\"\n", + ")\n", + "plt.xlabel(\"timestep index\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", + "plt.legend(loc=\"lower right\")\n", "plt.grid()\n", - "#plt.ylim([0.0001,0.0006])\n", - "#plt.savefig('parallel_single_rt_nolog_time.pdf')" + "# plt.ylim([0.0001,0.0006])\n", + "# plt.savefig('parallel_single_rt_nolog_time.pdf')" ] }, { diff --git a/examples/Notebooks/Performance/WSCC_9bus_iterations.ipynb b/examples/Notebooks/Performance/WSCC_9bus_iterations.ipynb index d33271b80b..7d4c383cb9 100644 --- a/examples/Notebooks/Performance/WSCC_9bus_iterations.ipynb +++ b/examples/Notebooks/Performance/WSCC_9bus_iterations.ipynb @@ -16,18 +16,42 @@ "import pandas as pd\n", "from dpsim.MeasurementUtils import Measurement\n", "\n", - "logs_dir = '../../../logs_rt_char/'\n", + "logs_dir = \"../../../logs_rt_char/\"\n", "decoupled_meas = []\n", "copies = 10\n", "threads = 8\n", - " \n", - "for seq in range(1,1001): \n", - " sim_dir = logs_dir + 'WSCC_9bus_decoupled_' + str(copies) + '_' + str(threads) + '_' + str(seq) + '/'\n", - " log_name = 'WSCC_9bus_decoupled_' + str(copies) + '_' + str(threads) + '_' + str(seq) + '_step_times.log'\n", + "\n", + "for seq in range(1, 1001):\n", + " sim_dir = (\n", + " logs_dir\n", + " + \"WSCC_9bus_decoupled_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"/\"\n", + " )\n", + " log_name = (\n", + " \"WSCC_9bus_decoupled_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"_step_times.log\"\n", + " )\n", " log_path = sim_dir + log_name\n", - " #print(log_path) \n", + " # print(log_path)\n", " meas = Measurement.read_timestep_csv(log_path)\n", - " decoupled_meas.append({'copies': copies, 'threads': threads, 'sequence': seq, 'values': meas['step_time'].data}) \n", + " decoupled_meas.append(\n", + " {\n", + " \"copies\": copies,\n", + " \"threads\": threads,\n", + " \"sequence\": seq,\n", + " \"values\": meas[\"step_time\"].data,\n", + " }\n", + " )\n", "\n", "pd_decoupled_meas = pd.DataFrame(decoupled_meas)" ] @@ -45,9 +69,14 @@ "metadata": {}, "outputs": [], "source": [ - "for seq in range(1,1001):\n", - " if pd_decoupled_meas.query('sequence == ' + str(seq))['values'].values[0][10:].argmax() == 0:\n", - " print('first entry') " + "for seq in range(1, 1001):\n", + " if (\n", + " pd_decoupled_meas.query(\"sequence == \" + str(seq))[\"values\"]\n", + " .values[0][10:]\n", + " .argmax()\n", + " == 0\n", + " ):\n", + " print(\"first entry\")" ] }, { @@ -66,11 +95,15 @@ "source": [ "decoupled_max = []\n", "absolute_max = 0\n", - "for seq in range(1,1001):\n", - " current_max = pd_decoupled_meas.query('sequence == ' + str(seq))['values'].values[0][10:].max()\n", + "for seq in range(1, 1001):\n", + " current_max = (\n", + " pd_decoupled_meas.query(\"sequence == \" + str(seq))[\"values\"]\n", + " .values[0][10:]\n", + " .max()\n", + " )\n", " if current_max > absolute_max:\n", " absolute_max = current_max\n", - " decoupled_max.append(absolute_max) " + " decoupled_max.append(absolute_max)" ] }, { @@ -81,15 +114,15 @@ "source": [ "import matplotlib.pyplot as plt\n", "\n", - "plt.figure(figsize=(12/2.54,8/2.54))\n", - "plt.plot(decoupled_max, label='real time')\n", - "plt.ticklabel_format(axis='y', style='sci', scilimits=(-3,3))\n", - "plt.xlabel('iterations')\n", - "plt.ylabel('timestep duration (s)')\n", + "plt.figure(figsize=(12 / 2.54, 8 / 2.54))\n", + "plt.plot(decoupled_max, label=\"real time\")\n", + "plt.ticklabel_format(axis=\"y\", style=\"sci\", scilimits=(-3, 3))\n", + "plt.xlabel(\"iterations\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('wscc_9bus_iter_rt_max.pdf')" + "plt.savefig(\"wscc_9bus_iter_rt_max.pdf\")" ] }, { @@ -108,10 +141,22 @@ "import numpy as np\n", "\n", "decoupled_concat = []\n", - "decoupled_concat.append(pd_decoupled_meas.query('sequence == 1')['values'].values[0][10:])\n", + "decoupled_concat.append(\n", + " pd_decoupled_meas.query(\"sequence == 1\")[\"values\"].values[0][10:]\n", + ")\n", "\n", - "for seq in range(2,1001):\n", - " decoupled_concat.append( np.concatenate( (decoupled_concat[-1], pd_decoupled_meas.query('sequence == ' + str(seq))['values'].values[0][10:]), axis=0 ) )" + "for seq in range(2, 1001):\n", + " decoupled_concat.append(\n", + " np.concatenate(\n", + " (\n", + " decoupled_concat[-1],\n", + " pd_decoupled_meas.query(\"sequence == \" + str(seq))[\"values\"].values[0][\n", + " 10:\n", + " ],\n", + " ),\n", + " axis=0,\n", + " )\n", + " )" ] }, { @@ -122,7 +167,7 @@ "source": [ "decoupled_mean = []\n", "\n", - "for seq in range(0,1000):\n", + "for seq in range(0, 1000):\n", " decoupled_mean.append(decoupled_concat[seq].mean())" ] }, @@ -132,14 +177,14 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12/2.54,8/2.54))\n", + "plt.figure(figsize=(12 / 2.54, 8 / 2.54))\n", "plt.plot(decoupled_mean)\n", - "plt.ticklabel_format(axis='y', style='sci', scilimits=(-3,3))\n", - "plt.xlabel('iterations')\n", - "plt.ylabel('timestep duration (s)')\n", + "plt.ticklabel_format(axis=\"y\", style=\"sci\", scilimits=(-3, 3))\n", + "plt.xlabel(\"iterations\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", "plt.grid()\n", "plt.tight_layout()\n", - "plt.savefig('wscc_9bus_iter_rt_mean.pdf')" + "plt.savefig(\"wscc_9bus_iter_rt_mean.pdf\")" ] }, { @@ -150,7 +195,7 @@ "source": [ "decoupled_std = []\n", "\n", - "for seq in range(0,1000): \n", + "for seq in range(0, 1000):\n", " decoupled_std.append(decoupled_concat[seq].std())" ] }, @@ -160,14 +205,14 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12/2.54,8/2.54))\n", + "plt.figure(figsize=(12 / 2.54, 8 / 2.54))\n", "plt.plot(decoupled_std)\n", - "plt.ticklabel_format(axis='y', style='sci', scilimits=(-3,3))\n", - "plt.xlabel('iterations')\n", - "plt.ylabel('timestep duration (s)')\n", + "plt.ticklabel_format(axis=\"y\", style=\"sci\", scilimits=(-3, 3))\n", + "plt.xlabel(\"iterations\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", "plt.grid()\n", "plt.tight_layout()\n", - "plt.savefig('wscc_9bus_iter_rt_std.pdf')" + "plt.savefig(\"wscc_9bus_iter_rt_std.pdf\")" ] }, { @@ -186,18 +231,42 @@ "import pandas as pd\n", "from dpsim.MeasurementUtils import Measurement\n", "\n", - "logs_dir = '../../../logs_tp_char/'\n", + "logs_dir = \"../../../logs_tp_char/\"\n", "tp_decoupled_meas = []\n", "copies = 10\n", "threads = 8\n", - " \n", - "for seq in range(1,1001): \n", - " sim_dir = logs_dir + 'WSCC_9bus_decoupled_' + str(copies) + '_' + str(threads) + '_' + str(seq) + '/'\n", - " log_name = 'WSCC_9bus_decoupled_' + str(copies) + '_' + str(threads) + '_' + str(seq) + '_step_times.log'\n", + "\n", + "for seq in range(1, 1001):\n", + " sim_dir = (\n", + " logs_dir\n", + " + \"WSCC_9bus_decoupled_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"/\"\n", + " )\n", + " log_name = (\n", + " \"WSCC_9bus_decoupled_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"_step_times.log\"\n", + " )\n", " log_path = sim_dir + log_name\n", - " #print(log_path) \n", + " # print(log_path)\n", " meas = Measurement.read_timestep_csv(log_path)\n", - " tp_decoupled_meas.append({'copies': copies, 'threads': threads, 'sequence': seq, 'values': meas['step_time'].data}) \n", + " tp_decoupled_meas.append(\n", + " {\n", + " \"copies\": copies,\n", + " \"threads\": threads,\n", + " \"sequence\": seq,\n", + " \"values\": meas[\"step_time\"].data,\n", + " }\n", + " )\n", "\n", "tp_pd_decoupled_meas = pd.DataFrame(tp_decoupled_meas)" ] @@ -212,11 +281,15 @@ "\n", "tp_decoupled_max = []\n", "absolute_max = 0\n", - "for seq in range(1,1000):\n", - " current_max = tp_pd_decoupled_meas.query('sequence == ' + str(seq))['values'].values[0][10:].max()\n", + "for seq in range(1, 1000):\n", + " current_max = (\n", + " tp_pd_decoupled_meas.query(\"sequence == \" + str(seq))[\"values\"]\n", + " .values[0][10:]\n", + " .max()\n", + " )\n", " if current_max > absolute_max:\n", " absolute_max = current_max\n", - " tp_decoupled_max.append(absolute_max) " + " tp_decoupled_max.append(absolute_max)" ] }, { @@ -225,17 +298,17 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12/2.54,8/2.54))\n", - "#plt.plot(decoupled_max, label='real time')\n", - "plt.plot(tp_decoupled_max, label='throughput')\n", - "plt.ticklabel_format(axis='y', style='sci', scilimits=(-3,3))\n", - "plt.xlabel('iterations')\n", - "plt.ylabel('timestep duration (s)')\n", + "plt.figure(figsize=(12 / 2.54, 8 / 2.54))\n", + "# plt.plot(decoupled_max, label='real time')\n", + "plt.plot(tp_decoupled_max, label=\"throughput\")\n", + "plt.ticklabel_format(axis=\"y\", style=\"sci\", scilimits=(-3, 3))\n", + "plt.xlabel(\"iterations\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", "plt.grid()\n", "ax = plt.gca()\n", - "#ax.legend()\n", + "# ax.legend()\n", "plt.tight_layout()\n", - "plt.savefig('wscc_9bus_iter_tp_max.pdf')" + "plt.savefig(\"wscc_9bus_iter_tp_max.pdf\")" ] }, { @@ -245,10 +318,22 @@ "outputs": [], "source": [ "tp_decoupled_concat = []\n", - "tp_decoupled_concat.append(tp_pd_decoupled_meas.query('sequence == 1')['values'].values[0][10:])\n", + "tp_decoupled_concat.append(\n", + " tp_pd_decoupled_meas.query(\"sequence == 1\")[\"values\"].values[0][10:]\n", + ")\n", "\n", - "for seq in range(2,1001):\n", - " tp_decoupled_concat.append( np.concatenate( (tp_decoupled_concat[-1], tp_pd_decoupled_meas.query('sequence == ' + str(seq))['values'].values[0][10:]), axis=0 ) )" + "for seq in range(2, 1001):\n", + " tp_decoupled_concat.append(\n", + " np.concatenate(\n", + " (\n", + " tp_decoupled_concat[-1],\n", + " tp_pd_decoupled_meas.query(\"sequence == \" + str(seq))[\"values\"].values[\n", + " 0\n", + " ][10:],\n", + " ),\n", + " axis=0,\n", + " )\n", + " )" ] }, { @@ -259,7 +344,7 @@ "source": [ "tp_decoupled_mean = []\n", "\n", - "for seq in range(0,1000):\n", + "for seq in range(0, 1000):\n", " tp_decoupled_mean.append(tp_decoupled_concat[seq].mean())" ] }, @@ -269,15 +354,15 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12/2.54,8/2.54))\n", - "#plt.plot(decoupled_mean, label='real time')\n", - "plt.plot(tp_decoupled_mean, label='throughput')\n", - "plt.ticklabel_format(axis='y', style='sci', scilimits=(-3,3))\n", - "plt.xlabel('iterations')\n", - "plt.ylabel('timestep duration (s)')\n", + "plt.figure(figsize=(12 / 2.54, 8 / 2.54))\n", + "# plt.plot(decoupled_mean, label='real time')\n", + "plt.plot(tp_decoupled_mean, label=\"throughput\")\n", + "plt.ticklabel_format(axis=\"y\", style=\"sci\", scilimits=(-3, 3))\n", + "plt.xlabel(\"iterations\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", "plt.grid()\n", "plt.tight_layout()\n", - "plt.savefig('wscc_9bus_iter_tp_mean.pdf')" + "plt.savefig(\"wscc_9bus_iter_tp_mean.pdf\")" ] }, { @@ -288,7 +373,7 @@ "source": [ "tp_decoupled_std = []\n", "\n", - "for seq in range(0,1000):\n", + "for seq in range(0, 1000):\n", " tp_decoupled_std.append(tp_decoupled_concat[seq].std())" ] }, @@ -298,14 +383,14 @@ "metadata": {}, "outputs": [], "source": [ - "plt.figure(figsize=(12/2.54,8/2.54))\n", + "plt.figure(figsize=(12 / 2.54, 8 / 2.54))\n", "plt.plot(tp_decoupled_std)\n", - "plt.ticklabel_format(axis='y', style='sci', scilimits=(-3,3))\n", - "plt.xlabel('iterations')\n", - "plt.ylabel('timestep duration (s)')\n", + "plt.ticklabel_format(axis=\"y\", style=\"sci\", scilimits=(-3, 3))\n", + "plt.xlabel(\"iterations\")\n", + "plt.ylabel(\"timestep duration (s)\")\n", "plt.grid()\n", "plt.tight_layout()\n", - "plt.savefig('wscc_9bus_iter_tp_std.pdf')" + "plt.savefig(\"wscc_9bus_iter_tp_std.pdf\")" ] }, { diff --git a/examples/Notebooks/Performance/WSCC_9bus_mult_coupled_validate_SparseLU_DenseLU_KLU.ipynb b/examples/Notebooks/Performance/WSCC_9bus_mult_coupled_validate_SparseLU_DenseLU_KLU.ipynb index 336dcc807f..33d08e48ac 100644 --- a/examples/Notebooks/Performance/WSCC_9bus_mult_coupled_validate_SparseLU_DenseLU_KLU.ipynb +++ b/examples/Notebooks/Performance/WSCC_9bus_mult_coupled_validate_SparseLU_DenseLU_KLU.ipynb @@ -27,19 +27,21 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX/WSCC-09_RX'\n", - "filename = 'WSCC-09_RX_WithoutSyngenParams'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", - "download_grid_data(filename+'_DI.xml', url+'_DI.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX/WSCC-09_RX\"\n", + "filename = \"WSCC-09_RX_WithoutSyngenParams\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "download_grid_data(filename + \"_DI.xml\", url + \"_DI.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -59,16 +61,25 @@ "num_copies = 0\n", "num_threads = 0\n", "num_seq = 0\n", - "sim_name = \"WSCC_9bus_coupled_\" + str(num_copies) + \"_\" + str(num_threads) + \"_\" + str(num_seq)\n", + "sim_name = (\n", + " \"WSCC_9bus_coupled_\" + str(num_copies) + \"_\" + str(num_threads) + \"_\" + str(num_seq)\n", + ")\n", + "\n", "\n", "def simulate_coupled(filenames, copies, threads, seq, implementation):\n", - " dpsimpy.Logger.set_log_dir(log_dir+\"/\"+sim_name)\n", + " dpsimpy.Logger.set_log_dir(log_dir + \"/\" + sim_name)\n", " reader = dpsimpy.CIMReader(sim_name, log_level, log_level)\n", - " sys = reader.loadCIM(60, filenames, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.IdealVoltageSource)\n", - " \n", + " sys = reader.loadCIM(\n", + " 60,\n", + " filenames,\n", + " dpsimpy.Domain.DP,\n", + " dpsimpy.PhaseType.Single,\n", + " dpsimpy.GeneratorType.IdealVoltageSource,\n", + " )\n", + "\n", " # if copies > 0:\n", " # multiply_connected(sys, copies, 12.5, 0.16, 1e-6)\n", - " \n", + "\n", " sim = dpsimpy.Simulation(sim_name, log_level)\n", " sim.set_system(sys)\n", " sim.set_domain(dpsimpy.Domain.DP)\n", @@ -88,8 +99,12 @@ "source": [ "%%capture\n", "simulate_coupled(files, 0, 0, 0, dpsimpy.DirectLinearSolverImpl.SparseLU)\n", - "ts_dpsim_lv_sparse = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_sparse = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_sparse = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_sparse = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -101,8 +116,12 @@ "source": [ "%%capture\n", "simulate_coupled(files, 0, 0, 0, dpsimpy.DirectLinearSolverImpl.KLU)\n", - "ts_dpsim_lv_klu = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_klu = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_klu = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_klu = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -114,8 +133,12 @@ "source": [ "%%capture\n", "simulate_coupled(files, 0, 0, 0, dpsimpy.DirectLinearSolverImpl.DenseLU)\n", - "ts_dpsim_lv_denselu = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_LeftVector.csv\")\n", - "ts_dpsim_rv_denselu = rt.read_timeseries_dpsim(dpsimpy.Logger.get_log_dir()+\"/\"+sim_name+\"_RightVector.csv\")" + "ts_dpsim_lv_denselu = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_LeftVector.csv\"\n", + ")\n", + "ts_dpsim_rv_denselu = rt.read_timeseries_dpsim(\n", + " dpsimpy.Logger.get_log_dir() + \"/\" + sim_name + \"_RightVector.csv\"\n", + ")" ] }, { @@ -132,20 +155,20 @@ " klu_values = ts_dpsim_rv_klu[entry].values\n", " denselu_values = ts_dpsim_rv_denselu[entry].values\n", " # 2-norm of errors\n", - " error_1 = np.linalg.norm(sparse_values-klu_values, ord=2)\n", - " error_2 = np.linalg.norm(denselu_values-sparse_values, ord=2)\n", - " assert(error_1 < tolerance)\n", - " assert(error_2 < tolerance)\n", + " error_1 = np.linalg.norm(sparse_values - klu_values, ord=2)\n", + " error_2 = np.linalg.norm(denselu_values - sparse_values, ord=2)\n", + " assert error_1 < tolerance\n", + " assert error_2 < tolerance\n", "\n", "for entry in ts_dpsim_lv_sparse:\n", " sparse_values = ts_dpsim_lv_sparse[entry].values\n", " klu_values = ts_dpsim_lv_klu[entry].values\n", " denselu_values = ts_dpsim_lv_denselu[entry].values\n", " # 2-norm of errors\n", - " error_1 = np.linalg.norm(sparse_values-klu_values, ord=2)\n", - " error_2 = np.linalg.norm(denselu_values-sparse_values, ord=2)\n", - " assert(error_1 < tolerance)\n", - " assert(error_2 < tolerance)" + " error_1 = np.linalg.norm(sparse_values - klu_values, ord=2)\n", + " error_2 = np.linalg.norm(denselu_values - sparse_values, ord=2)\n", + " assert error_1 < tolerance\n", + " assert error_2 < tolerance" ] } ], diff --git a/examples/Notebooks/Performance/WSCC_9bus_parallel.ipynb b/examples/Notebooks/Performance/WSCC_9bus_parallel.ipynb index 5b7eb8c600..3454ce8c9f 100644 --- a/examples/Notebooks/Performance/WSCC_9bus_parallel.ipynb +++ b/examples/Notebooks/Performance/WSCC_9bus_parallel.ipynb @@ -89,9 +89,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC_9bus_coupled_1_0_0/'\n", - "logName = 'WSCC_9bus_coupled_1_0_0'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC_9bus_coupled_1_0_0/\"\n", + "logName = \"WSCC_9bus_coupled_1_0_0\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_coupled = rt.read_timeseries_dpsim(logFilename)\n", @@ -104,9 +104,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC_9bus_decoupled_1_0_0/'\n", - "logName = 'WSCC_9bus_decoupled_1_0_0'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC_9bus_decoupled_1_0_0/\"\n", + "logName = \"WSCC_9bus_decoupled_1_0_0\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_decoupled = rt.read_timeseries_dpsim(logFilename)\n", @@ -119,13 +119,13 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC_9bus_diakoptics_1_0_0_0/'\n", - "logName = 'WSCC_9bus_diakoptics_1_0_0_0'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC_9bus_diakoptics_1_0_0_0/\"\n", + "logName = \"WSCC_9bus_diakoptics_1_0_0_0\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_diakpotics = rt.read_timeseries_dpsim(logFilename)\n", - "phasors_diakoptics= ts.phasors(ts_diakpotics)" + "phasors_diakoptics = ts.phasors(ts_diakpotics)" ] }, { @@ -135,7 +135,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_coupled.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1])\n", + " )" ] }, { @@ -145,7 +151,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_decoupled.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1])\n", + " )" ] }, { @@ -155,7 +167,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_diakoptics.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1])\n", + " )" ] }, { @@ -171,9 +189,9 @@ "metadata": {}, "outputs": [], "source": [ - "path = 'logs/WSCC-9bus/'\n", - "logName = 'WSCC-9bus'\n", - "logFilename = path + logName + '.csv'\n", + "path = \"logs/WSCC-9bus/\"\n", + "logName = \"WSCC-9bus\"\n", + "logFilename = path + logName + \".csv\"\n", "print(logFilename)\n", "\n", "ts_single = rt.read_timeseries_dpsim(logFilename)\n", @@ -187,7 +205,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_single.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1])\n", + " )" ] }, { @@ -204,7 +228,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_single.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1] - phasors_decoupled[node]['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1] - phasors_decoupled[node]['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1] - phasors_decoupled[node][\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1] - phasors_decoupled[node][\"phase\"].values[-1])\n", + " )" ] }, { @@ -214,7 +244,13 @@ "outputs": [], "source": [ "for node, phasor in phasors_coupled.items():\n", - " print(node + ': ' + str(phasor['abs'].values[-1] - phasors_diakoptics[node]['abs'].values[-1]) + '<' + str(phasor['phase'].values[-1] - phasors_diakoptics[node]['phase'].values[-1]))" + " print(\n", + " node\n", + " + \": \"\n", + " + str(phasor[\"abs\"].values[-1] - phasors_diakoptics[node][\"abs\"].values[-1])\n", + " + \"<\"\n", + " + str(phasor[\"phase\"].values[-1] - phasors_diakoptics[node][\"phase\"].values[-1])\n", + " )" ] }, { @@ -230,35 +266,56 @@ "metadata": {}, "outputs": [], "source": [ - "#%%capture\n", + "# %%capture\n", "import pandas as pd\n", "from dpsim.MeasurementUtils import Measurement\n", "import numpy as np\n", "\n", - "logs_dir = '../../../logs_9bus/'\n", - "#coupled_meas = []\n", + "logs_dir = \"../../../logs_9bus/\"\n", + "# coupled_meas = []\n", "coupled_mean = []\n", "coupled_max = []\n", "coupled_std = []\n", "\n", - "for copies in range(0,20): \n", - " for threads in range(0,13,2): \n", + "for copies in range(0, 20):\n", + " for threads in range(0, 13, 2):\n", " seq_meas = []\n", - " for seq in range(1,11):\n", - " log_path = logs_dir + 'WSCC_9bus_coupled_' + str(copies) + '_' + str(threads) + '_' + str(seq) + '/' + \\\n", - " 'WSCC_9bus_coupled_' + str(copies) + '_' + str(threads) + '_' + str(seq) + '_step_times.log' \n", - " #print(log_path)\n", - " meas = Measurement.read_timestep_csv(log_path)['step_time'].data\n", + " for seq in range(1, 11):\n", + " log_path = (\n", + " logs_dir\n", + " + \"WSCC_9bus_coupled_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"/\"\n", + " + \"WSCC_9bus_coupled_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"_step_times.log\"\n", + " )\n", + " # print(log_path)\n", + " meas = Measurement.read_timestep_csv(log_path)[\"step_time\"].data\n", " # aggregate the measurements from the different iterations\n", - " seq_meas = np.concatenate( (seq_meas, meas), axis=0)\n", - " \n", - " #print(seq_meas.shape)\n", - " #coupled_meas.append({'copies': copies, 'threads': threads, 'values': meas['step_time'].data}) \n", - " coupled_mean.append({'copies': copies, 'threads': threads, 'values': seq_meas.mean()}) \n", - " coupled_max.append({'copies': copies, 'threads': threads, 'values': seq_meas.max()}) \n", - " coupled_std.append({'copies': copies, 'threads': threads, 'values': seq_meas.std()}) \n", - " \n", - "#pd_coupled_meas = pd.DataFrame(coupled_meas)\n", + " seq_meas = np.concatenate((seq_meas, meas), axis=0)\n", + "\n", + " # print(seq_meas.shape)\n", + " # coupled_meas.append({'copies': copies, 'threads': threads, 'values': meas['step_time'].data})\n", + " coupled_mean.append(\n", + " {\"copies\": copies, \"threads\": threads, \"values\": seq_meas.mean()}\n", + " )\n", + " coupled_max.append(\n", + " {\"copies\": copies, \"threads\": threads, \"values\": seq_meas.max()}\n", + " )\n", + " coupled_std.append(\n", + " {\"copies\": copies, \"threads\": threads, \"values\": seq_meas.std()}\n", + " )\n", + "\n", + "# pd_coupled_meas = pd.DataFrame(coupled_meas)\n", "pd_coupled_mean = pd.DataFrame(coupled_mean)\n", "pd_coupled_max = pd.DataFrame(coupled_max)\n", "pd_coupled_std = pd.DataFrame(coupled_std)" @@ -275,17 +332,22 @@ "\n", "ax = plt.figure().gca()\n", "ax.xaxis.set_major_locator(ticker.MultipleLocator(2))\n", - "copies = np.arange(1,21)\n", - "\n", - "for threads in range(0,13,2):\n", - " plt.plot(copies, pd_coupled_mean.query('threads=='+str(threads))['values'].values, label=str(threads)+' threads', marker='o')\n", - "\n", - "plt.xlabel('number of system copies')\n", - "plt.ylabel('mean timestep duration (s)')\n", + "copies = np.arange(1, 21)\n", + "\n", + "for threads in range(0, 13, 2):\n", + " plt.plot(\n", + " copies,\n", + " pd_coupled_mean.query(\"threads==\" + str(threads))[\"values\"].values,\n", + " label=str(threads) + \" threads\",\n", + " marker=\"o\",\n", + " )\n", + "\n", + "plt.xlabel(\"number of system copies\")\n", + "plt.ylabel(\"mean timestep duration (s)\")\n", "plt.grid()\n", - "plt.legend(loc='upper left')\n", + "plt.legend(loc=\"upper left\")\n", "plt.tight_layout()\n", - "plt.savefig('9bus_coupled.pdf')" + "plt.savefig(\"9bus_coupled.pdf\")" ] }, { @@ -297,29 +359,50 @@ "import pandas as pd\n", "from dpsim.MeasurementUtils import Measurement\n", "\n", - "logs_dir = '../../../logs_9bus/'\n", + "logs_dir = \"../../../logs_9bus/\"\n", "decoupled_meas = []\n", "decoupled_mean = []\n", "decoupled_max = []\n", "decoupled_std = []\n", "\n", - "for copies in range(0,20): \n", - " for threads in range(0,13,2): \n", + "for copies in range(0, 20):\n", + " for threads in range(0, 13, 2):\n", " seq_meas = []\n", - " for seq in range(1,11):\n", - " log_path = logs_dir + 'WSCC_9bus_decoupled_' + str(copies) + '_' + str(threads) + '_' + str(seq) + '/' + \\\n", - " 'WSCC_9bus_decoupled_' + str(copies) + '_' + str(threads) + '_' + str(seq) + '_step_times.log' \n", - " #print(log_path)\n", - " meas = Measurement.read_timestep_csv(log_path)['step_time'].data\n", + " for seq in range(1, 11):\n", + " log_path = (\n", + " logs_dir\n", + " + \"WSCC_9bus_decoupled_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"/\"\n", + " + \"WSCC_9bus_decoupled_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"_step_times.log\"\n", + " )\n", + " # print(log_path)\n", + " meas = Measurement.read_timestep_csv(log_path)[\"step_time\"].data\n", " # aggregate the measurements from the different iterations\n", - " seq_meas = np.concatenate( (seq_meas, meas), axis=0)\n", - " \n", - " #print(seq_meas.shape)\n", - " #coupled_meas.append({'copies': copies, 'threads': threads, 'values': meas['step_time'].data}) \n", - " decoupled_mean.append({'copies': copies, 'threads': threads, 'values': seq_meas.mean()}) \n", - " decoupled_max.append({'copies': copies, 'threads': threads, 'values': seq_meas.max()}) \n", - " decoupled_std.append({'copies': copies, 'threads': threads, 'values': seq_meas.std()}) \n", - " \n", + " seq_meas = np.concatenate((seq_meas, meas), axis=0)\n", + "\n", + " # print(seq_meas.shape)\n", + " # coupled_meas.append({'copies': copies, 'threads': threads, 'values': meas['step_time'].data})\n", + " decoupled_mean.append(\n", + " {\"copies\": copies, \"threads\": threads, \"values\": seq_meas.mean()}\n", + " )\n", + " decoupled_max.append(\n", + " {\"copies\": copies, \"threads\": threads, \"values\": seq_meas.max()}\n", + " )\n", + " decoupled_std.append(\n", + " {\"copies\": copies, \"threads\": threads, \"values\": seq_meas.std()}\n", + " )\n", + "\n", "pd_decoupled_meas = pd.DataFrame(decoupled_meas)\n", "pd_decoupled_mean = pd.DataFrame(decoupled_mean)\n", "pd_decoupled_max = pd.DataFrame(decoupled_max)\n", @@ -336,19 +419,24 @@ "\n", "ax = plt.figure().gca()\n", "ax.xaxis.set_major_locator(ticker.MultipleLocator(2))\n", - "copies = np.arange(1,21)\n", + "copies = np.arange(1, 21)\n", "\n", - "for threads in range(0,13,2): \n", - " plt.plot(copies, pd_decoupled_mean.query('threads=='+str(threads))['values'].values, label=str(threads)+' threads', marker='o')\n", + "for threads in range(0, 13, 2):\n", + " plt.plot(\n", + " copies,\n", + " pd_decoupled_mean.query(\"threads==\" + str(threads))[\"values\"].values,\n", + " label=str(threads) + \" threads\",\n", + " marker=\"o\",\n", + " )\n", "\n", - "#plt.ylim([0,0.00025])\n", + "# plt.ylim([0,0.00025])\n", "\n", - "plt.xlabel('number of system copies')\n", - "plt.ylabel('mean timestep duration (s)')\n", + "plt.xlabel(\"number of system copies\")\n", + "plt.ylabel(\"mean timestep duration (s)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('9bus_decoupled.pdf')" + "plt.savefig(\"9bus_decoupled.pdf\")" ] }, { @@ -357,36 +445,76 @@ "metadata": {}, "outputs": [], "source": [ - "#%%capture\n", - "from dpsim.MeasurementUtils import Measurement \n", + "# %%capture\n", + "from dpsim.MeasurementUtils import Measurement\n", "import numpy as np\n", "import pandas as pd\n", "\n", - "logs_dir = '../../../logs_9bus/'\n", + "logs_dir = \"../../../logs_9bus/\"\n", "diakoptics_meas = []\n", "diakoptics_mean = []\n", "diakoptics_max = []\n", "diakoptics_std = []\n", - " \n", - "for copies in range(0,20): \n", - " for threads in range(0,13,2): \n", - " for splits in range(0, copies+2):\n", + "\n", + "for copies in range(0, 20):\n", + " for threads in range(0, 13, 2):\n", + " for splits in range(0, copies + 2):\n", " seq_meas = []\n", - " for seq in range(1,11):\n", - " log_path = logs_dir + 'WSCC_9bus_diakoptics_' + str(copies) + '_' + str(threads) + '_' + str(splits) + '_' + str(seq) + '/' + \\\n", - " 'WSCC_9bus_diakoptics_' + str(copies) + '_' + str(threads) + '_' + str(splits) + '_' + str(seq) + '_step_times.log' \n", - " #print(log_path)\n", - " meas = Measurement.read_timestep_csv(log_path)['step_time'].data\n", + " for seq in range(1, 11):\n", + " log_path = (\n", + " logs_dir\n", + " + \"WSCC_9bus_diakoptics_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(splits)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"/\"\n", + " + \"WSCC_9bus_diakoptics_\"\n", + " + str(copies)\n", + " + \"_\"\n", + " + str(threads)\n", + " + \"_\"\n", + " + str(splits)\n", + " + \"_\"\n", + " + str(seq)\n", + " + \"_step_times.log\"\n", + " )\n", + " # print(log_path)\n", + " meas = Measurement.read_timestep_csv(log_path)[\"step_time\"].data\n", " # aggregate the measurements from the different iterations\n", - " seq_meas = np.concatenate( (seq_meas, meas), axis=0)\n", - "\n", - " #print(seq_meas.shape)\n", - " #diakoptics_meas.append({'copies': copies, 'threads': threads, 'splits': splits, 'values': meas['step_time'].data}) \n", - " diakoptics_mean.append({'copies': copies, 'threads': threads, 'splits': splits, 'values': seq_meas.mean()}) \n", - " diakoptics_max.append({'copies': copies, 'threads': threads, 'splits': splits, 'values': seq_meas.max()}) \n", - " diakoptics_std.append({'copies': copies, 'threads': threads, 'splits': splits, 'values': seq_meas.std()}) \n", - " \n", - "#pd_diakoptics_meas = pd.DataFrame(diakoptics_meas)\n", + " seq_meas = np.concatenate((seq_meas, meas), axis=0)\n", + "\n", + " # print(seq_meas.shape)\n", + " # diakoptics_meas.append({'copies': copies, 'threads': threads, 'splits': splits, 'values': meas['step_time'].data})\n", + " diakoptics_mean.append(\n", + " {\n", + " \"copies\": copies,\n", + " \"threads\": threads,\n", + " \"splits\": splits,\n", + " \"values\": seq_meas.mean(),\n", + " }\n", + " )\n", + " diakoptics_max.append(\n", + " {\n", + " \"copies\": copies,\n", + " \"threads\": threads,\n", + " \"splits\": splits,\n", + " \"values\": seq_meas.max(),\n", + " }\n", + " )\n", + " diakoptics_std.append(\n", + " {\n", + " \"copies\": copies,\n", + " \"threads\": threads,\n", + " \"splits\": splits,\n", + " \"values\": seq_meas.std(),\n", + " }\n", + " )\n", + "\n", + "# pd_diakoptics_meas = pd.DataFrame(diakoptics_meas)\n", "pd_diakoptics_mean = pd.DataFrame(diakoptics_mean)\n", "pd_diakoptics_max = pd.DataFrame(diakoptics_max)\n", "pd_diakoptics_std = pd.DataFrame(diakoptics_std)" @@ -399,18 +527,39 @@ "outputs": [], "source": [ "diakoptics_mean_split_min = []\n", - "for copies in range(0,20): \n", - " for threads in range(0,13,2): \n", - " split_min_num = copies+1\n", - " split_min = pd_diakoptics_mean.query('copies=='+str(copies)+' and threads=='+str(threads)+' and splits=='+str(split_min_num))['values'].iloc[0]\n", - " for splits in range(1, copies+1):\n", - " tmp = pd_diakoptics_mean.query('copies=='+str(copies)+' and threads=='+str(threads)+' and splits=='+str(splits))['values'].iloc[0]\n", + "for copies in range(0, 20):\n", + " for threads in range(0, 13, 2):\n", + " split_min_num = copies + 1\n", + " split_min = pd_diakoptics_mean.query(\n", + " \"copies==\"\n", + " + str(copies)\n", + " + \" and threads==\"\n", + " + str(threads)\n", + " + \" and splits==\"\n", + " + str(split_min_num)\n", + " )[\"values\"].iloc[0]\n", + " for splits in range(1, copies + 1):\n", + " tmp = pd_diakoptics_mean.query(\n", + " \"copies==\"\n", + " + str(copies)\n", + " + \" and threads==\"\n", + " + str(threads)\n", + " + \" and splits==\"\n", + " + str(splits)\n", + " )[\"values\"].iloc[0]\n", " if tmp < split_min:\n", " split_min_num = splits\n", " split_min = tmp\n", - " \n", - " diakoptics_mean_split_min.append({'copies': copies, 'threads': threads, 'splits': split_min_num, 'values': split_min}) \n", - " \n", + "\n", + " diakoptics_mean_split_min.append(\n", + " {\n", + " \"copies\": copies,\n", + " \"threads\": threads,\n", + " \"splits\": split_min_num,\n", + " \"values\": split_min,\n", + " }\n", + " )\n", + "\n", "pd_diakoptics_mean_split_min = pd.DataFrame(diakoptics_mean_split_min)" ] }, @@ -420,7 +569,7 @@ "metadata": {}, "outputs": [], "source": [ - "pd_diakoptics_mean_split_min.query('threads=='+str(8))" + "pd_diakoptics_mean_split_min.query(\"threads==\" + str(8))" ] }, { @@ -431,9 +580,13 @@ "source": [ "diakoptics_splits = []\n", "\n", - "for copies in range(0,20): \n", - " for threads in range(0,13,2):\n", - " diakoptics_splits.append(pd_diakoptics_mean_split_min.query('copies=='+str(copies)+' and threads=='+str(threads))['splits'].values)" + "for copies in range(0, 20):\n", + " for threads in range(0, 13, 2):\n", + " diakoptics_splits.append(\n", + " pd_diakoptics_mean_split_min.query(\n", + " \"copies==\" + str(copies) + \" and threads==\" + str(threads)\n", + " )[\"splits\"].values\n", + " )" ] }, { @@ -446,18 +599,23 @@ "\n", "ax = plt.figure().gca()\n", "ax.xaxis.set_major_locator(ticker.MultipleLocator(2))\n", - "copies = np.arange(1,21)\n", + "copies = np.arange(1, 21)\n", "\n", - "for threads in range(0,13,2):\n", - " plt.plot(copies, pd_diakoptics_mean_split_min.query('threads=='+str(threads))['splits'].values, label= str(threads) + ' threads', marker='o')\n", + "for threads in range(0, 13, 2):\n", + " plt.plot(\n", + " copies,\n", + " pd_diakoptics_mean_split_min.query(\"threads==\" + str(threads))[\"splits\"].values,\n", + " label=str(threads) + \" threads\",\n", + " marker=\"o\",\n", + " )\n", "\n", "\n", - "plt.xlabel('number of system copies')\n", - "plt.ylabel('mean split number')\n", + "plt.xlabel(\"number of system copies\")\n", + "plt.ylabel(\"mean split number\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('diakoptics_min_mean_splits.pdf')" + "plt.savefig(\"diakoptics_min_mean_splits.pdf\")" ] }, { @@ -470,17 +628,22 @@ "\n", "ax = plt.figure().gca()\n", "ax.xaxis.set_major_locator(ticker.MultipleLocator(2))\n", - "copies = np.arange(1,21)\n", - "\n", - "for threads in range(0,13,2):\n", - " plt.plot(copies, pd_diakoptics_mean_split_min.query('threads=='+str(threads))['values'].values, label= str(threads) + ' threads', marker='o')\n", - "\n", - "plt.xlabel('number of system copies')\n", - "plt.ylabel('mean timestep duration (s)')\n", + "copies = np.arange(1, 21)\n", + "\n", + "for threads in range(0, 13, 2):\n", + " plt.plot(\n", + " copies,\n", + " pd_diakoptics_mean_split_min.query(\"threads==\" + str(threads))[\"values\"].values,\n", + " label=str(threads) + \" threads\",\n", + " marker=\"o\",\n", + " )\n", + "\n", + "plt.xlabel(\"number of system copies\")\n", + "plt.ylabel(\"mean timestep duration (s)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('9bus_diakoptics.pdf')" + "plt.savefig(\"9bus_diakoptics.pdf\")" ] }, { @@ -493,21 +656,36 @@ "\n", "ax = plt.figure().gca()\n", "ax.xaxis.set_major_locator(ticker.MultipleLocator(2))\n", - "copies = np.arange(1,21)\n", + "copies = np.arange(1, 21)\n", "threads = 8\n", "\n", - "plt.plot(copies, pd_coupled_mean.query('threads=='+str(threads))['values'].values, label='coupled, 8 threads', marker='o')\n", - "plt.plot(copies, pd_decoupled_mean.query('threads=='+str(threads))['values'].values, label='line decoupled, 8 threads', marker='o')\n", - "plt.plot(copies, pd_diakoptics_mean_split_min.query('threads=='+str(threads))['values'].values, label='diakoptics, 8 threads', marker='o')\n", - "\n", - "plt.xlabel('number of system copies')\n", - "plt.ylabel('mean timestep duration (s)')\n", + "plt.plot(\n", + " copies,\n", + " pd_coupled_mean.query(\"threads==\" + str(threads))[\"values\"].values,\n", + " label=\"coupled, 8 threads\",\n", + " marker=\"o\",\n", + ")\n", + "plt.plot(\n", + " copies,\n", + " pd_decoupled_mean.query(\"threads==\" + str(threads))[\"values\"].values,\n", + " label=\"line decoupled, 8 threads\",\n", + " marker=\"o\",\n", + ")\n", + "plt.plot(\n", + " copies,\n", + " pd_diakoptics_mean_split_min.query(\"threads==\" + str(threads))[\"values\"].values,\n", + " label=\"diakoptics, 8 threads\",\n", + " marker=\"o\",\n", + ")\n", + "\n", + "plt.xlabel(\"number of system copies\")\n", + "plt.ylabel(\"mean timestep duration (s)\")\n", "plt.grid()\n", "plt.legend()\n", - "plt.yscale('log')\n", + "plt.yscale(\"log\")\n", "plt.tight_layout()\n", - "plt.savefig('9bus_comparison.pdf')\n", - "plt.savefig('9bus_comparison.png', dpi=300)" + "plt.savefig(\"9bus_comparison.pdf\")\n", + "plt.savefig(\"9bus_comparison.png\", dpi=300)" ] }, { diff --git a/examples/Notebooks/Performance/WSCC_9bus_split.ipynb b/examples/Notebooks/Performance/WSCC_9bus_split.ipynb index de3af0b793..95bcf3e694 100644 --- a/examples/Notebooks/Performance/WSCC_9bus_split.ipynb +++ b/examples/Notebooks/Performance/WSCC_9bus_split.ipynb @@ -68,7 +68,8 @@ "import matplotlib.pyplot as plt\n", "import numpy as np\n", "import pandas as pd\n", - "#%matplotlib widget" + "\n", + "# %matplotlib widget" ] }, { @@ -77,24 +78,24 @@ "metadata": {}, "outputs": [], "source": [ - "path_split_dp = 'logs/WSCC_9bus_split_decoupled_DP_0_0/'\n", - "logName_split_dp = 'WSCC_9bus_split_decoupled_DP_0_0'\n", - "logFilename_split_dp = path_split_dp + logName_split_dp + '.csv'\n", + "path_split_dp = \"logs/WSCC_9bus_split_decoupled_DP_0_0/\"\n", + "logName_split_dp = \"WSCC_9bus_split_decoupled_DP_0_0\"\n", + "logFilename_split_dp = path_split_dp + logName_split_dp + \".csv\"\n", "print(logFilename_split_dp)\n", "\n", - "path_split_emt = 'logs/WSCC_9bus_split_decoupled_EMT_0_0/'\n", - "logName_split_emt = 'WSCC_9bus_split_decoupled_EMT_0_0'\n", - "logFilename_split_emt = path_split_emt + logName_split_emt + '.csv'\n", + "path_split_emt = \"logs/WSCC_9bus_split_decoupled_EMT_0_0/\"\n", + "logName_split_emt = \"WSCC_9bus_split_decoupled_EMT_0_0\"\n", + "logFilename_split_emt = path_split_emt + logName_split_emt + \".csv\"\n", "print(logFilename_split_emt)\n", "\n", - "path_mono_dp = 'logs/WSCC-9bus_monolithic_DP/'\n", - "logName_mono_dp = 'WSCC-9bus_monolithic_DP'\n", - "logFilename_mono_dp = path_mono_dp + logName_mono_dp + '.csv'\n", + "path_mono_dp = \"logs/WSCC-9bus_monolithic_DP/\"\n", + "logName_mono_dp = \"WSCC-9bus_monolithic_DP\"\n", + "logFilename_mono_dp = path_mono_dp + logName_mono_dp + \".csv\"\n", "print(logFilename_mono_dp)\n", "\n", - "path_mono_emt = 'logs/WSCC-9bus_monolithic_EMT/'\n", - "logName_mono_emt = 'WSCC-9bus_monolithic_EMT'\n", - "logFilename_mono_emt = path_mono_emt + logName_mono_emt + '.csv'\n", + "path_mono_emt = \"logs/WSCC-9bus_monolithic_EMT/\"\n", + "logName_mono_emt = \"WSCC-9bus_monolithic_EMT\"\n", + "logFilename_mono_emt = path_mono_emt + logName_mono_emt + \".csv\"\n", "print(logFilename_mono_emt)\n", "\n", "decoupled_dp_split = rt.read_timeseries_dpsim(logFilename_split_dp)\n", @@ -104,14 +105,14 @@ "\n", "# for v in range(1, 10):\n", "for i, v in enumerate([5]):\n", - " varname = 'v' + str(v)\n", - " pt.set_timeseries_labels(mono_dp[varname], varname + ' Monolithic, DP')\n", - " pt.plot_timeseries('decoupled', mono_dp[varname])\n", - " pt.set_timeseries_labels(decoupled_dp_split[varname], varname + ' DP')\n", - " pt.plot_timeseries('decoupled', decoupled_dp_split[varname], '--')\n", - " plt.title('WSCC-09 with 3 lines replaced by decoupling equivalents')\n", - " plt.xlabel('Time [s]')\n", - " plt.ylabel('Voltage [V]')\n", + " varname = \"v\" + str(v)\n", + " pt.set_timeseries_labels(mono_dp[varname], varname + \" Monolithic, DP\")\n", + " pt.plot_timeseries(\"decoupled\", mono_dp[varname])\n", + " pt.set_timeseries_labels(decoupled_dp_split[varname], varname + \" DP\")\n", + " pt.plot_timeseries(\"decoupled\", decoupled_dp_split[varname], \"--\")\n", + " plt.title(\"WSCC-09 with 3 lines replaced by decoupling equivalents\")\n", + " plt.xlabel(\"Time [s]\")\n", + " plt.ylabel(\"Voltage [V]\")\n", "\n", "plt.show()" ] @@ -125,14 +126,14 @@ "decoupled_emt_split = rt.read_timeseries_dpsim(logFilename_split_emt)\n", "\n", "for i, v in enumerate([5]):\n", - " varname_emt = 'v' + str(v) + '_0'\n", - " pt.set_timeseries_labels(mono_emt[varname_emt], varname_emt + ' Monolithic, EMT')\n", - " pt.plot_timeseries('decoupled, shifted', mono_emt[varname_emt])\n", - " pt.set_timeseries_labels(decoupled_emt_split[varname_emt], varname_emt + ' EMT')\n", - " pt.plot_timeseries('decoupled, shifted', decoupled_emt_split[varname_emt], '--')\n", - " plt.title('WSCC-09 with 3 lines replaced by decoupling equivalents')\n", - " plt.xlabel('Time [s]')\n", - " plt.ylabel('Voltage [V]')\n", + " varname_emt = \"v\" + str(v) + \"_0\"\n", + " pt.set_timeseries_labels(mono_emt[varname_emt], varname_emt + \" Monolithic, EMT\")\n", + " pt.plot_timeseries(\"decoupled, shifted\", mono_emt[varname_emt])\n", + " pt.set_timeseries_labels(decoupled_emt_split[varname_emt], varname_emt + \" EMT\")\n", + " pt.plot_timeseries(\"decoupled, shifted\", decoupled_emt_split[varname_emt], \"--\")\n", + " plt.title(\"WSCC-09 with 3 lines replaced by decoupling equivalents\")\n", + " plt.xlabel(\"Time [s]\")\n", + " plt.ylabel(\"Voltage [V]\")\n", "\n", "plt.show()" ] diff --git a/examples/Notebooks/Performance/multimachine_parallel.ipynb b/examples/Notebooks/Performance/multimachine_parallel.ipynb index 5123fa2f6f..3dd55de770 100644 --- a/examples/Notebooks/Performance/multimachine_parallel.ipynb +++ b/examples/Notebooks/Performance/multimachine_parallel.ipynb @@ -39,29 +39,44 @@ "metadata": {}, "outputs": [], "source": [ - "logs_dir = '../../../logs_multimachine/'\n", + "logs_dir = \"../../../logs_multimachine/\"\n", "gen_mean = []\n", "gen_max = []\n", "gen_std = []\n", "\n", - "for gens in range(1,21): \n", - " for threads in range(0,13,2): \n", + "for gens in range(1, 21):\n", + " for threads in range(0, 13, 2):\n", " seq_meas = []\n", - " for seq in range(1,51):\n", - " log_path = logs_dir + 'DP_Multimachine_th' + str(threads) + '_gen' + str(gens) + '_rep' + str(seq) + '/' \\\n", - " + 'DP_Multimachine_th' + str(threads) + '_gen' + str(gens) + '_rep' + str(seq) + '_step_times.log' \n", - " #print(log_path)\n", - " meas = Measurement.read_timestep_csv(log_path)['step_time'].data\n", + " for seq in range(1, 51):\n", + " log_path = (\n", + " logs_dir\n", + " + \"DP_Multimachine_th\"\n", + " + str(threads)\n", + " + \"_gen\"\n", + " + str(gens)\n", + " + \"_rep\"\n", + " + str(seq)\n", + " + \"/\"\n", + " + \"DP_Multimachine_th\"\n", + " + str(threads)\n", + " + \"_gen\"\n", + " + str(gens)\n", + " + \"_rep\"\n", + " + str(seq)\n", + " + \"_step_times.log\"\n", + " )\n", + " # print(log_path)\n", + " meas = Measurement.read_timestep_csv(log_path)[\"step_time\"].data\n", " # aggregate the measurements from the different iterations\n", - " seq_meas = np.concatenate( (seq_meas, meas), axis=0)\n", - " \n", - " #print(seq_meas.shape)\n", - " #coupled_meas.append({'copies': copies, 'threads': threads, 'values': meas['step_time'].data}) \n", - " gen_mean.append({'copies': gens, 'threads': threads, 'values': seq_meas.mean()}) \n", - " gen_max.append({'copies': gens, 'threads': threads, 'values': seq_meas.max()}) \n", - " gen_std.append({'copies': gens, 'threads': threads, 'values': seq_meas.std()}) \n", - " \n", - "#pd_coupled_meas = pd.DataFrame(coupled_meas)\n", + " seq_meas = np.concatenate((seq_meas, meas), axis=0)\n", + "\n", + " # print(seq_meas.shape)\n", + " # coupled_meas.append({'copies': copies, 'threads': threads, 'values': meas['step_time'].data})\n", + " gen_mean.append({\"copies\": gens, \"threads\": threads, \"values\": seq_meas.mean()})\n", + " gen_max.append({\"copies\": gens, \"threads\": threads, \"values\": seq_meas.max()})\n", + " gen_std.append({\"copies\": gens, \"threads\": threads, \"values\": seq_meas.std()})\n", + "\n", + "# pd_coupled_meas = pd.DataFrame(coupled_meas)\n", "pd_gen_mean = pd.DataFrame(gen_mean)\n", "pd_gen_max = pd.DataFrame(gen_max)\n", "pd_gen_std = pd.DataFrame(gen_std)" @@ -87,22 +102,47 @@ "ax = plt.figure().gca()\n", "ax.xaxis.set_major_locator(ticker.MultipleLocator(2))\n", "\n", - "xaxis = np.arange(1,21)\n", - "plt.plot(xaxis, pd_gen_mean.query('threads=='+str(0))['values'].values*1e3, label=str(0)+' threads', marker='o')\n", - "plt.plot(xaxis, pd_gen_mean.query('threads=='+str(2))['values'].values*1e3, label=str(2)+' threads', marker='o')\n", - "plt.plot(xaxis, pd_gen_mean.query('threads=='+str(4))['values'].values*1e3, label=str(4)+' threads', marker='o')\n", - "plt.plot(xaxis, pd_gen_mean.query('threads=='+str(8))['values'].values*1e3, label=str(8)+' threads', marker='o')\n", - "plt.plot(xaxis, pd_gen_mean.query('threads=='+str(12))['values'].values*1e3, label=str(12)+' threads', marker='o')\n", + "xaxis = np.arange(1, 21)\n", + "plt.plot(\n", + " xaxis,\n", + " pd_gen_mean.query(\"threads==\" + str(0))[\"values\"].values * 1e3,\n", + " label=str(0) + \" threads\",\n", + " marker=\"o\",\n", + ")\n", + "plt.plot(\n", + " xaxis,\n", + " pd_gen_mean.query(\"threads==\" + str(2))[\"values\"].values * 1e3,\n", + " label=str(2) + \" threads\",\n", + " marker=\"o\",\n", + ")\n", + "plt.plot(\n", + " xaxis,\n", + " pd_gen_mean.query(\"threads==\" + str(4))[\"values\"].values * 1e3,\n", + " label=str(4) + \" threads\",\n", + " marker=\"o\",\n", + ")\n", + "plt.plot(\n", + " xaxis,\n", + " pd_gen_mean.query(\"threads==\" + str(8))[\"values\"].values * 1e3,\n", + " label=str(8) + \" threads\",\n", + " marker=\"o\",\n", + ")\n", + "plt.plot(\n", + " xaxis,\n", + " pd_gen_mean.query(\"threads==\" + str(12))[\"values\"].values * 1e3,\n", + " label=str(12) + \" threads\",\n", + " marker=\"o\",\n", + ")\n", "\n", - "#plt.ylim([0,0.0004])\n", + "# plt.ylim([0,0.0004])\n", "\n", - "plt.xlabel('number of system copies')\n", - "plt.ylabel('mean timestep duration (ms)')\n", + "plt.xlabel(\"number of system copies\")\n", + "plt.ylabel(\"mean timestep duration (ms)\")\n", "plt.grid()\n", "plt.legend()\n", "plt.tight_layout()\n", - "plt.savefig('multimachine_parallel.pdf')\n", - "plt.savefig('multimachine_parallel.png', dpi=300)" + "plt.savefig(\"multimachine_parallel.pdf\")\n", + "plt.savefig(\"multimachine_parallel.png\", dpi=300)" ] }, { diff --git a/examples/Notebooks/Quickstart Guide.ipynb b/examples/Notebooks/Quickstart Guide.ipynb index bd10f81080..59b2c24b7a 100644 --- a/examples/Notebooks/Quickstart Guide.ipynb +++ b/examples/Notebooks/Quickstart Guide.ipynb @@ -56,12 +56,12 @@ "source": [ "# Nodes\n", "gnd = dpsimpy.dp.SimNode.gnd\n", - "n0 = dpsimpy.dp.SimNode(\"n0\")\n", - "n1 = dpsimpy.dp.SimNode(\"n1\")\n", - "n2 = dpsimpy.dp.SimNode(\"n2\")\n", + "n0 = dpsimpy.dp.SimNode(\"n0\")\n", + "n1 = dpsimpy.dp.SimNode(\"n1\")\n", + "n2 = dpsimpy.dp.SimNode(\"n2\")\n", "\n", "v_s = dpsimpy.dp.ph1.VoltageSource(\"v_s\")\n", - "v_s.V_ref = 10000+0j\n", + "v_s.V_ref = 10000 + 0j\n", "r_line = dpsimpy.dp.ph1.Resistor(\"r_line\")\n", "r_line.R = 1\n", "l_line = dpsimpy.dp.ph1.Inductor(\"l_line\")\n", @@ -69,7 +69,7 @@ "r_load = dpsimpy.dp.ph1.Resistor(\"r_load\")\n", "r_load.R = 1000\n", "\n", - "# Connections \n", + "# Connections\n", "v_s.connect([n0, gnd])\n", "r_line.connect([n0, n1])\n", "l_line.connect([n1, n2])\n", @@ -89,7 +89,7 @@ "metadata": {}, "outputs": [], "source": [ - "sys = dpsimpy.SystemTopology(50, [ n0, n1, n2 ], [ v_s, r_line, l_line, r_load ])" + "sys = dpsimpy.SystemTopology(50, [n0, n1, n2], [v_s, r_line, l_line, r_load])" ] }, { @@ -131,7 +131,7 @@ " log.log_attribute(\"v\" + str(i), \"v\", sys.nodes[i])\n", "\n", "sim.add_logger(log)\n", - " \n", + "\n", "sim.run()" ] }, @@ -157,11 +157,11 @@ "import villas.dataprocessing.readtools as rt\n", "import villas.dataprocessing.timeseries as ts\n", "\n", - "results = rt.read_timeseries_dpsim('logs/Example1.csv')\n", - "results_emt = [ results[series].frequency_shift(freq=50) for series in results ]\n", + "results = rt.read_timeseries_dpsim(\"logs/Example1.csv\")\n", + "results_emt = [results[series].frequency_shift(freq=50) for series in results]\n", "\n", "for series in results_emt:\n", - " pt.plot_timeseries('Results EMT', series)\n", + " pt.plot_timeseries(\"Results EMT\", series)\n", "\n", "plt.show()" ] diff --git a/examples/Notebooks/Understanding_DP.ipynb b/examples/Notebooks/Understanding_DP.ipynb index 3fc1624c78..dfee8051a9 100644 --- a/examples/Notebooks/Understanding_DP.ipynb +++ b/examples/Notebooks/Understanding_DP.ipynb @@ -72,11 +72,11 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/DP_VS_RL_f60/'\n", - "log_name = 'DP_VS_RL_f60'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/DP_VS_RL_f60/\"\n", + "log_name = \"DP_VS_RL_f60\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_dp_f60 = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_dp_f60 = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_dp_f60_emt = ts.frequency_shift_list(ts_dpsim_dp_f60, 50)" ] }, @@ -87,11 +87,11 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/EMT_VS_RL_f60/'\n", - "log_name = 'EMT_VS_RL_f60'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/EMT_VS_RL_f60/\"\n", + "log_name = \"EMT_VS_RL_f60\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_emt_f60 = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "ts_dpsim_emt_f60 = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -100,35 +100,77 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_emt_f60['v1'].time, ts_dpsim_emt_f60['v1'].values, color='#939393ff', label='v1 emt')\n", - "plt.plot(ts_dpsim_emt_f60['v3'].time, ts_dpsim_emt_f60['v3'].values, color='#939393ff', label='v3 emt')\n", - "plt.plot(ts_dpsim_dp_f60_emt['v1_shift'].time, ts_dpsim_dp_f60_emt['v1_shift'].values, linestyle='-.', label='v1 dp')\n", - "plt.plot(ts_dpsim_dp_f60_emt['v3_shift'].time, ts_dpsim_dp_f60_emt['v3_shift'].values, linestyle='-.', label='v3 dp')\n", - "plt.xlim([0,0.1])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (v)')\n", - "plt.title('DP 50Hz shift (100µs ts) vs EMT (100µs ts), 60Hz source')\n", - "plt.savefig('emt_dp_100mics_60Hz_src.pdf')\n", + "plt.plot(\n", + " ts_dpsim_emt_f60[\"v1\"].time,\n", + " ts_dpsim_emt_f60[\"v1\"].values,\n", + " color=\"#939393ff\",\n", + " label=\"v1 emt\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_f60[\"v3\"].time,\n", + " ts_dpsim_emt_f60[\"v3\"].values,\n", + " color=\"#939393ff\",\n", + " label=\"v3 emt\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_emt[\"v1_shift\"].time,\n", + " ts_dpsim_dp_f60_emt[\"v1_shift\"].values,\n", + " linestyle=\"-.\",\n", + " label=\"v1 dp\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_emt[\"v3_shift\"].time,\n", + " ts_dpsim_dp_f60_emt[\"v3_shift\"].values,\n", + " linestyle=\"-.\",\n", + " label=\"v3 dp\",\n", + ")\n", + "plt.xlim([0, 0.1])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (v)\")\n", + "plt.title(\"DP 50Hz shift (100µs ts) vs EMT (100µs ts), 60Hz source\")\n", + "plt.savefig(\"emt_dp_100mics_60Hz_src.pdf\")\n", "\n", "ts_dpsim_dp_f60_phasors = ts.phasors(ts_dpsim_dp_f60)\n", "plt.figure()\n", - "plt.plot(ts_dpsim_dp_f60_phasors['v1']['phase'].time, ts_dpsim_dp_f60_phasors['v1']['phase'].values, label='v1 dp')\n", - "plt.plot(ts_dpsim_dp_f60_phasors['v3']['phase'].time, ts_dpsim_dp_f60_phasors['v3']['phase'].values, label='v3 dp')\n", - "plt.xlim([0,0.1])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('phase (deg)')\n", - "plt.title('DP 50Hz shift (100µs ts), 60Hz source')\n", - "plt.savefig('emt_dp_100mics_60Hz_src_phase.pdf')\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_phasors[\"v1\"][\"phase\"].time,\n", + " ts_dpsim_dp_f60_phasors[\"v1\"][\"phase\"].values,\n", + " label=\"v1 dp\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_phasors[\"v3\"][\"phase\"].time,\n", + " ts_dpsim_dp_f60_phasors[\"v3\"][\"phase\"].values,\n", + " label=\"v3 dp\",\n", + ")\n", + "plt.xlim([0, 0.1])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"phase (deg)\")\n", + "plt.title(\"DP 50Hz shift (100µs ts), 60Hz source\")\n", + "plt.savefig(\"emt_dp_100mics_60Hz_src_phase.pdf\")\n", "\n", "plt.figure()\n", - "plt.plot(ts_dpsim_dp_f60_emt['v1_shift'].time, ts_dpsim_dp_f60_emt['v1_shift'].values, linestyle='-.')\n", - "plt.plot(ts_dpsim_dp_f60_emt['v3_shift'].time, ts_dpsim_dp_f60_emt['v3_shift'].values, linestyle='-.')\n", - "plt.plot(ts_dpsim_dp_f60_phasors['v1']['abs'].time, ts_dpsim_dp_f60_phasors['v1']['abs'].values)\n", - "plt.plot(ts_dpsim_dp_f60_phasors['v3']['abs'].time, ts_dpsim_dp_f60_phasors['v3']['abs'].values)\n", - "plt.xlim([0,0.1])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('votlage (V)')\n", - "plt.title('DP 50Hz shift (100µs ts), 60Hz source')" + "plt.plot(\n", + " ts_dpsim_dp_f60_emt[\"v1_shift\"].time,\n", + " ts_dpsim_dp_f60_emt[\"v1_shift\"].values,\n", + " linestyle=\"-.\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_emt[\"v3_shift\"].time,\n", + " ts_dpsim_dp_f60_emt[\"v3_shift\"].values,\n", + " linestyle=\"-.\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_phasors[\"v1\"][\"abs\"].time,\n", + " ts_dpsim_dp_f60_phasors[\"v1\"][\"abs\"].values,\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_phasors[\"v3\"][\"abs\"].time,\n", + " ts_dpsim_dp_f60_phasors[\"v3\"][\"abs\"].values,\n", + ")\n", + "plt.xlim([0, 0.1])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"votlage (V)\")\n", + "plt.title(\"DP 50Hz shift (100µs ts), 60Hz source\")" ] }, { @@ -170,11 +212,11 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/DP_VS_RL_f60_largeTs/'\n", - "log_name = 'DP_VS_RL_f60_largeTs'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/DP_VS_RL_f60_largeTs/\"\n", + "log_name = \"DP_VS_RL_f60_largeTs\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_dp_f60_lTs = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_dp_f60_lTs = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_dp_f60_lTs_intp = ts.interpolate_cmpl_list(ts_dpsim_dp_f60_lTs, 0.0001)\n", "ts_dpsim_dp_f60_lTs_intp_emt = ts.frequency_shift_list(ts_dpsim_dp_f60_lTs_intp, 50)" ] @@ -186,11 +228,11 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/EMT_VS_RL_f60_largeTs/'\n", - "log_name = 'EMT_VS_RL_f60_largeTs'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/EMT_VS_RL_f60_largeTs/\"\n", + "log_name = \"EMT_VS_RL_f60_largeTs\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_emt_f60_lTs = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_emt_f60_lTs = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_emt_f60_lTs_intp = ts.interpolate_cmpl_list(ts_dpsim_emt_f60_lTs, 0.0001)" ] }, @@ -200,23 +242,42 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_emt_f60['v3'].time, ts_dpsim_emt_f60['v3'].values, label='v3 emt 100µs', color = '#939393ff')\n", - "plt.plot(ts_dpsim_dp_f60_lTs_intp_emt['v3_intpl_shift'].time, ts_dpsim_dp_f60_lTs_intp_emt['v3_intpl_shift'].values, label='v3 dp 10ms', linestyle='-.') \n", - "plt.plot(ts_dpsim_emt_f60_lTs_intp['v3_intpl'].time, ts_dpsim_emt_f60_lTs_intp['v3_intpl'].values, label='v3 emt 10ms', linestyle=':')\n", - "plt.xlim([0,0.1])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (v)')\n", - "plt.title('DP 50Hz shift (10ms ts) vs EMT (10ms ts), 60Hz source')\n", - "plt.legend(loc='lower right')\n", - "plt.savefig('emt_dp_10ms_60Hz_src.pdf')\n", + "plt.plot(\n", + " ts_dpsim_emt_f60[\"v3\"].time,\n", + " ts_dpsim_emt_f60[\"v3\"].values,\n", + " label=\"v3 emt 100µs\",\n", + " color=\"#939393ff\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_lTs_intp_emt[\"v3_intpl_shift\"].time,\n", + " ts_dpsim_dp_f60_lTs_intp_emt[\"v3_intpl_shift\"].values,\n", + " label=\"v3 dp 10ms\",\n", + " linestyle=\"-.\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_f60_lTs_intp[\"v3_intpl\"].time,\n", + " ts_dpsim_emt_f60_lTs_intp[\"v3_intpl\"].values,\n", + " label=\"v3 emt 10ms\",\n", + " linestyle=\":\",\n", + ")\n", + "plt.xlim([0, 0.1])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (v)\")\n", + "plt.title(\"DP 50Hz shift (10ms ts) vs EMT (10ms ts), 60Hz source\")\n", + "plt.legend(loc=\"lower right\")\n", + "plt.savefig(\"emt_dp_10ms_60Hz_src.pdf\")\n", "\n", "ts_dpsim_dp_f60_lTs_phasors = ts.phasors(ts_dpsim_dp_f60_lTs_intp)\n", "plt.figure()\n", - "plt.plot(ts_dpsim_dp_f60_lTs_phasors['v3_intpl']['phase'].time, ts_dpsim_dp_f60_lTs_phasors['v3_intpl']['phase'].values, label='v3 dp 10ms')\n", - "plt.xlim([0,0.1])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('phase (deg)')\n", - "plt.title('DP 50Hz shift (10ms ts), 60Hz source')" + "plt.plot(\n", + " ts_dpsim_dp_f60_lTs_phasors[\"v3_intpl\"][\"phase\"].time,\n", + " ts_dpsim_dp_f60_lTs_phasors[\"v3_intpl\"][\"phase\"].values,\n", + " label=\"v3 dp 10ms\",\n", + ")\n", + "plt.xlim([0, 0.1])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"phase (deg)\")\n", + "plt.title(\"DP 50Hz shift (10ms ts), 60Hz source\")" ] }, { @@ -290,11 +351,11 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/DP_VS_RL_f60_vlargeTs/'\n", - "log_name = 'DP_VS_RL_f60_vlargeTs'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/DP_VS_RL_f60_vlargeTs/\"\n", + "log_name = \"DP_VS_RL_f60_vlargeTs\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_dp_f60_vlTs = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_dp_f60_vlTs = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_dp_f60_vlTs_intp = ts.interpolate_cmpl_list(ts_dpsim_dp_f60_vlTs, 0.0001)\n", "ts_dpsim_dp_f60_vlTs_intp_emt = ts.frequency_shift_list(ts_dpsim_dp_f60_vlTs_intp, 50)" ] @@ -305,23 +366,39 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_dp_f60_vlTs_intp_emt['v1_intpl_shift'].time, ts_dpsim_dp_f60_vlTs_intp_emt['v1_intpl_shift'].values, label='v1 dp intpl')\n", - "plt.plot(ts_dpsim_dp_f60_vlTs_intp_emt['v3_intpl_shift'].time, ts_dpsim_dp_f60_vlTs_intp_emt['v3_intpl_shift'].values, label='v3 dp intpl')\n", - "plt.xlim([0,0.1])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (v)')\n", - "plt.title('DP 50Hz shift (50ms ts), 60Hz source')\n", - "plt.legend(loc='lower right')\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_vlTs_intp_emt[\"v1_intpl_shift\"].time,\n", + " ts_dpsim_dp_f60_vlTs_intp_emt[\"v1_intpl_shift\"].values,\n", + " label=\"v1 dp intpl\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_vlTs_intp_emt[\"v3_intpl_shift\"].time,\n", + " ts_dpsim_dp_f60_vlTs_intp_emt[\"v3_intpl_shift\"].values,\n", + " label=\"v3 dp intpl\",\n", + ")\n", + "plt.xlim([0, 0.1])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (v)\")\n", + "plt.title(\"DP 50Hz shift (50ms ts), 60Hz source\")\n", + "plt.legend(loc=\"lower right\")\n", "\n", "ts_dpsim_dp_f60_vlTs_phasors = ts.phasors(ts_dpsim_dp_f60_vlTs_intp)\n", "plt.figure()\n", - "plt.plot(ts_dpsim_dp_f60_vlTs_phasors['v1_intpl']['phase'].time, ts_dpsim_dp_f60_vlTs_phasors['v1_intpl']['phase'].values, label='v1 dp intpl')\n", - "plt.plot(ts_dpsim_dp_f60_vlTs_phasors['v3_intpl']['phase'].time, ts_dpsim_dp_f60_vlTs_phasors['v3_intpl']['phase'].values, label='v3 dp intpl')\n", - "plt.xlim([0,0.1])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('phase (deg)')\n", - "plt.title('DP 50Hz shift (50ms ts), 60Hz source')\n", - "plt.legend(loc='lower right')" + "plt.plot(\n", + " ts_dpsim_dp_f60_vlTs_phasors[\"v1_intpl\"][\"phase\"].time,\n", + " ts_dpsim_dp_f60_vlTs_phasors[\"v1_intpl\"][\"phase\"].values,\n", + " label=\"v1 dp intpl\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f60_vlTs_phasors[\"v3_intpl\"][\"phase\"].time,\n", + " ts_dpsim_dp_f60_vlTs_phasors[\"v3_intpl\"][\"phase\"].values,\n", + " label=\"v3 dp intpl\",\n", + ")\n", + "plt.xlim([0, 0.1])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"phase (deg)\")\n", + "plt.title(\"DP 50Hz shift (50ms ts), 60Hz source\")\n", + "plt.legend(loc=\"lower right\")" ] }, { @@ -365,11 +442,11 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/DP_VS_RL_f500/'\n", - "log_name = 'DP_VS_RL_f500'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/DP_VS_RL_f500/\"\n", + "log_name = \"DP_VS_RL_f500\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_dp_f500 = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_dp_f500 = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_dp_f500_emt = ts.frequency_shift_list(ts_dpsim_dp_f500, 50)" ] }, @@ -380,11 +457,11 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/EMT_VS_RL_f500/'\n", - "log_name = 'EMT_VS_RL_f500'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/EMT_VS_RL_f500/\"\n", + "log_name = \"EMT_VS_RL_f500\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_emt_f500 = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "ts_dpsim_emt_f500 = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -393,23 +470,51 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_emt_f500['v1'].time, ts_dpsim_emt_f500['v1'].values, label='v1 emt', color = '#939393ff')\n", - "plt.plot(ts_dpsim_emt_f500['v3'].time, ts_dpsim_emt_f500['v3'].values, label='v3 emt', color = '#939393ff')\n", - "plt.plot(ts_dpsim_dp_f500_emt['v1_shift'].time, ts_dpsim_dp_f500_emt['v1_shift'].values, label='v1 dp', linestyle='-.')\n", - "plt.plot(ts_dpsim_dp_f500_emt['v3_shift'].time, ts_dpsim_dp_f500_emt['v3_shift'].values, label='v3 dp', linestyle='-.')\n", - "plt.xlim([0,0.01])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (v)')\n", - "plt.title('DP 50Hz shift (10µs ts) vs EMT (10µs ts), 500Hz source')\n", + "plt.plot(\n", + " ts_dpsim_emt_f500[\"v1\"].time,\n", + " ts_dpsim_emt_f500[\"v1\"].values,\n", + " label=\"v1 emt\",\n", + " color=\"#939393ff\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_f500[\"v3\"].time,\n", + " ts_dpsim_emt_f500[\"v3\"].values,\n", + " label=\"v3 emt\",\n", + " color=\"#939393ff\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f500_emt[\"v1_shift\"].time,\n", + " ts_dpsim_dp_f500_emt[\"v1_shift\"].values,\n", + " label=\"v1 dp\",\n", + " linestyle=\"-.\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f500_emt[\"v3_shift\"].time,\n", + " ts_dpsim_dp_f500_emt[\"v3_shift\"].values,\n", + " label=\"v3 dp\",\n", + " linestyle=\"-.\",\n", + ")\n", + "plt.xlim([0, 0.01])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (v)\")\n", + "plt.title(\"DP 50Hz shift (10µs ts) vs EMT (10µs ts), 500Hz source\")\n", "\n", "ts_dpsim_dp_f500_phasors = ts.phasors(ts_dpsim_dp_f500)\n", "plt.figure()\n", - "plt.plot(ts_dpsim_dp_f500_phasors['v1']['phase'].time, ts_dpsim_dp_f500_phasors['v1']['phase'].values, label='v1 dp')\n", - "plt.plot(ts_dpsim_dp_f500_phasors['v3']['phase'].time, ts_dpsim_dp_f500_phasors['v3']['phase'].values, label='v3 dp')\n", - "plt.xlim([0,0.01])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('phase (deg)')\n", - "plt.title('DP 50Hz shift (10µs ts), 500Hz source')" + "plt.plot(\n", + " ts_dpsim_dp_f500_phasors[\"v1\"][\"phase\"].time,\n", + " ts_dpsim_dp_f500_phasors[\"v1\"][\"phase\"].values,\n", + " label=\"v1 dp\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f500_phasors[\"v3\"][\"phase\"].time,\n", + " ts_dpsim_dp_f500_phasors[\"v3\"][\"phase\"].values,\n", + " label=\"v3 dp\",\n", + ")\n", + "plt.xlim([0, 0.01])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"phase (deg)\")\n", + "plt.title(\"DP 50Hz shift (10µs ts), 500Hz source\")" ] }, { @@ -434,11 +539,11 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/DP_VS_RL_f500_largeTs/'\n", - "log_name = 'DP_VS_RL_f500_largeTs'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/DP_VS_RL_f500_largeTs/\"\n", + "log_name = \"DP_VS_RL_f500_largeTs\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_dp_f500_lTs = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_dp_f500_lTs = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_dp_f500_lTs_intp = ts.interpolate_cmpl_list(ts_dpsim_dp_f500_lTs, 0.00001)\n", "ts_dpsim_dp_f500_lTs_intp_emt = ts.frequency_shift_list(ts_dpsim_dp_f500_lTs_intp, 50)" ] @@ -449,19 +554,25 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_dp_f500_lTs_intp_emt['v1_intpl_shift'].time, ts_dpsim_dp_f500_lTs_intp_emt['v1_intpl_shift'].values)\n", - "plt.xlim([0,0.01])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (v)')\n", - "plt.title('DP 50Hz shift (2ms ts), 500Hz source')\n", + "plt.plot(\n", + " ts_dpsim_dp_f500_lTs_intp_emt[\"v1_intpl_shift\"].time,\n", + " ts_dpsim_dp_f500_lTs_intp_emt[\"v1_intpl_shift\"].values,\n", + ")\n", + "plt.xlim([0, 0.01])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (v)\")\n", + "plt.title(\"DP 50Hz shift (2ms ts), 500Hz source\")\n", "\n", "ts_dpsim_dp_f500_lTs_phasors = ts.phasors(ts_dpsim_dp_f500_lTs_intp)\n", "plt.figure()\n", - "plt.plot(ts_dpsim_dp_f500_lTs_phasors['v1_intpl']['phase'].time, ts_dpsim_dp_f500_lTs_phasors['v1_intpl']['phase'].values)\n", - "plt.xlim([0,0.01])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('phase (deg)')\n", - "plt.title('DP 50Hz shift (2ms ts), 500Hz source')" + "plt.plot(\n", + " ts_dpsim_dp_f500_lTs_phasors[\"v1_intpl\"][\"phase\"].time,\n", + " ts_dpsim_dp_f500_lTs_phasors[\"v1_intpl\"][\"phase\"].values,\n", + ")\n", + "plt.xlim([0, 0.01])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"phase (deg)\")\n", + "plt.title(\"DP 50Hz shift (2ms ts), 500Hz source\")" ] }, { @@ -490,13 +601,15 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/DP_VS_RL_f500_ph500/'\n", - "log_name = 'DP_VS_RL_f500_ph500'\n", - "print(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/DP_VS_RL_f500_ph500/\"\n", + "log_name = \"DP_VS_RL_f500_ph500\"\n", + "print(work_dir + log_name + \".csv\")\n", "\n", - "ts_dpsim_dp_f500_ph500 = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "ts_dpsim_dp_f500_ph500 = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_dp_f500_ph500_intp = ts.interpolate_cmpl_list(ts_dpsim_dp_f500_ph500, 0.00001)\n", - "ts_dpsim_dp_f500_ph500_intp_emt = ts.frequency_shift_list(ts_dpsim_dp_f500_ph500_intp, 500)" + "ts_dpsim_dp_f500_ph500_intp_emt = ts.frequency_shift_list(\n", + " ts_dpsim_dp_f500_ph500_intp, 500\n", + ")" ] }, { @@ -505,22 +618,37 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_dpsim_emt_f500['v1'].time, ts_dpsim_emt_f500['v1'].values, color = '#939393ff')\n", - "plt.plot(ts_dpsim_emt_f500['v3'].time, ts_dpsim_emt_f500['v3'].values, color = '#939393ff')\n", - "plt.plot(ts_dpsim_dp_f500_ph500_intp_emt['v1_intpl_shift'].time, ts_dpsim_dp_f500_ph500_intp_emt['v1_intpl_shift'].values, linestyle='-.')\n", - "plt.plot(ts_dpsim_dp_f500_ph500_intp_emt['v3_intpl_shift'].time, ts_dpsim_dp_f500_ph500_intp_emt['v3_intpl_shift'].values, linestyle='-.')\n", - "plt.xlim([0,0.01])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (v)')\n", - "plt.title('DP 500Hz shift (10ms ts) vs EMT (10µs ts), 500Hz source')\n", + "plt.plot(\n", + " ts_dpsim_emt_f500[\"v1\"].time, ts_dpsim_emt_f500[\"v1\"].values, color=\"#939393ff\"\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_emt_f500[\"v3\"].time, ts_dpsim_emt_f500[\"v3\"].values, color=\"#939393ff\"\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f500_ph500_intp_emt[\"v1_intpl_shift\"].time,\n", + " ts_dpsim_dp_f500_ph500_intp_emt[\"v1_intpl_shift\"].values,\n", + " linestyle=\"-.\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_dp_f500_ph500_intp_emt[\"v3_intpl_shift\"].time,\n", + " ts_dpsim_dp_f500_ph500_intp_emt[\"v3_intpl_shift\"].values,\n", + " linestyle=\"-.\",\n", + ")\n", + "plt.xlim([0, 0.01])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (v)\")\n", + "plt.title(\"DP 500Hz shift (10ms ts) vs EMT (10µs ts), 500Hz source\")\n", "\n", "ts_dpsim_dp_f500_ph500_intp_phasors = ts.phasors(ts_dpsim_dp_f500_ph500_intp)\n", "plt.figure()\n", - "plt.plot(ts_dpsim_dp_f500_ph500_intp_phasors['v1_intpl']['phase'].time, ts_dpsim_dp_f500_ph500_intp_phasors['v1_intpl']['phase'].values)\n", - "plt.xlim([0,0.01])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('phase (deg)')\n", - "plt.title('DP 500Hz shift (10ms ts), 500Hz source')" + "plt.plot(\n", + " ts_dpsim_dp_f500_ph500_intp_phasors[\"v1_intpl\"][\"phase\"].time,\n", + " ts_dpsim_dp_f500_ph500_intp_phasors[\"v1_intpl\"][\"phase\"].values,\n", + ")\n", + "plt.xlim([0, 0.01])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"phase (deg)\")\n", + "plt.title(\"DP 500Hz shift (10ms ts), 500Hz source\")" ] }, { @@ -556,10 +684,10 @@ "outputs": [], "source": [ "# read log file\n", - "work_dir = '../../../logs/DP_SynGenDq7odODE_ThreePhFault/'\n", - "log_name = 'DP_SynGenDq7odODE_ThreePhFault'\n", - "print(work_dir + log_name + '.csv')\n", - "ts_dpsim_ode_tpf = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "work_dir = \"../../../logs/DP_SynGenDq7odODE_ThreePhFault/\"\n", + "log_name = \"DP_SynGenDq7odODE_ThreePhFault\"\n", + "print(work_dir + log_name + \".csv\")\n", + "ts_dpsim_ode_tpf = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")\n", "ts_dpsim_ode_tpf_emt = ts.frequency_shift_list(ts_dpsim_ode_tpf, 60)\n", "ts_dpsim_ode_tpf_phasors = ts.phasors(ts_dpsim_ode_tpf)" ] @@ -574,12 +702,12 @@ "import os\n", "import urllib.request\n", "\n", - "if not os.path.exists('reference-results'):\n", - " os.mkdir('reference-results')\n", + "if not os.path.exists(\"reference-results\"):\n", + " os.mkdir(\"reference-results\")\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Simulink/SynchronousGenerator/SynGen_dq_7th_ThreePhFault/SL_SynGenDq7od_ThreePhFault_v_i.csv'\n", - "local_file = 'reference-results/SL_SynGenDq7od_ThreePhFault_v_i.csv'\n", - "urllib.request.urlretrieve(url, local_file) \n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Simulink/SynchronousGenerator/SynGen_dq_7th_ThreePhFault/SL_SynGenDq7od_ThreePhFault_v_i.csv\"\n", + "local_file = \"reference-results/SL_SynGenDq7od_ThreePhFault_v_i.csv\"\n", + "urllib.request.urlretrieve(url, local_file)\n", "\n", "ts_sl_tpf = rt.read_timeseries_simulink(local_file)" ] @@ -590,26 +718,41 @@ "metadata": {}, "outputs": [], "source": [ - "ts_sl_tpf_i1 = ts('i1', ts_sl_tpf['i1'].time, -ts_sl_tpf['i1'].values)\n", - "ts_sl_tpf_i2 = ts('i2', ts_sl_tpf['i2'].time, -ts_sl_tpf['i2'].values)\n", - "ts_sl_tpf_i3 = ts('i3', ts_sl_tpf['i3'].time, -ts_sl_tpf['i3'].values)\n", - "\n", - "ts_sl_tpf_i1.label = 'ia_sl'\n", - "ts_sl_tpf_i2.label = 'ib_sl'\n", - "ts_sl_tpf_i3.label = 'ic_sl'\n", - "ts_dpsim_ode_tpf_emt['i_gen_0_shift'].label = 'ia_dpsim'\n", - "ts_dpsim_ode_tpf_emt['i_gen_1_shift'].label = 'ib_dpsim'\n", - "ts_dpsim_ode_tpf_emt['i_gen_2_shift'].label = 'ic_dpsim'\n", - "plt.plot(ts_sl_tpf_i1.time, ts_sl_tpf_i1.values, color = '#939393ff')\n", - "plt.plot(ts_sl_tpf_i2.time, ts_sl_tpf_i2.values, color = '#939393ff')\n", - "plt.plot(ts_sl_tpf_i3.time, ts_sl_tpf_i3.values, color = '#939393ff')\n", - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_0_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_0_shift'].values, linestyle='-.', color = '#d62728ff')\n", - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_1_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_1_shift'].values, linestyle='-.', color = '#0055ffff')\n", - "plt.plot(ts_dpsim_ode_tpf_emt['i_gen_2_shift'].time, ts_dpsim_ode_tpf_emt['i_gen_2_shift'].values, linestyle='-.', color = '#00aa7fff')\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (V)')\n", - "plt.xlim(0.05,0.25)\n", - "plt.savefig('syngen_three_phase_fault.pdf')" + "ts_sl_tpf_i1 = ts(\"i1\", ts_sl_tpf[\"i1\"].time, -ts_sl_tpf[\"i1\"].values)\n", + "ts_sl_tpf_i2 = ts(\"i2\", ts_sl_tpf[\"i2\"].time, -ts_sl_tpf[\"i2\"].values)\n", + "ts_sl_tpf_i3 = ts(\"i3\", ts_sl_tpf[\"i3\"].time, -ts_sl_tpf[\"i3\"].values)\n", + "\n", + "ts_sl_tpf_i1.label = \"ia_sl\"\n", + "ts_sl_tpf_i2.label = \"ib_sl\"\n", + "ts_sl_tpf_i3.label = \"ic_sl\"\n", + "ts_dpsim_ode_tpf_emt[\"i_gen_0_shift\"].label = \"ia_dpsim\"\n", + "ts_dpsim_ode_tpf_emt[\"i_gen_1_shift\"].label = \"ib_dpsim\"\n", + "ts_dpsim_ode_tpf_emt[\"i_gen_2_shift\"].label = \"ic_dpsim\"\n", + "plt.plot(ts_sl_tpf_i1.time, ts_sl_tpf_i1.values, color=\"#939393ff\")\n", + "plt.plot(ts_sl_tpf_i2.time, ts_sl_tpf_i2.values, color=\"#939393ff\")\n", + "plt.plot(ts_sl_tpf_i3.time, ts_sl_tpf_i3.values, color=\"#939393ff\")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_0_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_0_shift\"].values,\n", + " linestyle=\"-.\",\n", + " color=\"#d62728ff\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_1_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_1_shift\"].values,\n", + " linestyle=\"-.\",\n", + " color=\"#0055ffff\",\n", + ")\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_2_shift\"].time,\n", + " ts_dpsim_ode_tpf_emt[\"i_gen_2_shift\"].values,\n", + " linestyle=\"-.\",\n", + " color=\"#00aa7fff\",\n", + ")\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (V)\")\n", + "plt.xlim(0.05, 0.25)\n", + "plt.savefig(\"syngen_three_phase_fault.pdf\")" ] }, { @@ -628,18 +771,21 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(ts_dpsim_ode_tpf_phasors['i_gen_0']['phase'].time, ts_dpsim_ode_tpf_phasors['i_gen_0']['phase'].values)\n", - "plt.xlim([0.09,0.21])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('phase (deg)')\n", - "plt.savefig('syngen_three_phase_fault_phase.pdf')\n", + "plt.plot(\n", + " ts_dpsim_ode_tpf_phasors[\"i_gen_0\"][\"phase\"].time,\n", + " ts_dpsim_ode_tpf_phasors[\"i_gen_0\"][\"phase\"].values,\n", + ")\n", + "plt.xlim([0.09, 0.21])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"phase (deg)\")\n", + "plt.savefig(\"syngen_three_phase_fault_phase.pdf\")\n", "\n", "plt.figure()\n", - "plt.plot(ts_dpsim_ode_tpf['wr_gen'].time, ts_dpsim_ode_tpf['wr_gen'].values * 60)\n", - "plt.xlim([0.09,0.21])\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('rotor freq. (Hz)')\n", - "plt.savefig('syngen_three_phase_fault_wr.pdf')" + "plt.plot(ts_dpsim_ode_tpf[\"wr_gen\"].time, ts_dpsim_ode_tpf[\"wr_gen\"].values * 60)\n", + "plt.xlim([0.09, 0.21])\n", + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"rotor freq. (Hz)\")\n", + "plt.savefig(\"syngen_three_phase_fault_wr.pdf\")" ] }, { diff --git a/examples/Notebooks/matpower-case9.ipynb b/examples/Notebooks/matpower-case9.ipynb index c90df4fba9..392942c780 100644 --- a/examples/Notebooks/matpower-case9.ipynb +++ b/examples/Notebooks/matpower-case9.ipynb @@ -21,8 +21,9 @@ "outputs": [], "source": [ "import requests\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Matpower/case9results.mat'\n", - "with open('case9results.mat', 'wb') as out_file:\n", + "\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/reference-results/master/Matpower/case9results.mat\"\n", + "with open(\"case9results.mat\", \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)" ] @@ -34,7 +35,7 @@ "metadata": {}, "outputs": [], "source": [ - "mpc_reader = dpsim.matpower.Reader('case9results.mat', 'case9results')" + "mpc_reader = dpsim.matpower.Reader(\"case9results.mat\", \"case9results\")" ] }, { @@ -54,14 +55,14 @@ "metadata": {}, "outputs": [], "source": [ - "sim_name = 'case9'\n", - "dpsim.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"case9\"\n", + "dpsim.Logger.set_log_dir(\"logs/\" + sim_name)\n", "logger = dpsim.Logger(sim_name)\n", "\n", "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node)\n", - " logger.log_attribute(node.name()+'.S', 's', node)\n", - " \n", + " logger.log_attribute(node.name() + \".V\", \"v\", node)\n", + " logger.log_attribute(node.name() + \".S\", \"s\", node)\n", + "\n", "# Parametrize and run simulation\n", "sim = dpsim.Simulation(sim_name, dpsim.LogLevel.info)\n", "sim.set_system(system)\n", @@ -84,7 +85,7 @@ "import villas.dataprocessing.readtools as rt\n", "from villas.dataprocessing.timeseries import TimeSeries as ts\n", "\n", - "log_file = 'logs/' + sim_name +'/' + sim_name + '.csv'\n", + "log_file = \"logs/\" + sim_name + \"/\" + sim_name + \".csv\"\n", "print(log_file)\n", "ts_dpsimpy = rt.read_timeseries_dpsim(log_file)" ] @@ -96,16 +97,26 @@ "metadata": {}, "outputs": [], "source": [ - "results = pd.DataFrame(columns=['Bus', 'V_mag(pu)', 'V_angle(deg)', 'P(MW)', 'Q (MVAr)'])\n", + "results = pd.DataFrame(\n", + " columns=[\"Bus\", \"V_mag(pu)\", \"V_angle(deg)\", \"P(MW)\", \"Q (MVAr)\"]\n", + ")\n", "\n", "for i in range(len(system.nodes)):\n", " node = system.nodes[i].name()\n", - " node_baseV = mpc_reader.mpc_bus_data.loc[mpc_reader.mpc_bus_data['bus_i'] == int(node), 'baseKV'].iloc[0] * 1e3\n", + " node_baseV = (\n", + " mpc_reader.mpc_bus_data.loc[\n", + " mpc_reader.mpc_bus_data[\"bus_i\"] == int(node), \"baseKV\"\n", + " ].iloc[0]\n", + " * 1e3\n", + " )\n", " w_mw = 1e-6\n", - " results.loc[i] = ([node] + [np.absolute(ts_dpsimpy[node + '.V'].values[-1]) / node_baseV]\n", - " + [np.degrees(np.angle(ts_dpsimpy[node + '.V'].values[-1]))] \n", - " + [w_mw * np.real(ts_dpsimpy[node + '.S'].values[-1])] \n", - " + [w_mw * np.imag(ts_dpsimpy[node + '.S'].values[-1])])" + " results.loc[i] = (\n", + " [node]\n", + " + [np.absolute(ts_dpsimpy[node + \".V\"].values[-1]) / node_baseV]\n", + " + [np.degrees(np.angle(ts_dpsimpy[node + \".V\"].values[-1]))]\n", + " + [w_mw * np.real(ts_dpsimpy[node + \".S\"].values[-1])]\n", + " + [w_mw * np.imag(ts_dpsimpy[node + \".S\"].values[-1])]\n", + " )" ] }, { @@ -126,11 +137,26 @@ "outputs": [], "source": [ "import scipy.io\n", - "input_mat = 'case9results.mat'\n", + "\n", + "input_mat = \"case9results.mat\"\n", "data = scipy.io.loadmat(input_mat)\n", - " \n", - "bus_data = pd.DataFrame(data['case9results'][0][0]['bus'])\n", - "bus_data.columns = [\"bus_i\", \"type\", \"Pd\", \"Qd\", \"Gs\", \"Bs\", \"area\", \"Vm\", \"Va\", \"baseKV\", \"zone\", \"Vmax\", \"Vmin\"]" + "\n", + "bus_data = pd.DataFrame(data[\"case9results\"][0][0][\"bus\"])\n", + "bus_data.columns = [\n", + " \"bus_i\",\n", + " \"type\",\n", + " \"Pd\",\n", + " \"Qd\",\n", + " \"Gs\",\n", + " \"Bs\",\n", + " \"area\",\n", + " \"Vm\",\n", + " \"Va\",\n", + " \"baseKV\",\n", + " \"zone\",\n", + " \"Vmax\",\n", + " \"Vmin\",\n", + "]" ] }, { @@ -150,7 +176,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert all(bus_data['Vm'] - results['V_mag(pu)'] < 0.001)" + "assert all(bus_data[\"Vm\"] - results[\"V_mag(pu)\"] < 0.001)" ] }, { @@ -160,7 +186,7 @@ "metadata": {}, "outputs": [], "source": [ - "assert all(bus_data['Va'] - results['V_angle(deg)'] < 0.05)" + "assert all(bus_data[\"Va\"] - results[\"V_angle(deg)\"] < 0.05)" ] }, { diff --git a/examples/Python/Base/test_async.py b/examples/Python/Base/test_async.py index 80488d233b..fb4e9b4154 100644 --- a/examples/Python/Base/test_async.py +++ b/examples/Python/Base/test_async.py @@ -6,31 +6,35 @@ from dpsim.Event import Event + def my_callback(event, sim, myvar): assert myvar == 1337 - print('Received Event: %s' % event) + print("Received Event: %s" % event) - if event in [ Event.done, Event.stopped, Event.stopped, Event.failed, Event.overrun ]: + if event in [Event.done, Event.stopped, Event.stopped, Event.failed, Event.overrun]: el = asyncio.get_event_loop() el.stop() + def test_async(): el = asyncio.get_event_loop() # Nodes gnd = dpsim.dp.Node.GND() - n1 = dpsim.dp.Node('n1') + n1 = dpsim.dp.Node("n1") # Components - v1 = dpsim.dp.ph1.VoltageSource('v_1', [gnd, n1], V_ref=complex(10,0)) - r1 = dpsim.dp.ph1.Resistor('r_1', [n1, gnd], R=1) + v1 = dpsim.dp.ph1.VoltageSource("v_1", [gnd, n1], V_ref=complex(10, 0)) + r1 = dpsim.dp.ph1.Resistor("r_1", [n1, gnd], R=1) system = dpsim.SystemTopology(50, [gnd, n1], [v1, r1]) start = dt.datetime.now() + dt.timedelta(seconds=4) - sim = dpsim.RealTimeSimulation(__name__, system, duration=10, timestep=0.0005) # , start_time=start) + sim = dpsim.RealTimeSimulation( + __name__, system, duration=10, timestep=0.0005 + ) # , start_time=start) # Start in two seconds! sim.start() @@ -46,5 +50,6 @@ def test_async(): el.run_forever() -if __name__ == '__main__': + +if __name__ == "__main__": test_async() diff --git a/examples/Python/Base/test_attribute.py b/examples/Python/Base/test_attribute.py index 845f9e9b03..d8dba4f1e6 100644 --- a/examples/Python/Base/test_attribute.py +++ b/examples/Python/Base/test_attribute.py @@ -1,43 +1,48 @@ import dpsim import pytest + def test_read(): gnd = dpsim.dp.Node.GND() - c = dpsim.dp.ph1.Capacitor('c1', [gnd, gnd], C=1.234); + c = dpsim.dp.ph1.Capacitor("c1", [gnd, gnd], C=1.234) assert c.C == 1.234 - assert c.name == 'c1' + assert c.name == "c1" + def test_write(): gnd = dpsim.dp.Node.GND() - c = dpsim.dp.ph1.Capacitor('c1', [gnd, gnd], C=1.234); + c = dpsim.dp.ph1.Capacitor("c1", [gnd, gnd], C=1.234) c.C = 5 assert c.C == 5 + def test_invalid(): with pytest.raises(AttributeError) as e_info: gnd = dpsim.dp.Node.GND() - c = dpsim.dp.ph1.Capacitor('c1', [gnd, gnd], C=1.234); + c = dpsim.dp.ph1.Capacitor("c1", [gnd, gnd], C=1.234) # dp.Capacitor does not have an attribute named 'doesnotexist' # Accessing it should throw a AttributeError exception! x = c.doesnotexist + def test_access(): with pytest.raises(AttributeError) as e_info: gnd = dpsim.dp.Node.GND() - c = dpsim.dp.ph1.Capacitor('c1', [gnd, gnd], C=1.234); + c = dpsim.dp.ph1.Capacitor("c1", [gnd, gnd], C=1.234) # Current is a read-only property. # This should throw a AttributeError exception! c.current = 5 + def test_type(): with pytest.raises(TypeError) as e_info: gnd = dpsim.dp.Node.GND() - c = dpsim.dp.ph1.Capacitor('c1', [gnd, gnd], C=1.234); + c = dpsim.dp.ph1.Capacitor("c1", [gnd, gnd], C=1.234) # Capacitance is a real valued property. # Assigning a complex number should throw a TypeError exception! diff --git a/examples/Python/Base/test_simulation.py b/examples/Python/Base/test_simulation.py index e4a5802167..f6444a0c5d 100644 --- a/examples/Python/Base/test_simulation.py +++ b/examples/Python/Base/test_simulation.py @@ -4,13 +4,14 @@ from dpsim.Event import Event + def test_simulation(): logging.getLogger().setLevel(logging.DEBUG) - logging.info('hello\n') + logging.info("hello\n") - n1 = dpsim.dp.Node('n1') + n1 = dpsim.dp.Node("n1") gnd = dpsim.dp.Node.GND() - r = dpsim.dp.ph1.Resistor('r1', [gnd, n1]) + r = dpsim.dp.ph1.Resistor("r1", [gnd, n1]) sys = dpsim.SystemTopology(50, [n1], [r]) @@ -48,5 +49,6 @@ def test_simulation(): assert sim.wait_until() == Event.stopping assert sim.wait_until() == Event.stopped -if __name__ == '__main__': + +if __name__ == "__main__": test_simulation() diff --git a/examples/Python/Base/test_singlestepping.py b/examples/Python/Base/test_singlestepping.py index 874ebe2593..06e24e1d0e 100644 --- a/examples/Python/Base/test_singlestepping.py +++ b/examples/Python/Base/test_singlestepping.py @@ -4,25 +4,28 @@ from dpsim.Event import Event + def test_simulation(): logging.getLogger().setLevel(logging.DEBUG) - logging.info('hello\n') + logging.info("hello\n") - n1 = dpsim.dp.Node('n1') + n1 = dpsim.dp.Node("n1") gnd = dpsim.dp.Node.GND() - r = dpsim.dp.ph1.Resistor('r1', [gnd, n1]) + r = dpsim.dp.ph1.Resistor("r1", [gnd, n1]) sys = dpsim.SystemTopology(50, [n1], [r]) - sim = dpsim.Simulation(__name__, sys, duration=10, rt=True, pbar=True, single_stepping=True) + sim = dpsim.Simulation( + __name__, sys, duration=10, rt=True, pbar=True, single_stepping=True + ) sim.step() assert sim.wait_until() == Event.starting assert sim.wait_until() == Event.running assert sim.wait_until() == Event.paused - for x in range(2,10): + for x in range(2, 10): sim.step() assert sim.wait_until() == Event.resuming assert sim.wait_until() == Event.running @@ -34,5 +37,5 @@ def test_simulation(): assert sim.wait_until() == Event.stopped -if __name__ == '__main__': +if __name__ == "__main__": test_simulation() diff --git a/examples/Python/CIM/dpsim-cim.py b/examples/Python/CIM/dpsim-cim.py index ce4c8d9a30..5b4eb5715a 100644 --- a/examples/Python/CIM/dpsim-cim.py +++ b/examples/Python/CIM/dpsim-cim.py @@ -1,6 +1,7 @@ import sys import dpsim + def run_cim(): if len(sys.argv) <= 1: print("usage: %s CIM_FILES" % sys.argv[0]) @@ -16,7 +17,7 @@ def run_cim(): sw.resistance_open = 1e9 sw.resistance_closed = 0.1 sw.closed = False - sw.connect([ dpsim.dp.Node.GND(), system.nodes["BUS9"] ]) + sw.connect([dpsim.dp.Node.GND(), system.nodes["BUS9"]]) system.add_component(sw) @@ -24,5 +25,6 @@ def run_cim(): sim.add_switch_event(sw, 0.05, True) sim.run() + if __name__ == "__main__": run_cim() diff --git a/examples/Python/Circuits/test_circuit.py b/examples/Python/Circuits/test_circuit.py index ee990fa278..8df12bfdfb 100644 --- a/examples/Python/Circuits/test_circuit.py +++ b/examples/Python/Circuits/test_circuit.py @@ -3,22 +3,23 @@ PATH = os.path.dirname(__file__) + def test_circuit(): # Nodes gnd = dpsim.dp.Node.GND() - n1 = dpsim.dp.Node('n1') - n2 = dpsim.dp.Node('n2') - n3 = dpsim.dp.Node('n3') + n1 = dpsim.dp.Node("n1") + n2 = dpsim.dp.Node("n2") + n3 = dpsim.dp.Node("n3") # Components - v1 = dpsim.dp.ph1.VoltageSource('v_1') - v1.V_ref= complex(10, 0) - lL = dpsim.dp.ph1.Inductor('l_L') - lL.L= 0.001 - rL = dpsim.dp.ph1.Resistor('r_L') - rL.R= 0.1 - r1 = dpsim.dp.ph1.Resistor('r_1') - r1.R= 20 + v1 = dpsim.dp.ph1.VoltageSource("v_1") + v1.V_ref = complex(10, 0) + lL = dpsim.dp.ph1.Inductor("l_L") + lL.L = 0.001 + rL = dpsim.dp.ph1.Resistor("r_L") + rL.R = 0.1 + r1 = dpsim.dp.ph1.Resistor("r_1") + r1.R = 20 v1.connect([gnd, n1]) lL.connect([n2, n3]) @@ -37,9 +38,10 @@ def test_circuit(): # err += ts.TimeSeries.rmse(expected[0], results[0].dynphasor_shift_to_emt('n1_emt', 50)) # err += ts.TimeSeries.rmse(expected[1], results[1].dynphasor_shift_to_emt('n2_emt', 50)) - print('Total RMSE: %g' % (err)) + print("Total RMSE: %g" % (err)) assert err < 1e-4 -if __name__ == '__main__': + +if __name__ == "__main__": test_circuit() diff --git a/examples/Python/RealTime/test_realtime.py b/examples/Python/RealTime/test_realtime.py index 560030cfff..15e2d2f0bc 100644 --- a/examples/Python/RealTime/test_realtime.py +++ b/examples/Python/RealTime/test_realtime.py @@ -3,15 +3,16 @@ from dpsim.Event import Event + def test_realtime(): # Nodes gnd = dpsim.dp.Node.GND() - n1 = dpsim.dp.Node('n1') + n1 = dpsim.dp.Node("n1") # Components - v1 = dpsim.dp.ph1.VoltageSource('v_1') + v1 = dpsim.dp.ph1.VoltageSource("v_1") v1.V_ref = complex(10, 0) - r1 = dpsim.dp.ph1.Resistor('r_1') + r1 = dpsim.dp.ph1.Resistor("r_1") r1.R = 1 v1.connect([gnd, n1]) @@ -23,10 +24,13 @@ def test_realtime(): print(repr(start)) - sim = dpsim.RealTimeSimulation(__name__, system, duration=10, timestep=0.001, start_time=start) + sim = dpsim.RealTimeSimulation( + __name__, system, duration=10, timestep=0.001, start_time=start + ) sim.show_progressbar() sim.run(pbar=True) -if __name__ == '__main__': + +if __name__ == "__main__": test_realtime() diff --git a/examples/Python/RuntimeMeas/decoupling_9bus_comp.py b/examples/Python/RuntimeMeas/decoupling_9bus_comp.py index d3da2a9677..73cd8346c4 100644 --- a/examples/Python/RuntimeMeas/decoupling_9bus_comp.py +++ b/examples/Python/RuntimeMeas/decoupling_9bus_comp.py @@ -12,42 +12,51 @@ from villas.dataprocessing.timeseries import TimeSeries as ts import matplotlib.pyplot as plt + def multiply_decoupled(sys, num_copies, nodes, resistance, inductance, capacitance): sys.multiply(num_copies) counter = 0 for orig_node in nodes: node_names = [orig_node] - node_names += [orig_node + '_' + str(i) for i in range(2, num_copies+2)] + node_names += [orig_node + "_" + str(i) for i in range(2, num_copies + 2)] node_names.append(orig_node) - for i in range(0, num_copies+1): - sys.add_decoupling_line('dline' + str(counter), sys.nodes[node_names[i]], sys.nodes[node_names[i+1]], resistance, inductance, capacitance) + for i in range(0, num_copies + 1): + sys.add_decoupling_line( + "dline" + str(counter), + sys.nodes[node_names[i]], + sys.nodes[node_names[i + 1]], + resistance, + inductance, + capacitance, + ) counter += 1 + def multiply_coupled(sys, num_copies, nodes, resistance, inductance, capacitance): gnd = dpsim.dp.Node.GND() sys.multiply(num_copies) counter = 0 for orig_node in nodes: node_names = [orig_node] - node_names += [orig_node + '_' + str(i) for i in range(2, num_copies+2)] + node_names += [orig_node + "_" + str(i) for i in range(2, num_copies + 2)] node_names.append(orig_node) - for i in range(0, num_copies+1): + for i in range(0, num_copies + 1): # TODO lumped resistance? - rl_node = dpsim.dp.Node('N_add_' + str(counter)) - res = dpsim.dp.ph1.Resistor('R_' + str(counter)) + rl_node = dpsim.dp.Node("N_add_" + str(counter)) + res = dpsim.dp.ph1.Resistor("R_" + str(counter)) res.R = resistance - ind = dpsim.dp.ph1.Inductor('L_' + str(counter)) + ind = dpsim.dp.ph1.Inductor("L_" + str(counter)) ind.L = inductance - cap1 = dpsim.dp.ph1.Capacitor('C1_' + str(counter)) + cap1 = dpsim.dp.ph1.Capacitor("C1_" + str(counter)) cap1.C = capacitance / 2 - cap2 = dpsim.dp.ph1.Capacitor('C2_' + str(counter)) + cap2 = dpsim.dp.ph1.Capacitor("C2_" + str(counter)) cap2.C = capacitance / 2 sys.add_node(rl_node) res.connect([sys.nodes[node_names[i]], rl_node]) - ind.connect([rl_node, sys.nodes[node_names[i+1]]]) + ind.connect([rl_node, sys.nodes[node_names[i + 1]]]) cap1.connect([sys.nodes[node_names[i]], gnd]) - cap2.connect([sys.nodes[node_names[i+1]], gnd]) + cap2.connect([sys.nodes[node_names[i + 1]], gnd]) counter += 1 sys.add_component(res) @@ -55,29 +64,39 @@ def multiply_coupled(sys, num_copies, nodes, resistance, inductance, capacitance sys.add_component(cap1) sys.add_component(cap2) + def do_sim(name, system): logger = dpsim.Logger(name) for i in range(0, 6): - logger.log_attribute(system.nodes['BUS' + str(i+4)], 'v') - - sim = dpsim.Simulation(name, system, timestep=0.0001, duration=0.1, init_steady_state=False, pbar=False, split_subnets=True) - sim.set_scheduler('thread_level', threads=4) + logger.log_attribute(system.nodes["BUS" + str(i + 4)], "v") + + sim = dpsim.Simulation( + name, + system, + timestep=0.0001, + duration=0.1, + init_steady_state=False, + pbar=False, + split_subnets=True, + ) + sim.set_scheduler("thread_level", threads=4) sim.add_logger(logger) sim.run() -name = 'WSCC-9bus' -files = glob.glob('../dpsim/examples/CIM/WSCC-09_RX/*.xml') + +name = "WSCC-9bus" +files = glob.glob("../dpsim/examples/CIM/WSCC-09_RX/*.xml") system = dpsim.load_cim(name, files, frequency=60) -do_sim('normal', system) +do_sim("normal", system) system = dpsim.load_cim(name, files, frequency=60) -multiply_coupled(system, 1, ['BUS5', 'BUS6', 'BUS8'], 100, 0.16, 1e-6) -do_sim('coupled', system) +multiply_coupled(system, 1, ["BUS5", "BUS6", "BUS8"], 100, 0.16, 1e-6) +do_sim("coupled", system) system = dpsim.load_cim(name, files, frequency=60) -multiply_decoupled(system, 1, ['BUS5', 'BUS6', 'BUS8'], 100, 0.16, 1e-6) -do_sim('decoupled', system) +multiply_decoupled(system, 1, ["BUS5", "BUS6", "BUS8"], 100, 0.16, 1e-6) +do_sim("decoupled", system) normal_dp = rt.read_timeseries_dpsim("Logs/normal.csv") normal_emt = ts.frequency_shift_list(normal_dp, 60) @@ -89,16 +108,16 @@ def do_sim(name, system): decoupled_emt = ts.frequency_shift_list(decoupled_dp, 60) for i in range(0, 6): - varname = 'BUS' + str(i+4) + '.v' - - pt.set_timeseries_labels(normal_emt[varname], varname + ' normal') - pt.set_timeseries_labels(coupled_emt[varname], varname + ' coupled') - pt.set_timeseries_labels(decoupled_emt[varname], varname + ' decoupled') - pt.plot_timeseries(i+1, normal_emt[varname]) - pt.plot_timeseries(i+1, coupled_emt[varname]) - pt.plot_timeseries(i+1, decoupled_emt[varname]) - plt.title('WSCC-09_RX with copy connected by lines (100 Ohm, 0.16 H, 1e-6 F)') - plt.xlabel('Time [s]') - plt.ylabel('Voltage [V]') + varname = "BUS" + str(i + 4) + ".v" + + pt.set_timeseries_labels(normal_emt[varname], varname + " normal") + pt.set_timeseries_labels(coupled_emt[varname], varname + " coupled") + pt.set_timeseries_labels(decoupled_emt[varname], varname + " decoupled") + pt.plot_timeseries(i + 1, normal_emt[varname]) + pt.plot_timeseries(i + 1, coupled_emt[varname]) + pt.plot_timeseries(i + 1, decoupled_emt[varname]) + plt.title("WSCC-09_RX with copy connected by lines (100 Ohm, 0.16 H, 1e-6 F)") + plt.xlabel("Time [s]") + plt.ylabel("Voltage [V]") plt.show() diff --git a/examples/Python/RuntimeMeas/decoupling_9bus_existing.py b/examples/Python/RuntimeMeas/decoupling_9bus_existing.py index 2f96356c2c..138e232c45 100644 --- a/examples/Python/RuntimeMeas/decoupling_9bus_existing.py +++ b/examples/Python/RuntimeMeas/decoupling_9bus_existing.py @@ -12,15 +12,17 @@ from villas.dataprocessing.timeseries import TimeSeries as ts import matplotlib.pyplot as plt + def decouple_line(sys, line, node1, node2): orig_line = system.component(line) sys.remove_component(line) - R_line = orig_line.attr('R_series').get() - L_line = orig_line.attr('L_series').get() - C_line = orig_line.attr('C_parallel').get() + R_line = orig_line.attr("R_series").get() + L_line = orig_line.attr("L_series").get() + C_line = orig_line.attr("C_parallel").get() - line = dpsimpy.signal.DecouplingLine('dline_' + node1 + '_' + node2, - dpsimpy.LogLevel.info) + line = dpsimpy.signal.DecouplingLine( + "dline_" + node1 + "_" + node2, dpsimpy.LogLevel.info + ) line.set_parameters(sys.node(node1), sys.node(node2), R_line, L_line, C_line) # TODO: Probably interestingn to add the line this way @@ -29,12 +31,13 @@ def decouple_line(sys, line, node1, node2): sys.add_component(line) sys.add_components(line.get_line_components()) + def do_sim(name, system): logger = dpsimpy.Logger(name) - logger.log_attribute('BUS5.V', 'v', system.node('BUS5')) - logger.log_attribute('BUS6.V', 'v', system.node('BUS6')) - logger.log_attribute('BUS8.V', 'v', system.node('BUS8')) + logger.log_attribute("BUS5.V", "v", system.node("BUS5")) + logger.log_attribute("BUS6.V", "v", system.node("BUS6")) + logger.log_attribute("BUS8.V", "v", system.node("BUS8")) sim = dpsimpy.Simulation(name, dpsimpy.LogLevel.debug) sim.set_system(system) @@ -46,22 +49,40 @@ def do_sim(name, system): sim.add_logger(logger) sim.run() -name = 'WSCC-9bus' -dpsim_root_dir = subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8') +name = "WSCC-9bus" + +dpsim_root_dir = ( + subprocess.Popen(["git", "rev-parse", "--show-toplevel"], stdout=subprocess.PIPE) + .communicate()[0] + .rstrip() + .decode("utf-8") +) -files = glob.glob(dpsim_root_dir + '/build/_deps/cim-data-src/WSCC-09/WSCC-09/*.xml') +files = glob.glob(dpsim_root_dir + "/build/_deps/cim-data-src/WSCC-09/WSCC-09/*.xml") reader_normal = dpsimpy.CIMReader(name) -system = reader_normal.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.IdealVoltageSource) -do_sim('normal', system) +system = reader_normal.loadCIM( + 60, + files, + dpsimpy.Domain.DP, + dpsimpy.PhaseType.Single, + dpsimpy.GeneratorType.IdealVoltageSource, +) +do_sim("normal", system) reader_decoupled = dpsimpy.CIMReader(name) -system = reader_decoupled.loadCIM(60, files, dpsimpy.Domain.DP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.IdealVoltageSource) -decouple_line(system, 'LINE75', 'BUS5', 'BUS7') +system = reader_decoupled.loadCIM( + 60, + files, + dpsimpy.Domain.DP, + dpsimpy.PhaseType.Single, + dpsimpy.GeneratorType.IdealVoltageSource, +) +decouple_line(system, "LINE75", "BUS5", "BUS7") # decouple_line(system, 'LINE78', 'BUS7', 'BUS8') -decouple_line(system, 'LINE64', 'BUS6', 'BUS4') -decouple_line(system, 'LINE89', 'BUS8', 'BUS9') -do_sim('decoupled', system) +decouple_line(system, "LINE64", "BUS6", "BUS4") +decouple_line(system, "LINE89", "BUS8", "BUS9") +do_sim("decoupled", system) normal_dp = rt.read_timeseries_dpsim("logs/normal.csv") normal_emt = ts.frequency_shift_list(normal_dp, 60) @@ -70,13 +91,13 @@ def do_sim(name, system): decoupled_emt = ts.frequency_shift_list(decoupled_dp, 60) for i, v in enumerate([5, 6, 8]): - varname = 'BUS' + str(v) + '.V_shift' - pt.set_timeseries_labels(normal_emt[varname], varname + ' normal') - pt.set_timeseries_labels(decoupled_emt[varname], varname + ' decoupled') - pt.plot_timeseries(i+1, normal_emt[varname]) - pt.plot_timeseries(i+1, decoupled_emt[varname]) - plt.title('WSCC-09 with 3 lines replaced by decoupling equivalents') - plt.xlabel('Time [s]') - plt.ylabel('Voltage [V]') + varname = "BUS" + str(v) + ".V_shift" + pt.set_timeseries_labels(normal_emt[varname], varname + " normal") + pt.set_timeseries_labels(decoupled_emt[varname], varname + " decoupled") + pt.plot_timeseries(i + 1, normal_emt[varname]) + pt.plot_timeseries(i + 1, decoupled_emt[varname]) + plt.title("WSCC-09 with 3 lines replaced by decoupling equivalents") + plt.xlabel("Time [s]") + plt.ylabel("Voltage [V]") plt.show() diff --git a/examples/Python/RuntimeMeas/decoupling_sched.py b/examples/Python/RuntimeMeas/decoupling_sched.py index fd5f19eb4a..fa2f3d784f 100644 --- a/examples/Python/RuntimeMeas/decoupling_sched.py +++ b/examples/Python/RuntimeMeas/decoupling_sched.py @@ -5,6 +5,7 @@ from meas_utils import * + def decoupling_sched(instance, sizes, schedulers): times = {} sigmas = {} @@ -13,42 +14,47 @@ def decoupling_sched(instance, sizes, schedulers): sigmas[scheduler] = [] for size in sizes: sched_name, args = map_scheduler(scheduler, size) - if 'in_measurement_file' in list(args.keys()): + if "in_measurement_file" in list(args.keys()): do_meas(instance, size) - time, sigma = instance.do_sim(scheduler=sched_name, scheduler_args=args, size=size) + time, sigma = instance.do_sim( + scheduler=sched_name, scheduler_args=args, size=size + ) times[scheduler].append(time) sigmas[scheduler].append(sigma) - return Measurement(instance, sizes, 'size', times, sigma=sigmas) + return Measurement(instance, sizes, "size", times, sigma=sigmas) + -if __name__ == '__main__': - name = 'decoupling_sched' +if __name__ == "__main__": + name = "decoupling_sched" if len(sys.argv) > 1: name = sys.argv[1] - instance = SimInstance(name, glob.glob('../dpsim/examples/CIM/WSCC-09_RX_Dyn/*.xml'), 60.0, 10) + instance = SimInstance( + name, glob.glob("../dpsim/examples/CIM/WSCC-09_RX_Dyn/*.xml"), 60.0, 10 + ) instance.sim_args = { - 'timestep': 0.0001, - 'duration': 0.1, - 'init_steady_state': False, - 'pbar': False, - 'split_subnets': True, - 'log_level': 0, + "timestep": 0.0001, + "duration": 0.1, + "init_steady_state": False, + "pbar": False, + "split_subnets": True, + "log_level": 0, } instance.copy_settings = { - 'decouple': True, + "decouple": True, # 'decouple': 'diakoptics', - 'nodes': ['BUS5', 'BUS6', 'BUS8'], - 'resistance': 100, - 'inductance': 0.16, - 'capacitance': 1e-6, + "nodes": ["BUS5", "BUS6", "BUS8"], + "resistance": 100, + "inductance": 0.16, + "capacitance": 1e-6, } schedulers = { - 'omp_level 8', - 'thread_level 8', - 'thread_level meas 8', - 'thread_list 8', - 'thread_list meas 8', + "omp_level 8", + "thread_level 8", + "thread_level meas 8", + "thread_list 8", + "thread_list meas 8", } sizes = range(1, 41) diff --git a/examples/Python/RuntimeMeas/diakoptics_splitsize.py b/examples/Python/RuntimeMeas/diakoptics_splitsize.py index 70b244b5d6..1cb2f1182b 100644 --- a/examples/Python/RuntimeMeas/diakoptics_splitsize.py +++ b/examples/Python/RuntimeMeas/diakoptics_splitsize.py @@ -5,6 +5,7 @@ from meas_utils import * + def diakoptics_splitsize(instance, size, splits, scheduler): times = {} sigmas = {} @@ -13,40 +14,45 @@ def diakoptics_splitsize(instance, size, splits, scheduler): sigmas[scheduler] = [] for split in splits: sched_name, args = map_scheduler(scheduler, size) - if 'in_measurement_file' in list(args.keys()): + if "in_measurement_file" in list(args.keys()): do_meas(instance, size) - instance.copy_settings['splits'] = split - time, sigma = instance.do_sim(scheduler=sched_name, scheduler_args=args, size=size) + instance.copy_settings["splits"] = split + time, sigma = instance.do_sim( + scheduler=sched_name, scheduler_args=args, size=size + ) times[scheduler].append(time) sigmas[scheduler].append(sigma) - return Measurement(instance, splits, 'splits', times, sigma=sigmas) + return Measurement(instance, splits, "splits", times, sigma=sigmas) + -if __name__ == '__main__': - name = 'diakoptics_splitsize' +if __name__ == "__main__": + name = "diakoptics_splitsize" if len(sys.argv) > 1: name = sys.argv[1] - instance = SimInstance(name, glob.glob('../dpsim/examples/CIM/WSCC-09_RX_Dyn/*.xml'), 60.0, 10) + instance = SimInstance( + name, glob.glob("../dpsim/examples/CIM/WSCC-09_RX_Dyn/*.xml"), 60.0, 10 + ) instance.sim_args = { - 'timestep': 0.0001, - 'duration': 0.1, - 'init_steady_state': False, - 'pbar': False, - 'split_subnets': True, - 'log_level': 0, + "timestep": 0.0001, + "duration": 0.1, + "init_steady_state": False, + "pbar": False, + "split_subnets": True, + "log_level": 0, } instance.copy_settings = { # 'decouple': True, - 'decouple': 'diakoptics', - 'nodes': ['BUS5', 'BUS6', 'BUS8'], - 'resistance': 100, - 'inductance': 0.16, - 'capacitance': 1e-6, + "decouple": "diakoptics", + "nodes": ["BUS5", "BUS6", "BUS8"], + "resistance": 100, + "inductance": 0.16, + "capacitance": 1e-6, } schedulers = { - 'sequential', - 'omp_level 8', + "sequential", + "omp_level 8", } size = 60 diff --git a/examples/Python/RuntimeMeas/fix_powertransformers.py b/examples/Python/RuntimeMeas/fix_powertransformers.py index cebb6727af..ea54180b5b 100644 --- a/examples/Python/RuntimeMeas/fix_powertransformers.py +++ b/examples/Python/RuntimeMeas/fix_powertransformers.py @@ -4,26 +4,32 @@ import xml.etree.ElementTree if len(sys.argv) != 3: - sys.exit('usage: fix_powertransformers.py ') + sys.exit("usage: fix_powertransformers.py ") tree = xml.etree.ElementTree.parse(sys.argv[1]) -ns = {'cim': 'http://iec.ch/TC57/2009/CIM-schema-cim14#', - 'rdf': 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'} +ns = { + "cim": "http://iec.ch/TC57/2009/CIM-schema-cim14#", + "rdf": "http://www.w3.org/1999/02/22-rdf-syntax-ns#", +} pt_ends = dict() -for pt_end in tree.iterfind('cim:PowerTransformerEnd', namespaces=ns): - pt_ends[pt_end.get('{'+ns['rdf']+'}ID')] = pt_end +for pt_end in tree.iterfind("cim:PowerTransformerEnd", namespaces=ns): + pt_ends[pt_end.get("{" + ns["rdf"] + "}ID")] = pt_end -for terminal in tree.iterfind('cim:Terminal', ns): - condeq = terminal.find('cim:Terminal.ConductingEquipment', ns) - condeq_id = condeq.get('{'+ns['rdf']+'}resource')[1:] +for terminal in tree.iterfind("cim:Terminal", ns): + condeq = terminal.find("cim:Terminal.ConductingEquipment", ns) + condeq_id = condeq.get("{" + ns["rdf"] + "}resource")[1:] if condeq_id in pt_ends: pt_end = pt_ends[condeq_id] - pt_id = pt_end.find('cim:PowerTransformerEnd.MemberOf_PowerTransformer', ns).get('{'+ns['rdf']+'}resource')[1:] - terminal_id = terminal.get('{'+ns['rdf']+'}ID') - end_term = xml.etree.ElementTree.Element('cim:TransformerEnd.Terminal', {'rdf:resource': '#' + terminal_id}) + pt_id = pt_end.find( + "cim:PowerTransformerEnd.MemberOf_PowerTransformer", ns + ).get("{" + ns["rdf"] + "}resource")[1:] + terminal_id = terminal.get("{" + ns["rdf"] + "}ID") + end_term = xml.etree.ElementTree.Element( + "cim:TransformerEnd.Terminal", {"rdf:resource": "#" + terminal_id} + ) pt_end.append(end_term) - condeq.set('{'+ns['rdf']+'}resource', '#'+pt_id) + condeq.set("{" + ns["rdf"] + "}resource", "#" + pt_id) tree.write(sys.argv[2]) diff --git a/examples/Python/RuntimeMeas/meas_utils.py b/examples/Python/RuntimeMeas/meas_utils.py index 3c18497e7f..35cc8c9619 100644 --- a/examples/Python/RuntimeMeas/meas_utils.py +++ b/examples/Python/RuntimeMeas/meas_utils.py @@ -11,42 +11,51 @@ import _dpsim import matplotlib.pyplot as plt + def multiply_decoupled(sys, num_copies, nodes, resistance, inductance, capacitance): sys.multiply(num_copies) counter = 0 for orig_node in nodes: node_names = [orig_node] - node_names += [orig_node + '_' + str(i) for i in range(2, num_copies+2)] + node_names += [orig_node + "_" + str(i) for i in range(2, num_copies + 2)] node_names.append(orig_node) - for i in range(0, num_copies+1): - sys.add_decoupling_line('dline' + str(counter), sys.nodes[node_names[i]], sys.nodes[node_names[i+1]], resistance, inductance, capacitance) + for i in range(0, num_copies + 1): + sys.add_decoupling_line( + "dline" + str(counter), + sys.nodes[node_names[i]], + sys.nodes[node_names[i + 1]], + resistance, + inductance, + capacitance, + ) counter += 1 + def multiply_coupled(sys, num_copies, nodes, resistance, inductance, capacitance): gnd = dpsim.dp.Node.GND() sys.multiply(num_copies) counter = 0 for orig_node in nodes: node_names = [orig_node] - node_names += [orig_node + '_' + str(i) for i in range(2, num_copies+2)] + node_names += [orig_node + "_" + str(i) for i in range(2, num_copies + 2)] node_names.append(orig_node) - for i in range(0, num_copies+1): + for i in range(0, num_copies + 1): # TODO lumped resistance? - rl_node = dpsim.dp.Node('N_add_' + str(counter)) - res = dpsim.dp.ph1.Resistor('R_' + str(counter)) + rl_node = dpsim.dp.Node("N_add_" + str(counter)) + res = dpsim.dp.ph1.Resistor("R_" + str(counter)) res.R = resistance - ind = dpsim.dp.ph1.Inductor('L_' + str(counter)) + ind = dpsim.dp.ph1.Inductor("L_" + str(counter)) ind.L = inductance - cap1 = dpsim.dp.ph1.Capacitor('C1_' + str(counter)) + cap1 = dpsim.dp.ph1.Capacitor("C1_" + str(counter)) cap1.C = capacitance / 2 - cap2 = dpsim.dp.ph1.Capacitor('C2_' + str(counter)) + cap2 = dpsim.dp.ph1.Capacitor("C2_" + str(counter)) cap2.C = capacitance / 2 sys.add_node(rl_node) res.connect([sys.nodes[node_names[i]], rl_node]) - ind.connect([rl_node, sys.nodes[node_names[i+1]]]) + ind.connect([rl_node, sys.nodes[node_names[i + 1]]]) cap1.connect([sys.nodes[node_names[i]], gnd]) - cap2.connect([sys.nodes[node_names[i+1]], gnd]) + cap2.connect([sys.nodes[node_names[i + 1]], gnd]) counter += 1 sys.add_component(res) @@ -54,25 +63,28 @@ def multiply_coupled(sys, num_copies, nodes, resistance, inductance, capacitance sys.add_component(cap1) sys.add_component(cap2) -def multiply_diakoptics(sys, num_copies, nodes, resistance, inductance, capacitance, splits=0): + +def multiply_diakoptics( + sys, num_copies, nodes, resistance, inductance, capacitance, splits=0 +): gnd = dpsim.dp.Node.GND() sys.multiply(num_copies) counter = 0 tear_components = [] if splits > 0: - split_every = int(num_copies+1) / splits + split_every = int(num_copies + 1) / splits else: split_every = 1 for orig_node in nodes: node_names = [orig_node] - node_names += [orig_node + '_' + str(i) for i in range(2, num_copies+2)] + node_names += [orig_node + "_" + str(i) for i in range(2, num_copies + 2)] node_names.append(orig_node) - for i in range(0, num_copies+1): - line = dpsim.dp.ph1.PiLine('line' + str(counter)) + for i in range(0, num_copies + 1): + line = dpsim.dp.ph1.PiLine("line" + str(counter)) line.R_series = resistance line.L_series = inductance line.C_parallel = capacitance - line.connect([sys.nodes[node_names[i]], sys.nodes[node_names[i+1]]]) + line.connect([sys.nodes[node_names[i]], sys.nodes[node_names[i + 1]]]) if i % split_every == 0: tear_components.append(line) else: @@ -80,32 +92,39 @@ def multiply_diakoptics(sys, num_copies, nodes, resistance, inductance, capacita counter += 1 return tear_components + def map_scheduler(sched_string, size=0): - parts = sched_string.split(' ') + parts = sched_string.split(" ") scheduler = parts[0] sched_args = {} for s in parts: if s.isdigit(): - sched_args['threads'] = int(s) - elif s == 'meas': + sched_args["threads"] = int(s) + elif s == "meas": if size: - sched_args['in_measurement_file'] = 'measurements_'+str(size)+'.txt' + sched_args["in_measurement_file"] = "measurements_" + str(size) + ".txt" else: - sched_args['in_measurement_file'] = 'measurements.txt' - elif s == 'cv': - sched_args['use_condition_variable'] = True - elif s == 'tasktype': - sched_args['sort_task_types'] = True + sched_args["in_measurement_file"] = "measurements.txt" + elif s == "cv": + sched_args["use_condition_variable"] = True + elif s == "tasktype": + sched_args["sort_task_types"] = True return (scheduler, sched_args) + def do_meas(instance, size=0): instance = copy.copy(instance) instance.repetitions = 1 if size: - filename = 'measurements_'+str(size)+'.txt' + filename = "measurements_" + str(size) + ".txt" else: - filename = 'measurements.txt' - instance.do_sim(scheduler='sequential', scheduler_args={'out_measurement_file': filename}, size=size) + filename = "measurements.txt" + instance.do_sim( + scheduler="sequential", + scheduler_args={"out_measurement_file": filename}, + size=size, + ) + def check_numa(): try: @@ -117,9 +136,10 @@ def check_numa(): if numa.get_max_node() > 0 and len(numa.get_run_on_node_mask()) > 1: print("Warning: NUMA settings may be suboptimal!", file=sys.stderr) + class SimInstance: - """ Helper class that embeds all parameters that stay constant for multiple - runs of a simulation, e.g. for a performance plot. + """Helper class that embeds all parameters that stay constant for multiple + runs of a simulation, e.g. for a performance plot. """ def __init__(self, name, files, frequency, repetitions=1): @@ -130,7 +150,7 @@ def __init__(self, name, files, frequency, repetitions=1): try: self.version = _dpsim.__version__ except: - self.version = 'unknown' + self.version = "unknown" self.hostname = socket.gethostname() self.sim_args = {} self.copy_settings = None @@ -140,31 +160,34 @@ def do_sim(self, scheduler=None, scheduler_args={}, size=1): if size > 1: # TODO a bit ugly copy_args = self.copy_settings.copy() - decouple = copy_args['decouple'] - del(copy_args['decouple']) + decouple = copy_args["decouple"] + del copy_args["decouple"] for i in range(0, self.repetitions): sys = dpsim.load_cim(self.name, self.files, self.frequency, log_level=0) if size > 1: - if decouple == 'diakoptics': - self.sim_args['tear_components'] = multiply_diakoptics(sys, size-1, **copy_args) + if decouple == "diakoptics": + self.sim_args["tear_components"] = multiply_diakoptics( + sys, size - 1, **copy_args + ) elif decouple: - multiply_decoupled(sys, size-1, **copy_args) + multiply_decoupled(sys, size - 1, **copy_args) else: - multiply_coupled(sys, size-1, **copy_args) + multiply_coupled(sys, size - 1, **copy_args) sim = dpsim.Simulation(self.name, sys, **self.sim_args) if scheduler: sim.set_scheduler(scheduler, **scheduler_args) sim.run() times.append(sim.avg_step_time) - if 'tear_components' in self.sim_args: - del(self.sim_args['tear_components']) - avg = sum(times)/len(times) - sigma = math.sqrt(sum([(x - avg)**2 for x in times]) / len(times)) + if "tear_components" in self.sim_args: + del self.sim_args["tear_components"] + avg = sum(times) / len(times) + sigma = math.sqrt(sum([(x - avg) ** 2 for x in times]) / len(times)) return (avg, sigma) + class Measurement: - """ Generalized set of measurements (usually wall clock times per timestep) - generated with the same, otherwise fixed settings. + """Generalized set of measurements (usually wall clock times per timestep) + generated with the same, otherwise fixed settings. """ def __init__(self, instance, xaxis, xlabel, data, name=None, sigma=None): @@ -183,25 +206,27 @@ def __init__(self, instance, xaxis, xlabel, data, name=None, sigma=None): @staticmethod def read_csv(filename): - with open(filename, 'r') as csvfile: + with open(filename, "r") as csvfile: reader = csv.DictReader(csvfile) xlabel = reader.fieldnames[0] data = {} sigma = {} xaxis = [] for name in reader.fieldnames[1:]: - if not name.startswith('sigma '): + if not name.startswith("sigma "): data[name] = [] sigma[name] = [] for row in reader: for k, v in row.items(): if k == xlabel: xaxis.append(int(v)) - elif k.startswith('sigma '): + elif k.startswith("sigma "): sigma[k[6:]].append(float(v)) else: data[k].append(float(v)) - return Measurement(None, xaxis, xlabel, data, filename.rstrip('.csv'), sigma) + return Measurement( + None, xaxis, xlabel, data, filename.rstrip(".csv"), sigma + ) def speedup(self, old, name): if self.xaxis != old.xaxis: @@ -214,10 +239,10 @@ def speedup(self, old, name): return Measurement(None, self.xaxis, self.xlabel, data, name=name) def write_csv(self, filename): - with open(filename, 'w') as csvfile: + with open(filename, "w") as csvfile: fieldnames = [self.xlabel] + list(self.data.keys()) if self.sigma: - fieldnames += ['sigma ' + k for k in self.data.keys()] + fieldnames += ["sigma " + k for k in self.data.keys()] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() @@ -227,17 +252,19 @@ def write_csv(self, filename): row[k] = self.data[k][i] if self.sigma: for k in self.sigma.keys(): - row['sigma ' + k] = self.sigma[k][i] + row["sigma " + k] = self.sigma[k][i] writer.writerow(row) def write_settings(self, filename): - with open(filename, 'w') as f: + with open(filename, "w") as f: json.dump(self.instance.__dict__, f, indent=4) def plot(self, filename=None, **plot_args): for key, series in self.data.items(): if self.sigma and self.sigma[key]: - plt.errorbar(self.xaxis, series, self.sigma[key], label=key, **plot_args) + plt.errorbar( + self.xaxis, series, self.sigma[key], label=key, **plot_args + ) else: plt.plot(self.xaxis, series, label=key, **plot_args) plt.xlabel(self.xlabel) @@ -247,6 +274,6 @@ def plot(self, filename=None, **plot_args): def save(self): if self.instance: - self.write_settings(self.name + '.json') - self.write_csv(self.name + '.csv') - self.plot(self.name + '.svg') + self.write_settings(self.name + ".json") + self.write_csv(self.name + ".csv") + self.plot(self.name + ".svg") diff --git a/examples/Python/RuntimeMeas/mult_split.py b/examples/Python/RuntimeMeas/mult_split.py index d28def0bb8..23d052ac68 100644 --- a/examples/Python/RuntimeMeas/mult_split.py +++ b/examples/Python/RuntimeMeas/mult_split.py @@ -10,15 +10,16 @@ from dpsim.Event import Event import matplotlib -matplotlib.use('SVG') + +matplotlib.use("SVG") import matplotlib.pyplot as plt -name = 'WSCC-9bus_RX_dyn' -files = glob.glob('../dpsim/examples/CIM/WSCC-09_RX_Dyn/*.xml') +name = "WSCC-9bus_RX_dyn" +files = glob.glob("../dpsim/examples/CIM/WSCC-09_RX_Dyn/*.xml") threads = [1, 2, 4, 8, 16] sizes = range(1, 32) -scheduler = 'thread_level' +scheduler = "thread_level" reps = 5 for size in sizes: @@ -26,9 +27,18 @@ if not os.path.isfile(filename): system = dpsim.load_cim(name, files, frequency=60) if size > 1: - system.multiply(size-1) - sim = dpsim.Simulation(name, system, timestep=0.001, duration=0.5, init_steady_state=True, pbar=False, split_subnets=True, log_level=0) - sim.set_scheduler('sequential', out_measurement_file=filename) + system.multiply(size - 1) + sim = dpsim.Simulation( + name, + system, + timestep=0.001, + duration=0.5, + init_steady_state=True, + pbar=False, + split_subnets=True, + log_level=0, + ) + sim.set_scheduler("sequential", out_measurement_file=filename) sim.run() step_times = {} @@ -39,21 +49,30 @@ for i in range(0, reps): system = dpsim.load_cim(name, files, frequency=60) if size > 1: - system.multiply(size-1) - sim = dpsim.Simulation(name, system, timestep=0.001, duration=0.5, init_steady_state=True, pbar=False, split_subnets=True, log_level=0) + system.multiply(size - 1) + sim = dpsim.Simulation( + name, + system, + timestep=0.001, + duration=0.5, + init_steady_state=True, + pbar=False, + split_subnets=True, + log_level=0, + ) filename = "measurements_" + str(size) + ".txt" sim.set_scheduler(scheduler, threads=n, in_measurement_file=filename) sim.run() rep_times.append(sim.avg_step_time) - step_times[n].append(sum(rep_times)/len(rep_times)) + step_times[n].append(sum(rep_times) / len(rep_times)) for n in threads: - plt.plot(sizes, step_times[n], label=(str(n) + ' threads')) + plt.plot(sizes, step_times[n], label=(str(n) + " threads")) -plt.xlabel('System copies (with splitting)') -plt.ylabel('Wall time per step [s]') +plt.xlabel("System copies (with splitting)") +plt.ylabel("Wall time per step [s]") hostname = socket.gethostname() -plt.title('{} (using meas), on {}, {} reps average'.format(name, hostname, reps)) +plt.title("{} (using meas), on {}, {} reps average".format(name, hostname, reps)) plt.legend() -plt.savefig('mult_split_{}.svg'.format(hostname)) +plt.savefig("mult_split_{}.svg".format(hostname)) diff --git a/examples/Python/RuntimeMeas/sched_nthreads.py b/examples/Python/RuntimeMeas/sched_nthreads.py index eb73ae0b9f..89abeece68 100644 --- a/examples/Python/RuntimeMeas/sched_nthreads.py +++ b/examples/Python/RuntimeMeas/sched_nthreads.py @@ -5,6 +5,7 @@ from meas_utils import * + def sched_nthreads(instance, threads, schedulers, size): times = {} sigmas = {} @@ -13,46 +14,51 @@ def sched_nthreads(instance, threads, schedulers, size): sigmas[scheduler] = [] for n in threads: sched_name, args = map_scheduler(scheduler, size) - if 'in_measurement_file' in list(args.keys()): + if "in_measurement_file" in list(args.keys()): do_meas(instance, size) - args['threads'] = n - avg, sigma = instance.do_sim(scheduler=sched_name, scheduler_args=args, size=size) + args["threads"] = n + avg, sigma = instance.do_sim( + scheduler=sched_name, scheduler_args=args, size=size + ) times[scheduler].append(avg) sigmas[scheduler].append(sigma) - return Measurement(instance, threads, 'threads', times, sigma=sigmas) + return Measurement(instance, threads, "threads", times, sigma=sigmas) + -if __name__ == '__main__': +if __name__ == "__main__": threads = range(1, 11) schedulers = [ - # 'sequential', - 'omp_level', - 'thread_level', - 'thread_level meas', - 'thread_list', - 'thread_list meas', + # 'sequential', + "omp_level", + "thread_level", + "thread_level meas", + "thread_list", + "thread_list meas", ] size = 1 # size = 20 - name = 'sched_nthreads' + name = "sched_nthreads" if len(sys.argv) > 1: name = sys.argv[1] - instance = SimInstance(name, glob.glob('../dpsim/examples/CIM/WSCC-09_RX_Dyn/*.xml'), 60.0, 50) + instance = SimInstance( + name, glob.glob("../dpsim/examples/CIM/WSCC-09_RX_Dyn/*.xml"), 60.0, 50 + ) instance.sim_args = { - 'timestep': 0.0001, - 'duration': 0.1, - 'init_steady_state': False, - 'pbar': False, - 'split_subnets': True, - 'log_level': 0, + "timestep": 0.0001, + "duration": 0.1, + "init_steady_state": False, + "pbar": False, + "split_subnets": True, + "log_level": 0, } instance.copy_settings = { - 'decouple': False, - 'nodes': ['BUS5', 'BUS6', 'BUS8'], - 'resistance': 100, - 'inductance': 0.16, - 'capacitance': 1e-6, + "decouple": False, + "nodes": ["BUS5", "BUS6", "BUS8"], + "resistance": 100, + "inductance": 0.16, + "capacitance": 1e-6, } meas = sched_nthreads(instance, threads, schedulers, size) diff --git a/examples/conftest.py b/examples/conftest.py index d6337b59f9..3b3b2f2332 100644 --- a/examples/conftest.py +++ b/examples/conftest.py @@ -2,23 +2,26 @@ import subprocess import pytest + def pytest_collect_file(parent, path): - if path.ext == ".yml" and path.basename.startswith("test_") and os.name == 'posix': + if path.ext == ".yml" and path.basename.startswith("test_") and os.name == "posix": return YamlFile.from_parent(parent, fspath=path) - if path.ext == '.ipynb': + if path.ext == ".ipynb": return JupyterNotebook.from_parent(parent, fspath=path) + def parse_test_params(item, spec): - if 'skip' in spec and spec['skip']: + if "skip" in spec and spec["skip"]: item.add_marker(pytest.mark.skip) - if 'xfail' in spec and spec['xfail']: + if "xfail" in spec and spec["xfail"]: item.add_marker(pytest.mark.xfail) + class YamlFile(pytest.File): def collect(self): - # We need a yaml parser, e.g. PyYAML import yaml + raw = yaml.safe_load(self.fspath.open()) if not raw: @@ -27,49 +30,51 @@ def collect(self): for name, spec in sorted(raw.items()): yield YamlItem.from_parent(self, name=name, spec=spec) + class YamlItem(pytest.Item): def __init__(self, name, parent, spec): super().__init__(name, parent) self.spec = spec - if 'args' in spec: - self.args = spec['args'] + if "args" in spec: + self.args = spec["args"] else: - self.args = [ ] + self.args = [] - if 'shell' in spec: - self.shell = spec['shell'] + if "shell" in spec: + self.shell = spec["shell"] else: self.shell = False - if 'check' in spec: - self.check = spec['check'] + if "check" in spec: + self.check = spec["check"] else: self.check = True - if 'timeout' in spec: - self.timeout = spec['timeout'] + if "timeout" in spec: + self.timeout = spec["timeout"] else: self.timeout = 60 - if 'cwd' in spec: - self.cwd = spec['cwd'] + if "cwd" in spec: + self.cwd = spec["cwd"] else: - self.cwd = os.path.realpath(os.path.dirname(__file__) + '/..') + self.cwd = os.path.realpath(os.path.dirname(__file__) + "/..") parse_test_params(self, spec) - if 'cmd' in spec: - self.cmd = spec['cmd'] + if "cmd" in spec: + self.cmd = spec["cmd"] else: raise AttributeError('Test is missing mandatory "cmd" attribute') def runtest(self): - cp = subprocess.run([self.cmd] + self.args, - cwd = self.cwd, - shell = self.shell, - timeout = self.timeout, - check = True + cp = subprocess.run( + [self.cmd] + self.args, + cwd=self.cwd, + shell=self.shell, + timeout=self.timeout, + check=True, ) def repr_failure(self, excinfo): @@ -90,12 +95,12 @@ def collect(self): base = os.path.basename(self.name) name = os.path.splitext(base)[0] - spec = nb.metadata['tests'] if 'tests' in nb.metadata else {} + spec = nb.metadata["tests"] if "tests" in nb.metadata else {} yield JupyterNotebookExport.from_parent(self, name=name, spec=spec, nb=nb) -class JupyterNotebookExport(pytest.Item): +class JupyterNotebookExport(pytest.Item): def __init__(self, name, parent, spec, nb): super().__init__(name, parent) self.builddir = os.path.splitext(parent.name)[0] @@ -105,19 +110,20 @@ def __init__(self, name, parent, spec, nb): def runtest(self): from traitlets.config import Config + # from nbconvert import HTMLExporter from nbconvert import MarkdownExporter from nbconvert.writers import FilesWriter c = Config() - c.FilesWriter.build_directory = 'outputs/' + self.builddir + c.FilesWriter.build_directory = "outputs/" + self.builddir # c.HTMLExporter.preprocessors = [ # 'nbconvert.preprocessors.ExecutePreprocessor', # 'nbconvert.preprocessors.ExtractOutputPreprocessor' # ] c.MarkdownExporter.preprocessors = [ - 'nbconvert.preprocessors.ExecutePreprocessor', - 'nbconvert.preprocessors.ExtractOutputPreprocessor' + "nbconvert.preprocessors.ExecutePreprocessor", + "nbconvert.preprocessors.ExtractOutputPreprocessor", ] # exporter = HTMLExporter(config=c) exporter = MarkdownExporter(config=c) diff --git a/examples/villas-deprecated/ShmemDistributedDirect.ipynb b/examples/villas-deprecated/ShmemDistributedDirect.ipynb index 7ae0ee4df0..950c8d5cea 100644 --- a/examples/villas-deprecated/ShmemDistributedDirect.ipynb +++ b/examples/villas-deprecated/ShmemDistributedDirect.ipynb @@ -41,7 +41,7 @@ "metadata": {}, "outputs": [], "source": [ - "log_name = '../../../logs/ShmemDistributedRef/ShmemDistributedRef.csv'\n", + "log_name = \"../../../logs/ShmemDistributedRef/ShmemDistributedRef.csv\"\n", "ts_ref = rt.read_timeseries_dpsim(log_name)" ] }, @@ -53,9 +53,9 @@ "source": [ "import matplotlib.pyplot as plt\n", "\n", - "plt.plot(ts_ref['v1'].values.real)\n", - "plt.plot(ts_ref['v2'].values.real)\n", - "plt.plot(ts_ref['r12'].values.real)" + "plt.plot(ts_ref[\"v1\"].values.real)\n", + "plt.plot(ts_ref[\"v2\"].values.real)\n", + "plt.plot(ts_ref[\"r12\"].values.real)" ] }, { @@ -87,7 +87,7 @@ "metadata": {}, "outputs": [], "source": [ - "log_name = '../../../logs/ShmemDistributedDirect_1/ShmemDistributedDirect_1.csv'\n", + "log_name = \"../../../logs/ShmemDistributedDirect_1/ShmemDistributedDirect_1.csv\"\n", "ts_direct1 = rt.read_timeseries_dpsim(log_name)" ] }, @@ -97,7 +97,7 @@ "metadata": {}, "outputs": [], "source": [ - "log_name = '../../../logs/ShmemDistributedDirect_2/ShmemDistributedDirect_2.csv'\n", + "log_name = \"../../../logs/ShmemDistributedDirect_2/ShmemDistributedDirect_2.csv\"\n", "ts_direct2 = rt.read_timeseries_dpsim(log_name)" ] }, @@ -107,10 +107,10 @@ "metadata": {}, "outputs": [], "source": [ - "plt.plot(ts_direct1['v1'].values.real)\n", - "plt.plot(ts_direct1['v2'].values.real)\n", - "plt.plot(ts_direct2['v2'].values.real)\n", - "plt.plot(ts_direct1['r12'].values.real)" + "plt.plot(ts_direct1[\"v1\"].values.real)\n", + "plt.plot(ts_direct1[\"v2\"].values.real)\n", + "plt.plot(ts_direct2[\"v2\"].values.real)\n", + "plt.plot(ts_direct1[\"r12\"].values.real)" ] }, { diff --git a/examples/villas-deprecated/ShmemExample.ipynb b/examples/villas-deprecated/ShmemExample.ipynb index a142bbe410..e30c7cbcd2 100644 --- a/examples/villas-deprecated/ShmemExample.ipynb +++ b/examples/villas-deprecated/ShmemExample.ipynb @@ -35,7 +35,7 @@ "metadata": {}, "outputs": [], "source": [ - "filename = '../../../logs/Shmem_Example/villas-pipe-out.log'\n", + "filename = \"../../../logs/Shmem_Example/villas-pipe-out.log\"\n", "ts = rt.read_timeseries_villas(filename)" ] }, diff --git a/examples/villas-deprecated/cigre-mv-pf-profiles-shmem.ipynb b/examples/villas-deprecated/cigre-mv-pf-profiles-shmem.ipynb index 715a70e7a4..de55ecf74b 100644 --- a/examples/villas-deprecated/cigre-mv-pf-profiles-shmem.ipynb +++ b/examples/villas-deprecated/cigre-mv-pf-profiles-shmem.ipynb @@ -23,18 +23,20 @@ "import requests\n", "import glob\n", "\n", + "\n", "def download_grid_data(name, url):\n", - " with open(name, 'wb') as out_file:\n", + " with open(name, \"wb\") as out_file:\n", " content = requests.get(url, stream=True).content\n", " out_file.write(content)\n", "\n", - "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/Rootnet_FULL_NE_06J16h'\n", - "filename = 'CIGRE-MV'\n", - "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", - "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", - "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", "\n", - "files = glob.glob(filename+'_*.xml')\n", + "url = \"https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/Rootnet_FULL_NE_06J16h\"\n", + "filename = \"CIGRE-MV\"\n", + "download_grid_data(filename + \"_EQ.xml\", url + \"_EQ.xml\")\n", + "download_grid_data(filename + \"_TP.xml\", url + \"_TP.xml\")\n", + "download_grid_data(filename + \"_SV.xml\", url + \"_SV.xml\")\n", + "\n", + "files = glob.glob(filename + \"_*.xml\")\n", "print(files)" ] }, @@ -46,13 +48,37 @@ "source": [ "import os\n", "\n", - "profiles = ['Load_H_1','Load_H_3','Load_H_4','Load_H_5','Load_H_6','Load_H_8','Load_H_10','Load_H_11','Load_H_12','Load_H_14','Load_I_1','Load_I_3','Load_I_7','Load_I_9','Load_I_10','Load_I_12','Load_I_13','Load_I_14']\n", + "profiles = [\n", + " \"Load_H_1\",\n", + " \"Load_H_3\",\n", + " \"Load_H_4\",\n", + " \"Load_H_5\",\n", + " \"Load_H_6\",\n", + " \"Load_H_8\",\n", + " \"Load_H_10\",\n", + " \"Load_H_11\",\n", + " \"Load_H_12\",\n", + " \"Load_H_14\",\n", + " \"Load_I_1\",\n", + " \"Load_I_3\",\n", + " \"Load_I_7\",\n", + " \"Load_I_9\",\n", + " \"Load_I_10\",\n", + " \"Load_I_12\",\n", + " \"Load_I_13\",\n", + " \"Load_I_14\",\n", + "]\n", "for profile in profiles:\n", - " filename = './profiles/'+profile+'.csv'\n", + " filename = \"./profiles/\" + profile + \".csv\"\n", " os.makedirs(os.path.dirname(filename), exist_ok=True)\n", - " download_grid_data(filename, 'https://raw.githubusercontent.com/dpsim-simulator/example-profile-data/master/CIGRE_MV_NoTap/load_profiles/'+profile+'.csv')\n", - " \n", - "profile_files = glob.glob('profiles/Load*.csv')\n" + " download_grid_data(\n", + " filename,\n", + " \"https://raw.githubusercontent.com/dpsim-simulator/example-profile-data/master/CIGRE_MV_NoTap/load_profiles/\"\n", + " + profile\n", + " + \".csv\",\n", + " )\n", + "\n", + "profile_files = glob.glob(\"profiles/Load*.csv\")" ] }, { @@ -63,7 +89,7 @@ "source": [ "import pathlib\n", "\n", - "profile_path = str(pathlib.Path().resolve())+'/profiles/'\n", + "profile_path = str(pathlib.Path().resolve()) + \"/profiles/\"\n", "print(profile_path)" ] }, @@ -83,9 +109,11 @@ "metadata": {}, "outputs": [], "source": [ - "name = 'CIGRE-MV-Profiles'\n", + "name = \"CIGRE-MV-Profiles\"\n", "reader = dpsimpy.CIMReader(name)\n", - "system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode)" + "system = reader.loadCIM(\n", + " 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode\n", + ")" ] }, { @@ -94,25 +122,25 @@ "metadata": {}, "outputs": [], "source": [ - "assignList = { }\n", - "assignList['LOAD-H-1'] = 'Load_H_1'\n", - "assignList['LOAD-H-3'] = 'Load_H_3'\n", - "assignList['LOAD-H-4'] = 'Load_H_4'\n", - "assignList['LOAD-H-5'] = 'Load_H_5'\n", - "assignList['LOAD-H-6'] = 'Load_H_6'\n", - "assignList['LOAD-H-8'] = 'Load_H_8'\n", - "assignList['LOAD-H-10'] = 'Load_H_10'\n", - "assignList['LOAD-H-11'] = 'Load_H_11'\n", - "assignList['LOAD-H-12'] = 'Load_H_12'\n", - "assignList['LOAD-H-14'] = 'Load_H_14'\n", - "assignList['LOAD-I-1'] = 'Load_I_1'\n", - "assignList['LOAD-I-3'] = 'Load_I_3'\n", - "assignList['LOAD-I-7'] = 'Load_I_7'\n", - "assignList['LOAD-I-9'] = 'Load_I_9'\n", - "assignList['LOAD-I-10'] = 'Load_I_10'\n", - "assignList['LOAD-I-12'] = 'Load_I_12'\n", - "assignList['LOAD-I-13'] = 'Load_I_13'\n", - "assignList['LOAD-I-14'] = 'Load_I_14'" + "assignList = {}\n", + "assignList[\"LOAD-H-1\"] = \"Load_H_1\"\n", + "assignList[\"LOAD-H-3\"] = \"Load_H_3\"\n", + "assignList[\"LOAD-H-4\"] = \"Load_H_4\"\n", + "assignList[\"LOAD-H-5\"] = \"Load_H_5\"\n", + "assignList[\"LOAD-H-6\"] = \"Load_H_6\"\n", + "assignList[\"LOAD-H-8\"] = \"Load_H_8\"\n", + "assignList[\"LOAD-H-10\"] = \"Load_H_10\"\n", + "assignList[\"LOAD-H-11\"] = \"Load_H_11\"\n", + "assignList[\"LOAD-H-12\"] = \"Load_H_12\"\n", + "assignList[\"LOAD-H-14\"] = \"Load_H_14\"\n", + "assignList[\"LOAD-I-1\"] = \"Load_I_1\"\n", + "assignList[\"LOAD-I-3\"] = \"Load_I_3\"\n", + "assignList[\"LOAD-I-7\"] = \"Load_I_7\"\n", + "assignList[\"LOAD-I-9\"] = \"Load_I_9\"\n", + "assignList[\"LOAD-I-10\"] = \"Load_I_10\"\n", + "assignList[\"LOAD-I-12\"] = \"Load_I_12\"\n", + "assignList[\"LOAD-I-13\"] = \"Load_I_13\"\n", + "assignList[\"LOAD-I-14\"] = \"Load_I_14\"" ] }, { @@ -122,7 +150,9 @@ "outputs": [], "source": [ "csvreader = dpsimpy.CSVReader(name, profile_path, assignList, dpsimpy.LogLevel.info)\n", - "csvreader.assignLoadProfile(system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS)" + "csvreader.assignLoadProfile(\n", + " system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS\n", + ")" ] }, { @@ -161,7 +191,7 @@ "outputs": [], "source": [ "obj_list = system.list_idobjects()\n", - "node_list = {k: v for k, v in obj_list.items() if v == 'SimNode >'}\n", + "node_list = {k: v for k, v in obj_list.items() if v == \"SimNode >\"}\n", "node_list" ] }, @@ -172,8 +202,13 @@ "outputs": [], "source": [ "for i in range(14):\n", - " sim.export_attribute(sim.get_idobj_attr('N'+str(i), 'v').derive_coeff(0,0).derive_mag(), 2*i)\n", - " sim.export_attribute(sim.get_idobj_attr('N'+str(i), 'v').derive_coeff(0,0).derive_phase(), 2*i+1)" + " sim.export_attribute(\n", + " sim.get_idobj_attr(\"N\" + str(i), \"v\").derive_coeff(0, 0).derive_mag(), 2 * i\n", + " )\n", + " sim.export_attribute(\n", + " sim.get_idobj_attr(\"N\" + str(i), \"v\").derive_coeff(0, 0).derive_phase(),\n", + " 2 * i + 1,\n", + " )" ] }, { @@ -183,7 +218,7 @@ "outputs": [], "source": [ "for node in system.nodes:\n", - " logger.log_attribute(node.name()+'.V', 'v', node)" + " logger.log_attribute(node.name() + \".V\", \"v\", node)" ] }, { diff --git a/examples/villas-deprecated/shmem-distributed-villas.py b/examples/villas-deprecated/shmem-distributed-villas.py index 5cee187cda..bcef5ec615 100644 --- a/examples/villas-deprecated/shmem-distributed-villas.py +++ b/examples/villas-deprecated/shmem-distributed-villas.py @@ -10,8 +10,8 @@ import villas.dataprocessing.readtools as rt import villas.dataprocessing.plottools as pt -def villas(): +def villas(): villas_conf = """ hugepages = 100 @@ -60,7 +60,7 @@ def villas(): with open("villas-node.conf", "w") as text_file: text_file.write("%s" % villas_conf) - os.system('villas-node villas-node.conf') + os.system("villas-node villas-node.conf") def dpsim0(): @@ -68,16 +68,16 @@ def dpsim0(): time_step = 0.001 final_time = 10 - n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [10]) - n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) + n1 = dpsimpy.dp.SimNode("n1", dpsimpy.PhaseType.Single, [10]) + n2 = dpsimpy.dp.SimNode("n2", dpsimpy.PhaseType.Single, [5]) - evs = dpsimpy.dp.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.debug) + evs = dpsimpy.dp.ph1.VoltageSource("v_intf", dpsimpy.LogLevel.debug) evs.set_parameters(complex(5, 0)) - vs1 = dpsimpy.dp.ph1.VoltageSource('vs_1', dpsimpy.LogLevel.debug) + vs1 = dpsimpy.dp.ph1.VoltageSource("vs_1", dpsimpy.LogLevel.debug) vs1.set_parameters(complex(10, 0)) - r12 = dpsimpy.dp.ph1.Resistor('r_12', dpsimpy.LogLevel.debug) + r12 = dpsimpy.dp.ph1.Resistor("r_12", dpsimpy.LogLevel.debug) r12.set_parameters(1) evs.connect([dpsimpy.dp.SimNode.gnd, n2]) @@ -86,24 +86,24 @@ def dpsim0(): sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, vs1, r12]) - dpsimpy.Logger.set_log_dir('logs/' + sim_name) + dpsimpy.Logger.set_log_dir("logs/" + sim_name) logger = dpsimpy.Logger(sim_name) - logger.log_attribute('v1', 'v', n1) - logger.log_attribute('v2', 'v', n2) - logger.log_attribute('r12', 'i_intf', r12) - logger.log_attribute('ievs', 'i_intf', evs) - logger.log_attribute('vevs', 'v_intf', evs) + logger.log_attribute("v1", "v", n1) + logger.log_attribute("v2", "v", n2) + logger.log_attribute("r12", "i_intf", r12) + logger.log_attribute("ievs", "i_intf", evs) + logger.log_attribute("vevs", "v_intf", evs) sim = dpsimpy.RealTimeSimulation(sim_name) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) - intf = dpsimpyvillas.InterfaceShmem('/dpsim0-out', '/dpsim0-in') + intf = dpsimpyvillas.InterfaceShmem("/dpsim0-out", "/dpsim0-in") - sim.import_attribute(evs.attr('V_ref'), 0) - sim.export_attribute(evs.attr('i_intf').derive_coeff(0, 0), 0) + sim.import_attribute(evs.attr("V_ref"), 0) + sim.export_attribute(evs.attr("i_intf").derive_coeff(0, 0), 0) sim.add_interface(intf, True) sim.add_logger(logger) @@ -112,16 +112,17 @@ def dpsim0(): sim.run(1) + def dpsim1(): sim_name = "ShmemDistributed1" time_step = 0.001 final_time = 10 - n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) + n2 = dpsimpy.dp.SimNode("n2", dpsimpy.PhaseType.Single, [5]) - ecs = dpsimpy.dp.ph1.CurrentSource('i_intf', dpsimpy.LogLevel.debug) + ecs = dpsimpy.dp.ph1.CurrentSource("i_intf", dpsimpy.LogLevel.debug) ecs.set_parameters(complex(5, 0)) - r02 = dpsimpy.dp.ph1.Resistor('r_02', dpsimpy.LogLevel.debug) + r02 = dpsimpy.dp.ph1.Resistor("r_02", dpsimpy.LogLevel.debug) r02.set_parameters(1) ecs.connect([dpsimpy.dp.SimNode.gnd, n2]) @@ -129,22 +130,24 @@ def dpsim1(): sys = dpsimpy.SystemTopology(50, [n2], [ecs, r02]) - dpsimpy.Logger.set_log_dir('logs/' + sim_name) + dpsimpy.Logger.set_log_dir("logs/" + sim_name) logger = dpsimpy.Logger(sim_name) - logger.log_attribute('v2', 'v', n2) - logger.log_attribute('r02', 'i_intf', r02) - logger.log_attribute('vecs', 'v_intf', ecs) - logger.log_attribute('iecs', 'i_intf', ecs) + logger.log_attribute("v2", "v", n2) + logger.log_attribute("r02", "i_intf", r02) + logger.log_attribute("vecs", "v_intf", ecs) + logger.log_attribute("iecs", "i_intf", ecs) sim = dpsimpy.RealTimeSimulation(sim_name) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) - intf = dpsimpyvillas.InterfaceShmem('/dpsim1-out', '/dpsim1-in') + intf = dpsimpyvillas.InterfaceShmem("/dpsim1-out", "/dpsim1-in") - sim.import_attribute(ecs.attr('I_ref'), 0) - sim.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0) + sim.import_attribute(ecs.attr("I_ref"), 0) + sim.export_attribute( + ecs.attr("v_intf").derive_coeff(0, 0).derive_scaled(complex(-1, 0)), 0 + ) sim.add_interface(intf) sim.add_logger(logger) @@ -152,7 +155,7 @@ def dpsim1(): sim.run(1) -if __name__ == '__main__': +if __name__ == "__main__": queue = Queue() p_villas = Process(target=villas) p_dpsim0 = Process(target=dpsim0) @@ -165,6 +168,6 @@ def dpsim1(): p_dpsim0.join() p_dpsim1.join() - print('Both simulations have ended!') + print("Both simulations have ended!") p_villas.join() diff --git a/examples/villas-deprecated/test_shmem_cigre_mv_pf_profiles.py b/examples/villas-deprecated/test_shmem_cigre_mv_pf_profiles.py index e28b372aa4..e4681665bd 100644 --- a/examples/villas-deprecated/test_shmem_cigre_mv_pf_profiles.py +++ b/examples/villas-deprecated/test_shmem_cigre_mv_pf_profiles.py @@ -24,97 +24,87 @@ base = os.path.splitext(os.path.basename(sys.argv[0]))[0] log = logging.getLogger(base) -def villas(intf, mqtt=False): - log_filename=datetime.now().strftime(f'{base}-villas-%y-%m-%d_%H_%M_%S.log') +def villas(intf, mqtt=False): + log_filename = datetime.now().strftime(f"{base}-villas-%y-%m-%d_%H_%M_%S.log") nodes = { - 'dpsim1': intf.get_config(), - 'file1': { - 'type': 'file', - - 'uri': f'{base}-results-%y-%m-%d_%H_%M_%S.csv' - } + "dpsim1": intf.get_config(), + "file1": {"type": "file", "uri": f"{base}-results-%y-%m-%d_%H_%M_%S.csv"}, } - paths = [ - { - 'in': 'dpsim1', - 'out': 'file1' - } - ] + paths = [{"in": "dpsim1", "out": "file1"}] - config = { - 'nodes': nodes, - 'paths': paths - } + config = {"nodes": nodes, "paths": paths} if mqtt: - nodes['broker1'] = { - 'type': 'mqtt', - - 'format': 'json', - 'host': '172.17.0.1', - - 'in': { - 'subscribe': '/powerflow-dpsim' - }, - 'out': { - 'publish': '/dpsim-powerflow' - } + nodes["broker1"] = { + "type": "mqtt", + "format": "json", + "host": "172.17.0.1", + "in": {"subscribe": "/powerflow-dpsim"}, + "out": {"publish": "/dpsim-powerflow"}, } - paths.append({ - 'in': 'dpsim1', - 'out': 'broker1', + paths.append( + { + "in": "dpsim1", + "out": "broker1", + "hooks": [{"type": "limit_rate", "rate": 50}], + } + ) - 'hooks': [ - { - 'type': 'limit_rate', - 'rate': 50 - } - ] - }) + log.info("VILLASnode config: \n%s", json.dumps(config, indent=2)) - log.info('VILLASnode config: \n%s', json.dumps(config, indent=2)) + return VILLASnode(config=config, log_filename=log_filename) - return VILLASnode(config=config, - log_filename=log_filename) def dpsim(): - name = 'CIGRE-MV-Profiles' - files = glob.glob('build/_deps/cim-data-src/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/*.xml') - log.info('CIM files: %s', files) + name = "CIGRE-MV-Profiles" + files = glob.glob( + "build/_deps/cim-data-src/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/*.xml" + ) + log.info("CIM files: %s", files) reader = dpsimpy.CIMReader(name) - system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode) - - csv_files = glob.glob('build/_deps/profile-data-src/CIGRE_MV_NoTap/load_profiles/')[0] - log.info('CSV files: %s', csv_files) + system = reader.loadCIM( + 50, + files, + dpsimpy.Domain.SP, + dpsimpy.PhaseType.Single, + dpsimpy.GeneratorType.PVNode, + ) + + csv_files = glob.glob("build/_deps/profile-data-src/CIGRE_MV_NoTap/load_profiles/")[ + 0 + ] + log.info("CSV files: %s", csv_files) assignList = { - 'LOAD-H-1': 'Load_H_1', - 'LOAD-H-3': 'Load_H_3', - 'LOAD-H-4': 'Load_H_4', - 'LOAD-H-5': 'Load_H_5', - 'LOAD-H-6': 'Load_H_6', - 'LOAD-H-8': 'Load_H_8', - 'LOAD-H-10': 'Load_H_10', - 'LOAD-H-11': 'Load_H_11', - 'LOAD-H-12': 'Load_H_12', - 'LOAD-H-14': 'Load_H_14', - 'LOAD-I-1': 'Load_I_1', - 'LOAD-I-3': 'Load_I_3', - 'LOAD-I-7': 'Load_I_7', - 'LOAD-I-9': 'Load_I_9', - 'LOAD-I-10': 'Load_I_10', - 'LOAD-I-12': 'Load_I_12', - 'LOAD-I-13': 'Load_I_13', - 'LOAD-I-14': 'Load_I_14' + "LOAD-H-1": "Load_H_1", + "LOAD-H-3": "Load_H_3", + "LOAD-H-4": "Load_H_4", + "LOAD-H-5": "Load_H_5", + "LOAD-H-6": "Load_H_6", + "LOAD-H-8": "Load_H_8", + "LOAD-H-10": "Load_H_10", + "LOAD-H-11": "Load_H_11", + "LOAD-H-12": "Load_H_12", + "LOAD-H-14": "Load_H_14", + "LOAD-I-1": "Load_I_1", + "LOAD-I-3": "Load_I_3", + "LOAD-I-7": "Load_I_7", + "LOAD-I-9": "Load_I_9", + "LOAD-I-10": "Load_I_10", + "LOAD-I-12": "Load_I_12", + "LOAD-I-13": "Load_I_13", + "LOAD-I-14": "Load_I_14", } csvreader = dpsimpy.CSVReader(name, csv_files, assignList, dpsimpy.LogLevel.info) - csvreader.assignLoadProfile(system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS) + csvreader.assignLoadProfile( + system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS + ) sim = dpsimpy.RealTimeSimulation(name) sim.set_system(system) @@ -130,25 +120,33 @@ def dpsim(): sim.add_interface(intf) obj_list = system.list_idobjects() - node_list = {k: v for k, v in obj_list.items() if v == 'SimNode >'} - log.info('Node list: %s', node_list) + node_list = { + k: v for k, v in obj_list.items() if v == "SimNode >" + } + log.info("Node list: %s", node_list) for i in range(15): - objname = 'N'+str(i) - sim.export_attribute(sim.get_idobj_attr(objname, 'v') - .derive_coeff(0,0) - .derive_mag(), (i*2)) - sim.export_attribute(sim.get_idobj_attr(objname, 'v') - .derive_coeff(0,0) - .derive_phase(), (i*2)+1) + objname = "N" + str(i) + sim.export_attribute( + sim.get_idobj_attr(objname, "v").derive_coeff(0, 0).derive_mag(), (i * 2) + ) + sim.export_attribute( + sim.get_idobj_attr(objname, "v").derive_coeff(0, 0).derive_phase(), + (i * 2) + 1, + ) for node in system.nodes: - logger.log_attribute(node.name()+'.V', 'v', node) + logger.log_attribute(node.name() + ".V", "v", node) return sim, intf + def test_shmem_cigre_mv_pf_profiles(): - logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.INFO) + logging.basicConfig( + format="[%(asctime)s %(name)s %(levelname)s] %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO, + ) sim, intf = dpsim() node = villas(intf, mqtt=False) @@ -159,5 +157,6 @@ def test_shmem_cigre_mv_pf_profiles(): node.stop() -if __name__ == '__main__': + +if __name__ == "__main__": test_shmem_cigre_mv_pf_profiles() diff --git a/examples/villas-deprecated/test_shmem_distributed_direct.py b/examples/villas-deprecated/test_shmem_distributed_direct.py index d6e1d303f5..8568474bc4 100644 --- a/examples/villas-deprecated/test_shmem_distributed_direct.py +++ b/examples/villas-deprecated/test_shmem_distributed_direct.py @@ -2,51 +2,54 @@ import threading import dpsim + class Left(threading.Thread): def run(self): # Nodes gnd = dpsim.dp.Node.GND() - n1 = dpsim.dp.Node('n1') - n2 = dpsim.dp.Node('n2') + n1 = dpsim.dp.Node("n1") + n2 = dpsim.dp.Node("n2") - vs = dpsim.dp.ph1.VoltageSourceNorton('v_s', [n1, gnd], 10000+0j, 1) - evs = dpsim.dp.ph1.VoltageSource('v_ext', [n2, gnd], 0+0j) - l1 = dpsim.dp.ph1.Inductor('l_1', [n1, n2], 1e-3) + vs = dpsim.dp.ph1.VoltageSourceNorton("v_s", [n1, gnd], 10000 + 0j, 1) + evs = dpsim.dp.ph1.VoltageSource("v_ext", [n2, gnd], 0 + 0j) + l1 = dpsim.dp.ph1.Inductor("l_1", [n1, n2], 1e-3) - intf = dpsim.open_interface('/dpsim12', '/dpsim21', samplelen = 2) - intf.import_attribute(evs.attr('V_ref').derive_coeff(1, 0), 1) - intf.export_attribute(evs.attr('i_intf').derive_coeff(1, 0), 1) + intf = dpsim.open_interface("/dpsim12", "/dpsim21", samplelen=2) + intf.import_attribute(evs.attr("V_ref").derive_coeff(1, 0), 1) + intf.export_attribute(evs.attr("i_intf").derive_coeff(1, 0), 1) sys = dpsim.SystemTopology(50, [gnd, n1, n2], [evs, vs, l1]) - sim = dpsim.Simulation('shmem1', sys, duration = 1) + sim = dpsim.Simulation("shmem1", sys, duration=1) sim.add_interface(intf) - print('Starting simulation on left side') + print("Starting simulation on left side") sim.run() + class Right(threading.Thread): def run(self): # Nodes gnd = dpsim.dp.Node.GND() - n3 = dpsim.dp.Node('n3') + n3 = dpsim.dp.Node("n3") # Components - ecs = dpsim.dp.ph1.CurrentSource('i_ext', [n3, gnd], 0+0j) - r1 = dpsim.dp.ph1.Resistor('r_1', [n3, gnd], 1) + ecs = dpsim.dp.ph1.CurrentSource("i_ext", [n3, gnd], 0 + 0j) + r1 = dpsim.dp.ph1.Resistor("r_1", [n3, gnd], 1) - intf = dpsim.open_interface('/dpsim21', '/dpsim12', samplelen = 2) - intf.import_attribute(ecs.attr('I_ref').derive_coeff(1, 0), 1) - intf.export_attribute(r1.attr('v_intf').derive_coeff(1, 0), 1) + intf = dpsim.open_interface("/dpsim21", "/dpsim12", samplelen=2) + intf.import_attribute(ecs.attr("I_ref").derive_coeff(1, 0), 1) + intf.export_attribute(r1.attr("v_intf").derive_coeff(1, 0), 1) sys = dpsim.SystemTopology(50, [gnd, n3], [ecs, r1]) - sim = dpsim.Simulation('shmem2', sys, duration = 1) + sim = dpsim.Simulation("shmem2", sys, duration=1) sim.add_interface(intf) - print('Starting simulation on right side') + print("Starting simulation on right side") sim.run() + def test_ShmemDistributedDirect(): left_thread = Left() right_thread = Right() @@ -57,5 +60,6 @@ def test_ShmemDistributedDirect(): left_thread.join() right_thread.join() -if __name__ == '__main__': + +if __name__ == "__main__": test_ShmemDistributedDirect() diff --git a/examples/villas-deprecated/test_shmem_import_export.py b/examples/villas-deprecated/test_shmem_import_export.py index 9910be1628..d5597b32a5 100644 --- a/examples/villas-deprecated/test_shmem_import_export.py +++ b/examples/villas-deprecated/test_shmem_import_export.py @@ -15,48 +15,36 @@ base = os.path.splitext(os.path.basename(sys.argv[0]))[0] log = logging.getLogger(base) -def villas(intf): - log_filename=datetime.now().strftime(f'{base}-villas-%y-%m-%d_%H_%M_%S.log') +def villas(intf): + log_filename = datetime.now().strftime(f"{base}-villas-%y-%m-%d_%H_%M_%S.log") nodes = { - 'dpsim1': intf.get_config(), - 'file1': { - 'type': 'file', - 'uri': f'{base}-results-%y-%m-%d_%H_%M_%S.csv' - }, - 'sine' : { - 'type': 'signal', - 'signal': 'sine', - 'rate': 1, - 'frequency': 0.1, - 'amplitude': 50000, - 'offset': 100000 + "dpsim1": intf.get_config(), + "file1": {"type": "file", "uri": f"{base}-results-%y-%m-%d_%H_%M_%S.csv"}, + "sine": { + "type": "signal", + "signal": "sine", + "rate": 1, + "frequency": 0.1, + "amplitude": 50000, + "offset": 100000, }, } paths = [ - { - 'in': 'dpsim1', - 'out': 'file1' - }, - { - 'in': 'sine', - 'out': 'dpsim1', - 'hooks': [{'type':'print'}] - } + {"in": "dpsim1", "out": "file1"}, + {"in": "sine", "out": "dpsim1", "hooks": [{"type": "print"}]}, ] - config = { - 'nodes': nodes, - 'paths': paths - } - config['nodes']['dpsim1']['out']['hooks'] = [{'type':'print'}] + config = {"nodes": nodes, "paths": paths} + config["nodes"]["dpsim1"]["out"]["hooks"] = [{"type": "print"}] - log.info('VILLASnode config: \n%s', json.dumps(config, indent=2)) + log.info("VILLASnode config: \n%s", json.dumps(config, indent=2)) return VILLASnode(config=config, log_filename=log_filename) + def dpsim(): # Parameters V_nom = 20e3 @@ -65,23 +53,25 @@ def dpsim(): line_resistance = 0.05 line_inductance = 0.1 line_capacitance = 0.1e-6 - name = 'test_shmem_import_export' + name = "test_shmem_import_export" # Nodes and Components - n1 = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single) - n2 = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single) + n1 = dpsimpy.sp.SimNode("n1", dpsimpy.PhaseType.Single) + n2 = dpsimpy.sp.SimNode("n2", dpsimpy.PhaseType.Single) - extnet = dpsimpy.sp.ph1.NetworkInjection('Slack') + extnet = dpsimpy.sp.ph1.NetworkInjection("Slack") extnet.set_parameters(voltage_set_point=V_nom) extnet.set_base_voltage(V_nom) extnet.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD) - line = dpsimpy.sp.ph1.PiLine('PiLine') + line = dpsimpy.sp.ph1.PiLine("PiLine") line.set_parameters(R=line_resistance, L=line_inductance, C=line_capacitance) line.set_base_voltage(V_nom) - load = dpsimpy.sp.ph1.Load('Load') - load.set_parameters(active_power=p_load_nom, reactive_power=q_load_nom, nominal_voltage=V_nom) + load = dpsimpy.sp.ph1.Load("Load") + load.set_parameters( + active_power=p_load_nom, reactive_power=q_load_nom, nominal_voltage=V_nom + ) load.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PQ) extnet.connect([n1]) @@ -99,18 +89,23 @@ def dpsim(): logger = dpsimpy.Logger(name) sim.add_logger(logger) - sim.log_attribute('n1.v', n1.attr('v')) - sim.log_attribute('n2.v', n2.attr('v')) + sim.log_attribute("n1.v", n1.attr("v")) + sim.log_attribute("n2.v", n2.attr("v")) intf = dpsimpyvillas.InterfaceShmem() sim.add_interface(intf) - sim.import_attribute(load.attr('P'), 0) - sim.export_attribute(n2.attr('v').derive_coeff(0,0).derive_mag(), 0) + sim.import_attribute(load.attr("P"), 0) + sim.export_attribute(n2.attr("v").derive_coeff(0, 0).derive_mag(), 0) return sim, intf + def test_shmem_import_export(): - logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.INFO) + logging.basicConfig( + format="[%(asctime)s %(name)s %(levelname)s] %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO, + ) sim, intf = dpsim() node = villas(intf) @@ -121,5 +116,6 @@ def test_shmem_import_export(): node.stop() -if __name__ == '__main__': + +if __name__ == "__main__": test_shmem_import_export() diff --git a/examples/villas/dpsim-file.py b/examples/villas/dpsim-file.py index d7cdf73c56..39160d6b16 100644 --- a/examples/villas/dpsim-file.py +++ b/examples/villas/dpsim-file.py @@ -9,16 +9,16 @@ time_step = 0.01 final_time = 10 -n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [10]) -n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) +n1 = dpsimpy.dp.SimNode("n1", dpsimpy.PhaseType.Single, [10]) +n2 = dpsimpy.dp.SimNode("n2", dpsimpy.PhaseType.Single, [5]) -evs = dpsimpy.dp.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.debug) +evs = dpsimpy.dp.ph1.VoltageSource("v_intf", dpsimpy.LogLevel.debug) evs.set_parameters(complex(5, 0)) -vs1 = dpsimpy.dp.ph1.VoltageSource('vs_1', dpsimpy.LogLevel.debug) +vs1 = dpsimpy.dp.ph1.VoltageSource("vs_1", dpsimpy.LogLevel.debug) vs1.set_parameters(complex(10, 0)) -r12 = dpsimpy.dp.ph1.Resistor('r_12', dpsimpy.LogLevel.debug) +r12 = dpsimpy.dp.ph1.Resistor("r_12", dpsimpy.LogLevel.debug) r12.set_parameters(1) evs.connect([dpsimpy.dp.SimNode.gnd, n2]) @@ -27,14 +27,14 @@ sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, vs1, r12]) -dpsimpy.Logger.set_log_dir('logs/' + sim_name) +dpsimpy.Logger.set_log_dir("logs/" + sim_name) logger = dpsimpy.Logger(sim_name) -logger.log_attribute('v1', 'v', n1) -logger.log_attribute('v2', 'v', n2) -logger.log_attribute('r12', 'i_intf', r12) -logger.log_attribute('ievs', 'i_intf', evs) -logger.log_attribute('vevs', 'v_intf', evs) +logger.log_attribute("v1", "v", n1) +logger.log_attribute("v2", "v", n2) +logger.log_attribute("r12", "i_intf", r12) +logger.log_attribute("ievs", "i_intf", evs) +logger.log_attribute("vevs", "v_intf", evs) sim = dpsimpy.RealTimeSimulation(sim_name) sim.set_system(sys) @@ -42,16 +42,14 @@ sim.set_final_time(final_time) intf_config = { - 'type': 'file', - 'format': 'csv', - 'uri': 'logs/output.csv', - 'out': { - 'flush': True - } + "type": "file", + "format": "csv", + "uri": "logs/output.csv", + "out": {"flush": True}, } -intf = dpsimpyvillas.InterfaceVillas(name='dpsim-file', config=json.dumps(intf_config)) -intf.export_attribute(evs.attr('i_intf').derive_coeff(0, 0), 0) +intf = dpsimpyvillas.InterfaceVillas(name="dpsim-file", config=json.dumps(intf_config)) +intf.export_attribute(evs.attr("i_intf").derive_coeff(0, 0), 0) sim.add_interface(intf) # sim.import_attribute('v_intf', 'V_ref', 0) diff --git a/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py b/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py index ed7dded177..ea25edffee 100644 --- a/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py +++ b/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py @@ -10,7 +10,7 @@ import dpsimpyvillas # Setup -name = 'CIGRE-MV-Profiles' +name = "CIGRE-MV-Profiles" time_step = 1 final_time = 30 @@ -19,55 +19,59 @@ log = logging.getLogger(base) # Read topology from CIM -files = glob.glob('build/_deps/cim-data-src/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/*.xml') # Downloaded by CMake -log.info('CIM files: %s', files) +files = glob.glob( + "build/_deps/cim-data-src/CIGRE_MV/NEPLAN/CIGRE_MV_no_tapchanger_With_LoadFlow_Results/*.xml" +) # Downloaded by CMake +log.info("CIM files: %s", files) reader = dpsimpy.CIMReader(name) -system = reader.loadCIM(50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode) +system = reader.loadCIM( + 50, files, dpsimpy.Domain.SP, dpsimpy.PhaseType.Single, dpsimpy.GeneratorType.PVNode +) # Map from CSV to simulation names assignList = { - 'LOAD-H-1': 'Load_H_1', - 'LOAD-H-3': 'Load_H_3', - 'LOAD-H-4': 'Load_H_4', - 'LOAD-H-5': 'Load_H_5', - 'LOAD-H-6': 'Load_H_6', - 'LOAD-H-8': 'Load_H_8', - 'LOAD-H-10': 'Load_H_10', - 'LOAD-H-11': 'Load_H_11', - 'LOAD-H-12': 'Load_H_12', - 'LOAD-H-14': 'Load_H_14', - 'LOAD-I-1': 'Load_I_1', - 'LOAD-I-3': 'Load_I_3', - 'LOAD-I-7': 'Load_I_7', - 'LOAD-I-9': 'Load_I_9', - 'LOAD-I-10': 'Load_I_10', - 'LOAD-I-12': 'Load_I_12', - 'LOAD-I-13': 'Load_I_13', - 'LOAD-I-14': 'Load_I_14' + "LOAD-H-1": "Load_H_1", + "LOAD-H-3": "Load_H_3", + "LOAD-H-4": "Load_H_4", + "LOAD-H-5": "Load_H_5", + "LOAD-H-6": "Load_H_6", + "LOAD-H-8": "Load_H_8", + "LOAD-H-10": "Load_H_10", + "LOAD-H-11": "Load_H_11", + "LOAD-H-12": "Load_H_12", + "LOAD-H-14": "Load_H_14", + "LOAD-I-1": "Load_I_1", + "LOAD-I-3": "Load_I_3", + "LOAD-I-7": "Load_I_7", + "LOAD-I-9": "Load_I_9", + "LOAD-I-10": "Load_I_10", + "LOAD-I-12": "Load_I_12", + "LOAD-I-13": "Load_I_13", + "LOAD-I-14": "Load_I_14", } # Read profiles from CSV -csv_files = 'build/_deps/profile-data-src/CIGRE_MV_NoTap/load_profiles/' -log.info('CSV files: %s', csv_files) +csv_files = "build/_deps/profile-data-src/CIGRE_MV_NoTap/load_profiles/" +log.info("CSV files: %s", csv_files) csvreader = dpsimpy.CSVReader(name, csv_files, assignList, dpsimpy.LogLevel.info) -csvreader.assignLoadProfile(system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS) +csvreader.assignLoadProfile( + system, 0, 1, 300, dpsimpy.CSVReaderMode.MANUAL, dpsimpy.CSVReaderFormat.SECONDS +) # Instantiate logger logger = dpsimpy.Logger(name) # setup VILLASnode intf_mqtt_config = { - 'type': 'mqtt', - 'host': 'mqtt', - 'in': { - 'subscribe': 'mqtt-dpsim' - }, - 'out': { - 'publish': 'dpsim-mqtt' - } + "type": "mqtt", + "host": "mqtt", + "in": {"subscribe": "mqtt-dpsim"}, + "out": {"publish": "dpsim-mqtt"}, } -intf_mqtt = dpsimpyvillas.InterfaceVillas(name='MQTT', config=json.dumps(intf_mqtt_config)) +intf_mqtt = dpsimpyvillas.InterfaceVillas( + name="MQTT", config=json.dumps(intf_mqtt_config) +) # Setup simulation sim = dpsimpy.RealTimeSimulation(name) @@ -81,18 +85,16 @@ # Setup exports for i in range(15): - objname = 'N'+str(i) - intf_mqtt.export_attribute(sim \ - .get_idobj_attr(objname, 'v') \ - .derive_coeff(0,0) \ - .derive_mag(), 2*i) - intf_mqtt.export_attribute(sim \ - .get_idobj_attr(objname, 'v') \ - .derive_coeff(0,0) \ - .derive_phase(), 2*i+1) + objname = "N" + str(i) + intf_mqtt.export_attribute( + sim.get_idobj_attr(objname, "v").derive_coeff(0, 0).derive_mag(), 2 * i + ) + intf_mqtt.export_attribute( + sim.get_idobj_attr(objname, "v").derive_coeff(0, 0).derive_phase(), 2 * i + 1 + ) # Log exports for node in system.nodes: - sim.log_idobj_attribute(node.name(), 'v') + sim.log_idobj_attribute(node.name(), "v") sim.run(1) diff --git a/examples/villas/dpsim-mqtt-import-export-MIMO.py b/examples/villas/dpsim-mqtt-import-export-MIMO.py index 6e58c5a062..4e73896e3f 100644 --- a/examples/villas/dpsim-mqtt-import-export-MIMO.py +++ b/examples/villas/dpsim-mqtt-import-export-MIMO.py @@ -18,97 +18,61 @@ base = os.path.splitext(os.path.basename(sys.argv[0]))[0] log = logging.getLogger(base) -def villas(): - log_filename=datetime.now().strftime(f'{base}-villas-%y-%m-%d_%H_%M_%S.log') +def villas(): + log_filename = datetime.now().strftime(f"{base}-villas-%y-%m-%d_%H_%M_%S.log") nodes = { - 'mqtt': { - 'type': 'mqtt', - 'format': 'json', - 'host': 'mqtt', - 'in': { - 'subscribe': '/dpsim-mqtt', - 'signals': [ - { - 'name': 'v1', - 'type': 'complex' - }, - { - 'name': 'v2_mag', - 'type': 'float' - } - ] + "mqtt": { + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": { + "subscribe": "/dpsim-mqtt", + "signals": [ + {"name": "v1", "type": "complex"}, + {"name": "v2_mag", "type": "float"}, + ], }, - 'out': { - 'publish': '/mqtt-dpsim' - } + "out": {"publish": "/mqtt-dpsim"}, }, - 'shmem': { - 'type': 'shmem', - 'in': { - 'name': '/dpsim-shmem', - 'signals': [ - { - 'name': 'v1', - 'type': 'complex' - }, - { - 'name': 'v2_mag', - 'type': 'float' - } - ] + "shmem": { + "type": "shmem", + "in": { + "name": "/dpsim-shmem", + "signals": [ + {"name": "v1", "type": "complex"}, + {"name": "v2_mag", "type": "float"}, + ], }, - 'out': { - 'name': '/shmem-dpsim' - } - }, - 'file1': { - 'type': 'file', - 'uri': f'{base}-results-%y-%m-%d_%H_%M_%S.csv' - }, - 'file2': { - 'type': 'file', - 'uri': f'{base}-results-%y-%m-%d_%H_%M_%S_2.csv' + "out": {"name": "/shmem-dpsim"}, }, - 'sine' : { - 'type': 'signal', - 'signal': 'sine', - 'rate': 10, - 'frequency': 0.1, - 'amplitude': 50000, - 'offset': 100000 + "file1": {"type": "file", "uri": f"{base}-results-%y-%m-%d_%H_%M_%S.csv"}, + "file2": {"type": "file", "uri": f"{base}-results-%y-%m-%d_%H_%M_%S_2.csv"}, + "sine": { + "type": "signal", + "signal": "sine", + "rate": 10, + "frequency": 0.1, + "amplitude": 50000, + "offset": 100000, }, } paths = [ - { - 'in': 'mqtt', - 'out': 'file1', - 'hooks': [{'type':'print'}] - }, - { - 'in': 'shmem', - 'out': 'file2', - 'hooks': [{'type':'print'}] - }, - { - 'in': 'sine', - 'out': ['mqtt', 'shmem'], - 'hooks': [{'type':'print'}] - }, + {"in": "mqtt", "out": "file1", "hooks": [{"type": "print"}]}, + {"in": "shmem", "out": "file2", "hooks": [{"type": "print"}]}, + {"in": "sine", "out": ["mqtt", "shmem"], "hooks": [{"type": "print"}]}, ] - config = { - 'nodes': nodes, - 'paths': paths - } - config['nodes']['mqtt']['out']['hooks'] = [{'type':'print'}] + config = {"nodes": nodes, "paths": paths} + config["nodes"]["mqtt"]["out"]["hooks"] = [{"type": "print"}] - log.info('VILLASnode config: \n%s', json.dumps(config, indent=2)) + log.info("VILLASnode config: \n%s", json.dumps(config, indent=2)) return VILLASnode(config=config, log_filename=log_filename) + def dpsim(): # Parameters V_nom = 20e3 @@ -117,23 +81,25 @@ def dpsim(): line_resistance = 0.05 line_inductance = 0.1 line_capacitance = 0.1e-6 - name = 'dpsim_mqtt_import_export' + name = "dpsim_mqtt_import_export" # Nodes and Components - n1 = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single) - n2 = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single) + n1 = dpsimpy.sp.SimNode("n1", dpsimpy.PhaseType.Single) + n2 = dpsimpy.sp.SimNode("n2", dpsimpy.PhaseType.Single) - extnet = dpsimpy.sp.ph1.NetworkInjection('Slack') + extnet = dpsimpy.sp.ph1.NetworkInjection("Slack") extnet.set_parameters(voltage_set_point=V_nom) extnet.set_base_voltage(V_nom) extnet.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD) - line = dpsimpy.sp.ph1.PiLine('PiLine') + line = dpsimpy.sp.ph1.PiLine("PiLine") line.set_parameters(R=line_resistance, L=line_inductance, C=line_capacitance) line.set_base_voltage(V_nom) - load = dpsimpy.sp.ph1.Load('Load') - load.set_parameters(active_power=p_load_nom, reactive_power=q_load_nom, nominal_voltage=V_nom) + load = dpsimpy.sp.ph1.Load("Load") + load.set_parameters( + active_power=p_load_nom, reactive_power=q_load_nom, nominal_voltage=V_nom + ) load.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PQ) extnet.connect([n1]) @@ -151,54 +117,62 @@ def dpsim(): logger = dpsimpy.Logger(name) sim.add_logger(logger) - sim.log_attribute('n1.v', n1.attr('v')) - sim.log_attribute('n2.v', n1.attr('v')) + sim.log_attribute("n1.v", n1.attr("v")) + sim.log_attribute("n2.v", n1.attr("v")) intf_config = { - 'type': 'mqtt', - 'format': 'json', - 'host': 'mqtt', - 'in': { - 'subscribe': '/mqtt-dpsim' - }, - 'out': { - 'publish': '/dpsim-mqtt' - } + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": {"subscribe": "/mqtt-dpsim"}, + "out": {"publish": "/dpsim-mqtt"}, } intf_config_2 = { - 'type': 'shmem', - 'in': { - 'name': '/shmem-dpsim' - }, - 'out': { - 'name': '/dpsim-shmem' - } + "type": "shmem", + "in": {"name": "/shmem-dpsim"}, + "out": {"name": "/dpsim-shmem"}, } - intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) + intf = dpsimpyvillas.InterfaceVillas( + name="dpsim-mqtt", config=json.dumps(intf_config) + ) sim.add_interface(intf) - intf2 = dpsimpyvillas.InterfaceVillas(name='dpsim-shmem', config=json.dumps(intf_config_2)) + intf2 = dpsimpyvillas.InterfaceVillas( + name="dpsim-shmem", config=json.dumps(intf_config_2) + ) sim.add_interface(intf2) - intf.import_attribute(load.attr('P'), 0) - intf.export_attribute(n1.attr('v').derive_coeff(0,0), 0) - intf.export_attribute(n2.attr('v').derive_coeff(0,0).derive_mag(), 1) - intf2.import_attribute(load.attr('Q'), 0) - intf2.export_attribute(n1.attr('v').derive_coeff(0,0), 0) - intf2.export_attribute(n2.attr('v').derive_coeff(0,0).derive_mag(), 1) + intf.import_attribute(load.attr("P"), 0) + intf.export_attribute(n1.attr("v").derive_coeff(0, 0), 0) + intf.export_attribute(n2.attr("v").derive_coeff(0, 0).derive_mag(), 1) + intf2.import_attribute(load.attr("Q"), 0) + intf2.export_attribute(n1.attr("v").derive_coeff(0, 0), 0) + intf2.export_attribute(n2.attr("v").derive_coeff(0, 0).derive_mag(), 1) return sim, intf, intf2 -def test_shmem_import_export(): - logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.INFO) - sim, intf, intf2 = dpsim() # intf needs to be extracted from the dpsim-function since the interface object gets deleted otherwise leading to SegFault when starting the simulation +def test_shmem_import_export(): + logging.basicConfig( + format="[%(asctime)s %(name)s %(levelname)s] %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO, + ) + + ( + sim, + intf, + intf2, + ) = ( + dpsim() + ) # intf needs to be extracted from the dpsim-function since the interface object gets deleted otherwise leading to SegFault when starting the simulation node = villas() node.start() sim.run(1) node.stop() -if __name__ == '__main__': + +if __name__ == "__main__": test_shmem_import_export() diff --git a/examples/villas/dpsim-mqtt-import-export.py b/examples/villas/dpsim-mqtt-import-export.py index 87ca9cf879..28ee471a2d 100644 --- a/examples/villas/dpsim-mqtt-import-export.py +++ b/examples/villas/dpsim-mqtt-import-export.py @@ -16,69 +16,48 @@ base = os.path.splitext(os.path.basename(sys.argv[0]))[0] log = logging.getLogger(base) -def villas(): - log_filename=datetime.now().strftime(f'{base}-villas-%y-%m-%d_%H_%M_%S.log') +def villas(): + log_filename = datetime.now().strftime(f"{base}-villas-%y-%m-%d_%H_%M_%S.log") nodes = { - 'mqtt': { - 'type': 'mqtt', - 'format': 'json', - 'host': 'mqtt', - 'in': { - 'subscribe': '/dpsim-mqtt', - 'signals': [ - { - 'name': 'v1', - 'type': 'complex' - }, - { - 'name': 'v2_mag', - 'type': 'float' - } - ] + "mqtt": { + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": { + "subscribe": "/dpsim-mqtt", + "signals": [ + {"name": "v1", "type": "complex"}, + {"name": "v2_mag", "type": "float"}, + ], }, - 'out': { - 'publish': '/mqtt-dpsim' - } - }, - 'file1': { - 'type': 'file', - 'uri': f'{base}-results-%y-%m-%d_%H_%M_%S.csv' + "out": {"publish": "/mqtt-dpsim"}, }, - 'sine' : { - 'type': 'signal', - 'signal': 'sine', - 'rate': 10, - 'frequency': 0.1, - 'amplitude': 50000, - 'offset': 100000 + "file1": {"type": "file", "uri": f"{base}-results-%y-%m-%d_%H_%M_%S.csv"}, + "sine": { + "type": "signal", + "signal": "sine", + "rate": 10, + "frequency": 0.1, + "amplitude": 50000, + "offset": 100000, }, } paths = [ - { - 'in': 'mqtt', - 'out': 'file1', - 'hooks': [{'type':'print'}] - }, - { - 'in': 'sine', - 'out': 'mqtt', - 'hooks': [{'type':'print'}] - } + {"in": "mqtt", "out": "file1", "hooks": [{"type": "print"}]}, + {"in": "sine", "out": "mqtt", "hooks": [{"type": "print"}]}, ] - config = { - 'nodes': nodes, - 'paths': paths - } - config['nodes']['mqtt']['out']['hooks'] = [{'type':'print'}] + config = {"nodes": nodes, "paths": paths} + config["nodes"]["mqtt"]["out"]["hooks"] = [{"type": "print"}] - log.info('VILLASnode config: \n%s', json.dumps(config, indent=2)) + log.info("VILLASnode config: \n%s", json.dumps(config, indent=2)) return VILLASnode(config=config, log_filename=log_filename) + def dpsim(): # Parameters V_nom = 20e3 @@ -87,23 +66,25 @@ def dpsim(): line_resistance = 0.05 line_inductance = 0.1 line_capacitance = 0.1e-6 - name = 'dpsim_mqtt_import_export' + name = "dpsim_mqtt_import_export" # Nodes and Components - n1 = dpsimpy.sp.SimNode('n1', dpsimpy.PhaseType.Single) - n2 = dpsimpy.sp.SimNode('n2', dpsimpy.PhaseType.Single) + n1 = dpsimpy.sp.SimNode("n1", dpsimpy.PhaseType.Single) + n2 = dpsimpy.sp.SimNode("n2", dpsimpy.PhaseType.Single) - extnet = dpsimpy.sp.ph1.NetworkInjection('Slack') + extnet = dpsimpy.sp.ph1.NetworkInjection("Slack") extnet.set_parameters(voltage_set_point=V_nom) extnet.set_base_voltage(V_nom) extnet.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD) - line = dpsimpy.sp.ph1.PiLine('PiLine') + line = dpsimpy.sp.ph1.PiLine("PiLine") line.set_parameters(R=line_resistance, L=line_inductance, C=line_capacitance) line.set_base_voltage(V_nom) - load = dpsimpy.sp.ph1.Load('Load') - load.set_parameters(active_power=p_load_nom, reactive_power=q_load_nom, nominal_voltage=V_nom) + load = dpsimpy.sp.ph1.Load("Load") + load.set_parameters( + active_power=p_load_nom, reactive_power=q_load_nom, nominal_voltage=V_nom + ) load.modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PQ) extnet.connect([n1]) @@ -121,38 +102,47 @@ def dpsim(): logger = dpsimpy.Logger(name) sim.add_logger(logger) - sim.log_attribute('n1.v', n1.attr('v')) - sim.log_attribute('n2.v', n2.attr('v')) + sim.log_attribute("n1.v", n1.attr("v")) + sim.log_attribute("n2.v", n2.attr("v")) intf_config = { - 'type': 'mqtt', - 'format': 'json', - 'host': 'mqtt', - 'in': { - 'subscribe': '/mqtt-dpsim' - }, - 'out': { - 'publish': '/dpsim-mqtt' - } + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": {"subscribe": "/mqtt-dpsim"}, + "out": {"publish": "/dpsim-mqtt"}, } - intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) - intf.import_attribute(load.attr('P'), 0) - intf.export_attribute(n1.attr('v').derive_coeff(0,0), 0) - intf.export_attribute(n2.attr('v').derive_coeff(0,0).derive_mag(), 1) + intf = dpsimpyvillas.InterfaceVillas( + name="dpsim-mqtt", config=json.dumps(intf_config) + ) + intf.import_attribute(load.attr("P"), 0) + intf.export_attribute(n1.attr("v").derive_coeff(0, 0), 0) + intf.export_attribute(n2.attr("v").derive_coeff(0, 0).derive_mag(), 1) sim.add_interface(intf) return sim, intf -def test_shmem_import_export(): - logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.INFO) - sim, intf = dpsim() # intf needs to be extracted from the dpsim-function since the interface object gets deleted otherwise leading to SegFault when starting the simulation +def test_shmem_import_export(): + logging.basicConfig( + format="[%(asctime)s %(name)s %(levelname)s] %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO, + ) + + ( + sim, + intf, + ) = ( + dpsim() + ) # intf needs to be extracted from the dpsim-function since the interface object gets deleted otherwise leading to SegFault when starting the simulation node = villas() node.start() sim.run(1) node.stop() -if __name__ == '__main__': + +if __name__ == "__main__": test_shmem_import_export() diff --git a/examples/villas/dpsim-mqtt-producer.py b/examples/villas/dpsim-mqtt-producer.py index b5376982bc..5e49d93afa 100644 --- a/examples/villas/dpsim-mqtt-producer.py +++ b/examples/villas/dpsim-mqtt-producer.py @@ -2,24 +2,26 @@ import json import time + def build_message(sequence, v_ref): - ts_field = {"origin":[int(elem) for elem in str(time.time()).split('.')]} + ts_field = {"origin": [int(elem) for elem in str(time.time()).split(".")]} data_field = [v_ref] message = {"ts": ts_field, "sequence": sequence, "data": data_field} return "[" + json.dumps(message) + "]" -if __name__ == '__main__': + +if __name__ == "__main__": time.sleep(10) seq = 0 T_s = 0.01 tf = 10.0 - num_samples = int(tf/T_s) + 2 + num_samples = int(tf / T_s) + 2 for n in range(0, num_samples): - if n < int(num_samples/2): - m_v_ref = {"real":5.0, "imag":0.0} + if n < int(num_samples / 2): + m_v_ref = {"real": 5.0, "imag": 0.0} else: - m_v_ref = {"real":7.0, "imag":0.0} + m_v_ref = {"real": 7.0, "imag": 0.0} m_message = build_message(sequence=seq, v_ref=m_v_ref) print(m_message) publish.single(topic="/mqtt-dpsim", payload=m_message, hostname="mqtt") diff --git a/examples/villas/dpsim-mqtt.py b/examples/villas/dpsim-mqtt.py index f6337f3986..0d31ba7625 100644 --- a/examples/villas/dpsim-mqtt.py +++ b/examples/villas/dpsim-mqtt.py @@ -10,16 +10,16 @@ time_step = 0.01 final_time = 10 -n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [10]) -n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) +n1 = dpsimpy.dp.SimNode("n1", dpsimpy.PhaseType.Single, [10]) +n2 = dpsimpy.dp.SimNode("n2", dpsimpy.PhaseType.Single, [5]) -evs = dpsimpy.dp.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.debug) +evs = dpsimpy.dp.ph1.VoltageSource("v_intf", dpsimpy.LogLevel.debug) evs.set_parameters(complex(5, 0)) -vs1 = dpsimpy.dp.ph1.VoltageSource('vs_1', dpsimpy.LogLevel.debug) +vs1 = dpsimpy.dp.ph1.VoltageSource("vs_1", dpsimpy.LogLevel.debug) vs1.set_parameters(complex(10, 0)) -r12 = dpsimpy.dp.ph1.Resistor('r_12', dpsimpy.LogLevel.debug) +r12 = dpsimpy.dp.ph1.Resistor("r_12", dpsimpy.LogLevel.debug) r12.set_parameters(1) evs.connect([dpsimpy.dp.SimNode.gnd, n2]) @@ -28,14 +28,14 @@ sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, vs1, r12]) -dpsimpy.Logger.set_log_dir('logs/' + sim_name) +dpsimpy.Logger.set_log_dir("logs/" + sim_name) logger = dpsimpy.Logger(sim_name) -logger.log_attribute('v1', 'v', n1) -logger.log_attribute('v2', 'v', n2) -logger.log_attribute('r12', 'i_intf', r12) -logger.log_attribute('ievs', 'i_intf', evs) -logger.log_attribute('vevs', 'v_intf', evs) +logger.log_attribute("v1", "v", n1) +logger.log_attribute("v2", "v", n2) +logger.log_attribute("r12", "i_intf", r12) +logger.log_attribute("ievs", "i_intf", evs) +logger.log_attribute("vevs", "v_intf", evs) sim = dpsimpy.RealTimeSimulation(sim_name) sim.set_system(sys) @@ -43,20 +43,16 @@ sim.set_final_time(final_time) intf_config = { - 'type': 'mqtt', - 'format': 'json', - 'host': 'mqtt', - 'in': { - 'subscribe': '/mqtt-dpsim' - }, - 'out': { - 'publish': '/dpsim-mqtt' - } + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": {"subscribe": "/mqtt-dpsim"}, + "out": {"publish": "/dpsim-mqtt"}, } -intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=json.dumps(intf_config)) -intf.import_attribute(evs.attr('V_ref'), 0, True) -intf.export_attribute(r12.attr('i_intf').derive_coeff(0, 0), 0) +intf = dpsimpyvillas.InterfaceVillas(name="dpsim-mqtt", config=json.dumps(intf_config)) +intf.import_attribute(evs.attr("V_ref"), 0, True) +intf.export_attribute(r12.attr("i_intf").derive_coeff(0, 0), 0) sim.add_interface(intf) diff --git a/examples/villas/shmem-distributed-reference.py b/examples/villas/shmem-distributed-reference.py index f364a9619e..3bd953de95 100644 --- a/examples/villas/shmem-distributed-reference.py +++ b/examples/villas/shmem-distributed-reference.py @@ -10,18 +10,18 @@ import villas.dataprocessing.readtools as rt import villas.dataprocessing.plottools as pt -if __name__ == '__main__': +if __name__ == "__main__": sim_name = "ShmemDistributed" time_step = 0.001 - n1 = dpsimpy.dp.SimNode('n1') - n2 = dpsimpy.dp.SimNode('n2') + n1 = dpsimpy.dp.SimNode("n1") + n2 = dpsimpy.dp.SimNode("n2") - vs1 = dpsimpy.dp.ph1.VoltageSource('vs_1', dpsimpy.LogLevel.debug) + vs1 = dpsimpy.dp.ph1.VoltageSource("vs_1", dpsimpy.LogLevel.debug) vs1.set_parameters(complex(10, 0)) - r12 = dpsimpy.dp.ph1.Resistor('r_1', dpsimpy.LogLevel.debug) + r12 = dpsimpy.dp.ph1.Resistor("r_1", dpsimpy.LogLevel.debug) r12.set_parameters(1) - r02 = dpsimpy.dp.ph1.Resistor('r_02', dpsimpy.LogLevel.debug) + r02 = dpsimpy.dp.ph1.Resistor("r_02", dpsimpy.LogLevel.debug) r02.set_parameters(1) vs1.connect([dpsimpy.dp.SimNode.gnd, n1]) @@ -30,13 +30,13 @@ sys = dpsimpy.SystemTopology(50, [n1, n2], [vs1, r12, r02]) - dpsimpy.Logger.set_log_dir('logs/' + sim_name) + dpsimpy.Logger.set_log_dir("logs/" + sim_name) logger = dpsimpy.Logger(sim_name) - logger.log_attribute('v1', 'v', n1) - logger.log_attribute('v2', 'v', n2) - logger.log_attribute('r12', 'i_intf', r12) - logger.log_attribute('r02', 'i_intf', r02) + logger.log_attribute("v1", "v", n1) + logger.log_attribute("v2", "v", n2) + logger.log_attribute("r12", "i_intf", r12) + logger.log_attribute("r02", "i_intf", r02) sim = dpsimpy.RealTimeSimulation(sim_name) sim.set_system(sys) diff --git a/python/src/dpsim/__init__.py b/python/src/dpsim/__init__.py index f8e7fe940c..009dd2fae8 100644 --- a/python/src/dpsim/__init__.py +++ b/python/src/dpsim/__init__.py @@ -4,6 +4,6 @@ try: from dpsimpy import * except ImportError: # pragma: no cover - print('Error: Could not find dpsim C++ module.') + print("Error: Could not find dpsim C++ module.") -__all__ = ['matpower'] +__all__ = ["matpower"] diff --git a/python/src/dpsim/matpower.py b/python/src/dpsim/matpower.py index 4824023779..ceb29ec722 100644 --- a/python/src/dpsim/matpower.py +++ b/python/src/dpsim/matpower.py @@ -4,15 +4,14 @@ import dpsimpy -class Reader: - def __init__(self, mpc_file_path, mpc_name = 'mpc'): +class Reader: + def __init__(self, mpc_file_path, mpc_name="mpc"): # Read input file (returns multidimensional dict) self.mpc_raw = scipy.io.loadmat(mpc_file_path) self.mpc_name = mpc_name def process_mpc(self): - version_idx = 0 base_pow_idx = 1 bus_data_idx = 2 @@ -26,7 +25,7 @@ def process_mpc(self): # System frequency (not included in mpc but needed for setting dpsimpy component parameters i.e inductances, capacitances ..) self.mpc_freq = 50 - self.mpc_omega = 2*np.pi*50 + self.mpc_omega = 2 * np.pi * 50 # Base power (MVA) self.mpc_base_power_MVA = self.mpc_raw[self.mpc_name][0][0][base_pow_idx][0][0] @@ -34,46 +33,91 @@ def process_mpc(self): #### Busses mpc_bus_raw = self.mpc_raw[self.mpc_name][0][0][bus_data_idx] - bus_data_header = ["bus_i", "type", "Pd", "Qd", "Gs", "Bs", "area", - "Vm", "Va", "baseKV", "zone", "Vmax", "Vmin"] - - self.mpc_bus_data = pd.DataFrame(mpc_bus_raw, columns = bus_data_header) + bus_data_header = [ + "bus_i", + "type", + "Pd", + "Qd", + "Gs", + "Bs", + "area", + "Vm", + "Va", + "baseKV", + "zone", + "Vmax", + "Vmin", + ] + + self.mpc_bus_data = pd.DataFrame(mpc_bus_raw, columns=bus_data_header) # scipy.io.loadmat loads all matrix entries as double. Convert specific columns back to int - self.mpc_bus_data['bus_i'] = self.mpc_bus_data['bus_i'].astype(int) - self.mpc_bus_data['type'] = self.mpc_bus_data['type'].astype(int) - self.mpc_bus_data['area'] = self.mpc_bus_data['area'].astype(int) - self.mpc_bus_data['zone'] = self.mpc_bus_data['zone'].astype(int) + self.mpc_bus_data["bus_i"] = self.mpc_bus_data["bus_i"].astype(int) + self.mpc_bus_data["type"] = self.mpc_bus_data["type"].astype(int) + self.mpc_bus_data["area"] = self.mpc_bus_data["area"].astype(int) + self.mpc_bus_data["zone"] = self.mpc_bus_data["zone"].astype(int) #### Generators mpc_gen_raw = self.mpc_raw[self.mpc_name][0][0][gen_data_idx] - gen_data_header = ["bus", "Pg", "Qg", "Qmax", "Qmin", "Vg", "mBase", "status", - "Pmax", "Pmin", "Pc1", "Pc2", "Qc1min", "Qc1max", "Qc2min", - "Qc2max", "ramp_agc", "ramp_10", "ramp_30", "ramp_q", "apf"] - - self.mpc_gen_data = pd.DataFrame(mpc_gen_raw, columns = gen_data_header) - - self.mpc_gen_data['bus'] = self.mpc_gen_data['bus'].astype(int) - self.mpc_gen_data['status'] = self.mpc_gen_data['status'].astype(int) + gen_data_header = [ + "bus", + "Pg", + "Qg", + "Qmax", + "Qmin", + "Vg", + "mBase", + "status", + "Pmax", + "Pmin", + "Pc1", + "Pc2", + "Qc1min", + "Qc1max", + "Qc2min", + "Qc2max", + "ramp_agc", + "ramp_10", + "ramp_30", + "ramp_q", + "apf", + ] + + self.mpc_gen_data = pd.DataFrame(mpc_gen_raw, columns=gen_data_header) + + self.mpc_gen_data["bus"] = self.mpc_gen_data["bus"].astype(int) + self.mpc_gen_data["status"] = self.mpc_gen_data["status"].astype(int) #### Branches # Extract only first 13 columns since following columns include results mpc_branch_raw = self.mpc_raw[self.mpc_name][0][0][branch_data_idx][:, :13] - branch_data_header = ["fbus", "tbus", "r", "x", "b", "rateA", "rateB", - "rateC", "ratio", "angle", "status", "angmin", "angmax"] - - self.mpc_branch_data = pd.DataFrame(mpc_branch_raw, columns = branch_data_header) - - self.mpc_branch_data['fbus'] = self.mpc_branch_data['fbus'].astype(int) - self.mpc_branch_data['tbus'] = self.mpc_branch_data['tbus'].astype(int) - self.mpc_branch_data['status'] = self.mpc_branch_data['status'].astype(int) + branch_data_header = [ + "fbus", + "tbus", + "r", + "x", + "b", + "rateA", + "rateB", + "rateC", + "ratio", + "angle", + "status", + "angmin", + "angmax", + ] + + self.mpc_branch_data = pd.DataFrame(mpc_branch_raw, columns=branch_data_header) + + self.mpc_branch_data["fbus"] = self.mpc_branch_data["fbus"].astype(int) + self.mpc_branch_data["tbus"] = self.mpc_branch_data["tbus"].astype(int) + self.mpc_branch_data["status"] = self.mpc_branch_data["status"].astype(int) #### TODO Generator costs def create_dpsim_objects(self): - self.process_mpc() # Return values: nodes and components @@ -93,70 +137,106 @@ def create_dpsim_objects(self): for index, bus in self.mpc_bus_data.iterrows(): # Create dpsimpy busses bus = bus + 1 - bus_index = str(self.mpc_bus_data.at[index,'bus_i']) + bus_index = str(self.mpc_bus_data.at[index, "bus_i"]) bus_name = bus_index - dpsimpy_busses_dict[bus_name] = dpsimpy.sp.SimNode(bus_name, dpsimpy.PhaseType.Single) + dpsimpy_busses_dict[bus_name] = dpsimpy.sp.SimNode( + bus_name, dpsimpy.PhaseType.Single + ) # For each bus type create corresponding dpsimpy component # 1 = PQ, 2 = PV, 3 = ref, 4 = isolated - bus_type = self.mpc_bus_data.at[index,'type'] + bus_type = self.mpc_bus_data.at[index, "type"] # Loads if bus_type == 1: load = load + 1 - load_name = "load%s" %load - load_p = self.mpc_bus_data.at[index,'Pd'] * mw_w - load_q = self.mpc_bus_data.at[index,'Qd'] * mw_w - load_baseV = self.mpc_bus_data.at[index,'baseKV'] * kv_v - - dpsimpy_comp_dict[load_name] = [dpsimpy.sp.ph1.Load(load_name, dpsimpy.LogLevel.info)] - dpsimpy_comp_dict[load_name][0].set_parameters(load_p, load_q, load_baseV) - dpsimpy_comp_dict[load_name][0].modify_power_flow_bus_type(dpsimpy.PowerflowBusType.PQ) + load_name = "load%s" % load + load_p = self.mpc_bus_data.at[index, "Pd"] * mw_w + load_q = self.mpc_bus_data.at[index, "Qd"] * mw_w + load_baseV = self.mpc_bus_data.at[index, "baseKV"] * kv_v + + dpsimpy_comp_dict[load_name] = [ + dpsimpy.sp.ph1.Load(load_name, dpsimpy.LogLevel.info) + ] + dpsimpy_comp_dict[load_name][0].set_parameters( + load_p, load_q, load_baseV + ) + dpsimpy_comp_dict[load_name][0].modify_power_flow_bus_type( + dpsimpy.PowerflowBusType.PQ + ) # Add connections - dpsimpy_comp_dict[load_name].append([dpsimpy_busses_dict[bus_index]]) # [to bus] + dpsimpy_comp_dict[load_name].append( + [dpsimpy_busses_dict[bus_index]] + ) # [to bus] # Generators elif bus_type == 2: generator = generator + 1 - gen_name = "gen%s" %generator + gen_name = "gen%s" % generator # Relevant data from self.mpc_gen_data. Identification with bus number available in mpc_bus_data and mpc_gen_data - gen = self.mpc_gen_data.loc[self.mpc_gen_data['bus'] == self.mpc_bus_data.at[index,'bus_i']] - - gen_baseS = gen['mBase']*mw_w # Generator base MVA default is mpc.baseMVA - gen_baseV = self.mpc_bus_data.at[index,'baseKV']*kv_v # Generator base kV - gen_v = gen['Vg']*gen_baseV # Generator set point voltage (gen['Vg'] in p.u.) - gen_p = gen['Pg']*mw_w # Generator ini. active power (gen['Pg'] in MVA) + gen = self.mpc_gen_data.loc[ + self.mpc_gen_data["bus"] == self.mpc_bus_data.at[index, "bus_i"] + ] + + gen_baseS = ( + gen["mBase"] * mw_w + ) # Generator base MVA default is mpc.baseMVA + gen_baseV = ( + self.mpc_bus_data.at[index, "baseKV"] * kv_v + ) # Generator base kV + gen_v = ( + gen["Vg"] * gen_baseV + ) # Generator set point voltage (gen['Vg'] in p.u.) + gen_p = ( + gen["Pg"] * mw_w + ) # Generator ini. active power (gen['Pg'] in MVA) # gen_q = gen['Qg']*mw_w # Generator ini. reactive power (gen['Qg'] in MVAr) - gen_nom_s = abs(complex(gen['Pmax'], gen['Qmax'])) # Generator nominal power (set default to mpc.baseMVA ?) - - dpsimpy_comp_dict[gen_name] = [dpsimpy.sp.ph1.SynchronGenerator(gen_name, dpsimpy.LogLevel.info)] - dpsimpy_comp_dict[gen_name][0].set_parameters(gen_nom_s, gen_baseV, gen_p, gen_v, dpsimpy.PowerflowBusType.PV) + gen_nom_s = abs( + complex(gen["Pmax"], gen["Qmax"]) + ) # Generator nominal power (set default to mpc.baseMVA ?) + + dpsimpy_comp_dict[gen_name] = [ + dpsimpy.sp.ph1.SynchronGenerator(gen_name, dpsimpy.LogLevel.info) + ] + dpsimpy_comp_dict[gen_name][0].set_parameters( + gen_nom_s, gen_baseV, gen_p, gen_v, dpsimpy.PowerflowBusType.PV + ) dpsimpy_comp_dict[gen_name][0].set_base_voltage(gen_baseV) # Add connections - dpsimpy_comp_dict[gen_name].append([dpsimpy_busses_dict[bus_index]]) # [to bus] + dpsimpy_comp_dict[gen_name].append( + [dpsimpy_busses_dict[bus_index]] + ) # [to bus] # Network injection (slack bus) elif bus_type == 3: inj = inj + 1 - extnet_name = "extnet%s" %inj + extnet_name = "extnet%s" % inj # Relevant data from self.mpc_gen_data. Identification with bus number available in mpc_bus_data and mpc_gen_data - extnet = self.mpc_gen_data.loc[self.mpc_gen_data['bus'] == self.mpc_bus_data.at[index,'bus_i']] + extnet = self.mpc_gen_data.loc[ + self.mpc_gen_data["bus"] == self.mpc_bus_data.at[index, "bus_i"] + ] # extnet_baseS = extnet['mBase']*mw_w # Default is mpc.baseMVA - extnet_baseV = self.mpc_bus_data.at[index,'baseKV']*kv_v - extnet_v = extnet['Vg']*extnet_baseV + extnet_baseV = self.mpc_bus_data.at[index, "baseKV"] * kv_v + extnet_v = extnet["Vg"] * extnet_baseV - dpsimpy_comp_dict[extnet_name] = [dpsimpy.sp.ph1.NetworkInjection(extnet_name, dpsimpy.LogLevel.info)] + dpsimpy_comp_dict[extnet_name] = [ + dpsimpy.sp.ph1.NetworkInjection(extnet_name, dpsimpy.LogLevel.info) + ] dpsimpy_comp_dict[extnet_name][0].set_parameters(extnet_v) dpsimpy_comp_dict[extnet_name][0].set_base_voltage(extnet_baseV) - dpsimpy_comp_dict[extnet_name][0].modify_power_flow_bus_type(dpsimpy.PowerflowBusType.VD) + dpsimpy_comp_dict[extnet_name][0].modify_power_flow_bus_type( + dpsimpy.PowerflowBusType.VD + ) # Add connections - dpsimpy_comp_dict[extnet_name].append([dpsimpy_busses_dict[bus_index]]) # [to bus] + dpsimpy_comp_dict[extnet_name].append( + [dpsimpy_busses_dict[bus_index]] + ) # [to bus] # Isolated elif bus_type == 4: @@ -168,81 +248,145 @@ def create_dpsim_objects(self): line = 0 trafo = 0 for index, branch in self.mpc_branch_data.iterrows(): - - branch_ratio = self.mpc_branch_data.at[index,'ratio'] + branch_ratio = self.mpc_branch_data.at[index, "ratio"] # Lines if branch_ratio == 0: line = line + 1 - line_name = "line%s_%s-%s" %(line, self.mpc_branch_data.at[index,'fbus'] , self.mpc_branch_data.at[index,'tbus']) - - line_fbus = self.mpc_branch_data.at[index,'fbus'] - line_tbus = self.mpc_branch_data.at[index,'tbus'] - - tmp_fbus = self.mpc_bus_data.loc[self.mpc_bus_data['bus_i'] == line_fbus] - tmp_tbus = self.mpc_bus_data.loc[self.mpc_bus_data['bus_i'] == line_tbus] - - line_fbus_baseV = self.mpc_bus_data.at[tmp_fbus.first_valid_index(),'baseKV']*kv_v - line_tbus_baseV = self.mpc_bus_data.at[tmp_tbus.first_valid_index(),'baseKV']*kv_v - - line_baseZ = line_tbus_baseV*line_tbus_baseV / (self.mpc_base_power_MVA*mw_w) - line_r = self.mpc_branch_data.at[index,'r'] * line_baseZ - line_x = self.mpc_branch_data.at[index,'x'] * line_baseZ - line_b = self.mpc_branch_data.at[index,'b'] / line_baseZ + line_name = "line%s_%s-%s" % ( + line, + self.mpc_branch_data.at[index, "fbus"], + self.mpc_branch_data.at[index, "tbus"], + ) + + line_fbus = self.mpc_branch_data.at[index, "fbus"] + line_tbus = self.mpc_branch_data.at[index, "tbus"] + + tmp_fbus = self.mpc_bus_data.loc[ + self.mpc_bus_data["bus_i"] == line_fbus + ] + tmp_tbus = self.mpc_bus_data.loc[ + self.mpc_bus_data["bus_i"] == line_tbus + ] + + line_fbus_baseV = ( + self.mpc_bus_data.at[tmp_fbus.first_valid_index(), "baseKV"] * kv_v + ) + line_tbus_baseV = ( + self.mpc_bus_data.at[tmp_tbus.first_valid_index(), "baseKV"] * kv_v + ) + + line_baseZ = ( + line_tbus_baseV * line_tbus_baseV / (self.mpc_base_power_MVA * mw_w) + ) + line_r = self.mpc_branch_data.at[index, "r"] * line_baseZ + line_x = self.mpc_branch_data.at[index, "x"] * line_baseZ + line_b = self.mpc_branch_data.at[index, "b"] / line_baseZ line_l = line_x / self.mpc_omega line_c = line_b / self.mpc_omega - line_g = 0 # Line conductance is not included in mpc - - dpsimpy_comp_dict[line_name] = [dpsimpy.sp.ph1.PiLine(line_name, dpsimpy.LogLevel.info)] - dpsimpy_comp_dict[line_name][0].set_parameters(line_r, line_l, line_c, line_g) + line_g = 0 # Line conductance is not included in mpc + + dpsimpy_comp_dict[line_name] = [ + dpsimpy.sp.ph1.PiLine(line_name, dpsimpy.LogLevel.info) + ] + dpsimpy_comp_dict[line_name][0].set_parameters( + line_r, line_l, line_c, line_g + ) dpsimpy_comp_dict[line_name][0].set_base_voltage(line_tbus_baseV) # Add connections - dpsimpy_comp_dict[line_name].append([dpsimpy_busses_dict[str(line_fbus)], dpsimpy_busses_dict[str(line_tbus)]]) + dpsimpy_comp_dict[line_name].append( + [ + dpsimpy_busses_dict[str(line_fbus)], + dpsimpy_busses_dict[str(line_tbus)], + ] + ) # Transformers else: trafo = trafo + 1 - transf_name = "transformer%s_%s-%s" %(trafo, self.mpc_branch_data.at[index,'fbus'] , self.mpc_branch_data.at[index,'tbus']) - transf_s = self.mpc_branch_data.at[index,'rateA']*mw_w # Matpower: Used to specify branch flow limits. By default these are limits on apparent power with units in MV - - transf_fbus = self.mpc_branch_data.at[index,'fbus'] - transf_tbus = self.mpc_branch_data.at[index,'tbus'] - - tmp_fbus = self.mpc_bus_data.loc[self.mpc_bus_data['bus_i'] == transf_fbus] - tmp_tbus = self.mpc_bus_data.loc[self.mpc_bus_data['bus_i'] == transf_tbus] - - - transf_fbus_baseV = self.mpc_bus_data.at[tmp_fbus.first_valid_index(),'baseKV']*kv_v - transf_tbus_baseV = self.mpc_bus_data.at[tmp_tbus.first_valid_index(),'baseKV']*kv_v - - transf_primary_v = self.mpc_bus_data.at[tmp_fbus.first_valid_index(),'Vm']*transf_fbus_baseV - transf_secondary_v = self.mpc_bus_data.at[tmp_tbus.first_valid_index(),'Vm']*transf_tbus_baseV - - transf_offNom_ratio = self.mpc_branch_data.at[index,'ratio'] - transf_primary_v = transf_primary_v/ transf_offNom_ratio + transf_name = "transformer%s_%s-%s" % ( + trafo, + self.mpc_branch_data.at[index, "fbus"], + self.mpc_branch_data.at[index, "tbus"], + ) + transf_s = ( + self.mpc_branch_data.at[index, "rateA"] * mw_w + ) # Matpower: Used to specify branch flow limits. By default these are limits on apparent power with units in MV + + transf_fbus = self.mpc_branch_data.at[index, "fbus"] + transf_tbus = self.mpc_branch_data.at[index, "tbus"] + + tmp_fbus = self.mpc_bus_data.loc[ + self.mpc_bus_data["bus_i"] == transf_fbus + ] + tmp_tbus = self.mpc_bus_data.loc[ + self.mpc_bus_data["bus_i"] == transf_tbus + ] + + transf_fbus_baseV = ( + self.mpc_bus_data.at[tmp_fbus.first_valid_index(), "baseKV"] * kv_v + ) + transf_tbus_baseV = ( + self.mpc_bus_data.at[tmp_tbus.first_valid_index(), "baseKV"] * kv_v + ) + + transf_primary_v = ( + self.mpc_bus_data.at[tmp_fbus.first_valid_index(), "Vm"] + * transf_fbus_baseV + ) + transf_secondary_v = ( + self.mpc_bus_data.at[tmp_tbus.first_valid_index(), "Vm"] + * transf_tbus_baseV + ) + + transf_offNom_ratio = self.mpc_branch_data.at[index, "ratio"] + transf_primary_v = transf_primary_v / transf_offNom_ratio transf_ratio = transf_primary_v / transf_secondary_v - - transf_baseZ = transf_tbus_baseV*transf_tbus_baseV / (self.mpc_base_power_MVA*mw_w) - transf_r = self.mpc_branch_data.at[index,'r']* transf_baseZ - transf_x = self.mpc_branch_data.at[index,'x']* transf_baseZ + transf_baseZ = ( + transf_tbus_baseV + * transf_tbus_baseV + / (self.mpc_base_power_MVA * mw_w) + ) + transf_r = self.mpc_branch_data.at[index, "r"] * transf_baseZ + transf_x = self.mpc_branch_data.at[index, "x"] * transf_baseZ transf_l = transf_x / self.mpc_omega - dpsimpy_comp_dict[transf_name] = [dpsimpy.sp.ph1.Transformer(transf_name, dpsimpy.LogLevel.info)] - dpsimpy_comp_dict[transf_name][0].set_parameters(transf_primary_v, transf_secondary_v, np.abs(transf_ratio), np.angle(transf_ratio), transf_r, transf_l) + dpsimpy_comp_dict[transf_name] = [ + dpsimpy.sp.ph1.Transformer(transf_name, dpsimpy.LogLevel.info) + ] + dpsimpy_comp_dict[transf_name][0].set_parameters( + transf_primary_v, + transf_secondary_v, + np.abs(transf_ratio), + np.angle(transf_ratio), + transf_r, + transf_l, + ) dpsimpy_comp_dict[transf_name][0].set_base_voltage(transf_tbus_baseV) - print(transf_primary_v, transf_secondary_v, np.abs(transf_ratio), np.angle(transf_ratio), transf_r, transf_l) + print( + transf_primary_v, + transf_secondary_v, + np.abs(transf_ratio), + np.angle(transf_ratio), + transf_r, + transf_l, + ) print(transf_tbus_baseV) # Add connections - dpsimpy_comp_dict[transf_name].append([dpsimpy_busses_dict[str(transf_fbus)], dpsimpy_busses_dict[str(transf_tbus)]]) + dpsimpy_comp_dict[transf_name].append( + [ + dpsimpy_busses_dict[str(transf_fbus)], + dpsimpy_busses_dict[str(transf_tbus)], + ] + ) return dpsimpy_busses_dict, dpsimpy_comp_dict def load_mpc(self): - dpsimpy_busses_dict, dpsimpy_comp_dict = self.create_dpsim_objects() system_comp = [] diff --git a/setup.py b/setup.py index bf2cabb62f..f3fb9afd18 100644 --- a/setup.py +++ b/setup.py @@ -14,11 +14,10 @@ def __init__(self, name): class CMakeBuild(build_ext): def build_extension(self, ext): - extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) - cfg = 'Debug' if self.debug else 'Release' - print('building CMake extension in %s configuration' % cfg) + cfg = "Debug" if self.debug else "Release" + print("building CMake extension in %s configuration" % cfg) cmake_args = [ f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={extdir}", @@ -26,57 +25,46 @@ def build_extension(self, ext): f"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_RELEASE={extdir}", f"-DPYTHON_EXECUTABLE={sys.executable}", f"-DCMAKE_BUILD_TYPE={cfg}", # Not used on MSVC, but no harm - "-DCMAKE_POLICY_VERSION_MINIMUM=3.5" + "-DCMAKE_POLICY_VERSION_MINIMUM=3.5", ] - if platform.system() == 'Windows': - cmake_args += ['-A', 'x64'] - build_args = ['--', '/m'] + if platform.system() == "Windows": + cmake_args += ["-A", "x64"] + build_args = ["--", "/m"] else: if self.parallel: - build_args = ['--', '-j' + str(self.parallel)] + build_args = ["--", "-j" + str(self.parallel)] else: - build_args = ['--', '-j4'] + build_args = ["--", "-j4"] if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) env = os.environ.copy() - if env.get('CMAKE_OPTS'): - cmake_args += env.get('CMAKE_OPTS').split(' ') + if env.get("CMAKE_OPTS"): + cmake_args += env.get("CMAKE_OPTS").split(" ") # CMakeLists.txt is in the same directory as this setup.py file sourcedir = os.path.abspath(os.path.dirname(__file__)) - print(' '.join(['cmake', sourcedir] + cmake_args)) + print(" ".join(["cmake", sourcedir] + cmake_args)) subprocess.check_call( - ['cmake', sourcedir] + cmake_args, cwd=self.build_temp, env=env + ["cmake", sourcedir] + cmake_args, cwd=self.build_temp, env=env ) - print(' '.join(['cmake', '--build', '.', '--target', 'dpsimpy'] + build_args)) + print(" ".join(["cmake", "--build", ".", "--target", "dpsimpy"] + build_args)) subprocess.check_call( - ['cmake', '--build', '.', '--target', 'dpsimpy'] + build_args, cwd=self.build_temp + ["cmake", "--build", ".", "--target", "dpsimpy"] + build_args, + cwd=self.build_temp, ) setup( - packages=find_packages('python/src'), + packages=find_packages("python/src"), package_dir={"dpsim": "python/src/dpsim"}, python_requires=">=3.8", - setup_requires=[ - 'pytest-runner', - 'wheel' - ], - tests_require=[ - 'pytest', - 'pyyaml', - 'nbformat', - 'nbconvert' - ], - ext_modules=[ - CMakeExtension('dpsimpy') - ], - cmdclass={ - 'build_ext': CMakeBuild - }, - zip_safe=False + setup_requires=["pytest-runner", "wheel"], + tests_require=["pytest", "pyyaml", "nbformat", "nbconvert"], + ext_modules=[CMakeExtension("dpsimpy")], + cmdclass={"build_ext": CMakeBuild}, + zip_safe=False, ) From d0487f6ef3aa0b0afdc78cebebae962d63d20559 Mon Sep 17 00:00:00 2001 From: Ghassen Nakti Date: Fri, 15 Jul 2022 15:10:15 +0200 Subject: [PATCH 054/168] consider load and extnet components in determineNodeBaseVoltages() Signed-off-by: Ghassen Nakti --- dpsim/src/PFSolver.cpp | 101 ++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 51 deletions(-) diff --git a/dpsim/src/PFSolver.cpp b/dpsim/src/PFSolver.cpp index e6aad98821..dbbec9051a 100644 --- a/dpsim/src/PFSolver.cpp +++ b/dpsim/src/PFSolver.cpp @@ -259,58 +259,57 @@ void PFSolver::determinePFBusType() { void PFSolver::determineNodeBaseVoltages() { - SPDLOG_LOGGER_INFO(mSLog, "-- Determine base voltages for each node " - "according to connected components"); - mSLog->flush(); + SPDLOG_LOGGER_INFO(mSLog, "-- Determine base voltages for each node according to connected components"); + mSLog->flush(); - for (auto node : mSystem.mNodes) { - CPS::Real baseVoltage_ = 0; - for (auto comp : mSystem.mComponentsAtNode[node]) { - if (std::shared_ptr vsi = - std::dynamic_pointer_cast< - CPS::SP::Ph1::AvVoltageSourceInverterDQ>(comp)) { - baseVoltage_ = - Math::abs(vsi->attributeTyped("vnom")->get()); - SPDLOG_LOGGER_INFO( - mSLog, - "Choose base voltage {}V of {} to convert pu-solution of {}.", - baseVoltage_, vsi->name(), node->name()); - break; - } else if (std::shared_ptr rxline = - std::dynamic_pointer_cast(comp)) { - baseVoltage_ = rxline->attributeTyped("base_Voltage")->get(); - SPDLOG_LOGGER_INFO( - mSLog, - "Choose base voltage {}V of {} to convert pu-solution of {}.", - baseVoltage_, rxline->name(), node->name()); - break; - } else if (std::shared_ptr line = - std::dynamic_pointer_cast(comp)) { - baseVoltage_ = line->attributeTyped("base_Voltage")->get(); - SPDLOG_LOGGER_INFO( - mSLog, - "Choose base voltage {}V of {} to convert pu-solution of {}.", - baseVoltage_, line->name(), node->name()); - break; - } else if (std::shared_ptr trans = - std::dynamic_pointer_cast( - comp)) { - if (trans->terminal(0)->node()->name() == node->name()) { - baseVoltage_ = - trans->attributeTyped("nominal_voltage_end1")->get(); - SPDLOG_LOGGER_INFO( - mSLog, - "Choose base voltage {}V of {} to convert pu-solution of {}.", - baseVoltage_, trans->name(), node->name()); - break; - } else if (trans->terminal(1)->node()->name() == node->name()) { - baseVoltage_ = - trans->attributeTyped("nominal_voltage_end2")->get(); - SPDLOG_LOGGER_INFO( - mSLog, - "Choose base voltage {}V of {} to convert pu-solution of {}.", - baseVoltage_, trans->name(), node->name()); - break; + for (auto node : mSystem.mNodes) { + CPS::Real baseVoltage_ = 0; + for (auto comp : mSystem.mComponentsAtNode[node]) { + if (std::shared_ptr vsi = std::dynamic_pointer_cast(comp)) { + baseVoltage_=Math::abs(vsi->attributeTyped("vnom")->get()); + SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, vsi->name(), node->name()); + break; + } + else if (std::shared_ptr rxline = std::dynamic_pointer_cast(comp)) { + baseVoltage_ = rxline->attributeTyped("base_Voltage")->get(); + SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, rxline->name(), node->name()); + break; + } + else if (std::shared_ptr line = std::dynamic_pointer_cast(comp)) { + baseVoltage_ = line->attributeTyped("base_Voltage")->get(); + SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, line->name(), node->name()); + break; + } + else if (std::shared_ptr trans = std::dynamic_pointer_cast(comp)) { + if (trans->terminal(0)->node()->name() == node->name()){ + baseVoltage_ = trans->attributeTyped("nominal_voltage_end1")->get(); + SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, trans->name(), node->name()); + break; + } + else if (trans->terminal(1)->node()->name() == node->name()){ + baseVoltage_ = trans->attributeTyped("nominal_voltage_end2")->get(); + SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, trans->name(), node->name()); + break; + } + } + else if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { + baseVoltage_ = gen->attributeTyped("base_Voltage")->get(); + SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, gen->name(), node->name()); + break; + } + else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { + baseVoltage_ = load->attribute("V_nom")->get(); + mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", baseVoltage_, load->name(), node->name()); + break; + } + else if (std::shared_ptr extnet = std::dynamic_pointer_cast(comp)) { + baseVoltage_ = extnet->attribute("base_Voltage")->get(); + mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", baseVoltage_, extnet->name(), node->name()); + break; + } + else { + SPDLOG_LOGGER_WARN(mSLog, "Unable to get base voltage at {}", node->name()); + } } } else if (std::shared_ptr gen = std::dynamic_pointer_cast( From 6cbf9344167f4b037db9fb85942481ef87c9a43e Mon Sep 17 00:00:00 2001 From: Ghassen Nakti Date: Tue, 19 Jul 2022 13:30:13 +0200 Subject: [PATCH 055/168] set initial power of loads and generators in pq, pv and vd nodes Signed-off-by: Ghassen Nakti --- dpsim/src/PFSolverPowerPolar.cpp | 131 +++++++++++++++++++++++-------- 1 file changed, 99 insertions(+), 32 deletions(-) diff --git a/dpsim/src/PFSolverPowerPolar.cpp b/dpsim/src/PFSolverPowerPolar.cpp index 0ab6368019..b965c15c82 100644 --- a/dpsim/src/PFSolverPowerPolar.cpp +++ b/dpsim/src/PFSolverPowerPolar.cpp @@ -32,39 +32,106 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, load->calculatePerUnitParameters(mBaseApparentPower, mSystem.mSystemOmega); } - } - // set initial solution for the new time - for (auto pq : mPQBuses) { - if (!keep_last_solution) { - sol_V(pq->matrixNodeIndex()) = 1.0; - sol_D(pq->matrixNodeIndex()) = 0.0; - sol_V_complex(pq->matrixNodeIndex()) = CPS::Complex( - sol_V[pq->matrixNodeIndex()], sol_D[pq->matrixNodeIndex()]); - } - for (auto comp : mSystem.mComponentsAtNode[pq]) { - if (std::shared_ptr load = - std::dynamic_pointer_cast(comp)) { - sol_P(pq->matrixNodeIndex()) -= - load->attributeTyped("P_pu")->get(); - sol_Q(pq->matrixNodeIndex()) -= - load->attributeTyped("Q_pu")->get(); - } else if (std::shared_ptr sst = - std::dynamic_pointer_cast< - CPS::SP::Ph1::SolidStateTransformer>(comp)) { - sol_P(pq->matrixNodeIndex()) -= sst->getNodalInjection(pq).real(); - sol_Q(pq->matrixNodeIndex()) -= sst->getNodalInjection(pq).imag(); - } else if (std::shared_ptr vsi = - std::dynamic_pointer_cast< - CPS::SP::Ph1::AvVoltageSourceInverterDQ>(comp)) { - // TODO: add per-unit attributes to VSI and use here - sol_P(pq->matrixNodeIndex()) += - vsi->attributeTyped("P_ref")->get() / mBaseApparentPower; - sol_Q(pq->matrixNodeIndex()) += - vsi->attributeTyped("Q_ref")->get() / mBaseApparentPower; - } - sol_S_complex(pq->matrixNodeIndex()) = CPS::Complex( - sol_P[pq->matrixNodeIndex()], sol_Q[pq->matrixNodeIndex()]); + // set initial solution for the new time + for (auto pq : mPQBuses) { + if (!keep_last_solution) { + sol_V(pq->matrixNodeIndex()) = 1.0; + sol_D(pq->matrixNodeIndex()) = 0.0; + sol_V_complex(pq->matrixNodeIndex()) = CPS::Complex(sol_V[pq->matrixNodeIndex()], sol_D[pq->matrixNodeIndex()]); + } + for (auto comp : mSystem.mComponentsAtNode[pq]) { + if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { + sol_P(pq->matrixNodeIndex()) -= load->attributeTyped("P_pu")->get(); + sol_Q(pq->matrixNodeIndex()) -= load->attributeTyped("Q_pu")->get(); + } + else if(std::shared_ptr sst = + std::dynamic_pointer_cast(comp)){ + sol_P(pq->matrixNodeIndex()) -= sst->getNodalInjection(pq).real(); + sol_Q(pq->matrixNodeIndex()) -= sst->getNodalInjection(pq).imag(); + } + else if (std::shared_ptr vsi = + std::dynamic_pointer_cast(comp)) { + // TODO: add per-unit attributes to VSI and use here + sol_P(pq->matrixNodeIndex()) += vsi->attributeTyped("P_ref")->get() / mBaseApparentPower; + sol_Q(pq->matrixNodeIndex()) += vsi->attributeTyped("Q_ref")->get() / mBaseApparentPower; + } + else if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { + sol_P(pq->matrixNodeIndex()) += gen->attribute("P_set_pu")->get(); + sol_Q(pq->matrixNodeIndex()) += gen->attribute("Q_set_pu")->get(); + } + sol_S_complex(pq->matrixNodeIndex()) = CPS::Complex(sol_P[pq->matrixNodeIndex()], sol_Q[pq->matrixNodeIndex()]); + } + } + + for (auto pv : mPVBuses) { + if (!keep_last_solution) { + sol_Q(pv->matrixNodeIndex()) = 0; + sol_D(pv->matrixNodeIndex()) = 0; + } + for (auto comp : mSystem.mComponentsAtNode[pv]) { + if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { + sol_P(pv->matrixNodeIndex()) += gen->attributeTyped("P_set_pu")->get(); + sol_V(pv->matrixNodeIndex()) = gen->attributeTyped("V_set_pu")->get(); + sol_Q(pv->matrixNodeIndex()) += gen->attributeTyped("Q_set_pu")->get(); + } + else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { + sol_P(pv->matrixNodeIndex()) -= load->attributeTyped("P_pu")->get(); + sol_Q(pv->matrixNodeIndex()) -= load->attributeTyped("Q_pu")->get(); + } + else if (std::shared_ptr vsi = + std::dynamic_pointer_cast(comp)) { + sol_P(pv->matrixNodeIndex()) += vsi->attributeTyped("P_ref")->get() / mBaseApparentPower; + } + else if (std::shared_ptr extnet = + std::dynamic_pointer_cast(comp)) { + sol_P(pv->matrixNodeIndex()) += extnet->attributeTyped("p_inj")->get() / mBaseApparentPower; + sol_V(pv->matrixNodeIndex()) = extnet->attributeTyped("V_set_pu")->get(); + // sol_Q(pv->matrixNodeIndex()) += extnet->attribute("q_inj")->get() / mBaseApparentPower; //Todo allow initialisation of p_inj and q_inj in SP_NetworkInjection (use updatePowerInjection?) + } + sol_S_complex(pv->matrixNodeIndex()) = CPS::Complex(sol_P[pv->matrixNodeIndex()], sol_Q[pv->matrixNodeIndex()]); + sol_V_complex(pv->matrixNodeIndex()) = CPS::Complex(sol_V[pv->matrixNodeIndex()], sol_D[pv->matrixNodeIndex()]); + } + } + + for (auto vd : mVDBuses) { + sol_P(vd->matrixNodeIndex()) = 0.0; + sol_Q(vd->matrixNodeIndex()) = 0.0; + sol_V(vd->matrixNodeIndex()) = 1.0; + sol_D(vd->matrixNodeIndex()) = 0.0; + + // if external injection at VD bus, reset the voltage to injection's voltage set-point + for (auto comp : mSystem.mComponentsAtNode[vd]) { + if (std::shared_ptr extnet = std::dynamic_pointer_cast(comp)) { + sol_V(vd->matrixNodeIndex()) = extnet->attributeTyped("V_set_pu")->get(); + sol_P(vd->matrixNodeIndex()) += extnet->attributeTyped("p_inj")->get() / mBaseApparentPower; // Todo add p_set q_set to extnet + sol_Q(vd->matrixNodeIndex()) += extnet->attributeTyped("q_inj")->get() / mBaseApparentPower; + } + + // if load at VD bus, substract P and Q + else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { + sol_P(vd->matrixNodeIndex()) -= load->attributeTyped("P_pu")->get(); + sol_Q(vd->matrixNodeIndex()) -= load->attributeTyped("Q_pu")->get(); + } + + // if generator at VD, add P_set Q_Set + else if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { + sol_P(vd->matrixNodeIndex()) += gen->attributeTyped("P_set_pu")->get(); + sol_Q(vd->matrixNodeIndex()) += gen->attributeTyped("Q_set_pu")->get(); + } + } + + // if generator at VD bus, reset the voltage to generator's set-point + if (!mSynchronGenerators.empty()) { + for (auto gen : mSynchronGenerators) + { + if (gen->node(0)->matrixNodeIndex() == vd->matrixNodeIndex()) + sol_V(vd->matrixNodeIndex()) = gen->attributeTyped("V_set_pu")->get(); + } + } + + sol_S_complex(vd->matrixNodeIndex()) = CPS::Complex(sol_P[vd->matrixNodeIndex()], sol_Q[vd->matrixNodeIndex()]); + sol_V_complex(vd->matrixNodeIndex()) = CPS::Complex(sol_V[vd->matrixNodeIndex()], sol_D[vd->matrixNodeIndex()]); } } From 3ab9cd0638a6f1fea2c7738033e93b68d4faafc2 Mon Sep 17 00:00:00 2001 From: Ghassen Nakti Date: Thu, 2 Feb 2023 12:18:10 +0100 Subject: [PATCH 056/168] change attribute to attributeTyped Signed-off-by: Ghassen Nakti --- dpsim/src/PFSolver.cpp | 4 ++-- dpsim/src/PFSolverPowerPolar.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/dpsim/src/PFSolver.cpp b/dpsim/src/PFSolver.cpp index dbbec9051a..9df4a8d196 100644 --- a/dpsim/src/PFSolver.cpp +++ b/dpsim/src/PFSolver.cpp @@ -298,12 +298,12 @@ void PFSolver::determineNodeBaseVoltages() { break; } else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = load->attribute("V_nom")->get(); + baseVoltage_ = load->attributeTyped("V_nom")->get(); mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", baseVoltage_, load->name(), node->name()); break; } else if (std::shared_ptr extnet = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = extnet->attribute("base_Voltage")->get(); + baseVoltage_ = extnet->attributeTyped("base_Voltage")->get(); mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", baseVoltage_, extnet->name(), node->name()); break; } diff --git a/dpsim/src/PFSolverPowerPolar.cpp b/dpsim/src/PFSolverPowerPolar.cpp index b965c15c82..e200852a48 100644 --- a/dpsim/src/PFSolverPowerPolar.cpp +++ b/dpsim/src/PFSolverPowerPolar.cpp @@ -57,8 +57,8 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, sol_Q(pq->matrixNodeIndex()) += vsi->attributeTyped("Q_ref")->get() / mBaseApparentPower; } else if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { - sol_P(pq->matrixNodeIndex()) += gen->attribute("P_set_pu")->get(); - sol_Q(pq->matrixNodeIndex()) += gen->attribute("Q_set_pu")->get(); + sol_P(pq->matrixNodeIndex()) += gen->attributeTyped("P_set_pu")->get(); + sol_Q(pq->matrixNodeIndex()) += gen->attributeTyped("Q_set_pu")->get(); } sol_S_complex(pq->matrixNodeIndex()) = CPS::Complex(sol_P[pq->matrixNodeIndex()], sol_Q[pq->matrixNodeIndex()]); } @@ -87,7 +87,7 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, std::dynamic_pointer_cast(comp)) { sol_P(pv->matrixNodeIndex()) += extnet->attributeTyped("p_inj")->get() / mBaseApparentPower; sol_V(pv->matrixNodeIndex()) = extnet->attributeTyped("V_set_pu")->get(); - // sol_Q(pv->matrixNodeIndex()) += extnet->attribute("q_inj")->get() / mBaseApparentPower; //Todo allow initialisation of p_inj and q_inj in SP_NetworkInjection (use updatePowerInjection?) + // sol_Q(pv->matrixNodeIndex()) += extnet->attributeTyped("q_inj")->get() / mBaseApparentPower; //Todo allow initialisation of p_inj and q_inj in SP_NetworkInjection (use updatePowerInjection?) } sol_S_complex(pv->matrixNodeIndex()) = CPS::Complex(sol_P[pv->matrixNodeIndex()], sol_Q[pv->matrixNodeIndex()]); sol_V_complex(pv->matrixNodeIndex()) = CPS::Complex(sol_V[pv->matrixNodeIndex()], sol_D[pv->matrixNodeIndex()]); From 7e3a48375f675e05ca6b7a64d92805033deb4992 Mon Sep 17 00:00:00 2001 From: Martin Moraga Date: Fri, 14 Apr 2023 10:37:39 +0200 Subject: [PATCH 057/168] fix small error in function determineNodeBaseVoltages of PFSolver Signed-off-by: Martin Moraga resolve rebase conflicts Signed-off-by: Martin Moraga --- .../dpsim-models/SP/SP_Ph1_NetworkInjection.h | 4 +- dpsim-models/src/DP/DP_Ph1_PiLine.cpp | 4 +- dpsim-models/src/DP/DP_Ph1_RxLine.cpp | 4 +- .../src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp | 5 +- dpsim-models/src/DP/DP_Ph1_Transformer.cpp | 5 +- .../src/DP/DP_Ph1_VoltageSourceNorton.cpp | 5 +- dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp | 4 +- dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp | 4 +- .../EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp | 5 +- dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp | 5 +- dpsim-models/src/SP/SP_Ph1_Load.cpp | 8 +- .../src/SP/SP_Ph1_NetworkInjection.cpp | 9 +- dpsim-models/src/SP/SP_Ph1_PiLine.cpp | 4 +- dpsim-models/src/SP/SP_Ph1_RXLine.cpp | 8 +- .../src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp | 5 +- dpsim-models/src/SP/SP_Ph1_Transformer.cpp | 4 +- dpsim/src/PFSolver.cpp | 132 +++++++++------- dpsim/src/PFSolverPowerPolar.cpp | 144 ++++++------------ dpsim/src/Utils.cpp | 4 +- 19 files changed, 165 insertions(+), 198 deletions(-) diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h index f86f2ed20a..fc6e720e44 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h @@ -39,7 +39,7 @@ class NetworkInjection : public CompositePowerComp, // #### Powerflow section #### /// Base voltage [V] - Real mBaseVoltage; + const Attribute::Ptr mBaseVoltage; public: const Attribute::Ptr mVoltageRef; @@ -127,4 +127,4 @@ class NetworkInjection : public CompositePowerComp, }; } // namespace Ph1 } // namespace SP -} // namespace CPS +} // namespace CPS \ No newline at end of file diff --git a/dpsim-models/src/DP/DP_Ph1_PiLine.cpp b/dpsim-models/src/DP/DP_Ph1_PiLine.cpp index 81d08e4013..91f4223358 100644 --- a/dpsim-models/src/DP/DP_Ph1_PiLine.cpp +++ b/dpsim-models/src/DP/DP_Ph1_PiLine.cpp @@ -11,8 +11,8 @@ using namespace CPS; DP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel) { + : Base::Ph1::PiLine(mAttributes), CompositePowerComp( + uid, name, true, true, logLevel) { setVirtualNodeNumber(1); setTerminalNumber(2); diff --git a/dpsim-models/src/DP/DP_Ph1_RxLine.cpp b/dpsim-models/src/DP/DP_Ph1_RxLine.cpp index d41e32c1b5..217959ce44 100644 --- a/dpsim-models/src/DP/DP_Ph1_RxLine.cpp +++ b/dpsim-models/src/DP/DP_Ph1_RxLine.cpp @@ -11,8 +11,8 @@ using namespace CPS; DP::Ph1::RxLine::RxLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel) { + : Base::Ph1::PiLine(mAttributes), CompositePowerComp( + uid, name, true, true, logLevel) { setVirtualNodeNumber(1); setTerminalNumber(2); diff --git a/dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp b/dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp index af9559e8b6..7ec24659a8 100644 --- a/dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp +++ b/dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp @@ -11,8 +11,9 @@ using namespace CPS; DP::Ph1::SynchronGeneratorTrStab::SynchronGeneratorTrStab( String uid, String name, Logger::Level logLevel) - : Base::SynchronGenerator(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel), + : Base::SynchronGenerator(mAttributes), CompositePowerComp( + uid, name, true, true, + logLevel), mEp(mAttributes->create("Ep")), mEp_abs(mAttributes->create("Ep_mag")), mEp_phase(mAttributes->create("Ep_phase")), diff --git a/dpsim-models/src/DP/DP_Ph1_Transformer.cpp b/dpsim-models/src/DP/DP_Ph1_Transformer.cpp index b8b1084731..0a70ddef97 100644 --- a/dpsim-models/src/DP/DP_Ph1_Transformer.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Transformer.cpp @@ -13,8 +13,9 @@ using namespace CPS; DP::Ph1::Transformer::Transformer(String uid, String name, Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph1::Transformer(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel) { + : Base::Ph1::Transformer(mAttributes), CompositePowerComp( + uid, name, true, true, + logLevel) { if (withResistiveLosses) setVirtualNodeNumber(3); else diff --git a/dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp b/dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp index e12376fdf3..6c1b852407 100644 --- a/dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp +++ b/dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp @@ -12,8 +12,9 @@ using namespace CPS; DP::Ph1::VoltageSourceNorton::VoltageSourceNorton(String uid, String name, Logger::Level logLevel) - : Base::Ph1::VoltageSource(mAttributes), - MNASimPowerComp(uid, name, true, true, logLevel), + : Base::Ph1::VoltageSource(mAttributes), MNASimPowerComp( + uid, name, true, true, + logLevel), mResistance(mAttributes->create("R")) { setTerminalNumber(2); **mIntfVoltage = MatrixComp::Zero(1, 1); diff --git a/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp b/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp index 3fef318e8a..7888161332 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp @@ -11,8 +11,8 @@ using namespace CPS; EMT::Ph3::PiLine::PiLine(String uid, String name, Logger::Level logLevel) - : Base::Ph3::PiLine(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel) { + : Base::Ph3::PiLine(mAttributes), CompositePowerComp(uid, name, true, + true, logLevel) { mPhaseType = PhaseType::ABC; setVirtualNodeNumber(1); setTerminalNumber(2); diff --git a/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp b/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp index 07cf7fb412..d4d02b6780 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp @@ -14,8 +14,8 @@ using namespace CPS; // !!! with initialization from phase-to-phase RMS variables EMT::Ph3::RxLine::RxLine(String uid, String name, Logger::Level logLevel) - : Base::Ph3::PiLine(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel) { + : Base::Ph3::PiLine(mAttributes), CompositePowerComp(uid, name, true, + true, logLevel) { mPhaseType = PhaseType::ABC; setVirtualNodeNumber(1); setTerminalNumber(2); diff --git a/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp b/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp index ac96992a3c..d78653f662 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp @@ -32,8 +32,9 @@ Matrix EMT::Ph3::SynchronGeneratorTrStab::getParkTransformMatrixPowerInvariant( EMT::Ph3::SynchronGeneratorTrStab::SynchronGeneratorTrStab( String uid, String name, Logger::Level logLevel) - : Base::SynchronGenerator(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel), + : Base::SynchronGenerator(mAttributes), CompositePowerComp(uid, name, + true, true, + logLevel), mEp(mAttributes->create("Ep")), mEp_abs(mAttributes->create("Ep_mag")), mEp_phase(mAttributes->create("Ep_phase")), diff --git a/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp b/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp index f86f4aa64a..d9a370c8e7 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp @@ -13,8 +13,9 @@ using namespace CPS; EMT::Ph3::Transformer::Transformer(String uid, String name, Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph3::Transformer(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel) { + : Base::Ph3::Transformer(mAttributes), CompositePowerComp(uid, name, + true, true, + logLevel) { mPhaseType = PhaseType::ABC; if (withResistiveLosses) setVirtualNodeNumber(3); diff --git a/dpsim-models/src/SP/SP_Ph1_Load.cpp b/dpsim-models/src/SP/SP_Ph1_Load.cpp index 8215d2cd25..8b834d3b0d 100644 --- a/dpsim-models/src/SP/SP_Ph1_Load.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Load.cpp @@ -36,8 +36,10 @@ void SP::Ph1::Load::setParameters(Real activePower, Real reactivePower, **mReactivePower = reactivePower; **mNomVoltage = nominalVoltage; - SPDLOG_LOGGER_INFO(mSLog, "Active Power={} [W] Reactive Power={} [VAr]", - **mActivePower, **mReactivePower); + SPDLOG_LOGGER_INFO( + mSLog, + "Active Power={}[W]\nReactive Power={} [VAr]\nNominal Voltage={} [V]", + **mActivePower, **mReactivePower, **mNomVoltage); mSLog->flush(); mParametersSet = true; @@ -196,4 +198,4 @@ void SP::Ph1::Load::mnaCompUpdateCurrent(const Matrix &leftVector) { for (auto &subc : mSubComponents) { (**mIntfCurrent)(0, 0) += subc->intfCurrent()(0, 0); } -} +} \ No newline at end of file diff --git a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp index 73585f32e3..5563b5f942 100644 --- a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp +++ b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp @@ -15,6 +15,7 @@ SP::Ph1::NetworkInjection::NetworkInjection(String uid, String name, : CompositePowerComp(uid, name, true, true, logLevel), mVoltageRef(mAttributes->createDynamic("V_ref")), mSrcFreq(mAttributes->createDynamic("f_src")), + mBaseVoltage(mAttributes->create("base_Voltage")), mVoltageSetPoint(mAttributes->create("V_set")), mVoltageSetPointPerUnit(mAttributes->create("V_set_pu", 1.0)), mActivePowerInjection(mAttributes->create("p_inj")), @@ -92,16 +93,16 @@ void SP::Ph1::NetworkInjection::setParameters(Complex initialPhasor, } void SP::Ph1::NetworkInjection::setBaseVoltage(Real baseVoltage) { - mBaseVoltage = baseVoltage; + **mBaseVoltage = baseVoltage; } void SP::Ph1::NetworkInjection::calculatePerUnitParameters( Real baseApparentPower, Real baseOmega) { SPDLOG_LOGGER_INFO(mSLog, "#### Calculate Per Unit Parameters for {}", **mName); - SPDLOG_LOGGER_INFO(mSLog, "Base Voltage={} [V]", mBaseVoltage); + SPDLOG_LOGGER_INFO(mSLog, "Base Voltage={} [V]", **mBaseVoltage); - **mVoltageSetPointPerUnit = **mVoltageSetPoint / mBaseVoltage; + **mVoltageSetPointPerUnit = **mVoltageSetPoint / **mBaseVoltage; SPDLOG_LOGGER_INFO(mSLog, "Voltage Set-Point ={} [pu]", **mVoltageSetPointPerUnit); @@ -229,4 +230,4 @@ void SP::Ph1::NetworkInjection::daeResidual(double ttime, const double state[], Complex SP::Ph1::NetworkInjection::daeInitialize() { (**mIntfVoltage)(0, 0) = (**mSubVoltageSource->mIntfVoltage)(0, 0); return (**mSubVoltageSource->mIntfVoltage)(0, 0); -} +} \ No newline at end of file diff --git a/dpsim-models/src/SP/SP_Ph1_PiLine.cpp b/dpsim-models/src/SP/SP_Ph1_PiLine.cpp index acb6cad204..aae0abcd4d 100644 --- a/dpsim-models/src/SP/SP_Ph1_PiLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_PiLine.cpp @@ -11,8 +11,8 @@ using namespace CPS; SP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), - CompositePowerComp(uid, name, false, true, logLevel), + : Base::Ph1::PiLine(mAttributes), CompositePowerComp( + uid, name, false, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage")), mCurrent(mAttributes->create("current_vector")), mActivePowerBranch(mAttributes->create("p_branch_vector")), diff --git a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp index 78c1340030..dcd69253c6 100644 --- a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp @@ -13,8 +13,8 @@ using namespace CPS; SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage, Real resistance, Real inductance, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel), + : Base::Ph1::PiLine(mAttributes), CompositePowerComp( + uid, name, true, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage", baseVoltage)), mInductance(mAttributes->create("L_series")), mActivePowerInjection(mAttributes->create("p_inj")), @@ -37,8 +37,8 @@ SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage, } SP::Ph1::RXLine::RXLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel), + : Base::Ph1::PiLine(mAttributes), CompositePowerComp( + uid, name, true, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage")), mInductance(mAttributes->create("L_series")), mActivePowerInjection(mAttributes->create("p_inj")), diff --git a/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp b/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp index 42e5d22a05..094fe838d8 100644 --- a/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp +++ b/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp @@ -11,8 +11,9 @@ using namespace CPS; SP::Ph1::SynchronGeneratorTrStab::SynchronGeneratorTrStab( String uid, String name, Logger::Level logLevel) - : Base::SynchronGenerator(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel), + : Base::SynchronGenerator(mAttributes), CompositePowerComp( + uid, name, true, true, + logLevel), mEp(mAttributes->create("Ep")), mEp_abs(mAttributes->create("Ep_mag")), mEp_phase(mAttributes->create("Ep_phase")), diff --git a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp index e94606355e..1aaae0b8ec 100644 --- a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp @@ -14,8 +14,8 @@ using namespace CPS; SP::Ph1::Transformer::Transformer(String uid, String name, Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph1::Transformer(mAttributes), - CompositePowerComp(uid, name, true, true, logLevel), + : Base::Ph1::Transformer(mAttributes), CompositePowerComp( + uid, name, true, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage")), mCurrent(mAttributes->create("current_vector")), mActivePowerBranch(mAttributes->create("p_branch_vector")), diff --git a/dpsim/src/PFSolver.cpp b/dpsim/src/PFSolver.cpp index 9df4a8d196..445b628796 100644 --- a/dpsim/src/PFSolver.cpp +++ b/dpsim/src/PFSolver.cpp @@ -185,48 +185,48 @@ void PFSolver::determinePFBusType() { // determine powerflow bus types according connected type of connected components // only PQ type component connected -> set as PQ bus if (!connectedPV && connectedPQ && !connectedVD) { - SPDLOG_LOGGER_DEBUG( + SPDLOG_LOGGER_INFO( mSLog, "{}: only PQ type component connected -> set as PQ bus", node->name()); mPQBusIndices.push_back(node->matrixNodeIndex()); mPQBuses.push_back(node); } // no component connected -> set as PQ bus (P & Q will be zero) else if (!connectedPV && !connectedPQ && !connectedVD) { - SPDLOG_LOGGER_DEBUG(mSLog, "{}: no component connected -> set as PQ bus", - node->name()); + SPDLOG_LOGGER_INFO(mSLog, "{}: no component connected -> set as PQ bus", + node->name()); mPQBusIndices.push_back(node->matrixNodeIndex()); mPQBuses.push_back(node); } // only PV type component connected -> set as PV bus else if (connectedPV && !connectedPQ && !connectedVD) { - SPDLOG_LOGGER_DEBUG( + SPDLOG_LOGGER_INFO( mSLog, "{}: only PV type component connected -> set as PV bus", node->name()); mPVBusIndices.push_back(node->matrixNodeIndex()); mPVBuses.push_back(node); } // PV and PQ type component connected -> set as PV bus (TODO: bus type should be modifiable by user afterwards) else if (connectedPV && connectedPQ && !connectedVD) { - SPDLOG_LOGGER_DEBUG( + SPDLOG_LOGGER_INFO( mSLog, "{}: PV and PQ type component connected -> set as PV bus", node->name()); mPVBusIndices.push_back(node->matrixNodeIndex()); mPVBuses.push_back(node); } // only VD type component connected -> set as VD bus else if (!connectedPV && !connectedPQ && connectedVD) { - SPDLOG_LOGGER_DEBUG( + SPDLOG_LOGGER_INFO( mSLog, "{}: only VD type component connected -> set as VD bus", node->name()); mVDBusIndices.push_back(node->matrixNodeIndex()); mVDBuses.push_back(node); } // VD and PV type component connect -> set as VD bus else if (connectedPV && !connectedPQ && connectedVD) { - SPDLOG_LOGGER_DEBUG( + SPDLOG_LOGGER_INFO( mSLog, "{}: VD and PV type component connect -> set as VD bus", node->name()); mVDBusIndices.push_back(node->matrixNodeIndex()); mVDBuses.push_back(node); } // VD, PV and PQ type component connect -> set as VD bus else if (connectedPV && connectedPQ && connectedVD) { - SPDLOG_LOGGER_DEBUG( + SPDLOG_LOGGER_INFO( mSLog, "{}: VD, PV and PQ type component connect -> set as VD bus", node->name()); mVDBusIndices.push_back(node->matrixNodeIndex()); @@ -259,57 +259,58 @@ void PFSolver::determinePFBusType() { void PFSolver::determineNodeBaseVoltages() { - SPDLOG_LOGGER_INFO(mSLog, "-- Determine base voltages for each node according to connected components"); - mSLog->flush(); + SPDLOG_LOGGER_INFO(mSLog, "-- Determine base voltages for each node " + "according to connected components"); + mSLog->flush(); - for (auto node : mSystem.mNodes) { - CPS::Real baseVoltage_ = 0; - for (auto comp : mSystem.mComponentsAtNode[node]) { - if (std::shared_ptr vsi = std::dynamic_pointer_cast(comp)) { - baseVoltage_=Math::abs(vsi->attributeTyped("vnom")->get()); - SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, vsi->name(), node->name()); - break; - } - else if (std::shared_ptr rxline = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = rxline->attributeTyped("base_Voltage")->get(); - SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, rxline->name(), node->name()); - break; - } - else if (std::shared_ptr line = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = line->attributeTyped("base_Voltage")->get(); - SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, line->name(), node->name()); - break; - } - else if (std::shared_ptr trans = std::dynamic_pointer_cast(comp)) { - if (trans->terminal(0)->node()->name() == node->name()){ - baseVoltage_ = trans->attributeTyped("nominal_voltage_end1")->get(); - SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, trans->name(), node->name()); - break; - } - else if (trans->terminal(1)->node()->name() == node->name()){ - baseVoltage_ = trans->attributeTyped("nominal_voltage_end2")->get(); - SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, trans->name(), node->name()); - break; - } - } - else if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = gen->attributeTyped("base_Voltage")->get(); - SPDLOG_LOGGER_INFO(mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, gen->name(), node->name()); - break; - } - else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = load->attributeTyped("V_nom")->get(); - mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", baseVoltage_, load->name(), node->name()); - break; - } - else if (std::shared_ptr extnet = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = extnet->attributeTyped("base_Voltage")->get(); - mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", baseVoltage_, extnet->name(), node->name()); - break; - } - else { - SPDLOG_LOGGER_WARN(mSLog, "Unable to get base voltage at {}", node->name()); - } + for (auto node : mSystem.mNodes) { + CPS::Real baseVoltage_ = 0; + for (auto comp : mSystem.mComponentsAtNode[node]) { + if (std::shared_ptr vsi = + std::dynamic_pointer_cast< + CPS::SP::Ph1::AvVoltageSourceInverterDQ>(comp)) { + baseVoltage_ = + Math::abs(vsi->attributeTyped("vnom")->get()); + SPDLOG_LOGGER_INFO( + mSLog, + "Choose base voltage {}V of {} to convert pu-solution of {}.", + baseVoltage_, vsi->name(), node->name()); + break; + } else if (std::shared_ptr rxline = + std::dynamic_pointer_cast(comp)) { + baseVoltage_ = rxline->attributeTyped("base_Voltage")->get(); + SPDLOG_LOGGER_INFO( + mSLog, + "Choose base voltage {}V of {} to convert pu-solution of {}.", + baseVoltage_, rxline->name(), node->name()); + break; + } else if (std::shared_ptr line = + std::dynamic_pointer_cast(comp)) { + baseVoltage_ = line->attributeTyped("base_Voltage")->get(); + SPDLOG_LOGGER_INFO( + mSLog, + "Choose base voltage {}V of {} to convert pu-solution of {}.", + baseVoltage_, line->name(), node->name()); + break; + } else if (std::shared_ptr trans = + std::dynamic_pointer_cast( + comp)) { + if (trans->terminal(0)->node()->name() == node->name()) { + baseVoltage_ = + trans->attributeTyped("nominal_voltage_end1")->get(); + SPDLOG_LOGGER_INFO( + mSLog, + "Choose base voltage {}V of {} to convert pu-solution of {}.", + baseVoltage_, trans->name(), node->name()); + break; + } else if (trans->terminal(1)->node()->name() == node->name()) { + baseVoltage_ = + trans->attributeTyped("nominal_voltage_end2")->get(); + SPDLOG_LOGGER_INFO( + mSLog, + "Choose base voltage {}V of {} to convert pu-solution of {}.", + baseVoltage_, trans->name(), node->name()); + break; } } else if (std::shared_ptr gen = std::dynamic_pointer_cast( @@ -320,6 +321,19 @@ void PFSolver::determineNodeBaseVoltages() { "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, gen->name(), node->name()); break; + } else if (std::shared_ptr load = + std::dynamic_pointer_cast(comp)) { + baseVoltage_ = load->attributeTyped("V_nom")->get(); + mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", + baseVoltage_, load->name(), node->name()); + break; + } else if (std::shared_ptr extnet = + std::dynamic_pointer_cast( + comp)) { + baseVoltage_ = extnet->attributeTyped("base_Voltage")->get(); + mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", + baseVoltage_, extnet->name(), node->name()); + break; } else { SPDLOG_LOGGER_WARN(mSLog, "Unable to get base voltage at {}", node->name()); @@ -470,4 +484,4 @@ void PFSolver::SolveTask::execute(Real time, Int timeStepCount) { Task::List PFSolver::getTasks() { return Task::List{std::make_shared(*this)}; -} +} \ No newline at end of file diff --git a/dpsim/src/PFSolverPowerPolar.cpp b/dpsim/src/PFSolverPowerPolar.cpp index e200852a48..b5954f40ae 100644 --- a/dpsim/src/PFSolverPowerPolar.cpp +++ b/dpsim/src/PFSolverPowerPolar.cpp @@ -32,106 +32,46 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, load->calculatePerUnitParameters(mBaseApparentPower, mSystem.mSystemOmega); } + } - // set initial solution for the new time - for (auto pq : mPQBuses) { - if (!keep_last_solution) { - sol_V(pq->matrixNodeIndex()) = 1.0; - sol_D(pq->matrixNodeIndex()) = 0.0; - sol_V_complex(pq->matrixNodeIndex()) = CPS::Complex(sol_V[pq->matrixNodeIndex()], sol_D[pq->matrixNodeIndex()]); - } - for (auto comp : mSystem.mComponentsAtNode[pq]) { - if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { - sol_P(pq->matrixNodeIndex()) -= load->attributeTyped("P_pu")->get(); - sol_Q(pq->matrixNodeIndex()) -= load->attributeTyped("Q_pu")->get(); - } - else if(std::shared_ptr sst = - std::dynamic_pointer_cast(comp)){ - sol_P(pq->matrixNodeIndex()) -= sst->getNodalInjection(pq).real(); - sol_Q(pq->matrixNodeIndex()) -= sst->getNodalInjection(pq).imag(); - } - else if (std::shared_ptr vsi = - std::dynamic_pointer_cast(comp)) { - // TODO: add per-unit attributes to VSI and use here - sol_P(pq->matrixNodeIndex()) += vsi->attributeTyped("P_ref")->get() / mBaseApparentPower; - sol_Q(pq->matrixNodeIndex()) += vsi->attributeTyped("Q_ref")->get() / mBaseApparentPower; - } - else if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { - sol_P(pq->matrixNodeIndex()) += gen->attributeTyped("P_set_pu")->get(); - sol_Q(pq->matrixNodeIndex()) += gen->attributeTyped("Q_set_pu")->get(); - } - sol_S_complex(pq->matrixNodeIndex()) = CPS::Complex(sol_P[pq->matrixNodeIndex()], sol_Q[pq->matrixNodeIndex()]); - } - } - - for (auto pv : mPVBuses) { - if (!keep_last_solution) { - sol_Q(pv->matrixNodeIndex()) = 0; - sol_D(pv->matrixNodeIndex()) = 0; - } - for (auto comp : mSystem.mComponentsAtNode[pv]) { - if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { - sol_P(pv->matrixNodeIndex()) += gen->attributeTyped("P_set_pu")->get(); - sol_V(pv->matrixNodeIndex()) = gen->attributeTyped("V_set_pu")->get(); - sol_Q(pv->matrixNodeIndex()) += gen->attributeTyped("Q_set_pu")->get(); - } - else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { - sol_P(pv->matrixNodeIndex()) -= load->attributeTyped("P_pu")->get(); - sol_Q(pv->matrixNodeIndex()) -= load->attributeTyped("Q_pu")->get(); - } - else if (std::shared_ptr vsi = - std::dynamic_pointer_cast(comp)) { - sol_P(pv->matrixNodeIndex()) += vsi->attributeTyped("P_ref")->get() / mBaseApparentPower; - } - else if (std::shared_ptr extnet = - std::dynamic_pointer_cast(comp)) { - sol_P(pv->matrixNodeIndex()) += extnet->attributeTyped("p_inj")->get() / mBaseApparentPower; - sol_V(pv->matrixNodeIndex()) = extnet->attributeTyped("V_set_pu")->get(); - // sol_Q(pv->matrixNodeIndex()) += extnet->attributeTyped("q_inj")->get() / mBaseApparentPower; //Todo allow initialisation of p_inj and q_inj in SP_NetworkInjection (use updatePowerInjection?) - } - sol_S_complex(pv->matrixNodeIndex()) = CPS::Complex(sol_P[pv->matrixNodeIndex()], sol_Q[pv->matrixNodeIndex()]); - sol_V_complex(pv->matrixNodeIndex()) = CPS::Complex(sol_V[pv->matrixNodeIndex()], sol_D[pv->matrixNodeIndex()]); - } - } - - for (auto vd : mVDBuses) { - sol_P(vd->matrixNodeIndex()) = 0.0; - sol_Q(vd->matrixNodeIndex()) = 0.0; - sol_V(vd->matrixNodeIndex()) = 1.0; - sol_D(vd->matrixNodeIndex()) = 0.0; - - // if external injection at VD bus, reset the voltage to injection's voltage set-point - for (auto comp : mSystem.mComponentsAtNode[vd]) { - if (std::shared_ptr extnet = std::dynamic_pointer_cast(comp)) { - sol_V(vd->matrixNodeIndex()) = extnet->attributeTyped("V_set_pu")->get(); - sol_P(vd->matrixNodeIndex()) += extnet->attributeTyped("p_inj")->get() / mBaseApparentPower; // Todo add p_set q_set to extnet - sol_Q(vd->matrixNodeIndex()) += extnet->attributeTyped("q_inj")->get() / mBaseApparentPower; - } - - // if load at VD bus, substract P and Q - else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { - sol_P(vd->matrixNodeIndex()) -= load->attributeTyped("P_pu")->get(); - sol_Q(vd->matrixNodeIndex()) -= load->attributeTyped("Q_pu")->get(); - } - - // if generator at VD, add P_set Q_Set - else if (std::shared_ptr gen = std::dynamic_pointer_cast(comp)) { - sol_P(vd->matrixNodeIndex()) += gen->attributeTyped("P_set_pu")->get(); - sol_Q(vd->matrixNodeIndex()) += gen->attributeTyped("Q_set_pu")->get(); - } - } - - // if generator at VD bus, reset the voltage to generator's set-point - if (!mSynchronGenerators.empty()) { - for (auto gen : mSynchronGenerators) - { - if (gen->node(0)->matrixNodeIndex() == vd->matrixNodeIndex()) - sol_V(vd->matrixNodeIndex()) = gen->attributeTyped("V_set_pu")->get(); - } - } - - sol_S_complex(vd->matrixNodeIndex()) = CPS::Complex(sol_P[vd->matrixNodeIndex()], sol_Q[vd->matrixNodeIndex()]); - sol_V_complex(vd->matrixNodeIndex()) = CPS::Complex(sol_V[vd->matrixNodeIndex()], sol_D[vd->matrixNodeIndex()]); + // set initial solution for the new time + for (auto pq : mPQBuses) { + if (!keep_last_solution) { + sol_V(pq->matrixNodeIndex()) = 1.0; + sol_D(pq->matrixNodeIndex()) = 0.0; + sol_V_complex(pq->matrixNodeIndex()) = CPS::Complex( + sol_V[pq->matrixNodeIndex()], sol_D[pq->matrixNodeIndex()]); + } + for (auto comp : mSystem.mComponentsAtNode[pq]) { + if (std::shared_ptr load = + std::dynamic_pointer_cast(comp)) { + sol_P(pq->matrixNodeIndex()) -= + load->attributeTyped("P_pu")->get(); + sol_Q(pq->matrixNodeIndex()) -= + load->attributeTyped("Q_pu")->get(); + } else if (std::shared_ptr sst = + std::dynamic_pointer_cast< + CPS::SP::Ph1::SolidStateTransformer>(comp)) { + sol_P(pq->matrixNodeIndex()) -= sst->getNodalInjection(pq).real(); + sol_Q(pq->matrixNodeIndex()) -= sst->getNodalInjection(pq).imag(); + } else if (std::shared_ptr vsi = + std::dynamic_pointer_cast< + CPS::SP::Ph1::AvVoltageSourceInverterDQ>(comp)) { + // TODO: add per-unit attributes to VSI and use here + sol_P(pq->matrixNodeIndex()) += + vsi->attributeTyped("P_ref")->get() / mBaseApparentPower; + sol_Q(pq->matrixNodeIndex()) += + vsi->attributeTyped("Q_ref")->get() / mBaseApparentPower; + } else if (std::shared_ptr gen = + std::dynamic_pointer_cast( + comp)) { + sol_P(pq->matrixNodeIndex()) += + gen->attributeTyped("P_set_pu")->get(); + sol_Q(pq->matrixNodeIndex()) += + gen->attributeTyped("Q_set_pu")->get(); + } + sol_S_complex(pq->matrixNodeIndex()) = CPS::Complex( + sol_P[pq->matrixNodeIndex()], sol_Q[pq->matrixNodeIndex()]); } } @@ -148,10 +88,14 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, gen->attributeTyped("P_set_pu")->get(); sol_V(pv->matrixNodeIndex()) = gen->attributeTyped("V_set_pu")->get(); + sol_Q(pv->matrixNodeIndex()) += + gen->attributeTyped("Q_set_pu")->get(); } else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { sol_P(pv->matrixNodeIndex()) -= load->attributeTyped("P_pu")->get(); + sol_Q(pv->matrixNodeIndex()) -= + load->attributeTyped("Q_pu")->get(); } else if (std::shared_ptr vsi = std::dynamic_pointer_cast< CPS::SP::Ph1::AvVoltageSourceInverterDQ>(comp)) { @@ -618,4 +562,4 @@ CPS::Real PFSolverPowerPolar::sol_Vi(UInt k) { CPS::Complex PFSolverPowerPolar::sol_Vcx(UInt k) { return CPS::Complex(sol_Vr(k), sol_Vi(k)); -} +} \ No newline at end of file diff --git a/dpsim/src/Utils.cpp b/dpsim/src/Utils.cpp index 1619d1c411..cad402f359 100644 --- a/dpsim/src/Utils.cpp +++ b/dpsim/src/Utils.cpp @@ -98,8 +98,8 @@ CommandLineArgs::CommandLineArgs(String nm, Real dt, Real d, Real sf, Int s, {"name", required_argument, 0, 'n', "NAME", "Name of log files"}, {0}}, timeStep(dt), duration(d), sysFreq(sf), scenario(s), logLevel(ll), - cliLogLevel(clill), name(nm), startSynch(ss), blocking(b), steadyInit(si), - solver{sd, st}, directImpl(mi), solverPluginName(spn) {} + cliLogLevel(clill), name(nm), startSynch(ss), blocking(b), + steadyInit(si), solver{sd, st}, directImpl(mi), solverPluginName(spn) {} void CommandLineArgs::parseArguments(int argc, char *argv[]) { mProgramName = argv[0]; From 2e980c1ca9260a4e31abc52fe40e9d35412eccbf Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 7 Apr 2025 10:45:25 +0200 Subject: [PATCH 058/168] Minimize file changes Signed-off-by: Leonardo Carreras --- dpsim-models/src/DP/DP_Ph1_PiLine.cpp | 4 ++-- dpsim-models/src/DP/DP_Ph1_RxLine.cpp | 4 ++-- dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp | 5 ++--- dpsim-models/src/DP/DP_Ph1_Transformer.cpp | 5 ++--- dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp | 5 ++--- dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp | 4 ++-- dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp | 4 ++-- dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp | 5 ++--- dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp | 5 ++--- dpsim-models/src/SP/SP_Ph1_Load.cpp | 2 +- dpsim-models/src/SP/SP_Ph1_PiLine.cpp | 4 ++-- dpsim-models/src/SP/SP_Ph1_RXLine.cpp | 8 ++++---- dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp | 5 ++--- dpsim-models/src/SP/SP_Ph1_Transformer.cpp | 4 ++-- dpsim/src/Utils.cpp | 4 ++-- 15 files changed, 31 insertions(+), 37 deletions(-) diff --git a/dpsim-models/src/DP/DP_Ph1_PiLine.cpp b/dpsim-models/src/DP/DP_Ph1_PiLine.cpp index 91f4223358..81d08e4013 100644 --- a/dpsim-models/src/DP/DP_Ph1_PiLine.cpp +++ b/dpsim-models/src/DP/DP_Ph1_PiLine.cpp @@ -11,8 +11,8 @@ using namespace CPS; DP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), CompositePowerComp( - uid, name, true, true, logLevel) { + : Base::Ph1::PiLine(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel) { setVirtualNodeNumber(1); setTerminalNumber(2); diff --git a/dpsim-models/src/DP/DP_Ph1_RxLine.cpp b/dpsim-models/src/DP/DP_Ph1_RxLine.cpp index 217959ce44..d41e32c1b5 100644 --- a/dpsim-models/src/DP/DP_Ph1_RxLine.cpp +++ b/dpsim-models/src/DP/DP_Ph1_RxLine.cpp @@ -11,8 +11,8 @@ using namespace CPS; DP::Ph1::RxLine::RxLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), CompositePowerComp( - uid, name, true, true, logLevel) { + : Base::Ph1::PiLine(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel) { setVirtualNodeNumber(1); setTerminalNumber(2); diff --git a/dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp b/dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp index 7ec24659a8..af9559e8b6 100644 --- a/dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp +++ b/dpsim-models/src/DP/DP_Ph1_SynchronGeneratorTrStab.cpp @@ -11,9 +11,8 @@ using namespace CPS; DP::Ph1::SynchronGeneratorTrStab::SynchronGeneratorTrStab( String uid, String name, Logger::Level logLevel) - : Base::SynchronGenerator(mAttributes), CompositePowerComp( - uid, name, true, true, - logLevel), + : Base::SynchronGenerator(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel), mEp(mAttributes->create("Ep")), mEp_abs(mAttributes->create("Ep_mag")), mEp_phase(mAttributes->create("Ep_phase")), diff --git a/dpsim-models/src/DP/DP_Ph1_Transformer.cpp b/dpsim-models/src/DP/DP_Ph1_Transformer.cpp index 0a70ddef97..b8b1084731 100644 --- a/dpsim-models/src/DP/DP_Ph1_Transformer.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Transformer.cpp @@ -13,9 +13,8 @@ using namespace CPS; DP::Ph1::Transformer::Transformer(String uid, String name, Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph1::Transformer(mAttributes), CompositePowerComp( - uid, name, true, true, - logLevel) { + : Base::Ph1::Transformer(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel) { if (withResistiveLosses) setVirtualNodeNumber(3); else diff --git a/dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp b/dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp index 6c1b852407..e12376fdf3 100644 --- a/dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp +++ b/dpsim-models/src/DP/DP_Ph1_VoltageSourceNorton.cpp @@ -12,9 +12,8 @@ using namespace CPS; DP::Ph1::VoltageSourceNorton::VoltageSourceNorton(String uid, String name, Logger::Level logLevel) - : Base::Ph1::VoltageSource(mAttributes), MNASimPowerComp( - uid, name, true, true, - logLevel), + : Base::Ph1::VoltageSource(mAttributes), + MNASimPowerComp(uid, name, true, true, logLevel), mResistance(mAttributes->create("R")) { setTerminalNumber(2); **mIntfVoltage = MatrixComp::Zero(1, 1); diff --git a/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp b/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp index 7888161332..3fef318e8a 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp @@ -11,8 +11,8 @@ using namespace CPS; EMT::Ph3::PiLine::PiLine(String uid, String name, Logger::Level logLevel) - : Base::Ph3::PiLine(mAttributes), CompositePowerComp(uid, name, true, - true, logLevel) { + : Base::Ph3::PiLine(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel) { mPhaseType = PhaseType::ABC; setVirtualNodeNumber(1); setTerminalNumber(2); diff --git a/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp b/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp index d4d02b6780..07cf7fb412 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp @@ -14,8 +14,8 @@ using namespace CPS; // !!! with initialization from phase-to-phase RMS variables EMT::Ph3::RxLine::RxLine(String uid, String name, Logger::Level logLevel) - : Base::Ph3::PiLine(mAttributes), CompositePowerComp(uid, name, true, - true, logLevel) { + : Base::Ph3::PiLine(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel) { mPhaseType = PhaseType::ABC; setVirtualNodeNumber(1); setTerminalNumber(2); diff --git a/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp b/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp index d78653f662..ac96992a3c 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp @@ -32,9 +32,8 @@ Matrix EMT::Ph3::SynchronGeneratorTrStab::getParkTransformMatrixPowerInvariant( EMT::Ph3::SynchronGeneratorTrStab::SynchronGeneratorTrStab( String uid, String name, Logger::Level logLevel) - : Base::SynchronGenerator(mAttributes), CompositePowerComp(uid, name, - true, true, - logLevel), + : Base::SynchronGenerator(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel), mEp(mAttributes->create("Ep")), mEp_abs(mAttributes->create("Ep_mag")), mEp_phase(mAttributes->create("Ep_phase")), diff --git a/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp b/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp index d9a370c8e7..f86f4aa64a 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp @@ -13,9 +13,8 @@ using namespace CPS; EMT::Ph3::Transformer::Transformer(String uid, String name, Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph3::Transformer(mAttributes), CompositePowerComp(uid, name, - true, true, - logLevel) { + : Base::Ph3::Transformer(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel) { mPhaseType = PhaseType::ABC; if (withResistiveLosses) setVirtualNodeNumber(3); diff --git a/dpsim-models/src/SP/SP_Ph1_Load.cpp b/dpsim-models/src/SP/SP_Ph1_Load.cpp index 8b834d3b0d..a021554c97 100644 --- a/dpsim-models/src/SP/SP_Ph1_Load.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Load.cpp @@ -198,4 +198,4 @@ void SP::Ph1::Load::mnaCompUpdateCurrent(const Matrix &leftVector) { for (auto &subc : mSubComponents) { (**mIntfCurrent)(0, 0) += subc->intfCurrent()(0, 0); } -} \ No newline at end of file +} diff --git a/dpsim-models/src/SP/SP_Ph1_PiLine.cpp b/dpsim-models/src/SP/SP_Ph1_PiLine.cpp index aae0abcd4d..acb6cad204 100644 --- a/dpsim-models/src/SP/SP_Ph1_PiLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_PiLine.cpp @@ -11,8 +11,8 @@ using namespace CPS; SP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), CompositePowerComp( - uid, name, false, true, logLevel), + : Base::Ph1::PiLine(mAttributes), + CompositePowerComp(uid, name, false, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage")), mCurrent(mAttributes->create("current_vector")), mActivePowerBranch(mAttributes->create("p_branch_vector")), diff --git a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp index dcd69253c6..78c1340030 100644 --- a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp @@ -13,8 +13,8 @@ using namespace CPS; SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage, Real resistance, Real inductance, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), CompositePowerComp( - uid, name, true, true, logLevel), + : Base::Ph1::PiLine(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage", baseVoltage)), mInductance(mAttributes->create("L_series")), mActivePowerInjection(mAttributes->create("p_inj")), @@ -37,8 +37,8 @@ SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage, } SP::Ph1::RXLine::RXLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), CompositePowerComp( - uid, name, true, true, logLevel), + : Base::Ph1::PiLine(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage")), mInductance(mAttributes->create("L_series")), mActivePowerInjection(mAttributes->create("p_inj")), diff --git a/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp b/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp index 094fe838d8..42e5d22a05 100644 --- a/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp +++ b/dpsim-models/src/SP/SP_Ph1_SynchronGeneratorTrStab.cpp @@ -11,9 +11,8 @@ using namespace CPS; SP::Ph1::SynchronGeneratorTrStab::SynchronGeneratorTrStab( String uid, String name, Logger::Level logLevel) - : Base::SynchronGenerator(mAttributes), CompositePowerComp( - uid, name, true, true, - logLevel), + : Base::SynchronGenerator(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel), mEp(mAttributes->create("Ep")), mEp_abs(mAttributes->create("Ep_mag")), mEp_phase(mAttributes->create("Ep_phase")), diff --git a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp index 1aaae0b8ec..e94606355e 100644 --- a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp @@ -14,8 +14,8 @@ using namespace CPS; SP::Ph1::Transformer::Transformer(String uid, String name, Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph1::Transformer(mAttributes), CompositePowerComp( - uid, name, true, true, logLevel), + : Base::Ph1::Transformer(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage")), mCurrent(mAttributes->create("current_vector")), mActivePowerBranch(mAttributes->create("p_branch_vector")), diff --git a/dpsim/src/Utils.cpp b/dpsim/src/Utils.cpp index cad402f359..1619d1c411 100644 --- a/dpsim/src/Utils.cpp +++ b/dpsim/src/Utils.cpp @@ -98,8 +98,8 @@ CommandLineArgs::CommandLineArgs(String nm, Real dt, Real d, Real sf, Int s, {"name", required_argument, 0, 'n', "NAME", "Name of log files"}, {0}}, timeStep(dt), duration(d), sysFreq(sf), scenario(s), logLevel(ll), - cliLogLevel(clill), name(nm), startSynch(ss), blocking(b), - steadyInit(si), solver{sd, st}, directImpl(mi), solverPluginName(spn) {} + cliLogLevel(clill), name(nm), startSynch(ss), blocking(b), steadyInit(si), + solver{sd, st}, directImpl(mi), solverPluginName(spn) {} void CommandLineArgs::parseArguments(int argc, char *argv[]) { mProgramName = argv[0]; From d0d3bac6c257f937aaf91b4292b26254dbc7f654 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 7 Apr 2025 10:45:55 +0200 Subject: [PATCH 059/168] Fixes in PFSolver Signed-off-by: Leonardo Carreras --- dpsim/src/PFSolver.cpp | 12 +++++++----- dpsim/src/PFSolverPowerPolar.cpp | 5 ++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/dpsim/src/PFSolver.cpp b/dpsim/src/PFSolver.cpp index 445b628796..c929591831 100644 --- a/dpsim/src/PFSolver.cpp +++ b/dpsim/src/PFSolver.cpp @@ -324,15 +324,17 @@ void PFSolver::determineNodeBaseVoltages() { } else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { baseVoltage_ = load->attributeTyped("V_nom")->get(); - mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", - baseVoltage_, load->name(), node->name()); + SPDLOG_LOGGER_INFO( + mSLog, "Choose base voltage of {}V to convert pu-solution of {}.", + baseVoltage_, load->name(), node->name()); break; } else if (std::shared_ptr extnet = std::dynamic_pointer_cast( comp)) { baseVoltage_ = extnet->attributeTyped("base_Voltage")->get(); - mSLog->info("Choose base voltage of {}V to convert pu-solution of {}.", - baseVoltage_, extnet->name(), node->name()); + SPDLOG_LOGGER_INFO( + mSLog, "Choose base voltage of {}V to convert pu-solution of {}.", + baseVoltage_, extnet->name(), node->name()); break; } else { SPDLOG_LOGGER_WARN(mSLog, "Unable to get base voltage at {}", @@ -484,4 +486,4 @@ void PFSolver::SolveTask::execute(Real time, Int timeStepCount) { Task::List PFSolver::getTasks() { return Task::List{std::make_shared(*this)}; -} \ No newline at end of file +} diff --git a/dpsim/src/PFSolverPowerPolar.cpp b/dpsim/src/PFSolverPowerPolar.cpp index b5954f40ae..87e014af1e 100644 --- a/dpsim/src/PFSolverPowerPolar.cpp +++ b/dpsim/src/PFSolverPowerPolar.cpp @@ -107,6 +107,9 @@ void PFSolverPowerPolar::generateInitialSolution(Real time, sol_P(pv->matrixNodeIndex()) += extnet->attributeTyped("p_inj")->get() / mBaseApparentPower; + sol_Q(pv->matrixNodeIndex()) += + extnet->attributeTyped("q_inj")->get() / + mBaseApparentPower; sol_V(pv->matrixNodeIndex()) = extnet->attributeTyped("V_set_pu")->get(); } @@ -562,4 +565,4 @@ CPS::Real PFSolverPowerPolar::sol_Vi(UInt k) { CPS::Complex PFSolverPowerPolar::sol_Vcx(UInt k) { return CPS::Complex(sol_Vr(k), sol_Vi(k)); -} \ No newline at end of file +} From 6db438a70099c678cbcb53bb425eaaefbdc590fb Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 7 Apr 2025 10:46:31 +0200 Subject: [PATCH 060/168] Allow to initialize q_ing in extnet Signed-off-by: Leonardo Carreras --- dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h | 2 +- dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h index fc6e720e44..bf99c32006 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h @@ -127,4 +127,4 @@ class NetworkInjection : public CompositePowerComp, }; } // namespace Ph1 } // namespace SP -} // namespace CPS \ No newline at end of file +} // namespace CPS diff --git a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp index 5563b5f942..22618dba68 100644 --- a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp +++ b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp @@ -230,4 +230,4 @@ void SP::Ph1::NetworkInjection::daeResidual(double ttime, const double state[], Complex SP::Ph1::NetworkInjection::daeInitialize() { (**mIntfVoltage)(0, 0) = (**mSubVoltageSource->mIntfVoltage)(0, 0); return (**mSubVoltageSource->mIntfVoltage)(0, 0); -} \ No newline at end of file +} From 145f31d48eeb51b5e1a6363c9954936de5d12ef6 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 7 Apr 2025 13:04:41 +0200 Subject: [PATCH 061/168] Fix format of logs Signed-off-by: Leonardo Carreras --- dpsim-models/src/SP/SP_Ph1_Load.cpp | 2 +- dpsim/src/PFSolver.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/dpsim-models/src/SP/SP_Ph1_Load.cpp b/dpsim-models/src/SP/SP_Ph1_Load.cpp index a021554c97..ef4b8ccddf 100644 --- a/dpsim-models/src/SP/SP_Ph1_Load.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Load.cpp @@ -38,7 +38,7 @@ void SP::Ph1::Load::setParameters(Real activePower, Real reactivePower, SPDLOG_LOGGER_INFO( mSLog, - "Active Power={}[W]\nReactive Power={} [VAr]\nNominal Voltage={} [V]", + "Active Power={} [W] Reactive Power={} [VAr] Nominal Voltage={} [V]", **mActivePower, **mReactivePower, **mNomVoltage); mSLog->flush(); diff --git a/dpsim/src/PFSolver.cpp b/dpsim/src/PFSolver.cpp index c929591831..73297ed001 100644 --- a/dpsim/src/PFSolver.cpp +++ b/dpsim/src/PFSolver.cpp @@ -325,7 +325,7 @@ void PFSolver::determineNodeBaseVoltages() { std::dynamic_pointer_cast(comp)) { baseVoltage_ = load->attributeTyped("V_nom")->get(); SPDLOG_LOGGER_INFO( - mSLog, "Choose base voltage of {}V to convert pu-solution of {}.", + mSLog, "Choose base voltage of {} V to convert pu-solution of {}.", baseVoltage_, load->name(), node->name()); break; } else if (std::shared_ptr extnet = From dcafb753ba5f1ba12a9c2b1fcfc4050cae757873 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 25 Mar 2025 01:53:56 +0100 Subject: [PATCH 062/168] chore(cmake): Rename "KLU" dependency to name of actual library "SuiteSparse" Signed-off-by: Steffen Vogel --- CMakeLists.txt | 90 ++++++++++--------- cmake/FetchJson.cmake | 11 +++ cmake/FetchJsonLibrary.cmake | 9 -- cmake/FetchReaderWriterQueue.cmake | 2 + ...{FetchKLU.cmake => FetchSuiteSparse.cmake} | 8 +- cmake/FindCIMpp.cmake | 15 ++-- cmake/FindSuiteSparse.cmake | 35 ++++++++ cmake/FindSundials.cmake | 2 +- dpsim/include/dpsim/MNASolverFactory.h | 2 +- dpsim/src/CMakeLists.txt | 17 ++-- 10 files changed, 118 insertions(+), 73 deletions(-) create mode 100644 cmake/FetchJson.cmake delete mode 100644 cmake/FetchJsonLibrary.cmake rename cmake/{FetchKLU.cmake => FetchSuiteSparse.cmake} (55%) create mode 100644 cmake/FindSuiteSparse.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index cf57badcea..98e5e1a55e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,27 +13,28 @@ set(PROJECT_HOMEPAGE_URL "https://dpsim.fein-aachen.org/") set(PROJECT_VCS_URL "https://github.com/sogno-platform/dpsim") # Build options -option(FETCH_EIGEN "Fetch Eigen3 as module" OFF) -option(FETCH_KLU "Fetch KLU as module" ON) -option(FETCH_SPDLOG "Fetch spdlog as module" OFF) -option(FETCH_CIMPP "Fetch CIMpp as module" OFF) -option(FETCH_PYBIND "Fetch pybind11 as module" OFF) -option(FETCH_GRID_DATA "Fetch grid data" ON) -option(FETCH_FILESYSTEM "Fetch standalone implementation of std::filesystem" OFF) -option(FETCH_JSON "Fetch json library as module" ON) - -option(WITH_LTO "Enable Link Time Optimization in Release builds" OFF) -option(WITH_MARCH_NATIVE "Optimize build for native host architecture" OFF) -option(WITH_PROFILING "Add `-pg` profiling flag to compilation" OFF) -option(WITH_ASAN "Adds compiler flags to use the address sanitizer" OFF) -option(WITH_TSAN "Adds compiler flags to use the thread sanitizer" OFF) -option(WITH_SPARSE "Use sparse matrices in MNA-Solver" ON) - -option(BUILD_SHARED_LIBS "Build shared library" OFF) -option(DPSIM_BUILD_EXAMPLES "Build C++ examples" ON) -option(DPSIM_BUILD_DOC "Build documentation" ON) - -option(CGMES_BUILD "Build with CGMES instead of CIMpp" OFF) +option(FETCH_EIGEN "Fetch Eigen3 as module" OFF) +option(FETCH_SUITESPARSE "Fetch SuiteSparse as module" ON) +option(FETCH_SPDLOG "Fetch spdlog as module" OFF) +option(FETCH_CIMPP "Fetch CIMpp as module" OFF) +option(FETCH_PYBIND "Fetch pybind11 as module" OFF) +option(FETCH_GRID_DATA "Fetch grid data" ON) +option(FETCH_FILESYSTEM "Fetch standalone implementation of std::filesystem" OFF) +option(FETCH_JSON "Fetch json library as module" ON) +option(FETCH_READERWRITERQUEUE "Fetch readerwriterqueue as module" ON) + +option(WITH_LTO "Enable Link Time Optimization in Release builds" OFF) +option(WITH_MARCH_NATIVE "Optimize build for native host architecture" OFF) +option(WITH_PROFILING "Add `-pg` profiling flag to compilation" OFF) +option(WITH_ASAN "Adds compiler flags to use the address sanitizer" OFF) +option(WITH_TSAN "Adds compiler flags to use the thread sanitizer" OFF) +option(WITH_SPARSE "Use sparse matrices in MNA-Solver" ON) + +option(BUILD_SHARED_LIBS "Build shared library" OFF) +option(DPSIM_BUILD_EXAMPLES "Build C++ examples" ON) +option(DPSIM_BUILD_DOC "Build documentation" ON) + +option(CGMES_BUILD "Build with CGMES instead of CIMpp" OFF) # Required for dpsim_python @@ -151,8 +152,10 @@ else() find_package(Eigen3 3.0 REQUIRED) endif() -if (FETCH_KLU) - include(FetchKLU) +if(FETCH_SUITESPARSE) + include(FetchSuiteSparse) +else() + find_package(SuiteSparse 5.10) endif() if(FETCH_SPDLOG OR WIN32) @@ -179,7 +182,15 @@ if(FETCH_GRID_DATA) endif() if(FETCH_JSON) - include(FetchJsonLibrary) + include(FetchJson) +else() + find_package(nlohmann_json 3.9.1 REQUIRED) +endif() + +if(FETCH_READERWRITERQUEUE) + include(FetchReaderWriterQueue) +else() + find_package(readerwriterqueue 1.0.0 REQUIRED) endif() if(WITH_PROFILING) @@ -203,8 +214,6 @@ if(WITH_TSAN) endif() endif() -include(FetchReaderWriterQueue) - if("${CMAKE_SYSTEM}" MATCHES "Linux") set(Linux_FOUND ON) elseif("${CMAKE_SYSTEM}" MATCHES "Darwin") @@ -212,18 +221,19 @@ elseif("${CMAKE_SYSTEM}" MATCHES "Darwin") endif() include(CMakeDependentOption) -cmake_dependent_option(WITH_SUNDIALS "Enable sundials solver suite" ON "Sundials_FOUND" OFF) -cmake_dependent_option(WITH_VILLAS "Enable VILLASnode interface" ON "VILLASnode_FOUND" OFF) -cmake_dependent_option(WITH_RT "Enable real-time features" ON "Linux_FOUND" OFF) -cmake_dependent_option(WITH_CIM "Enable support for parsing CIM" ON "CIMpp_FOUND" OFF) -cmake_dependent_option(WITH_OPENMP "Enable OpenMP-based parallelisation" ON "OPENMP_FOUND" OFF) -cmake_dependent_option(WITH_KLU "Enable KLU factorization" ON "FETCH_KLU" OFF) -cmake_dependent_option(WITH_CUDA "Enable CUDA-based parallelisation" OFF "CUDA_FOUND" OFF) -cmake_dependent_option(WITH_GRAPHVIZ "Enable Graphviz Graphs" ON "GRAPHVIZ_FOUND" OFF) -cmake_dependent_option(WITH_PYBIND "Enable PYBIND support" ON "pybind11_FOUND" OFF) -cmake_dependent_option(WITH_JSON "Enable JSON library support" ON "FETCH_JSON" OFF) -cmake_dependent_option(WITH_MAGMA "Enable MAGMA features" ON "MAGMA_FOUND" OFF) -cmake_dependent_option(WITH_MNASOLVERPLUGIN "Enable MNASolver Plugins" ON "NOT WIN32" OFF) +cmake_dependent_option(WITH_CIM "Enable support for parsing CIM" ON "CIMpp_FOUND" OFF) +cmake_dependent_option(WITH_CUDA "Enable CUDA-based parallelisation" OFF "CUDA_FOUND" OFF) +cmake_dependent_option(WITH_GRAPHVIZ "Enable Graphviz Graphs" ON "GRAPHVIZ_FOUND" OFF) +cmake_dependent_option(WITH_GSL "Enable GSL features" ON "GSL_FOUND" OFF) +cmake_dependent_option(WITH_JSON "Enable JSON library support" ON "nlohmann_json_FOUND" OFF) +cmake_dependent_option(WITH_KLU "Enable KLU factorization" ON "SuiteSparse_FOUND" OFF) +cmake_dependent_option(WITH_MAGMA "Enable MAGMA features" ON "MAGMA_FOUND" OFF) +cmake_dependent_option(WITH_MNASOLVERPLUGIN "Enable MNASolver Plugins" ON "NOT WIN32" OFF) +cmake_dependent_option(WITH_OPENMP "Enable OpenMP-based parallelisation" ON "OPENMP_FOUND" OFF) +cmake_dependent_option(WITH_PYBIND "Enable pybind support" ON "pybind11_FOUND" OFF) +cmake_dependent_option(WITH_RT "Enable real-time features" ON "Linux_FOUND" OFF) +cmake_dependent_option(WITH_SUNDIALS "Enable Sundials solver suite" ON "Sundials_FOUND" OFF) +cmake_dependent_option(WITH_VILLAS "Enable VILLASnode interface" ON "VILLASnode_FOUND" OFF) if(WITH_CUDA) # BEGIN OF WORKAROUND - enable cuda dynamic linking. @@ -282,7 +292,8 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) add_feature_info(CUDA WITH_CUDA "CUDA-based parallelisation") add_feature_info(Graphviz WITH_GRAPHVIZ "Graphviz graphs") add_feature_info(GSL WITH_GSL "GNU Scientific library") - add_feature_info(JSON WITH_JSON "JSON library") + add_feature_info(JSON WITH_JSON "JSON parsing") + add_feature_info(KLU WITH_KLU "Use sparse KLU factorization") add_feature_info(MAGMA WITH_MAGMA "MAGMA features") add_feature_info(MNASolverPlugin WITH_MNASOLVERPLUGIN "MNASolver Plugins") add_feature_info(OpenMP WITH_OPENMP "OpenMP-based parallelisation") @@ -290,7 +301,6 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) add_feature_info(RealTime WITH_RT "Extended real-time features") add_feature_info(Sundials WITH_SUNDIALS "Sundials solvers") add_feature_info(VILLASnode WITH_VILLAS "Interface DPsim solvers via VILLASnode interfaces") - add_feature_info(KLU WITH_KLU "Use custom KLU module") feature_summary(WHAT ALL VAR enabledFeaturesText) diff --git a/cmake/FetchJson.cmake b/cmake/FetchJson.cmake new file mode 100644 index 0000000000..9752bc9ee4 --- /dev/null +++ b/cmake/FetchJson.cmake @@ -0,0 +1,11 @@ +include(FetchContent) +FetchContent_Declare(json + GIT_REPOSITORY https://github.com/nlohmann/json + GIT_TAG v3.11.3 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE +) + +FetchContent_MakeAvailable(json) + +set(nlohmann_json_FOUND ON) diff --git a/cmake/FetchJsonLibrary.cmake b/cmake/FetchJsonLibrary.cmake deleted file mode 100644 index 9b361ddcf7..0000000000 --- a/cmake/FetchJsonLibrary.cmake +++ /dev/null @@ -1,9 +0,0 @@ -include(FetchContent) -FetchContent_Declare(json-module - GIT_REPOSITORY https://github.com/ArthurSonzogni/nlohmann_json_cmake_fetchcontent - GIT_TAG v3.9.1 - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE -) - -FetchContent_MakeAvailable(json-module) diff --git a/cmake/FetchReaderWriterQueue.cmake b/cmake/FetchReaderWriterQueue.cmake index 7fbd78e2c9..8d89131c90 100644 --- a/cmake/FetchReaderWriterQueue.cmake +++ b/cmake/FetchReaderWriterQueue.cmake @@ -7,3 +7,5 @@ FetchContent_Declare(readerwriterqueue-module ) FetchContent_MakeAvailable(readerwriterqueue-module) + +add_library(readerwriterqueue::readerwriterqueue ALIAS readerwriterqueue) diff --git a/cmake/FetchKLU.cmake b/cmake/FetchSuiteSparse.cmake similarity index 55% rename from cmake/FetchKLU.cmake rename to cmake/FetchSuiteSparse.cmake index d0719d6685..aaf1e257e9 100644 --- a/cmake/FetchKLU.cmake +++ b/cmake/FetchSuiteSparse.cmake @@ -1,8 +1,12 @@ include(FetchContent) FetchContent_Declare( - klu-module + suitesparse-module URL https://github.com/dpsim-simulator/SuiteSparse/releases/download/release-v5.10.6/SuiteSparse-release-v5.10.6.tar.gz ) -FetchContent_MakeAvailable(klu-module) +FetchContent_MakeAvailable(suitesparse-module) + +add_library(SuiteSparse::KLU ALIAS klu) + +set(SuiteSparse_FOUND ON) diff --git a/cmake/FindCIMpp.cmake b/cmake/FindCIMpp.cmake index b22b6115cc..08bb17aec3 100644 --- a/cmake/FindCIMpp.cmake +++ b/cmake/FindCIMpp.cmake @@ -6,8 +6,7 @@ message(STATUS "CIM Version: ${CIM_VERSION}") if(CIM_VERSION STREQUAL "16v29a") set(USE_CIM_VERSION "IEC61970_16v29a") -endif() -if(CIM_VERSION STREQUAL "CGMES_2.4.15_16FEB2016") +elseif(CIM_VERSION STREQUAL "CGMES_2.4.15_16FEB2016") set(USE_CIM_VERSION "CGMES_2.4.15_16FEB2016") set(CGMES_BUILD ON) endif() @@ -15,17 +14,17 @@ endif() find_path(CIMPP_INCLUDE_DIR NAMES CIMModel.hpp PATH_SUFFIXES - cimpp/${CIM_VERSION} - ${CIM_VERSION} - cimpp/${USE_CIM_VERSION} - ${USE_CIM_VERSION} - include/src + include/cimpp/${CIM_VERSION} + include/cimpp/${USE_CIM_VERSION} ) find_library(CIMPP_LIBRARY - NAMES cimpp${CIM_VERSION} cimpp${USE_CIM_VERSION} + NAMES + cimpp${CIM_VERSION} + cimpp${USE_CIM_VERSION} PATH_SUFFIXES lib/static + lib/cimpp ) set(CIMPP_LIBRARIES diff --git a/cmake/FindSuiteSparse.cmake b/cmake/FindSuiteSparse.cmake new file mode 100644 index 0000000000..80b4ab3e65 --- /dev/null +++ b/cmake/FindSuiteSparse.cmake @@ -0,0 +1,35 @@ +find_path(SUITESPARSE_INCLUDE_DIR NAMES amd.h) +find_library(SUITESPARSE_AMD_LIBRARY NAMES amd) +find_library(SUITESPARSE_COLAMD_LIBRARY NAMES colamd) +find_library(SUITESPARSE_BTF_LIBRARY NAMES btf) +find_library(SUITESPARSE_KLU_LIBRARY NAMES klu) + +set(SUITESPARSE_LIBRARIES ${SUITESPARSE_AMD_LIBRARY} ${SUITESPARSE_COLAMD_LIBRARY} ${SUITESPARSE_BTF_LIBRARY} ${SUITESPARSE_KLU_LIBRARY}) +set(SUITESPARSE_INCLUDE_DIRS ${SUITESPARSE_INCLUDE_DIR}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SuiteSparse DEFAULT_MSG SUITESPARSE_LIBRARIES SUITESPARSE_INCLUDE_DIR) + +mark_as_advanced(SUITESPARSE_INCLUDE_DIR SUITESPARSE_LIBRARIES) + +add_library(SuiteSparse::BTF STATIC IMPORTED) +set_property(TARGET SuiteSparse::BTF PROPERTY IMPORTED_LOCATION ${SUITESPARSE_BTF_LIBRARY}) +target_include_directories(SuiteSparse::BTF INTERFACE ${SUITESPARSE_INCLUDE_DIR}) + +add_library(SuiteSparse::COLAMD STATIC IMPORTED) +set_property(TARGET SuiteSparse::COLAMD PROPERTY IMPORTED_LOCATION ${SUITESPARSE_COLAMD_LIBRARY}) +target_include_directories(SuiteSparse::COLAMD INTERFACE ${SUITESPARSE_INCLUDE_DIR}) + +add_library(SuiteSparse::AMD STATIC IMPORTED) +set_property(TARGET SuiteSparse::AMD PROPERTY IMPORTED_LOCATION ${SUITESPARSE_AMD_LIBRARY}) +target_include_directories(SuiteSparse::AMD INTERFACE ${SUITESPARSE_INCLUDE_DIR}) + +add_library(SuiteSparse::KLU STATIC IMPORTED) +set_property(TARGET SuiteSparse::KLU PROPERTY IMPORTED_LOCATION ${SUITESPARSE_KLU_LIBRARY}) +target_include_directories(SuiteSparse::KLU INTERFACE ${SUITESPARSE_INCLUDE_DIR}) + +target_link_libraries(SuiteSparse::KLU INTERFACE + SuiteSparse::AMD + SuiteSparse::BTF + SuiteSparse::COLAMD +) diff --git a/cmake/FindSundials.cmake b/cmake/FindSundials.cmake index 59cc023e0d..9c5756c412 100644 --- a/cmake/FindSundials.cmake +++ b/cmake/FindSundials.cmake @@ -42,5 +42,5 @@ else() include(FindPackageHandleStandardArgs) find_package_handle_standard_args(Sundials DEFAULT_MSG SUNDIALS_ARKODE_LIBRARY SUNDIALS_INCLUDE_DIR) - mark_as_advanced(SUNDIALS_INCLUDE_DIR) + mark_as_advanced(SUNDIALS_INCLUDE_DIR SUNDIALS_LIBRARIES) endif() diff --git a/dpsim/include/dpsim/MNASolverFactory.h b/dpsim/include/dpsim/MNASolverFactory.h index a349cffd0c..94835e1604 100644 --- a/dpsim/include/dpsim/MNASolverFactory.h +++ b/dpsim/include/dpsim/MNASolverFactory.h @@ -52,7 +52,7 @@ class MnaSolverFactory { DirectLinearSolverImpl::DenseLU, DirectLinearSolverImpl::SparseLU, #ifdef WITH_KLU DirectLinearSolverImpl::KLU -#endif //WITH_KLU +#endif // WITH_KLU }; return ret; } diff --git a/dpsim/src/CMakeLists.txt b/dpsim/src/CMakeLists.txt index e9dc0c049e..e24e2b668d 100644 --- a/dpsim/src/CMakeLists.txt +++ b/dpsim/src/CMakeLists.txt @@ -25,8 +25,8 @@ set(DPSIM_SOURCES list(APPEND DPSIM_LIBRARIES dpsim-models - readerwriterqueue filesystem + readerwriterqueue::readerwriterqueue ) if(WITH_MNASOLVERPLUGIN) @@ -57,10 +57,8 @@ if(WITH_JSON) endif() if(WITH_KLU) - list(APPEND DPSIM_LIBRARIES klu) - list(APPEND DPSIM_SOURCES - KLUAdapter.cpp - ) + list(APPEND DPSIM_LIBRARIES SuiteSparse::KLU) + list(APPEND DPSIM_SOURCES KLUAdapter.cpp) endif() if(WITH_CUDA) @@ -77,18 +75,13 @@ if(WITH_CUDA) ) if(WITH_MAGMA) - list(APPEND DPSIM_SOURCES - GpuMagmaAdapter.cpp - ) + list(APPEND DPSIM_SOURCES GpuMagmaAdapter.cpp) list(APPEND DPSIM_LIBRARIES ${MAGMA_LIBRARIES}) list(APPEND DPSIM_LIBRARIES ${CUDA_cusparse_LIBRARY}) list(APPEND DPSIM_INCLUDE_DIRS ${MAGMA_INCLUDE_DIR}) endif() if(WITH_CUDA_SPARSE) - list(APPEND DPSIM_SOURCES - GpuSparseAdapter.cpp - ) - + list(APPEND DPSIM_SOURCES GpuSparseAdapter.cpp) list(APPEND DPSIM_LIBRARIES ${CUDA_cusparse_LIBRARY}) endif() endif() From 06337a0a5d6219e89871ea4616ab8d78d9695f48 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 2 Apr 2025 22:15:39 +0200 Subject: [PATCH 063/168] fix(cmake): Fix typos and style Signed-off-by: Steffen Vogel --- CMakeLists.txt | 20 +++++++++--------- dpsim-villas/examples/cxx/CMakeLists.txt | 26 ++++++++++++------------ dpsim/examples/cxx/CMakeLists.txt | 5 ++--- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 98e5e1a55e..9f747bce6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,13 +55,13 @@ endif() # Allow shadowing of CMake targets # As we include dependencies via add_subdirectory() # we import their targets into the DPsim CMake tree -# which might cause collissions in target names. +# which might cause collisions in target names. set(CMAKE_POLICY_DEFAULT_CMP0077 NEW) # Select C++-Version # For the pybind11-python interface to compile, a minimum version of C++14 is required # If you need to compile using C++11, either disable the python interface or modify the source-files in Source/pybind, -# replacing all occurences of py::overload_cast with py::detail::overload_cast_impl as specified on +# replacing all occurrences of py::overload_cast with py::detail::overload_cast_impl as specified on # https://pybind11.readthedocs.io/en/stable/classes.html#overloaded-methods set(CMAKE_CXX_STANDARD 17) @@ -111,7 +111,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebI # This option causes all calls to functions checking for infinity or NaN to raise # a warning (e.g. std::isnan). # As we also set -Werror, these warnings are causing the build to fail. - # With this compiler option, we excplicity silence this warning. + # With this compiler option, we explicitly silence this warning. check_cxx_compiler_flag("-Wno-nan-infinity-disabled" CXX_SUPPORTS_WNAN_INFINITY_DISABLED) if(CXX_SUPPORTS_WNAN_INFINITY_DISABLED) add_compile_options(-Wno-nan-infinity-disabled) @@ -126,7 +126,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebI endif() endif() -# Get version info and buildid from Git +# Get version info and commit hash from Git include(GetVersion) GetVersion(${PROJECT_SOURCE_DIR} "DPSIM") @@ -222,21 +222,21 @@ endif() include(CMakeDependentOption) cmake_dependent_option(WITH_CIM "Enable support for parsing CIM" ON "CIMpp_FOUND" OFF) -cmake_dependent_option(WITH_CUDA "Enable CUDA-based parallelisation" OFF "CUDA_FOUND" OFF) +cmake_dependent_option(WITH_CUDA "Enable CUDA-based parallelization" OFF "CUDA_FOUND" OFF) cmake_dependent_option(WITH_GRAPHVIZ "Enable Graphviz Graphs" ON "GRAPHVIZ_FOUND" OFF) cmake_dependent_option(WITH_GSL "Enable GSL features" ON "GSL_FOUND" OFF) cmake_dependent_option(WITH_JSON "Enable JSON library support" ON "nlohmann_json_FOUND" OFF) cmake_dependent_option(WITH_KLU "Enable KLU factorization" ON "SuiteSparse_FOUND" OFF) cmake_dependent_option(WITH_MAGMA "Enable MAGMA features" ON "MAGMA_FOUND" OFF) cmake_dependent_option(WITH_MNASOLVERPLUGIN "Enable MNASolver Plugins" ON "NOT WIN32" OFF) -cmake_dependent_option(WITH_OPENMP "Enable OpenMP-based parallelisation" ON "OPENMP_FOUND" OFF) +cmake_dependent_option(WITH_OPENMP "Enable OpenMP-based parallelization" ON "OPENMP_FOUND" OFF) cmake_dependent_option(WITH_PYBIND "Enable pybind support" ON "pybind11_FOUND" OFF) cmake_dependent_option(WITH_RT "Enable real-time features" ON "Linux_FOUND" OFF) cmake_dependent_option(WITH_SUNDIALS "Enable Sundials solver suite" ON "Sundials_FOUND" OFF) cmake_dependent_option(WITH_VILLAS "Enable VILLASnode interface" ON "VILLASnode_FOUND" OFF) if(WITH_CUDA) - # BEGIN OF WORKAROUND - enable cuda dynamic linking. + # BEGIN OF WORKAROUND - enable CUDA dynamic linking. # Starting with Cmake 3.17 we can use # set(CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT "SHARED") instead set(CMAKE_CUDA_FLAGS "" CACHE STRING "") @@ -248,7 +248,7 @@ if(WITH_CUDA) enable_language(CUDA) - # BEGIN OF WORKAROUND - enable cuda dynamic linking. + # BEGIN OF WORKAROUND - enable CUDA dynamic linking. if(CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES) list(REMOVE_ITEM CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "cudart_static") list(REMOVE_ITEM CMAKE_CUDA_HOST_IMPLICIT_LINK_LIBRARIES "cudadevrt") @@ -289,14 +289,14 @@ endif() if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) include(FeatureSummary) add_feature_info(CIM WITH_CIM "Loading Common Information Model (CIM) files") - add_feature_info(CUDA WITH_CUDA "CUDA-based parallelisation") + add_feature_info(CUDA WITH_CUDA "CUDA-based parallelization") add_feature_info(Graphviz WITH_GRAPHVIZ "Graphviz graphs") add_feature_info(GSL WITH_GSL "GNU Scientific library") add_feature_info(JSON WITH_JSON "JSON parsing") add_feature_info(KLU WITH_KLU "Use sparse KLU factorization") add_feature_info(MAGMA WITH_MAGMA "MAGMA features") add_feature_info(MNASolverPlugin WITH_MNASOLVERPLUGIN "MNASolver Plugins") - add_feature_info(OpenMP WITH_OPENMP "OpenMP-based parallelisation") + add_feature_info(OpenMP WITH_OPENMP "OpenMP-based parallelization") add_feature_info(Pybind WITH_PYBIND "Python extension / bindings") add_feature_info(RealTime WITH_RT "Extended real-time features") add_feature_info(Sundials WITH_SUNDIALS "Sundials solvers") diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index a8fb2e8254..e499857119 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -1,7 +1,7 @@ set(LIBRARIES "dpsim-villas") if(NOT WIN32) - # Needed so CIMParser and arabica (which are first compiled into static libs) + # Needed so CIMParser and Arabica (which are first compiled into static libs) # can be included in the .so set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif() @@ -21,14 +21,14 @@ set(DPSIM_VILLAS_EXAMPLE_SOURCES FpgaCosim3PhInfiniteBus.cpp FpgaCosimulation.cpp SharedMemExample.cpp - #ShmemExample.cpp - #ShmemDistributedReference.cpp - #ShmemDistributedDirect.cpp - #ShmemDistributedVillas.cpp - #ShmemControllableSource.cpp - #ShmemControllableFiltSource.cpp - #Shmem_CIGRE_MV_PowerFlowTest.cpp - #Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp + # ShmemExample.cpp + # ShmemDistributedReference.cpp + # ShmemDistributedDirect.cpp + # ShmemDistributedVillas.cpp + # ShmemControllableSource.cpp + # ShmemControllableFiltSource.cpp + # Shmem_CIGRE_MV_PowerFlowTest.cpp + # Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp ) if(WITH_CIM) @@ -46,7 +46,7 @@ foreach(SOURCE ${DPSIM_VILLAS_EXAMPLE_SOURCES} ${CIM_DPSIM_VILLAS_SOURCES}) target_compile_options(${TARGET} PUBLIC ${DPSIM_CXX_FLAGS}) endforeach() -#add_executable(ShmemRealtimeExample ShmemExample.cpp) -#target_link_libraries(ShmemRealtimeExample ${LIBRARIES}) -#target_include_directories(ShmemRealtimeExample PRIVATE ${INCLUDE_DIRS}) -#target_compile_definitions(ShmemRealtimeExample PUBLIC REALTIME) +# add_executable(ShmemRealtimeExample ShmemExample.cpp) +# target_link_libraries(ShmemRealtimeExample ${LIBRARIES}) +# target_include_directories(ShmemRealtimeExample PRIVATE ${INCLUDE_DIRS}) +# target_compile_definitions(ShmemRealtimeExample PUBLIC REALTIME) diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index e4dd0a00a6..99eea261a6 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -1,7 +1,7 @@ set(LIBRARIES "dpsim") if(NOT WIN32) - # Needed so CIMParser and arabica (which are first compiled into static libs) + # Needed so CIMParser and Arabica (which are first compiled into static libs) # can be included in the .so set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif() @@ -84,12 +84,11 @@ set(CIRCUIT_SOURCES Circuits/EMT_SMIB_ReducedOrderSGIterative_LoadStep.cpp Circuits/DP_SMIB_ReducedOrderSGIterative_LoadStep.cpp - #3Bus System + # 3Bus System Circuits/SP_SynGenTrStab_3Bus_SteadyState.cpp Circuits/DP_SynGenTrStab_3Bus_SteadyState.cpp Circuits/DP_SynGenTrStab_3Bus_Fault.cpp Circuits/SP_SynGenTrStab_3Bus_Fault.cpp - ) if(WITH_JSON) From cffd372c8e7d4000312dacc54c08c187aee1be2c Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 8 Apr 2025 06:40:54 +0200 Subject: [PATCH 064/168] feat(pre-commit): Enable EditorConfig checker hook Signed-off-by: Steffen Vogel --- .pre-commit-config.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 612e5426b1..728a652ea3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -29,11 +29,12 @@ repos: files: \.(c|cpp|h|hpp)(\.in)?$ args: [] - # - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - # rev: "2.7.3" - # hooks: - # - id: editorconfig-checker - # alias: ec + - repo: https://github.com/editorconfig-checker/editorconfig-checker.python + rev: "2.7.3" + hooks: + - id: editorconfig-checker + alias: ec + args: [-disable-indent-size] # Using this mirror lets us use mypyc-compiled black, which is about 2x faster - repo: https://github.com/psf/black-pre-commit-mirror From 2d12d9eb3417c7735b46a940c6888722cc4a6875 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 8 Apr 2025 06:42:58 +0200 Subject: [PATCH 065/168] fix(style): Harmonize comments and indentation Signed-off-by: Steffen Vogel --- cmake/FetchCIMpp.cmake | 2 +- cmake/FindSuiteSparse.cmake | 6 +++--- docs/hugo/Dockerfile | 14 +++++++------- dpsim-models/CMakeLists.txt | 8 ++++---- dpsim-villas/CMakeLists.txt | 8 ++++---- dpsim/CMakeLists.txt | 8 ++++---- packaging/Docker/Dockerfile.dev-docs | 2 +- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/cmake/FetchCIMpp.cmake b/cmake/FetchCIMpp.cmake index dff0edce1e..4a504571f3 100644 --- a/cmake/FetchCIMpp.cmake +++ b/cmake/FetchCIMpp.cmake @@ -4,7 +4,7 @@ endif() # Allow overriding the commit hash externally if(NOT DEFINED CIMPP_COMMIT) - set(CIMPP_COMMIT "1b11d5c17bedf0ae042628b42ecb4e49df70b2f6") # Default commit + set(CIMPP_COMMIT "1b11d5c17bedf0ae042628b42ecb4e49df70b2f6") # Default commit endif() message(STATUS "CIM Version: ${CIM_VERSION}") diff --git a/cmake/FindSuiteSparse.cmake b/cmake/FindSuiteSparse.cmake index 80b4ab3e65..bef36448c7 100644 --- a/cmake/FindSuiteSparse.cmake +++ b/cmake/FindSuiteSparse.cmake @@ -29,7 +29,7 @@ set_property(TARGET SuiteSparse::KLU PROPERTY IMPORTED_LOCATION ${SUITESPARSE_KL target_include_directories(SuiteSparse::KLU INTERFACE ${SUITESPARSE_INCLUDE_DIR}) target_link_libraries(SuiteSparse::KLU INTERFACE - SuiteSparse::AMD - SuiteSparse::BTF - SuiteSparse::COLAMD + SuiteSparse::AMD + SuiteSparse::BTF + SuiteSparse::COLAMD ) diff --git a/docs/hugo/Dockerfile b/docs/hugo/Dockerfile index bd8799de55..a4a88b8d29 100644 --- a/docs/hugo/Dockerfile +++ b/docs/hugo/Dockerfile @@ -3,18 +3,18 @@ FROM fedora:34 RUN dnf -y update RUN dnf -y install \ - pandoc \ - wget \ - git \ - nodejs + pandoc \ + wget \ + git \ + nodejs WORKDIR /hugo RUN wget https://github.com/gohugoio/hugo/releases/download/v0.95.0/hugo_extended_0.95.0_Linux-64bit.tar.gz && \ - tar -xvf hugo_extended_0.95.0_Linux-64bit.tar.gz && \ - install hugo /usr/bin + tar -xvf hugo_extended_0.95.0_Linux-64bit.tar.gz && \ + install hugo /usr/bin WORKDIR /website -# this is installed by the entrypoint script in the mounted volume +# This is installed by the entrypoint script in the mounted volume # npm install -D --save autoprefixer # npm install -D --save postcss-cli diff --git a/dpsim-models/CMakeLists.txt b/dpsim-models/CMakeLists.txt index 6c013de297..e51fd34162 100644 --- a/dpsim-models/CMakeLists.txt +++ b/dpsim-models/CMakeLists.txt @@ -20,10 +20,10 @@ add_subdirectory(src) file(GLOB_RECURSE HEADER_FILES include/*.h) target_sources(dpsim-models PUBLIC - FILE_SET public_headers - TYPE HEADERS - BASE_DIRS include - FILES "${HEADER_FILES}" + FILE_SET public_headers + TYPE HEADERS + BASE_DIRS include + FILES "${HEADER_FILES}" ) install(TARGETS dpsim-models diff --git a/dpsim-villas/CMakeLists.txt b/dpsim-villas/CMakeLists.txt index 10f3ef681f..29e4a5bea7 100644 --- a/dpsim-villas/CMakeLists.txt +++ b/dpsim-villas/CMakeLists.txt @@ -24,10 +24,10 @@ endif() file(GLOB_RECURSE HEADER_FILES include/*.h) target_sources(dpsim-villas PUBLIC - FILE_SET public_headers - TYPE HEADERS - BASE_DIRS include - FILES "${HEADER_FILES}" + FILE_SET public_headers + TYPE HEADERS + BASE_DIRS include + FILES "${HEADER_FILES}" ) install(TARGETS dpsim-villas diff --git a/dpsim/CMakeLists.txt b/dpsim/CMakeLists.txt index 3f78075f5f..ef0a3d1c7c 100644 --- a/dpsim/CMakeLists.txt +++ b/dpsim/CMakeLists.txt @@ -22,10 +22,10 @@ endif() file(GLOB_RECURSE HEADER_FILES include/*.h) target_sources(dpsim PUBLIC - FILE_SET public_headers - TYPE HEADERS - BASE_DIRS include - FILES "${HEADER_FILES}" + FILE_SET public_headers + TYPE HEADERS + BASE_DIRS include + FILES "${HEADER_FILES}" ) install(TARGETS dpsim diff --git a/packaging/Docker/Dockerfile.dev-docs b/packaging/Docker/Dockerfile.dev-docs index a5286fcb4a..6a322252ba 100644 --- a/packaging/Docker/Dockerfile.dev-docs +++ b/packaging/Docker/Dockerfile.dev-docs @@ -3,7 +3,7 @@ FROM ubuntu:latest RUN apt update RUN apt install -y git golang curl sudo RUN curl -fsSL https://deb.nodesource.com/setup_19.x | sudo -E bash - && \ - sudo apt-get install -y nodejs + sudo apt-get install -y nodejs RUN go install -tags extended github.com/gohugoio/hugo@latest RUN cp /root/go/bin/hugo /usr/bin/hugo EXPOSE 1313/tcp From ccd059ab4e27121efd3f133727934ef7b7aebde5 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 8 Apr 2025 07:28:26 +0200 Subject: [PATCH 066/168] fix(style): Remove tab indentation from C/C++ code and harmonize comment style Signed-off-by: Steffen Vogel --- dpsim-models/include/dpsim-models/Attribute.h | 315 ++++++------- .../include/dpsim-models/AttributeList.h | 8 +- dpsim-models/include/dpsim-models/CSVReader.h | 36 +- .../EMT_Ph3_AvVoltSourceInverterStateSpace.h | 26 +- .../include/dpsim-models/EMT/EMT_Ph3_PiLine.h | 12 +- dpsim-models/include/dpsim-models/Graph.h | 5 +- .../dpsim-models/TopologicalPowerComp.h | 4 +- .../dpsim-models/TopologicalSignalComp.h | 4 +- dpsim-models/src/CIM/Reader.cpp | 22 +- dpsim-models/src/CSVReader.cpp | 417 +++++++++--------- .../src/DP/DP_Ph1_NetworkInjection.cpp | 22 +- .../src/DP/DP_Ph1_ProfileVoltageSource.cpp | 22 +- dpsim-models/src/DP/DP_Ph1_Resistor.cpp | 39 +- dpsim-models/src/DP/DP_Ph1_VoltageSource.cpp | 22 +- dpsim-models/src/DP/DP_Ph3_Capacitor.cpp | 59 +-- dpsim-models/src/DP/DP_Ph3_Inductor.cpp | 22 +- .../src/DP/DP_Ph3_SynchronGeneratorDQ.cpp | 90 ++-- .../src/DP/DP_Ph3_SynchronGeneratorDQODE.cpp | 4 +- dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp | 56 +-- ...EMT_Ph3_AvVoltSourceInverterStateSpace.cpp | 39 +- .../EMT/EMT_Ph3_SynchronGeneratorDQODE.cpp | 8 +- .../src/SP/SP_Ph1_NetworkInjection.cpp | 22 +- dpsim-models/src/SP/SP_Ph1_RXLine.cpp | 50 ++- dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp | 46 +- dpsim-models/src/SP/SP_Ph3_Capacitor.cpp | 39 +- dpsim-models/src/SP/SP_Ph3_Inductor.cpp | 38 +- dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp | 83 ++-- dpsim-models/src/Signal/Exciter.cpp | 17 +- dpsim-villas/examples/cxx/FileExample.cpp | 12 +- .../examples/cxx/SharedMemExample.cpp | 18 +- dpsim-villas/src/InterfaceWorkerVillas.cpp | 6 +- dpsim/examples/cxx/Circuits/DP_VSI.cpp | 14 +- .../DP_SynGenDq7odODEint_ThreePhFault.cpp | 14 +- .../DP_SynchronGenerator_BalancedResLoad.cpp | 6 +- ...DP_SynchronGenerator_ExciterAndTurbine.cpp | 6 +- ..._SynchronGenerator_SimpThreePhaseFault.cpp | 20 +- ...onGenerator_Simplified_ThreePhaseFault.cpp | 6 +- .../DP_SynchronGenerator_ThreePhaseFault.cpp | 6 +- ...MT_SynchronGenerator_ExciterAndTurbine.cpp | 6 +- ...MT_SynchronGenerator_PhaseToPhaseFault.cpp | 6 +- ...onGenerator_Simplified_ThreePhaseFault.cpp | 166 ++++--- .../EMT_SynchronGenerator_ThreePhaseFault.cpp | 25 +- dpsim/examples/cxx/cim_graphviz/cimviz.cpp | 12 +- dpsim/include/dpsim/Compat/getopt.h | 15 +- dpsim/include/dpsim/InterfaceWorker.h | 30 +- dpsim/include/dpsim/MNASolverFactory.h | 5 +- dpsim/include/dpsim/ODESolver.h | 12 +- dpsim/include/dpsim/RealTimeSimulation.h | 6 +- dpsim/src/KLUAdapter.cpp | 33 +- dpsim/src/ODESolver.cpp | 79 ++-- dpsim/src/Simulation.cpp | 58 +-- dpsim/src/Timer.cpp | 10 +- dpsim/src/pybind/main.cpp | 10 +- 53 files changed, 1076 insertions(+), 1032 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Attribute.h b/dpsim-models/include/dpsim-models/Attribute.h index 2fafa6e0f4..3207a0ee53 100644 --- a/dpsim-models/include/dpsim-models/Attribute.h +++ b/dpsim-models/include/dpsim-models/Attribute.h @@ -17,13 +17,13 @@ namespace CPS { /** - * Enum to describe when a given ´UpdateTask` should be executed. - * UPDATE_ONCE tasks are currently executed instantly after they have been set, and then never again. - * UPDATE_ON_GET tasks are executed whenever the attribute is dereferenced. - * UPDATE_ON_SET tasks are only executed whenever the `set` method is called. Since `get` provides mutable references, - * this is not guaranteed to happen on every change to the attribute! - * UPDATE_ON_SIMULATION_STEP is currently unused. - * */ + * Enum to describe when a given ´UpdateTask` should be executed. + * UPDATE_ONCE tasks are currently executed instantly after they have been set, and then never again. + * UPDATE_ON_GET tasks are executed whenever the attribute is dereferenced. + * UPDATE_ON_SET tasks are only executed whenever the `set` method is called. Since `get` provides mutable references, + * this is not guaranteed to happen on every change to the attribute! + * UPDATE_ON_SIMULATION_STEP is currently unused. + */ enum UpdateTaskKind { UPDATE_ONCE, UPDATE_ON_GET, @@ -38,11 +38,11 @@ template class AttributeStatic; template class AttributeDynamic; /** - * Custom pointer class for storing attributes as member variables and in the `mAttributes` attribute map. - * Using this type over the normal `std::shared_ptr` allows for disabling certain operator overloads, e.g. the comparison with the nullptr / the number 0 - * that is possible with shared ptrs. Since attribute pointers rarely need to be compared with the nullptr, disabling the implicit comparison allows for - * detecting more errors at compile time. Explicit comparison still remains possible via the `getPtr` method. - * */ + * Custom pointer class for storing attributes as member variables and in the `mAttributes` attribute map. + * Using this type over the normal `std::shared_ptr` allows for disabling certain operator overloads, e.g. the comparison with the nullptr / the number 0 + * that is possible with shared ptrs. Since attribute pointers rarely need to be compared with the nullptr, disabling the implicit comparison allows for + * detecting more errors at compile time. Explicit comparison still remains possible via the `getPtr` method. + */ template class AttributePointer { public: using element_type = T; @@ -90,37 +90,37 @@ template class AttributePointer { bool isNull() const { return mPtr == nullptr; } - /* - These (implicit) comparison operators are disabled to avoid accidentally comparing pointers instead of attribute values. - When a pointer comparison is necessary, this can be done via the `getPtr` method or by using the `AttributeCmp` and `AttributeEq` structs. - - template - bool operator<(const AttributePointer& rhs) const noexcept { - return this->mPtr < rhs.getPtr(); - } + // These (implicit) comparison operators are disabled to avoid accidentally comparing pointers instead of attribute values. + // When a pointer comparison is necessary, this can be done via the `getPtr` method or by using the `AttributeCmp` and `AttributeEq` structs. +#if 0 + template + bool operator<(const AttributePointer& rhs) const noexcept { + return this->mPtr < rhs.getPtr(); + } - template - bool operator>(const AttributePointer& rhs) const noexcept { - return this->mPtr > rhs.getPtr(); - } + template + bool operator>(const AttributePointer& rhs) const noexcept { + return this->mPtr > rhs.getPtr(); + } - template - bool operator==(const AttributePointer& rhs) const noexcept { - return this->mPtr == rhs.getPtr(); - } + template + bool operator==(const AttributePointer& rhs) const noexcept { + return this->mPtr == rhs.getPtr(); + } - template - bool operator!=(const AttributePointer& rhs) const noexcept { - return this->mPtr != rhs.getPtr(); - }*/ + template + bool operator!=(const AttributePointer& rhs) const noexcept { + return this->mPtr != rhs.getPtr(); + } +#endif private: std::shared_ptr mPtr; }; /** - * Struct providing an (explicit) comparison function for Attribute Pointers. Can be used in STL containers. - * */ + * Struct providing an (explicit) comparison function for Attribute Pointers. Can be used in STL containers. + */ template struct AttributeCmp { bool operator()(CPS::AttributePointer a, CPS::AttributePointer b) const { @@ -129,8 +129,8 @@ template struct AttributeCmp { }; /** - * Struct providing an (explicit) equals function for Attribute Pointers. Can be used in STL containers. - * */ + * Struct providing an (explicit) equals function for Attribute Pointers. Can be used in STL containers. + */ template struct AttributeEq { bool operator()(CPS::AttributePointer a, CPS::AttributePointer b) const { @@ -139,8 +139,8 @@ template struct AttributeEq { }; /** - * Base class for all Attribute types. Can be used in STL containers to hide the template information. - * */ + * Base class for all Attribute types. Can be used in STL containers to hide the template information. + */ class AttributeBase { public: typedef AttributePointer Ptr; @@ -149,47 +149,47 @@ class AttributeBase { typedef std::map Map; /** - * Display this attribute's value as a string - * */ + * Display this attribute's value as a string + */ virtual String toString() = 0; /** - * Check whether this is a static or dynamic attribute - * @return true for instances of `AttributeStatic`, false for instances of `AttributeDynamic` - * */ + * Check whether this is a static or dynamic attribute + * @return true for instances of `AttributeStatic`, false for instances of `AttributeDynamic` + */ virtual bool isStatic() const = 0; virtual ~AttributeBase() = default; /** - * @brief Copy the attribute value of `copyFrom` onto this attribute - * @return true if the copy operation was successful, false otherwise - */ + * @brief Copy the attribute value of `copyFrom` onto this attribute + * @return true if the copy operation was successful, false otherwise + */ virtual bool copyValue(AttributeBase::Ptr copyFrom) = 0; /** - * @brief Get the type of this attribute - * @return std::type_info - */ + * @brief Get the type of this attribute + * @return std::type_info + */ virtual const std::type_info &getType() = 0; /** - * @brief Generates a new attribute of the same type and copies the current value in the heap. Does not copy any dependency relations! - * @return Pointer to the copied attribute - */ + * @brief Generates a new attribute of the same type and copies the current value in the heap. Does not copy any dependency relations! + * @return Pointer to the copied attribute + */ virtual AttributeBase::Ptr cloneValueOntoNewAttribute() = 0; /** - * Append all dependencies of this attribute to the given set. - * For static attributes, this will only append `this`, for dynamic attributes, it will recursively collect and append - * all dependencies. - * */ + * Append all dependencies of this attribute to the given set. + * For static attributes, this will only append `this`, for dynamic attributes, it will recursively collect and append + * all dependencies. + */ virtual void appendDependencies(AttributeBase::Set *deps) = 0; /** - * Get a set of all attributes this attribute depends on. For static attributes, this set will only contain `this`. - * For dynamic attributes, this will recursively collect all dependency attributes. - * */ + * Get a set of all attributes this attribute depends on. For static attributes, this set will only contain `this`. + * For dynamic attributes, this will recursively collect all dependency attributes. + */ virtual AttributeBase::Set getDependencies() final { AttributeBase::Set deps = AttributeBase::Set(); this->appendDependencies(&deps); @@ -198,8 +198,8 @@ class AttributeBase { }; /** - * Base class for all AttributeUpdateTasks. Enables storing tasks in an STL list independent of the dependency types. - * */ + * Base class for all AttributeUpdateTasks. Enables storing tasks in an STL list independent of the dependency types. + */ template class AttributeUpdateTaskBase { public: @@ -211,10 +211,10 @@ template class AttributeUpdateTaskBase { }; /** - * Specialized class for AttributeUpdateTasks that includes information about the types of attributes this task depends on. - * @param DependentType The type of the attribute which is updated by this task - * @param DependencyTypes List of the types of the attributes whose values are used to update the dependent attribute - * */ + * Specialized class for AttributeUpdateTasks that includes information about the types of attributes this task depends on. + * @param DependentType The type of the attribute which is updated by this task + * @param DependencyTypes List of the types of the attributes whose values are used to update the dependent attribute + */ template class AttributeUpdateTask : public AttributeUpdateTaskBase, @@ -246,8 +246,8 @@ class AttributeUpdateTask } /** - * Returns all dependency elements in the `mDependency` tuple in a list over AttributeBase pointers. - * */ + * Returns all dependency elements in the `mDependency` tuple in a list over AttributeBase pointers. + */ virtual AttributeBase::List getDependencies() override { return std::apply( [](auto &&...elems) { @@ -259,9 +259,9 @@ class AttributeUpdateTask }; /** - * Main Attribute class. The template class `T` holds the attribute's type. This is used as the type for all attribute member variables. - * @param T The type of this attribute - * */ + * Main Attribute class. The template class `T` holds the attribute's type. This is used as the type for all attribute member variables. + * @param T The type of this attribute + */ template class Attribute : public AttributeBase, public std::enable_shared_from_this> { @@ -279,57 +279,62 @@ class Attribute : public AttributeBase, } /** - * Manually set the attribute to the given value. For dynamic attributes, this will trigger the UPDATE_ON_SET tasks for updating any - * dependency attributes. - * */ + * Manually set the attribute to the given value. For dynamic attributes, this will trigger the UPDATE_ON_SET tasks for updating any + * dependency attributes. + */ virtual void set(T value) = 0; /** - * Get a mutable reference to the attribute's underlying data. This method is also called when dereferencing an attribute using the * operator - * */ + * Get a mutable reference to the attribute's underlying data. This method is also called when dereferencing an attribute using the * operator + */ virtual T &get() = 0; /** - * Convenience method for setting this attribute to always equal another attribute. - * When `this` is dynamic, this will set up an UPDATE_ONCE task that sets this attribute's data pointer to equal the data pointer of the referenced attribute. - * If `this` is static, calling this method will result in a runtime error. - * @param reference The attribute which's value will be adapted - * */ + * Convenience method for setting this attribute to always equal another attribute. + * When `this` is dynamic, this will set up an UPDATE_ONCE task that sets this attribute's data pointer to equal the data pointer of the referenced attribute. + * If `this` is static, calling this method will result in a runtime error. + * @param reference The attribute which's value will be adapted + */ virtual void setReference(Attribute::Ptr reference) = 0; /** - * Exposing the underlying shared_ptr for this attribute's data. Used to create reference relations between two attributes. - * @return The shared_ptr to this attribute's underlying data - * */ + * Exposing the underlying shared_ptr for this attribute's data. Used to create reference relations between two attributes. + * @return The shared_ptr to this attribute's underlying data + */ virtual std::shared_ptr asRawPointer() = 0; - /// Fallback method for all attribute types not covered by the specifications in Attribute.cpp + /** + * @brief Fallback method for all attribute types not covered by the specifications in Attribute.cpp + */ String toString() override { std::stringstream ss; ss << this->get(); return ss.str(); } - /// @brief User-defined cast operator - /// - /// Allows attributes to be casted to their value type: - /// - /// Real v = 1.2; - /// auto a = Attribute(&v); - /// - /// Real x = v; - /// + /** + * @brief User-defined cast operator + * + * Allows attributes to be casted to their value type: + * + * Real v = 1.2; + * auto a = Attribute(&v); + * + * Real x = v; + */ operator const T &() { return this->get(); } - /// @brief User-defined dereference operator - /// - /// Allows easier access to the attribute's underlying data + /** + * @brief User-defined dereference operator + * + * Allows easier access to the attribute's underlying data + */ T &operator*() { return this->get(); } /** - * @brief Copy the attribute value of `copyFrom` onto this attribute - * @return true if the copy operation was successful, false otherwise - */ + * @brief Copy the attribute value of `copyFrom` onto this attribute + * @return true if the copy operation was successful, false otherwise + */ bool copyValue(AttributeBase::Ptr copyFrom) override { Attribute::Ptr copyFromTyped = std::dynamic_pointer_cast>(copyFrom.getPtr()); @@ -341,15 +346,15 @@ class Attribute : public AttributeBase, } /** - * @brief Get the type of this attribute - * @return std::type_info - */ + * @brief Get the type of this attribute + * @return std::type_info + */ const std::type_info &getType() override { return typeid(T); } /** - * @brief Generates a new attribute of the same type and copies the current value in the heap. Does not copy any dependency relations! - * @return Pointer to the copied attribute - */ + * @brief Generates a new attribute of the same type and copies the current value in the heap. Does not copy any dependency relations! + * @return Pointer to the copied attribute + */ AttributeBase::Ptr cloneValueOntoNewAttribute() override { return AttributePointer( AttributeStatic::make(this->get())); @@ -357,13 +362,13 @@ class Attribute : public AttributeBase, }; /** - * General method for deriving a new attribute from this attribute. Custom getter and setter functions have to be provided. The newly created - * attribute will only depend on this attribute in a 1:1 relationship. - * @param U The type of the newly derived attribute - * @param getter The getter actor function to use for updating the derived attribute - * @param setter The setter actor function for updating `this` when the derived attribute is changed - * @return a newly created attribute of type `U` which will calculate its value using the provided getter and update `this` on changes using the provided setter - * */ + * General method for deriving a new attribute from this attribute. Custom getter and setter functions have to be provided. The newly created + * attribute will only depend on this attribute in a 1:1 relationship. + * @param U The type of the newly derived attribute + * @param getter The getter actor function to use for updating the derived attribute + * @param setter The setter actor function for updating `this` when the derived attribute is changed + * @return a newly created attribute of type `U` which will calculate its value using the provided getter and update `this` on changes using the provided setter + */ template typename Attribute::Ptr derive(typename AttributeUpdateTask::Actor getter = @@ -389,9 +394,9 @@ class Attribute : public AttributeBase, } /** - * Convenience method for deriving the real part of a complex attribute - * @return a new attribute whose value will always equal the real part of `this` - * */ + * Convenience method for deriving the real part of a complex attribute + * @return a new attribute whose value will always equal the real part of `this` + */ template , bool> = true> AttributePointer> deriveReal() @@ -413,9 +418,9 @@ class Attribute : public AttributeBase, } /** - * Convenience method for deriving the imaginary part of a complex attribute - * @return a new attribute whose value will always equal the imaginary part of `this` - * */ + * Convenience method for deriving the imaginary part of a complex attribute + * @return a new attribute whose value will always equal the imaginary part of `this` + */ template , bool> = true> AttributePointer> deriveImag() @@ -437,9 +442,9 @@ class Attribute : public AttributeBase, } /** - * Convenience method for deriving the magnitude of a complex attribute - * @return a new attribute whose value will always equal the magnitude of `this` - * */ + * Convenience method for deriving the magnitude of a complex attribute + * @return a new attribute whose value will always equal the magnitude of `this` + */ template , bool> = true> AttributePointer> deriveMag() @@ -460,9 +465,9 @@ class Attribute : public AttributeBase, } /** - * Convenience method for deriving the phase of a complex attribute - * @return a new attribute whose value will always equal the phase of `this` - * */ + * Convenience method for deriving the phase of a complex attribute + * @return a new attribute whose value will always equal the phase of `this` + */ template , bool> = true> AttributePointer> derivePhase() @@ -483,10 +488,10 @@ class Attribute : public AttributeBase, } /** - * Convenience method for deriving an attribute whose value is always scaled by `scale` - * @param scale The scaling to apply to the attribute's value - * @return a new attribute whose value will always equal the value of `this` but scaled by `scale` - * */ + * Convenience method for deriving an attribute whose value is always scaled by `scale` + * @param scale The scaling to apply to the attribute's value + * @return a new attribute whose value will always equal the value of `this` but scaled by `scale` + */ template || std::is_same_v, bool> = true> @@ -505,12 +510,12 @@ class Attribute : public AttributeBase, } /** - * Convenience method for deriving an attribute which covers one coefficient of this matrix - * @param U The type of the coefficient (usally Real or Complex) - * @param row The coefficients row coordinate - * @param column The coefficients column coordinate - * @return a new attribute whose value will always equal the value of the coefficient `this(row, column)` - * */ + * Convenience method for deriving an attribute which covers one coefficient of this matrix + * @param U The type of the coefficient (usally Real or Complex) + * @param row The coefficients row coordinate + * @param column The coefficients column coordinate + * @return a new attribute whose value will always equal the value of the coefficient `this(row, column)` + */ template , V>, bool> = true> AttributePointer> @@ -535,9 +540,9 @@ class Attribute : public AttributeBase, }; /** - * Class for static attributes. A static attribute's value can only ever by changed via the `get` and `set` methods (or the reference provided by `get`). - * Static attributes do not directly depend on any other attributes and currently cannot have any update tasks. - * */ + * Class for static attributes. A static attribute's value can only ever by changed via the `get` and `set` methods (or the reference provided by `get`). + * Static attributes do not directly depend on any other attributes and currently cannot have any update tasks. + */ template class AttributeStatic : public Attribute, public SharedFactory> { @@ -564,8 +569,8 @@ class AttributeStatic : public Attribute, }; /** - * Class for dynamic attributes. A dynamic attribute has an internal value which can be updated by update tasks. - * */ + * Class for dynamic attributes. A dynamic attribute has an internal value which can be updated by update tasks. + */ template class AttributeDynamic : public Attribute, public SharedFactory> { @@ -580,16 +585,16 @@ class AttributeDynamic : public Attribute, AttributeDynamic(T initialValue = T()) : Attribute(initialValue) {} /** - * Allows for adding a new update task to this attribute. - * @param kind The kind of update task - * @param task The update task itself - * */ + * Allows for adding a new update task to this attribute. + * @param kind The kind of update task + * @param task The update task itself + */ void addTask(UpdateTaskKind kind, typename AttributeUpdateTaskBase::Ptr task) { switch (kind) { case UpdateTaskKind::UPDATE_ONCE: updateTasksOnce.push_back(task); - ///THISISBAD: This is probably not the right time to run this kind of task + // THISISBAD: This is probably not the right time to run this kind of task task->executeUpdate(this->mData); break; case UpdateTaskKind::UPDATE_ON_GET: @@ -604,9 +609,9 @@ class AttributeDynamic : public Attribute, } /** - * Removes all update tasks of a given kind from this attribute. - * @param kind The kind of tasks to remove - * */ + * Removes all update tasks of a given kind from this attribute. + * @param kind The kind of tasks to remove + */ void clearTasks(UpdateTaskKind kind) { switch (kind) { case UpdateTaskKind::UPDATE_ONCE: @@ -624,8 +629,8 @@ class AttributeDynamic : public Attribute, } /** - * Remove all update tasks from this attribute, regardless of their kind. - * */ + * Remove all update tasks from this attribute, regardless of their kind. + */ void clearAllTasks() { updateTasksOnce.clear(); updateTasksOnGet.clear(); @@ -674,10 +679,10 @@ class AttributeDynamic : public Attribute, virtual bool isStatic() const override { return false; } /** - * Implementation for dynamic attributes.This will recursively collect all attributes this attribute depends on, either in the UPDATE_ONCE or the UPDATE_ON_GET tasks. - * This is done by performing a Depth-First-Search on the dependency graph where the task dependencies of each attribute are the outgoing edges. - * The `deps` set contains all the nodes that have already been visited in the graph - * */ + * Implementation for dynamic attributes.This will recursively collect all attributes this attribute depends on, either in the UPDATE_ONCE or the UPDATE_ON_GET tasks. + * This is done by performing a Depth-First-Search on the dependency graph where the task dependencies of each attribute are the outgoing edges. + * The `deps` set contains all the nodes that have already been visited in the graph + */ virtual void appendDependencies(AttributeBase::Set *deps) override { deps->insert(this->shared_from_this()); @@ -708,8 +713,8 @@ template <> String Attribute::toString(); namespace std { /** - * Struct for making the custom `AttributePointer` type hashable. This enables these pointers to be used in STL Maps. - * */ + * Struct for making the custom `AttributePointer` type hashable. This enables these pointers to be used in STL Maps. + */ template struct hash> { size_t operator()(CPS::AttributePointer const &x) const { return std::hash>()(x.getPtr()); diff --git a/dpsim-models/include/dpsim-models/AttributeList.h b/dpsim-models/include/dpsim-models/AttributeList.h index eab0aaeba4..af90d68b42 100644 --- a/dpsim-models/include/dpsim-models/AttributeList.h +++ b/dpsim-models/include/dpsim-models/AttributeList.h @@ -29,9 +29,7 @@ class AttributeList : public SharedFactory { const AttributeBase::Map &attributes() const { return mAttributeMap; }; - /** - * Creates a new static Attribute and enters a pointer to it into this Attribute Map using the provided name. - * */ + // Creates a new static Attribute and enters a pointer to it into this Attribute Map using the provided name. template typename Attribute::Ptr create(const String &name, T intitialValue = T()) { typename Attribute::Ptr newAttr = @@ -40,9 +38,7 @@ class AttributeList : public SharedFactory { return newAttr; } - /** - * Creates a new dynamic Attribute and enters a pointer to it into this Attribute Map using the provided name. - * */ + // Creates a new dynamic Attribute and enters a pointer to it into this Attribute Map using the provided name. template typename Attribute::Ptr createDynamic(const String &name) { typename Attribute::Ptr newAttr = diff --git a/dpsim-models/include/dpsim-models/CSVReader.h b/dpsim-models/include/dpsim-models/CSVReader.h index 2ec921122b..3b45f3db4c 100644 --- a/dpsim-models/include/dpsim-models/CSVReader.h +++ b/dpsim-models/include/dpsim-models/CSVReader.h @@ -43,12 +43,12 @@ class CSVReader { /// MANUAL for providing an assign pattern manually. see power flow example: CIM/CIGRE_MV_PowerFlowTest_LoadProfiles.cpp enum class Mode { AUTO, MANUAL }; - /* - Time Stamp Format. - HHMMSS: Hours : Minutes : Seconds, it be casted to the corresponding SECONDS. - SECONDS: profiles recorded with total seconds. - PVGEN: format comply with https://www.fein-aachen.org/projects/PVgenerator/ - */ + /* Time Stamp Format. + * + * HHMMSS: Hours : Minutes : Seconds, it be casted to the corresponding SECONDS. + * SECONDS: profiles recorded with total seconds. + * PVGEN: format comply with https://www.fein-aachen.org/projects/PVgenerator/ + */ enum class DataFormat { HHMMSS, SECONDS, HOURS, MINUTES }; /// @@ -62,8 +62,8 @@ class CSVReader { CSVReader(String name, String path, std::map &assignList, Logger::Level logLevel); - /// convert HH:MM:SS format timestamp into total seconds. - /// e.g.: 00 : 01 : 00 -- > 60. + /// Convert HH:MM:SS format timestamp into total seconds. + /// e.g.: 00 : 01 : 00 -- > 60. Real time_format_convert(const String &time); /// Skip first row if it has no digits at beginning void doSkipFirstRow(Bool value = true) { mSkipFirstRow = value; } @@ -75,15 +75,17 @@ class CSVReader { Real end_time = -1, Real scale_factor = 1, CSVReader::DataFormat format = CSVReader::DataFormat::SECONDS); - // void assignLoadProfilePF(std::vector>& loads, - // Real start_time = -1, Real time_step = 1, Real end_time = -1, Real scale_factor= 1, - // CSVReader::Mode mode = CSVReader::Mode::AUTO, - // CSVReader::DataFormat format = CSVReader::DataFormat::SECONDS); - - // void assignLoadProfileSP(std::vector>& loads, - // Real start_time = -1, Real time_step = 1, Real end_time = -1, Real scale_factor= 1, - // CSVReader::Mode mode = CSVReader::Mode::AUTO, - // CSVReader::DataFormat format = CSVReader::DataFormat::SECONDS); +#if 0 + void assignLoadProfilePF(std::vector>& loads, + Real start_time = -1, Real time_step = 1, Real end_time = -1, Real scale_factor= 1, + CSVReader::Mode mode = CSVReader::Mode::AUTO, + CSVReader::DataFormat format = CSVReader::DataFormat::SECONDS); + + void assignLoadProfileSP(std::vector>& loads, + Real start_time = -1, Real time_step = 1, Real end_time = -1, Real scale_factor= 1, + CSVReader::Mode mode = CSVReader::Mode::AUTO, + CSVReader::DataFormat format = CSVReader::DataFormat::SECONDS); +#endif void assignLoadProfileDP( std::vector> diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.h index 5fd7dd2572..635fb3a261 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.h @@ -72,13 +72,15 @@ class AvVoltSourceInverterStateSpace protected: Matrix mIfabc = Matrix::Zero(3, 1); - /*Real mIfa; - Real mIfb; - Real mIfc;*/ +#if 0 + Real mIfa; + Real mIfb; + Real mIfc; - /*Real mVca; - Real mVcb; - Real mVcc;*/ + Real mVca; + Real mVcb; + Real mVcc; +#endif // Norton equivalant voltage source Matrix mEquivCurrent = Matrix::Zero(3, 1); @@ -111,12 +113,14 @@ class AvVoltSourceInverterStateSpace void initializeStates(Real omega, Real timeStep, Attribute::Ptr leftVector); - // initialize with parameters. - //void initialize(Real theta, Real phi_pll, Real p, Real q, Real phi_d, Real phi_q, - // Real gamma_d, Real gamma_q, Real i_fd, Real i_fq, Real v_cd, Real v_cq); +#if 0 + // Initialize with parameters. + void initialize(Real theta, Real phi_pll, Real p, Real q, Real phi_d, Real phi_q, + Real gamma_d, Real gamma_q, Real i_fd, Real i_fq, Real v_cd, Real v_cq); - //void initStates(Real initOmegaPLL, Real initPhiPLL, Real initP, Real initQ, - // Real initPhid, Real initPhiQ, Real initGamma_d, Real initGamma_q, Real initVcabc, Real initIfabc); + void initStates(Real initOmegaPLL, Real initPhiPLL, Real initP, Real initQ, + Real initPhid, Real initPhiQ, Real initGamma_d, Real initGamma_q, Real initVcabc, Real initIfabc); +#endif void updateStates(); diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h index 588c3a91c2..3cc9e8f615 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h @@ -76,11 +76,13 @@ class PiLine : public CompositePowerComp, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; - //MNAInterface::List mnaTearGroundComponents(); - /*void mnaTearInitialize(Real omega, Real timeStep); - void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix); - void mnaTearApplyVoltageStamp(Matrix& voltageVector); - void mnaTearPostStep(Matrix voltage, Matrix current);*/ +#if 0 + MNAInterface::List mnaTearGroundComponents(); + void mnaTearInitialize(Real omega, Real timeStep); + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix); + void mnaTearApplyVoltageStamp(Matrix& voltageVector); + void mnaTearPostStep(Matrix voltage, Matrix current); +#endif }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/Graph.h b/dpsim-models/include/dpsim-models/Graph.h index 894d0fedf2..773192685a 100644 --- a/dpsim-models/include/dpsim-models/Graph.h +++ b/dpsim-models/include/dpsim-models/Graph.h @@ -45,10 +45,7 @@ class Edge : public Element { Edge(Graph *g, const String &name, Node *head, Node *tail); }; -/** - * - * See: http://www.graphviz.org/pdf/libguide.pdf - */ +// See: http://www.graphviz.org/pdf/libguide.pdf class Graph : public Element { protected: diff --git a/dpsim-models/include/dpsim-models/TopologicalPowerComp.h b/dpsim-models/include/dpsim-models/TopologicalPowerComp.h index 9155d02b26..8806232153 100644 --- a/dpsim-models/include/dpsim-models/TopologicalPowerComp.h +++ b/dpsim-models/include/dpsim-models/TopologicalPowerComp.h @@ -49,8 +49,8 @@ class TopologicalPowerComp : public IdentifiedObject { Logger::Level logLevel = Logger::Level::off) : IdentifiedObject(uid, name), /* We also want to set the CLI loglevel according to the logLevel - * std::max(Logger::Level::info, logLevel). But because of excessive - * logging to Level::info that is currently infeasible. */ + * std::max(Logger::Level::info, logLevel). But because of excessive + * logging to Level::info that is currently infeasible. */ mSLog(Logger::get(name, logLevel, Logger::Level::warn)), mLogLevel(logLevel) {} diff --git a/dpsim-models/include/dpsim-models/TopologicalSignalComp.h b/dpsim-models/include/dpsim-models/TopologicalSignalComp.h index f789b06b11..a423612bc4 100644 --- a/dpsim-models/include/dpsim-models/TopologicalSignalComp.h +++ b/dpsim-models/include/dpsim-models/TopologicalSignalComp.h @@ -31,8 +31,8 @@ class TopologicalSignalComp : public IdentifiedObject { Logger::Level logLevel = Logger::Level::off) : IdentifiedObject(uid, name), /* We also want to set the CLI loglevel according to the logLevel - * std::max(Logger::Level::info, logLevel). But because of excessive - * logging to Level::info that is currently infeasible. */ + * std::max(Logger::Level::info, logLevel). But because of excessive + * logging to Level::info that is currently infeasible. */ mSLog(Logger::get(name, logLevel, Logger::Level::warn)), mLogLevel(logLevel) {} diff --git a/dpsim-models/src/CIM/Reader.cpp b/dpsim-models/src/CIM/Reader.cpp index 2d1dda5789..27867fa271 100644 --- a/dpsim-models/src/CIM/Reader.cpp +++ b/dpsim-models/src/CIM/Reader.cpp @@ -342,17 +342,17 @@ Reader::mapEnergyConsumer(CIMPP::EnergyConsumer *consumer) { mComponentLogLevel); // TODO: Use EnergyConsumer.P and EnergyConsumer.Q if available, overwrite if existent SvPowerFlow data - /* - Real p = 0; - Real q = 0; - if (consumer->p.value){ - p = unitValue(consumer->p.value,UnitMultiplier::M); - } - if (consumer->q.value){ - q = unitValue(consumer->q.value,UnitMultiplier::M); - } - load->setParameters(p, q, 0); - */ +#if 0 + Real p = 0; + Real q = 0; + if (consumer->p.value){ + p = unitValue(consumer->p.value,UnitMultiplier::M); + } + if (consumer->q.value){ + q = unitValue(consumer->q.value,UnitMultiplier::M); + } + load->setParameters(p, q, 0); +#endif // P and Q values will be set according to SvPowerFlow data load->modifyPowerFlowBusType( diff --git a/dpsim-models/src/CSVReader.cpp b/dpsim-models/src/CSVReader.cpp index f31f4ca0bc..aa95162b12 100644 --- a/dpsim-models/src/CSVReader.cpp +++ b/dpsim-models/src/CSVReader.cpp @@ -139,24 +139,21 @@ std::vector CSVReader::readLoadProfileDP(fs::path file, Real start_time, std::ifstream csvfile(file); CSVReaderIterator row_(csvfile); - // ignore the first row if it is a title + // Ignore the first row if it is a title if (mSkipFirstRow && !std::isdigit((*row_).get(0)[0])) { row_.next(); } - /* - loop over rows of the csv file to find the entry point to read in. - if start_time and end_time are negative (as default), it reads in all rows. - */ + /* Loop over rows of the csv file to find the entry point to read in. + * if start_time and end_time are negative (as default), it reads in all rows. + */ Real presentTime = 0; for (; row_ != CSVReaderIterator(); row_.next()) { if ((start_time < 0) | (Int(presentTime) + 1 > Int(start_time))) break; presentTime++; } - /* - reading data after entry point until end_time is reached - */ + // Reading data after entry point until end_time is reached. for (; row_ != CSVReaderIterator(); row_.next()) { // IMPORTANT: take care of units. assume kW PQData pq; @@ -166,196 +163,199 @@ std::vector CSVReader::readLoadProfileDP(fs::path file, Real start_time, load_profileDP.push_back(pq); if (end_time > 0 && presentTime > end_time) break; - /*while (presentTime + time_step < Int(presentTime) + 1) - { - presentTime += time_step; - p_data.push_back(p_data.back()); - }*/ +#if 0 + while (presentTime + time_step < Int(presentTime) + 1) { + presentTime += time_step; + p_data.push_back(p_data.back()); + } +#endif presentTime = Int(presentTime) + 1; } std::cout << "CSV loaded." << std::endl; return load_profileDP; } -// void CSVReader::assignLoadProfileSP(std::vector>& loads, -// Real start_time, Real time_step, Real end_time, Real scale_factor, -// CSVReader::Mode mode, CSVReader::DataFormat format) { - -// switch (mode) { -// case CSVReader::Mode::AUTO: { -// for (auto load : loads) { -// if(!load->isLoad()) -// continue; -// String load_name = load->name(); -// for (auto file : mFileList) { -// String file_name = file.filename().string(); -// /// changing file name and load name to upper case for later matching -// for (auto & c : load_name) c = toupper(c); -// for (auto & c : file_name) c = toupper(c); -// /// strip off all non-alphanumeric characters -// load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); -// file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); -// if (std::stoi(file_name) == std::stoi(load_name)) { -// load->mLoadProfile = readLoadProfileDP(file, start_time, time_step, end_time, scale_factor, format); -// SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); -// } -// } -// } - -// break; -// } -// case CSVReader::Mode::MANUAL: { -// Int LP_assigned_counter = 0; -// Int LP_not_assigned_counter = 0; -// SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); -// for (auto load : loads) { -// std::map::iterator file = mAssignPattern.find(load->name()); -// if (file == mAssignPattern.end()) { - -// SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); -// LP_not_assigned_counter++; -// continue; -// } -// for(auto path: mFileList){ -// if(path.string().find(file->second)!= std::string::npos){ -// load->mLoadProfile = readLoadProfileDP(path, start_time, time_step, end_time, scale_factor); -// SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); -// LP_assigned_counter++; -// } - -// } -// } -// SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); -// break; -// } -// default: { -// throw std::invalid_argument( -// "Load profile assign mode error"); -// break; -// } -// } -// } - -// void CSVReader::assignLoadProfilePF(std::vector>& loads, -// Real start_time, Real time_step, Real end_time, Real scale_factor, -// CSVReader::Mode mode, CSVReader::DataFormat format) { - -// switch (mode) { -// case CSVReader::Mode::AUTO: { -// for (auto load : loads) { -// if(!load->isLoad()) -// continue; -// String load_name = load->name(); -// for (auto file : mFileList) { -// String file_name = file.filename().string(); -// /// changing file name and load name to upper case for later matching -// for (auto & c : load_name) c = toupper(c); -// for (auto & c : file_name) c = toupper(c); -// /// strip off all non-alphanumeric characters -// load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); -// file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); -// if (std::stoi(file_name) == std::stoi(load_name)) { -// load->mPFAvVoltageSourceInverter->mLoadProfile = readLoadProfile(fs::path(mPath + file->second + ".csv"), start_time, time_step, end_time); -// load->mPFAvVoltageSourceInverter->use_profile = true; -// SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); -// } -// } -// } - -// break; -// } -// case CSVReader::Mode::MANUAL: { -// Int LP_assigned_counter = 0; -// Int LP_not_assigned_counter = 0; -// SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); -// for (auto load : loads) { -// std::map::iterator file = mAssignPattern.find(load->name()); -// if (file == mAssignPattern.end()) { - -// SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); -// LP_not_assigned_counter++; -// continue; -// } -// for(auto path: mFileList){ -// if(path.string().find(file->second)!= std::string::npos){ -// load->mPFAvVoltageSourceInverter->mLoadProfile = readLoadProfile(fs::path(mPath + file->second + ".csv"), start_time, time_step, end_time); -// load->mPFAvVoltageSourceInverter->use_profile = true; -// SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); -// LP_assigned_counter++; -// } - -// } -// } -// SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); -// break; -// } -// default: { -// throw std::invalid_argument( -// "Load profile assign mode error"); -// break; -// } -// } -// } +#if 0 +void CSVReader::assignLoadProfileSP(std::vector>& loads, + Real start_time, Real time_step, Real end_time, Real scale_factor, + CSVReader::Mode mode, CSVReader::DataFormat format) { + + switch (mode) { + case CSVReader::Mode::AUTO: { + for (auto load : loads) { + if(!load->isLoad()) + continue; + String load_name = load->name(); + for (auto file : mFileList) { + String file_name = file.filename().string(); + // Changing file name and load name to upper case for later matching + for (auto & c : load_name) c = toupper(c); + for (auto & c : file_name) c = toupper(c); + // Strip off all non-alphanumeric characters + load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); + file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); + if (std::stoi(file_name) == std::stoi(load_name)) { + load->mLoadProfile = readLoadProfileDP(file, start_time, time_step, end_time, scale_factor, format); + SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); + } + } + } + + break; + } + case CSVReader::Mode::MANUAL: { + Int LP_assigned_counter = 0; + Int LP_not_assigned_counter = 0; + SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); + for (auto load : loads) { + std::map::iterator file = mAssignPattern.find(load->name()); + if (file == mAssignPattern.end()) { + + SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); + LP_not_assigned_counter++; + continue; + } + for(auto path: mFileList){ + if(path.string().find(file->second)!= std::string::npos){ + load->mLoadProfile = readLoadProfileDP(path, start_time, time_step, end_time, scale_factor); + SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); + LP_assigned_counter++; + } + + } + } + SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); + break; + } + default: { + throw std::invalid_argument( + "Load profile assign mode error"); + break; + } + } +} + +void CSVReader::assignLoadProfilePF(std::vector>& loads, + Real start_time, Real time_step, Real end_time, Real scale_factor, + CSVReader::Mode mode, CSVReader::DataFormat format) { + + switch (mode) { + case CSVReader::Mode::AUTO: { + for (auto load : loads) { + if(!load->isLoad()) + continue; + String load_name = load->name(); + for (auto file : mFileList) { + String file_name = file.filename().string(); + // Changing file name and load name to upper case for later matching + for (auto & c : load_name) c = toupper(c); + for (auto & c : file_name) c = toupper(c); + // Strip off all non-alphanumeric characters + load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); + file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); + if (std::stoi(file_name) == std::stoi(load_name)) { + load->mPFAvVoltageSourceInverter->mLoadProfile = readLoadProfile(fs::path(mPath + file->second + ".csv"), start_time, time_step, end_time); + load->mPFAvVoltageSourceInverter->use_profile = true; + SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); + } + } + } + + break; + } + case CSVReader::Mode::MANUAL: { + Int LP_assigned_counter = 0; + Int LP_not_assigned_counter = 0; + SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); + for (auto load : loads) { + std::map::iterator file = mAssignPattern.find(load->name()); + if (file == mAssignPattern.end()) { + + SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); + LP_not_assigned_counter++; + continue; + } + for(auto path: mFileList){ + if(path.string().find(file->second)!= std::string::npos){ + load->mPFAvVoltageSourceInverter->mLoadProfile = readLoadProfile(fs::path(mPath + file->second + ".csv"), start_time, time_step, end_time); + load->mPFAvVoltageSourceInverter->use_profile = true; + SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); + LP_assigned_counter++; + } + + } + } + SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); + break; + } + default: { + throw std::invalid_argument( + "Load profile assign mode error"); + break; + } + } +} // TODO: profile handling currently not supported by average inverter in DP1ph -// void CSVReader::assignLoadProfileDP(std::vector>& loads, -// Real start_time, Real time_step, Real end_time, Real scale_factor, -// CSVReader::Mode mode, CSVReader::DataFormat format) { - -// switch (mode) { -// case CSVReader::Mode::AUTO: { -// for (auto load : loads) { -// if(!load->isLoad()) -// continue; -// String load_name = load->name(); -// for (auto file : mFileList) { -// String file_name = file.filename().string(); -// /// changing file name and load name to upper case for later matching -// for (auto & c : load_name) c = toupper(c); -// for (auto & c : file_name) c = toupper(c); -// /// strip off all non-alphanumeric characters -// load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); -// file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); -// if (std::stoi(file_name) == std::stoi(load_name)) { -// load->mLoadProfile = readLoadProfileDP(file, start_time, time_step, end_time, scale_factor, format); -// SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); -// } -// } -// } - -// break; -// } -// case CSVReader::Mode::MANUAL: { -// Int LP_assigned_counter = 0; -// Int LP_not_assigned_counter = 0; -// SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); -// for (auto load : loads) { -// std::map::iterator file = mAssignPattern.find(load->name()); -// if (file == mAssignPattern.end()) { - -// SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); -// LP_not_assigned_counter++; -// continue; -// } -// for(auto path: mFileList){ -// if(path.string().find(file->second)!= std::string::npos){ -// load->mLoadProfile = readLoadProfileDP(path, start_time, time_step, end_time, scale_factor); -// SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); -// LP_assigned_counter++; -// } - -// } -// } -// SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); -// break; -// } -// default: { -// throw std::invalid_argument( -// "Load profile assign mode error"); -// break; -// } -// } -// } +void CSVReader::assignLoadProfileDP(std::vector>& loads, + Real start_time, Real time_step, Real end_time, Real scale_factor, + CSVReader::Mode mode, CSVReader::DataFormat format) { + + switch (mode) { + case CSVReader::Mode::AUTO: { + for (auto load : loads) { + if(!load->isLoad()) + continue; + String load_name = load->name(); + for (auto file : mFileList) { + String file_name = file.filename().string(); + // Changing file name and load name to upper case for later matching + for (auto & c : load_name) c = toupper(c); + for (auto & c : file_name) c = toupper(c); + // Strip off all non-alphanumeric characters + load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); + file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); + if (std::stoi(file_name) == std::stoi(load_name)) { + load->mLoadProfile = readLoadProfileDP(file, start_time, time_step, end_time, scale_factor, format); + SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); + } + } + } + + break; + } + case CSVReader::Mode::MANUAL: { + Int LP_assigned_counter = 0; + Int LP_not_assigned_counter = 0; + SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); + for (auto load : loads) { + std::map::iterator file = mAssignPattern.find(load->name()); + if (file == mAssignPattern.end()) { + + SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); + LP_not_assigned_counter++; + continue; + } + for(auto path: mFileList){ + if(path.string().find(file->second)!= std::string::npos){ + load->mLoadProfile = readLoadProfileDP(path, start_time, time_step, end_time, scale_factor); + SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); + LP_assigned_counter++; + } + + } + } + SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); + break; + } + default: { + throw std::invalid_argument( + "Load profile assign mode error"); + break; + } + } +} +#endif PowerProfile CSVReader::readLoadProfile(fs::path file, Real start_time, Real time_step, Real end_time, @@ -374,10 +374,10 @@ PowerProfile CSVReader::readLoadProfile(fs::path file, Real start_time, } /* - loop over rows of the csv file to find the entry point to read in. - and determine data type prior to read in. (assuming only time,p,q or time,weighting factor) - if start_time and end_time are negative (as default), it reads in all rows. - */ + loop over rows of the csv file to find the entry point to read in. + and determine data type prior to read in. (assuming only time,p,q or time,weighting factor) + if start_time and end_time are negative (as default), it reads in all rows. + */ for (; loop != CSVReaderIterator(); loop.next()) { CSVReaderIterator nextRow = loop; nextRow.next(); @@ -392,8 +392,8 @@ PowerProfile CSVReader::readLoadProfile(fs::path file, Real start_time, } } /* - reading data after entry point until end_time is reached - */ + reading data after entry point until end_time is reached + */ for (; loop != CSVReaderIterator(); loop.next()) { CPS::Real currentTime = (need_that_conversion) ? time_format_convert((*loop).get(0)) @@ -448,28 +448,27 @@ std::vector CSVReader::readPQData(fs::path file, Real start_time, } /* - loop over rows of the csv file to find the entry point to read in. - if start_time and end_time are negative (as default), it reads in all rows. - */ + loop over rows of the csv file to find the entry point to read in. + if start_time and end_time are negative (as default), it reads in all rows. + */ Real presentTime = 0; for (; row_ != CSVReaderIterator(); row_.next()) { if ((start_time < 0) | (Int(presentTime) + 1 > Int(start_time))) break; presentTime++; } - /* - reading data after entry point until end_time is reached - */ + // Reading data after entry point until end_time is reached. for (; row_ != CSVReaderIterator(); row_.next()) { // IMPORTANT: take care of units. assume kW p_data.push_back(std::stod((*row_).get(0)) * 1000); if (end_time > 0 && presentTime > end_time) break; - /*while (presentTime + time_step < Int(presentTime) + 1) - { - presentTime += time_step; - p_data.push_back(p_data.back()); - }*/ +#if 0 + while (presentTime + time_step < Int(presentTime) + 1) { + presentTime += time_step; + p_data.push_back(p_data.back()); + } +#endif presentTime = Int(presentTime) + 1; } std::cout << "CSV loaded." << std::endl; @@ -491,12 +490,12 @@ void CSVReader::assignLoadProfile(CPS::SystemTopology &sys, Real start_time, String load_name = load->name(); for (auto file : mFileList) { String file_name = file.filename().string(); - /// changing file name and load name to upper case for later matching + // Changing file name and load name to upper case for later matching for (auto &c : load_name) c = toupper(c); for (auto &c : file_name) c = toupper(c); - /// strip off all non-alphanumeric characters + // Strip off all non-alphanumeric characters load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); diff --git a/dpsim-models/src/DP/DP_Ph1_NetworkInjection.cpp b/dpsim-models/src/DP/DP_Ph1_NetworkInjection.cpp index ccd16a84e7..6413b9d8f4 100644 --- a/dpsim-models/src/DP/DP_Ph1_NetworkInjection.cpp +++ b/dpsim-models/src/DP/DP_Ph1_NetworkInjection.cpp @@ -159,17 +159,17 @@ void DP::Ph1::NetworkInjection::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { - /* new state vector definintion: - state[0]=node0_voltage - state[1]=node1_voltage - .... - state[n]=noden_voltage - state[n+1]=component0_voltage - state[n+2]=component0_inductance (not yet implemented) - ... - state[m-1]=componentm_voltage - state[m]=componentm_inductance - */ + /* New state vector definintion: + * state[0]=node0_voltage + * state[1]=node1_voltage + * .... + * state[n]=noden_voltage + * state[n+1]=component0_voltage + * state[n+2]=component0_inductance (not yet implemented) + * ... + * state[m-1]=componentm_voltage + * state[m]=componentm_inductance + */ int Pos1 = matrixNodeIndex(0); int Pos2 = matrixNodeIndex(1); diff --git a/dpsim-models/src/DP/DP_Ph1_ProfileVoltageSource.cpp b/dpsim-models/src/DP/DP_Ph1_ProfileVoltageSource.cpp index 8d36e4c56f..0918852ae0 100644 --- a/dpsim-models/src/DP/DP_Ph1_ProfileVoltageSource.cpp +++ b/dpsim-models/src/DP/DP_Ph1_ProfileVoltageSource.cpp @@ -294,17 +294,17 @@ void DP::Ph1::ProfileVoltageSource::daeResidual(double ttime, const double dstate_dt[], double resid[], std::vector &off) { - /* new state vector definintion: - state[0]=node0_voltage - state[1]=node1_voltage - .... - state[n]=noden_voltage - state[n+1]=component0_voltage - state[n+2]=component0_inductance (not yet implemented) - ... - state[m-1]=componentm_voltage - state[m]=componentm_inductance - */ + /* New state vector definintion: + * state[0]=node0_voltage + * state[1]=node1_voltage + * .... + * state[n]=noden_voltage + * state[n+1]=component0_voltage + * state[n+2]=component0_inductance (not yet implemented) + * ... + * state[m-1]=componentm_voltage + * state[m]=componentm_inductance + */ int Pos1 = matrixNodeIndex(0); int Pos2 = matrixNodeIndex(1); diff --git a/dpsim-models/src/DP/DP_Ph1_Resistor.cpp b/dpsim-models/src/DP/DP_Ph1_Resistor.cpp index 3ef1f4fb28..148c52b8f8 100644 --- a/dpsim-models/src/DP/DP_Ph1_Resistor.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Resistor.cpp @@ -174,31 +174,34 @@ void DP::Ph1::Resistor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { void DP::Ph1::Resistor::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { - // new state vector definintion: - // state[0]=node0_voltage - // state[1]=node1_voltage - // .... - // state[n]=noden_voltage - // state[n+1]=component0_voltage - // state[n+2]=component0_inductance (not yet implemented) - // ... - // state[m-1]=componentm_voltage - // state[m]=componentm_inductance - // ... - // state[x] = nodal_equation_1 - // state[x+1] = nodal_equation_2 - // ... + /* New state vector definintion: + * state[0]=node0_voltage + * state[1]=node1_voltage + * .... + * state[n]=noden_voltage + * state[n+1]=component0_voltage + * state[n+2]=component0_inductance (not yet implemented) + * ... + * state[m-1]=componentm_voltage + * state[m]=componentm_inductance + * ... + * state[x] = nodal_equation_1 + * state[x+1] = nodal_equation_2 + * ... + */ int Pos1 = matrixNodeIndex(0); int Pos2 = matrixNodeIndex(1); - int c_offset = off[0] + off[1]; //current offset for component + int c_offset = off[0] + off[1]; // Current offset for component int n_offset_1 = - c_offset + Pos1 + 1; // current offset for first nodal equation + c_offset + Pos1 + 1; // Current offset for first nodal equation int n_offset_2 = - c_offset + Pos2 + 1; // current offset for second nodal equation + c_offset + Pos2 + 1; // Current offset for second nodal equation resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor - //resid[c_offset+1] = ; //TODO : add inductance equation +#if 0 + resid[c_offset+1] = ; // TODO : add inductance equation +#endif resid[n_offset_1] += 1.0 / **mResistance * state[c_offset]; resid[n_offset_2] += 1.0 / **mResistance * state[c_offset]; off[1] += 1; diff --git a/dpsim-models/src/DP/DP_Ph1_VoltageSource.cpp b/dpsim-models/src/DP/DP_Ph1_VoltageSource.cpp index dc825e2e28..5c79c9fe51 100644 --- a/dpsim-models/src/DP/DP_Ph1_VoltageSource.cpp +++ b/dpsim-models/src/DP/DP_Ph1_VoltageSource.cpp @@ -286,17 +286,17 @@ void DP::Ph1::VoltageSource::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { - /* new state vector definintion: - state[0]=node0_voltage - state[1]=node1_voltage - .... - state[n]=noden_voltage - state[n+1]=component0_voltage - state[n+2]=component0_inductance (not yet implemented) - ... - state[m-1]=componentm_voltage - state[m]=componentm_inductance - */ + /* New state vector definintion: + * state[0]=node0_voltage + * state[1]=node1_voltage + * .... + * state[n]=noden_voltage + * state[n+1]=component0_voltage + * state[n+2]=component0_inductance (not yet implemented) + * ... + * state[m-1]=componentm_voltage + * state[m]=componentm_inductance + */ int Pos1 = matrixNodeIndex(0); int Pos2 = matrixNodeIndex(1); diff --git a/dpsim-models/src/DP/DP_Ph3_Capacitor.cpp b/dpsim-models/src/DP/DP_Ph3_Capacitor.cpp index 5233267620..1ff468107a 100644 --- a/dpsim-models/src/DP/DP_Ph3_Capacitor.cpp +++ b/dpsim-models/src/DP/DP_Ph3_Capacitor.cpp @@ -83,10 +83,11 @@ void DP::Ph3::Capacitor::initVars(Real omega, Real timeStep) { Complex(equivCondReal(2, 1), equivCondImag(2, 1)), Complex(equivCondReal(2, 2), equivCondImag(2, 2)); - // since equivCondReal == a.inverse() - // and - /*Matrix mPrevVoltCoeffReal = a.inverse(); - Matrix mPrevVoltCoeffImag = -b * a.inverse();*/ + // Since equivCondReal == a.inverse() and +#if 0 + Matrix mPrevVoltCoeffReal = a.inverse(); + Matrix mPrevVoltCoeffImag = -b * a.inverse(); +#endif Matrix mPrevVoltCoeffReal = equivCondReal; Matrix mPrevVoltCoeffImag = -b * equivCondReal; @@ -108,32 +109,34 @@ void DP::Ph3::Capacitor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); initVars(omega, timeStep); - //Matrix equivCondReal = 2.0 * mCapacitance / timeStep; - //Matrix equivCondImag = omega * mCapacitance; - //mEquivCond << - // Complex(equivCondReal(0, 0), equivCondImag(0, 0)), - // Complex(equivCondReal(1, 0), equivCondImag(1, 0)), - // Complex(equivCondReal(2, 0), equivCondImag(2, 0)); - - // TODO: something is wrong here -- from Ph1_Capacitor - /*Matrix prevVoltCoeffReal = 2.0 * mCapacitance / timeStep; - Matrix prevVoltCoeffImag = - omega * mCapacitance; - mPrevVoltCoeff = Matrix::Zero(3, 1); - mPrevVoltCoeff << - Complex(prevVoltCoeffReal(0, 0), prevVoltCoeffImag(0, 0)), - Complex(prevVoltCoeffReal(1, 0), prevVoltCoeffImag(1, 0)), - Complex(prevVoltCoeffReal(2, 0), prevVoltCoeffImag(2, 0)); - - mEquivCurrent = -**mIntfCurrent + -mPrevVoltCoeff.cwiseProduct( **mIntfVoltage);*/ - // no need to update current now +#if 0 + Matrix equivCondReal = 2.0 * mCapacitance / timeStep; + Matrix equivCondImag = omega * mCapacitance; + mEquivCond << + Complex(equivCondReal(0, 0), equivCondImag(0, 0)), + Complex(equivCondReal(1, 0), equivCondImag(1, 0)), + Complex(equivCondReal(2, 0), equivCondImag(2, 0)); + + // TODO: Something is wrong here -- from Ph1_Capacitor + Matrix prevVoltCoeffReal = 2.0 * mCapacitance / timeStep; + Matrix prevVoltCoeffImag = - omega * mCapacitance; + mPrevVoltCoeff = Matrix::Zero(3, 1); + mPrevVoltCoeff << + Complex(prevVoltCoeffReal(0, 0), prevVoltCoeffImag(0, 0)), + Complex(prevVoltCoeffReal(1, 0), prevVoltCoeffImag(1, 0)), + Complex(prevVoltCoeffReal(2, 0), prevVoltCoeffImag(2, 0)); + + mEquivCurrent = -**mIntfCurrent + -mPrevVoltCoeff.cwiseProduct( **mIntfVoltage);*/ + // No need to update current now //**mIntfCurrent = mEquivCond.cwiseProduct(**mIntfVoltage) + mEquivCurrent; - // mLog.info() << "\n--- MNA Initialization ---" << std::endl - // << "Initial voltage " << Math::abs((**mIntfVoltage)(0,0)) - // << "<" << Math::phaseDeg((**mIntfVoltage)(0,0)) << std::endl - // << "Initial current " << Math::abs((**mIntfCurrent)(0,0)) - // << "<" << Math::phaseDeg((**mIntfCurrent)(0,0)) << std::endl - // << "--- MNA initialization finished ---" << std::endl; + mLog.info() << "\n--- MNA Initialization ---" << std::endl + << "Initial voltage " << Math::abs((**mIntfVoltage)(0,0)) + << "<" << Math::phaseDeg((**mIntfVoltage)(0,0)) << std::endl + << "Initial current " << Math::abs((**mIntfCurrent)(0,0)) + << "<" << Math::phaseDeg((**mIntfCurrent)(0,0)) << std::endl + << "--- MNA initialization finished ---" << std::endl; +#endif } void DP::Ph3::Capacitor::mnaCompApplySystemMatrixStamp( diff --git a/dpsim-models/src/DP/DP_Ph3_Inductor.cpp b/dpsim-models/src/DP/DP_Ph3_Inductor.cpp index be0ff3e8dc..1a7fad29fe 100644 --- a/dpsim-models/src/DP/DP_Ph3_Inductor.cpp +++ b/dpsim-models/src/DP/DP_Ph3_Inductor.cpp @@ -198,21 +198,21 @@ void DP::Ph3::Inductor::mnaTearInitialize(Real omega, Real timeStep) { } void DP::Ph3::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { - /* - Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx, mEquivCond.cwiseInverse()(0,0)); - */ +#if 0 + Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx, mEquivCond.cwiseInverse()(0,0)); +#endif } void DP::Ph3::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) { - /* - mEquivCurrent = mEquivCond * (**mIntfVoltage)(0,0) + mPrevCurrFac * (**mIntfCurrent)(0,0); - Math::addToVectorElement(voltageVector, mTearIdx, mEquivCurrent .cwiseProduct( mEquivCond.cwiseInverse())); - */ +#if 0 + mEquivCurrent = mEquivCond * (**mIntfVoltage)(0,0) + mPrevCurrFac * (**mIntfCurrent)(0,0); + Math::addToVectorElement(voltageVector, mTearIdx, mEquivCurrent .cwiseProduct( mEquivCond.cwiseInverse())); +#endif } void DP::Ph3::Inductor::mnaTearPostStep(Complex voltage, Complex current) { - /* - **mIntfVoltage = voltage; - **mIntfCurrent = mEquivCond * voltage + mEquivCurrent; - */ +#if 0 + **mIntfVoltage = voltage; + **mIntfCurrent = mEquivCond * voltage + mEquivCurrent; +#endif } diff --git a/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQ.cpp b/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQ.cpp index f3ff484338..a5829feab9 100644 --- a/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQ.cpp +++ b/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQ.cpp @@ -194,52 +194,52 @@ MatrixComp DP::Ph3::SynchronGeneratorDQ::dq0ToAbcTransform(Real theta, } void DP::Ph3::SynchronGeneratorDQ::trapezoidalFluxStates() { - /* - // Calculation of rotational speed with euler - if (mHasTurbineGovernor == true) - mMechTorque = mTurbineGovernor.step(mOmMech, 1, 300e6 / 555e6, mTimeStep); - - mElecTorque = (mPsid*mIq - mPsiq*mId); - mOmMech = mOmMech + mTimeStep * (1 / (2 * mH) * (mMechTorque - mElecTorque)); - - //Calculation of flux - Matrix A = (mResistanceMat*mReactanceMat - mOmMech*mOmegaFluxMat); - Matrix B = Matrix::Identity(7, 7); - - if (numMethod == NumericalMethod::Trapezoidal_flux) - Fluxes = Math::StateSpaceTrapezoidal(Fluxes, A, B, mTimeStep*mBase_OmElec, dqVoltages); - else - Fluxes = Math::StateSpaceEuler(Fluxes, A, B, mTimeStep*mBase_OmElec, dqVoltages); - - // Calculation of currents based on inverse of inductance matrix - mId = ((mLlfd*mLlkd + mLmd*(mLlfd + mLlkd))*mPsid - mLmd*mLlkd*mPsifd - mLlfd*mLmd*mPsikd) / detLd; - mIfd = (mLlkd*mLmd*mPsid - (mLl*mLlkd + mLmd*(mLl + mLlkd))*mPsifd + mLmd*mLl*mPsikd) / detLd; - mIkd = (mLmd*mLlfd*mPsid + mLmd*mLl*mPsifd - (mLmd*(mLlfd + mLl) + mLl*mLlfd)*mPsikd) / detLd; - mIq = ((mLlkq1*mLlkq2 + mLmq*(mLlkq1 + mLlkq2))*mPsiq - mLmq*mLlkq2*mPsikq1 - mLmq*mLlkq1*mPsikq2) / detLq; - mIkq1 = (mLmq*mLlkq2*mPsiq - (mLmq*(mLlkq2 + mLl) + mLl*mLlkq2)*mPsikq1 + mLmq*mLl*mPsikq2) / detLq; - mIkq2 = (mLmq*mLlkq1*mPsiq + mLmq*mLl*mPsikq1 - (mLmq*(mLlkq1 + mLl) + mLl*mLlkq1)*mPsikq2) / detLq; - mI0 = -mPsi0 / mLl; - */ +#if 0 + // Calculation of rotational speed with euler + if (mHasTurbineGovernor == true) + mMechTorque = mTurbineGovernor.step(mOmMech, 1, 300e6 / 555e6, mTimeStep); + + mElecTorque = (mPsid*mIq - mPsiq*mId); + mOmMech = mOmMech + mTimeStep * (1 / (2 * mH) * (mMechTorque - mElecTorque)); + + //Calculation of flux + Matrix A = (mResistanceMat*mReactanceMat - mOmMech*mOmegaFluxMat); + Matrix B = Matrix::Identity(7, 7); + + if (numMethod == NumericalMethod::Trapezoidal_flux) + Fluxes = Math::StateSpaceTrapezoidal(Fluxes, A, B, mTimeStep*mBase_OmElec, dqVoltages); + else + Fluxes = Math::StateSpaceEuler(Fluxes, A, B, mTimeStep*mBase_OmElec, dqVoltages); + + // Calculation of currents based on inverse of inductance matrix + mId = ((mLlfd*mLlkd + mLmd*(mLlfd + mLlkd))*mPsid - mLmd*mLlkd*mPsifd - mLlfd*mLmd*mPsikd) / detLd; + mIfd = (mLlkd*mLmd*mPsid - (mLl*mLlkd + mLmd*(mLl + mLlkd))*mPsifd + mLmd*mLl*mPsikd) / detLd; + mIkd = (mLmd*mLlfd*mPsid + mLmd*mLl*mPsifd - (mLmd*(mLlfd + mLl) + mLl*mLlfd)*mPsikd) / detLd; + mIq = ((mLlkq1*mLlkq2 + mLmq*(mLlkq1 + mLlkq2))*mPsiq - mLmq*mLlkq2*mPsikq1 - mLmq*mLlkq1*mPsikq2) / detLq; + mIkq1 = (mLmq*mLlkq2*mPsiq - (mLmq*(mLlkq2 + mLl) + mLl*mLlkq2)*mPsikq1 + mLmq*mLl*mPsikq2) / detLq; + mIkq2 = (mLmq*mLlkq1*mPsiq + mLmq*mLl*mPsikq1 - (mLmq*(mLlkq1 + mLl) + mLl*mLlkq1)*mPsikq2) / detLq; + mI0 = -mPsi0 / mLl; +#endif } void DP::Ph3::SynchronGeneratorDQ::trapezoidalCurrentStates() { - /* - Matrix A = (mReactanceMat*mResistanceMat); - Matrix B = mReactanceMat; - Matrix C = Matrix::Zero(7, 1); - C(0, 0) = -mOmMech*mPsid; - C(1, 0) = mOmMech*mPsiq; - C = mReactanceMat*C; - - dqCurrents = Math::StateSpaceTrapezoidal(dqCurrents, A, B, C, mTimeStep*mOmMech, dqVoltages); - - //Calculation of currents based on inverse of inductance matrix - mPsiq = -(mLl + mLmq)*mIq + mLmq*mIkq1 + mLmq*mIkq2; - mPsid = -(mLl + mLmd)*mId + mLmd*mIfd + mLmd*mIkd; - mPsi0 = -mLl*mI0; - mPsikq1 = -mLmq*mIq + (mLlkq1 + mLmq)*mIkq1 + mLmq*mIkq2; - mPsikq2 = -mLmq*mIq + mLmq*mIkq1 + (mLlkq2 + mLmq)*mIkq2; - mPsifd = -mLmd*mId + (mLlfd + mLmd)*mIfd + mLmd*mIkd; - mPsikd = -mLmd*mId + mLmd*mIfd + (mLlkd + mLmd)*mIkd; - */ +#if 0 + Matrix A = (mReactanceMat*mResistanceMat); + Matrix B = mReactanceMat; + Matrix C = Matrix::Zero(7, 1); + C(0, 0) = -mOmMech*mPsid; + C(1, 0) = mOmMech*mPsiq; + C = mReactanceMat*C; + + dqCurrents = Math::StateSpaceTrapezoidal(dqCurrents, A, B, C, mTimeStep*mOmMech, dqVoltages); + + //Calculation of currents based on inverse of inductance matrix + mPsiq = -(mLl + mLmq)*mIq + mLmq*mIkq1 + mLmq*mIkq2; + mPsid = -(mLl + mLmd)*mId + mLmd*mIfd + mLmd*mIkd; + mPsi0 = -mLl*mI0; + mPsikq1 = -mLmq*mIq + (mLlkq1 + mLmq)*mIkq1 + mLmq*mIkq2; + mPsikq2 = -mLmq*mIq + mLmq*mIkq1 + (mLlkq2 + mLmq)*mIkq2; + mPsifd = -mLmd*mId + (mLlfd + mLmd)*mIfd + mLmd*mIkd; + mPsikd = -mLmd*mId + mLmd*mIfd + (mLlkd + mLmd)*mIkd; +#endif } diff --git a/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQODE.cpp b/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQODE.cpp index c755d29647..b3fb4212d4 100644 --- a/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQODE.cpp +++ b/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQODE.cpp @@ -113,8 +113,8 @@ void DP::Ph3::SynchronGeneratorDQODE::odeStateSpace(double t, const double y[], ydot[mDim - 2] = (y[mDim - 1] - 1) * mBase_OmMech; /* Auxiliary variables to compute - * T_e= lambda_d * i_q - lambda_q * i_d - * needed for omega: */ + * T_e= lambda_d * i_q - lambda_q * i_d + * needed for omega: */ realtype i_d = 0, i_q = 0; // Compute new currents (depending on updated fluxes) for (int i = 0; i < mDim - 2; i++) { diff --git a/dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp b/dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp index 649431da27..0b29712c20 100644 --- a/dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp +++ b/dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp @@ -36,12 +36,14 @@ void DP::Ph3::VoltageSource::initializeFromNodesAndTerminals(Real frequency) { if (**mVoltageRef == Complex(0, 0)) **mVoltageRef = initialSingleVoltage(1) - initialSingleVoltage(0); - // mLog.info() << "--- Initialize according to power flow ---" << std::endl; - // mLog.info() << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - // << "<" << std::arg(initialSingleVoltage(0)) << std::endl; - // mLog.info() << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - // << "<" << std::arg(initialSingleVoltage(1)) << std::endl; - // mLog.info() << "Voltage across: " << std::abs(mVoltageRef->get()) << "<" << std::arg(mVoltageRef->get()) << std::endl; +#if 0 + mLog.info() << "--- Initialize according to power flow ---" << std::endl; + mLog.info() << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) + << "<" << std::arg(initialSingleVoltage(0)) << std::endl; + mLog.info() << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) + << "<" << std::arg(initialSingleVoltage(1)) << std::endl; + mLog.info() << "Voltage across: " << std::abs(mVoltageRef->get()) << "<" << std::arg(mVoltageRef->get()) << std::endl; +#endif } void DP::Ph3::VoltageSource::mnaCompInitialize( @@ -107,15 +109,17 @@ void DP::Ph3::VoltageSource::mnaCompApplySystemMatrixStamp( matrixNodeIndex(1, 2), Complex(1, 0)); } - // mLog.info() << "--- System matrix stamp ---" << std::endl; - // if (terminalNotGrounded(0)) { - // mLog.info() << "Add " << Complex(-1, 0) << " to " << matrixNodeIndex(0) << "," << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << std::endl; - // mLog.info() << "Add " << Complex(-1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << "," << matrixNodeIndex(0) << std::endl; - // } - // if (terminalNotGrounded(1)) { - // mLog.info() << "Add " << Complex(1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << "," << matrixNodeIndex(1) << std::endl; - // mLog.info() << "Add " << Complex(1, 0) << " to " << matrixNodeIndex(1) << "," << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << std::endl; - // } +#if 0 + mLog.info() << "--- System matrix stamp ---" << std::endl; + if (terminalNotGrounded(0)) { + mLog.info() << "Add " << Complex(-1, 0) << " to " << matrixNodeIndex(0) << "," << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << std::endl; + mLog.info() << "Add " << Complex(-1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << "," << matrixNodeIndex(0) << std::endl; + } + if (terminalNotGrounded(1)) { + mLog.info() << "Add " << Complex(1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << "," << matrixNodeIndex(1) << std::endl; + mLog.info() << "Add " << Complex(1, 0) << " to " << matrixNodeIndex(1) << "," << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << std::endl; + } +#endif } void DP::Ph3::VoltageSource::mnaCompApplyRightSideVectorStamp( @@ -189,17 +193,17 @@ void DP::Ph3::VoltageSource::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { - /* new state vector definintion: - state[0]=node0_voltage - state[1]=node1_voltage - .... - state[n]=noden_voltage - state[n+1]=component0_voltage - state[n+2]=component0_inductance (not yet implemented) - ... - state[m-1]=componentm_voltage - state[m]=componentm_inductance - */ + /* New state vector definintion: + * state[0]=node0_voltage + * state[1]=node1_voltage + * .... + * state[n]=noden_voltage + * state[n+1]=component0_voltage + * state[n+2]=component0_inductance (not yet implemented) + * ... + * state[m-1]=componentm_voltage + * state[m]=componentm_inductance + */ //int Pos1 = matrixNodeIndex(0); //int Pos2 = matrixNodeIndex(1); diff --git a/dpsim-models/src/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp b/dpsim-models/src/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp index c6bc96ff2b..0064030ab9 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp @@ -10,8 +10,8 @@ using namespace CPS; -// !!! TODO: Adaptions to use in EMT_Ph3 models phase-to-ground peak variables -// !!! with initialization from phase-to-phase RMS variables +// !!! TODO: Adaptions to use in EMT_Ph3 models phase-to-ground peak variables +// !!! with initialization from phase-to-phase RMS variables EMT::Ph3::AvVoltSourceInverterStateSpace::AvVoltSourceInverterStateSpace( String uid, String name, Logger::Level logLevel) @@ -148,12 +148,14 @@ void EMT::Ph3::AvVoltSourceInverterStateSpace::initializeStates( **mGamma_q = 0.006339; **mVcabc = initVgabc; mIfabc = Matrix::Zero(3, 1); - /*mVca = initVcabc(0, 0); - mVcb = initVcabc(1, 0); - mVcc = initVcabc(2, 0); - mIfa = initIfabc(0, 0); - mIfb = initIfabc(1, 0); - mIfc = initIfabc(2, 0);*/ +#if 0 + mVca = initVcabc(0, 0); + mVcb = initVcabc(1, 0); + mVcc = initVcabc(2, 0); + mIfa = initIfabc(0, 0); + mIfb = initIfabc(1, 0); + mIfc = initIfabc(2, 0); +#endif mStates << **mThetaPLL, **mPhiPLL, **mP, **mQ, **mPhi_d, **mPhi_q, **mGamma_d, **mGamma_q, **mVcabc, mIfabc; @@ -181,14 +183,14 @@ void EMT::Ph3::AvVoltSourceInverterStateSpace::updateStates() { **mGamma_d = newStates(7, 0); **mVcabc = newStates.block(8, 0, 3, 1); mIfabc = newStates.block(11, 0, 3, 1); - /* - mIfa = newStates(8, 1); - mIfb = newStates(9, 1); - mIfc = newStates(10, 1); - mVca = newStates(11, 1); - mVcb = newStates(12, 1); - mVcc = newStates(13, 1); -*/ +#if 0 + mIfa = newStates(8, 1); + mIfb = newStates(9, 1); + mIfc = newStates(10, 1); + mVca = newStates(11, 1); + mVcb = newStates(12, 1); + mVcc = newStates(13, 1); +#endif mStates = newStates; mU = newU; @@ -220,10 +222,7 @@ void EMT::Ph3::AvVoltSourceInverterStateSpace::updateLinearizedCoeffs() { Tabc2 * mKiCurrCtrlq, Matrix::Zero(3, 3), -Tabc1 * mKpCurrCtrld * Td - Tabc2 * mKpCurrCtrlq * Tq; mA.block(11, 0, 3, 14) = A_bottom; - /* - will it be faster to reconstruct the full B matrix (14x5) - rather than doing three insertions? - */ + // Will it be faster to reconstruct the full B matrix (14x5) rather than doing three insertions? mB.block(2, 2, 1, 3) = 3. / 2. * mOmegaCutoff * (Td * mIg_abc * Td + Tq * mIg_abc * Tq); mB.block(3, 2, 1, 3) = diff --git a/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorDQODE.cpp b/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorDQODE.cpp index 897b5295b8..d172ef2dab 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorDQODE.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_SynchronGeneratorDQODE.cpp @@ -10,8 +10,8 @@ using namespace CPS; -// !!! TODO: Adaptions to use in EMT_Ph3 models phase-to-ground peak variables -// !!! with initialization from phase-to-phase RMS variables +// !!! TODO: Adaptions to use in EMT_Ph3 models phase-to-ground peak variables +// !!! with initialization from phase-to-phase RMS variables EMT::Ph3::SynchronGeneratorDQODE::SynchronGeneratorDQODE(String uid, String name, @@ -118,8 +118,8 @@ void EMT::Ph3::SynchronGeneratorDQODE::odeStateSpace(double t, const double y[], ydot[mDim - 2] = y[mDim - 1] * mBase_OmMech; /* Auxiliary variables to compute - * T_e= lambda_d * i_q - lambda_q * i_d - * needed for omega: */ + * T_e= lambda_d * i_q - lambda_q * i_d + * needed for omega: */ realtype i_d = 0, i_q = 0; // Compute new currents (depending on updated fluxes) for (int i = 0; i < mDim - 2; i++) { diff --git a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp index 22618dba68..48f8ffd330 100644 --- a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp +++ b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp @@ -200,17 +200,17 @@ void SP::Ph1::NetworkInjection::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { - /* new state vector definintion: - state[0]=node0_voltage - state[1]=node1_voltage - .... - state[n]=noden_voltage - state[n+1]=component0_voltage - state[n+2]=component0_inductance (not yet implemented) - ... - state[m-1]=componentm_voltage - state[m]=componentm_inductance - */ + /* New state vector definintion: + * state[0]=node0_voltage + * state[1]=node1_voltage + * .... + * state[n]=noden_voltage + * state[n+1]=component0_voltage + * state[n+2]=component0_inductance (not yet implemented) + * ... + * state[m-1]=componentm_voltage + * state[m]=componentm_inductance + */ int Pos1 = matrixNodeIndex(0); int Pos2 = matrixNodeIndex(1); diff --git a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp index 78c1340030..1e9dd342d0 100644 --- a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp @@ -31,9 +31,11 @@ SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage, **mCurrent = MatrixComp::Zero(2, 1); **mActivePowerBranch = Matrix::Zero(2, 1); **mReactivePowerBranch = Matrix::Zero(2, 1); - // mLog.Log(Logger::Level::DEBUG) << "Create " << this->type() << " " << name - // << " R=" << resistance << " L=" << inductance - // << std::endl; +#if 0 + mLog.Log(Logger::Level::DEBUG) << "Create " << this->type() << " " << name + << " R=" << resistance << " L=" << inductance + << std::endl; +#endif } SP::Ph1::RXLine::RXLine(String uid, String name, Logger::Level logLevel) @@ -61,18 +63,21 @@ void SP::Ph1::RXLine::setPerUnitSystem(Real baseApparentPower, Real baseOmega) { mBaseInductance = mBaseImpedance / mBaseOmega; /// I_base = S_base / V_line mBaseCurrent = baseApparentPower / (**mBaseVoltage * sqrt(3)); - /* - mLog.Log(Logger::Level::INFO) << "#### Set Per Unit System for " << **mName << std::endl; - mLog.Log(Logger::Level::INFO) << " Base Voltage= " << mBaseVoltage << " [V] " << " Base Impedance= " << mBaseImpedance << " [Ohm] " << std::endl; - */ + +#if 0 + mLog.Log(Logger::Level::INFO) << "#### Set Per Unit System for " << **mName << std::endl; + mLog.Log(Logger::Level::INFO) << " Base Voltage= " << mBaseVoltage << " [V] " << " Base Impedance= " << mBaseImpedance << " [Ohm] " << std::endl; +#endif mSeriesResPerUnit = **mSeriesRes / mBaseImpedance; mSeriesIndPerUnit = **mInductance / mBaseInductance; - /* - mLog.Log(Logger::Level::INFO) << "Series Resistance Per Unit= " << " " << mSeriesResPerUnit << " [Ohm] " - << " Series Inductance Per Unit= " << " " << mSeriesIndPerUnit << " [H] " - << std::endl; - mLog.Log(Logger::Level::INFO) << "r " << mSeriesResPerUnit << std::endl << " x: " << mBaseOmega * mInductance / mBaseImpedance<matrixNodeIndex(0); int bus2 = this->matrixNodeIndex(1); - //dimension check - /* TODO: FIX - if (bus1 > (n - 1) || bus2 > (n - 1)) { - std::stringstream ss; - ss << "Line>>" << this->getName() << ": Wrong Y dimension: " << n; - throw std::invalid_argument(ss.str()); - //std::cout << "Line>>" << Name << ": Wrong Y dimension: " << n << endl; - return; - } - */ + // Dimension check + // TODO: FIX +#if 0 + if (bus1 > (n - 1) || bus2 > (n - 1)) { + std::stringstream ss; + ss << "Line>>" << this->getName() << ": Wrong Y dimension: " << n; + throw std::invalid_argument(ss.str()); + //std::cout << "Line>>" << Name << ": Wrong Y dimension: " << n << endl; + return; + } +#endif //create the element admittance matrix Complex y = diff --git a/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp b/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp index 44d34e5a69..34e57d36fb 100644 --- a/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp +++ b/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp @@ -207,28 +207,30 @@ void SP::Ph1::VoltageSource::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { - /* new state vector definintion: - state[0]=node0_voltage - state[1]=node1_voltage - .... - state[n]=noden_voltage - state[n+1]=component0_voltage - state[n+2]=component0_inductance (not yet implemented) - ... - state[m-1]=componentm_voltage - state[m]=componentm_inductance - */ - - //int Pos1 = matrixNodeIndex(0); - //int Pos2 = matrixNodeIndex(1); - //int c_offset = off[0] + off[1]; //current offset for component - //int n_offset_1 = c_offset + Pos1 + 1;// current offset for first nodal equation - //int n_offset_2 = c_offset + Pos2 + 1;// current offset for second nodal equation - //resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor - ////resid[++c_offset] = ; //TODO : add inductance equation - //resid[n_offset_1] += std::real(current()); - //resid[n_offset_2] += std::real(current()); - //off[1] += 1; + /* New state vector definintion: + * state[0]=node0_voltage + * state[1]=node1_voltage + * .... + * state[n]=noden_voltage + * state[n+1]=component0_voltage + * state[n+2]=component0_inductance (not yet implemented) + * ... + * state[m-1]=componentm_voltage + * state[m]=componentm_inductance + */ + +#if 0 + int Pos1 = matrixNodeIndex(0); + int Pos2 = matrixNodeIndex(1); + int c_offset = off[0] + off[1]; //current offset for component + int n_offset_1 = c_offset + Pos1 + 1;// current offset for first nodal equation + int n_offset_2 = c_offset + Pos2 + 1;// current offset for second nodal equation + resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor + //resid[++c_offset] = ; //TODO : add inductance equation + resid[n_offset_1] += std::real(current()); + resid[n_offset_2] += std::real(current()); + off[1] += 1; +#endif } Complex SP::Ph1::VoltageSource::daeInitialize() { diff --git a/dpsim-models/src/SP/SP_Ph3_Capacitor.cpp b/dpsim-models/src/SP/SP_Ph3_Capacitor.cpp index ac38f68188..3fa2c06e20 100644 --- a/dpsim-models/src/SP/SP_Ph3_Capacitor.cpp +++ b/dpsim-models/src/SP/SP_Ph3_Capacitor.cpp @@ -48,30 +48,33 @@ void SP::Ph3::Capacitor::initializeFromNodesAndTerminals(Real frequency) { **mIntfCurrent = mSusceptance * **mIntfVoltage; // TODO: add updated logger - /* - mLog.info() << "\n--- Initialize from power flow ---" << std::endl - << "Impedance: " << impedance << std::endl - << "Voltage across: " << std::abs((**mIntfVoltage)(0, 0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl - << "Current: " << std::abs((**mIntfCurrent)(0, 0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl - << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl - << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl - << "--- Power flow initialization finished ---" << std::endl;*/ +#if 0 + mLog.info() << "\n--- Initialize from power flow ---" << std::endl + << "Impedance: " << impedance << std::endl + << "Voltage across: " << std::abs((**mIntfVoltage)(0, 0)) + << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl + << "Current: " << std::abs((**mIntfCurrent)(0, 0)) + << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl + << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) + << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl + << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) + << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl + << "--- Power flow initialization finished ---" << std::endl; +#endif } void SP::Ph3::Capacitor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); // TODO add updated logger - /*mLog.info() << "\n--- MNA Initialization ---" << std::endl - << "Initial voltage " << Math::abs((**mIntfVoltage)(0, 0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl - << "Initial current " << Math::abs((**mIntfCurrent)(0, 0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl - << "--- MNA initialization finished ---" << std::endl;*/ +#if 0 +mLog.info() << "\n--- MNA Initialization ---" << std::endl + << "Initial voltage " << Math::abs((**mIntfVoltage)(0, 0)) + << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl + << "Initial current " << Math::abs((**mIntfCurrent)(0, 0)) + << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl + << "--- MNA initialization finished ---" << std::endl; +#endif } void SP::Ph3::Capacitor::mnaCompApplySystemMatrixStamp( diff --git a/dpsim-models/src/SP/SP_Ph3_Inductor.cpp b/dpsim-models/src/SP/SP_Ph3_Inductor.cpp index e40f7007f3..ab002d3213 100644 --- a/dpsim-models/src/SP/SP_Ph3_Inductor.cpp +++ b/dpsim-models/src/SP/SP_Ph3_Inductor.cpp @@ -49,31 +49,31 @@ void SP::Ph3::Inductor::initializeFromNodesAndTerminals(Real frequency) { **mIntfCurrent = mSusceptance * **mIntfVoltage; SPDLOG_LOGGER_INFO(mSLog, "--- Initialize according to power flow ---"); - /* - mLog.info() << "--- Initialize according to power flow ---" << std::endl - << "in phase A: " << std::endl - << "Voltage across: " << std::abs((**mIntfVoltage)(0, 0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl - << "Current: " << std::abs((**mIntfCurrent)(0, 0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl - << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl - << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl - << "--- Power flow initialization finished ---" << std::endl; -*/ +#if 0 + mLog.info() << "--- Initialize according to power flow ---" << std::endl + << "in phase A: " << std::endl + << "Voltage across: " << std::abs((**mIntfVoltage)(0, 0)) + << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl + << "Current: " << std::abs((**mIntfCurrent)(0, 0)) + << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl + << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) + << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl + << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) + << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl + << "--- Power flow initialization finished ---" << std::endl; +#endif } void SP::Ph3::Inductor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); // TODO - /* - mLog.info() << "Initial voltage " << Math::abs((**mIntfVoltage)(0, 0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl - << "Initial current " << Math::abs((**mIntfCurrent)(0, 0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl; -*/ +#if 0 + mLog.info() << "Initial voltage " << Math::abs((**mIntfVoltage)(0, 0)) + << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl + << "Initial current " << Math::abs((**mIntfCurrent)(0, 0)) + << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl; +#endif } void SP::Ph3::Inductor::mnaCompApplySystemMatrixStamp( diff --git a/dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp b/dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp index a124fcb4a3..15f751c1d7 100644 --- a/dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp +++ b/dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp @@ -37,13 +37,14 @@ void SP::Ph3::VoltageSource::initializeFromNodesAndTerminals(Real frequency) { if (**mVoltageRef == Complex(0, 0)) **mVoltageRef = initialSingleVoltage(1) - initialSingleVoltage(0); - /* - mLog.info() << "--- Initialize according to power flow ---" << std::endl; - mLog.info() << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - << "<" << std::arg(initialSingleVoltage(0)) << std::endl; - mLog.info() << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - << "<" << std::arg(initialSingleVoltage(1)) << std::endl; - mLog.info() << "Voltage across: " << std::abs(mVoltageRef->get()) << "<" << std::arg(mVoltageRef->get()) << std::endl;*/ +#if 0 + mLog.info() << "--- Initialize according to power flow ---" << std::endl; + mLog.info() << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) + << "<" << std::arg(initialSingleVoltage(0)) << std::endl; + mLog.info() << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) + << "<" << std::arg(initialSingleVoltage(1)) << std::endl; + mLog.info() << "Voltage across: " << std::abs(mVoltageRef->get()) << "<" << std::arg(mVoltageRef->get()) << std::endl; +#endif } void SP::Ph3::VoltageSource::mnaCompInitialize( @@ -109,17 +110,17 @@ void SP::Ph3::VoltageSource::mnaCompApplySystemMatrixStamp( matrixNodeIndex(1, 2), Complex(1, 0)); } - /* - - mLog.info() << "--- System matrix stamp ---" << std::endl; - if (terminalNotGrounded(0)) { - mLog.info() << "Add " << Complex(-1, 0) << " to " << matrixNodeIndex(0) << "," << mVirtualNodes[0]->matrixNodeIndex() << std::endl; - mLog.info() << "Add " << Complex(-1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex() << "," << matrixNodeIndex(0) << std::endl; - } - if (terminalNotGrounded(1)) { - mLog.info() << "Add " << Complex(1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex() << "," << matrixNodeIndex(1) << std::endl; - mLog.info() << "Add " << Complex(1, 0) << " to " << matrixNodeIndex(1) << "," << mVirtualNodes[0]->matrixNodeIndex() << std::endl; - }*/ +#if 0 + mLog.info() << "--- System matrix stamp ---" << std::endl; + if (terminalNotGrounded(0)) { + mLog.info() << "Add " << Complex(-1, 0) << " to " << matrixNodeIndex(0) << "," << mVirtualNodes[0]->matrixNodeIndex() << std::endl; + mLog.info() << "Add " << Complex(-1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex() << "," << matrixNodeIndex(0) << std::endl; + } + if (terminalNotGrounded(1)) { + mLog.info() << "Add " << Complex(1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex() << "," << matrixNodeIndex(1) << std::endl; + mLog.info() << "Add " << Complex(1, 0) << " to " << matrixNodeIndex(1) << "," << mVirtualNodes[0]->matrixNodeIndex() << std::endl; + } +#endif } void SP::Ph3::VoltageSource::mnaCompApplyRightSideVectorStamp( @@ -194,28 +195,30 @@ void SP::Ph3::VoltageSource::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { - /* new state vector definintion: - state[0]=node0_voltage - state[1]=node1_voltage - .... - state[n]=noden_voltage - state[n+1]=component0_voltage - state[n+2]=component0_inductance (not yet implemented) - ... - state[m-1]=componentm_voltage - state[m]=componentm_inductance - */ - - //int Pos1 = matrixNodeIndex(0); - //int Pos2 = matrixNodeIndex(1); - //int c_offset = off[0] + off[1]; //current offset for component - //int n_offset_1 = c_offset + Pos1 + 1;// current offset for first nodal equation - //int n_offset_2 = c_offset + Pos2 + 1;// current offset for second nodal equation - //resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor - ////resid[++c_offset] = ; //TODO : add inductance equation - //resid[n_offset_1] += std::real(current()); - //resid[n_offset_2] += std::real(current()); - //off[1] += 1; + /* New state vector definintion: + * state[0]=node0_voltage + * state[1]=node1_voltage + * .... + * state[n]=noden_voltage + * state[n+1]=component0_voltage + * state[n+2]=component0_inductance (not yet implemented) + * ... + * state[m-1]=componentm_voltage + * state[m]=componentm_inductance + */ + +#if 0 + int Pos1 = matrixNodeIndex(0); + int Pos2 = matrixNodeIndex(1); + int c_offset = off[0] + off[1]; //current offset for component + int n_offset_1 = c_offset + Pos1 + 1;// current offset for first nodal equation + int n_offset_2 = c_offset + Pos2 + 1;// current offset for second nodal equation + resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor + //resid[++c_offset] = ; //TODO : add inductance equation + resid[n_offset_1] += std::real(current()); + resid[n_offset_2] += std::real(current()); + off[1] += 1; +#endif } Complex SP::Ph3::VoltageSource::daeInitialize() { diff --git a/dpsim-models/src/Signal/Exciter.cpp b/dpsim-models/src/Signal/Exciter.cpp index 904d2d446a..b44b8631fa 100644 --- a/dpsim-models/src/Signal/Exciter.cpp +++ b/dpsim-models/src/Signal/Exciter.cpp @@ -119,19 +119,18 @@ Real Signal::Exciter::step(Real mVd, Real mVq, Real dt) { return **mEf; } -/* +#if 0 // Saturation function according to Viviane thesis Real Signal::Exciter::saturation_fcn1(Real mVd, Real mVq, Real Vref, Real dt) { - if (mEf <= 2.3) - mVse = (0.1 / 2.3)*mEf; - else - mVse = (0.33 / 3.1)*mEf; - mVse = mVse*mEf; + if (mEf <= 2.3) + mVse = (0.1 / 2.3)*mEf; + else + mVse = (0.33 / 3.1)*mEf; + mVse = mVse*mEf; } // Saturation function according to PSAT Real Signal::Exciter::saturation_fcn2() { - return mA * (exp(mB * abs(mEf)) - 1); + return mA * (exp(mB * abs(mEf)) - 1); } - -*/ +#endif diff --git a/dpsim-villas/examples/cxx/FileExample.cpp b/dpsim-villas/examples/cxx/FileExample.cpp index af096c7021..ec9956917e 100644 --- a/dpsim-villas/examples/cxx/FileExample.cpp +++ b/dpsim-villas/examples/cxx/FileExample.cpp @@ -50,12 +50,12 @@ int main(int argc, char *argv[]) { sim.setFinalTime(10.0); std::string fileConfig = R"STRING({ - "type": "file", - "uri": "logs/output.csv", - "format": "csv", - "out": { - "flush": true - } + "type": "file", + "uri": "logs/output.csv", + "format": "csv", + "out": { + "flush": true + } })STRING"; auto intf = std::make_shared(fileConfig); diff --git a/dpsim-villas/examples/cxx/SharedMemExample.cpp b/dpsim-villas/examples/cxx/SharedMemExample.cpp index 1fe3c453ac..5fda8761a7 100644 --- a/dpsim-villas/examples/cxx/SharedMemExample.cpp +++ b/dpsim-villas/examples/cxx/SharedMemExample.cpp @@ -50,15 +50,15 @@ int main(int argc, char *argv[]) { sim.setFinalTime(2.0); std::string shmemConfig = R"STRING( - { - "type": "shmem", - "in": { - "name": "shmem-dpsim" - }, - "out": { - "name": "dpsim-shmem" - }, - "queuelen": 1024 + { + "type": "shmem", + "in": { + "name": "shmem-dpsim" + }, + "out": { + "name": "dpsim-shmem" + }, + "queuelen": 1024 })STRING"; auto intf = std::make_shared(shmemConfig); diff --git a/dpsim-villas/src/InterfaceWorkerVillas.cpp b/dpsim-villas/src/InterfaceWorkerVillas.cpp index 2a99ac6a74..faf35681c0 100644 --- a/dpsim-villas/src/InterfaceWorkerVillas.cpp +++ b/dpsim-villas/src/InterfaceWorkerVillas.cpp @@ -362,9 +362,9 @@ void InterfaceWorkerVillas::writeValuesToEnv( sample_decref(sample); } catch (const std::exception &) { /* We need to at least send something, so determine where exactly the - * timer expired and either resend the last successfully sent sample or - * just try to send this one again. - * TODO: can this be handled better? */ + * timer expired and either resend the last successfully sent sample or + * just try to send this one again. + * TODO: can this be handled better? */ if (!done) sample = mLastSample; diff --git a/dpsim/examples/cxx/Circuits/DP_VSI.cpp b/dpsim/examples/cxx/Circuits/DP_VSI.cpp index b147dde6b1..b204c0c815 100644 --- a/dpsim/examples/cxx/Circuits/DP_VSI.cpp +++ b/dpsim/examples/cxx/Circuits/DP_VSI.cpp @@ -110,12 +110,14 @@ void DP_Ph1_VSI2_4bus_SampleGrid() { } // Logging auto logger = DataLogger::make(simName); - // currents - /*logger->logAttribute("i_vs", vs->attribute("i_intf")); - logger->logAttribute("i_vsi", vsi->attribute("i_intf")); - logger->logAttribute("i_vsi2", vsi2->attribute("i_intf")); - logger->logAttribute("iload", rload->attribute("i_intf")); - logger->logAttribute("iqload", Lload->attribute("i_intf"));*/ +#if 0 + // Currents + logger->logAttribute("i_vs", vs->attribute("i_intf")); + logger->logAttribute("i_vsi", vsi->attribute("i_intf")); + logger->logAttribute("i_vsi2", vsi2->attribute("i_intf")); + logger->logAttribute("iload", rload->attribute("i_intf")); + logger->logAttribute("iqload", Lload->attribute("i_intf")); +#endif // nodal voltages logger->logAttribute("vBus1", n1->attribute("v")); logger->logAttribute("v_slack", n5->attribute("v")); diff --git a/dpsim/examples/cxx/Components/DP_SynGenDq7odODEint_ThreePhFault.cpp b/dpsim/examples/cxx/Components/DP_SynGenDq7odODEint_ThreePhFault.cpp index a09031cd5d..8fbf3457ed 100644 --- a/dpsim/examples/cxx/Components/DP_SynGenDq7odODEint_ThreePhFault.cpp +++ b/dpsim/examples/cxx/Components/DP_SynGenDq7odODEint_ThreePhFault.cpp @@ -13,13 +13,13 @@ using namespace DPsim; using namespace CPS::DP; using namespace CPS::DP::Ph3; -/*###### For execution at least one command line argument is required: ########### - First argument: binary flag (0 or 1), - 0: The Generator Equations are solved without using the ODE-Simulation Class - 1: The Generator Equations are solved using the ODE-Simulation Class - - This is a general Test of the ODEintSolver Class. TODO: Add ODEint Solver option to Sim_ODE interface - */ +/* For execution at least one command line argument is required: + * First argument: binary flag (0 or 1), + * 0: The Generator Equations are solved without using the ODE-Simulation Class + * 1: The Generator Equations are solved using the ODE-Simulation Class + * + * This is a general Test of the ODEintSolver Class. TODO: Add ODEint Solver option to Sim_ODE interface + */ int main(int argc, char *argv[]) { // Define simulation parameters diff --git a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_BalancedResLoad.cpp b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_BalancedResLoad.cpp index 77693461db..cc599b977a 100644 --- a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_BalancedResLoad.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_BalancedResLoad.cpp @@ -77,9 +77,9 @@ int main(int argc, char *argv[]) { // Calculate initial values for circuit at generator connection point #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif sim.run(); diff --git a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_ExciterAndTurbine.cpp b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_ExciterAndTurbine.cpp index 717e9ca320..2d83691f8c 100644 --- a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_ExciterAndTurbine.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_ExciterAndTurbine.cpp @@ -128,9 +128,9 @@ int main(int argc, char *argv[]) { // Calculate initial values for circuit at generator connection point #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif sim.setSwitchTime(1, 1); diff --git a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_SimpThreePhaseFault.cpp b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_SimpThreePhaseFault.cpp index f841ff9945..7c3451c503 100644 --- a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_SimpThreePhaseFault.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_SimpThreePhaseFault.cpp @@ -21,13 +21,13 @@ int main(int argc, char *argv[]) { Real H = 3.7; #if 0 - Real Ka = 20; - Real Ta = 0.2; - Real Ke = 1; - Real Te = 0.314; - Real Kf = 0.063; - Real Tf = 0.35; - Real Tr = 0.02; + Real Ka = 20; + Real Ta = 0.2; + Real Ke = 1; + Real Te = 0.314; + Real Kf = 0.063; + Real Tf = 0.35; + Real Tr = 0.02; #endif Real Rs = 0.003; @@ -107,9 +107,9 @@ int main(int argc, char *argv[]) { // Calculate initial values for circuit at generator connection point #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif sim.setSwitchTime(0.1, 1); diff --git a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_Simplified_ThreePhaseFault.cpp b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_Simplified_ThreePhaseFault.cpp index ec789fcb1c..b8912301b0 100644 --- a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_Simplified_ThreePhaseFault.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_Simplified_ThreePhaseFault.cpp @@ -99,9 +99,9 @@ int main(int argc, char *argv[]) { // Calculate initial values for circuit at generator connection point #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif sim.setSwitchTime(0.1, 1); diff --git a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_ThreePhaseFault.cpp b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_ThreePhaseFault.cpp index 5413348b1c..f4cd6fe687 100644 --- a/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_ThreePhaseFault.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/DP_SynchronGenerator_ThreePhaseFault.cpp @@ -95,9 +95,9 @@ int main(int argc, char *argv[]) { // Calculate initial values for circuit at generator connection point #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif sim.setSwitchTime(0.1, 1); diff --git a/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_ExciterAndTurbine.cpp b/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_ExciterAndTurbine.cpp index 27486d691b..d5e7b21195 100644 --- a/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_ExciterAndTurbine.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_ExciterAndTurbine.cpp @@ -126,9 +126,9 @@ int main(int argc, char *argv[]) { #endif // Calculate initial values for circuit at generator connection point #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif sim.setSwitchTime(1, 1); diff --git a/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_PhaseToPhaseFault.cpp b/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_PhaseToPhaseFault.cpp index 26b294f1ec..f1135ab8da 100644 --- a/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_PhaseToPhaseFault.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_PhaseToPhaseFault.cpp @@ -85,9 +85,9 @@ int main(int argc, char *argv[]) { // Calculate initial values for circuit at generator connection point #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif sim.setSwitchTime(0.1, 1); diff --git a/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_Simplified_ThreePhaseFault.cpp b/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_Simplified_ThreePhaseFault.cpp index 87e94180ab..0e981ad3d4 100644 --- a/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_Simplified_ThreePhaseFault.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_Simplified_ThreePhaseFault.cpp @@ -12,94 +12,92 @@ using namespace DPsim; using namespace CPS::EMT::Ph3; int main(int argc, char *argv[]) { - /* simplified VBR model does not exist at the moment - - // Define machine parameters in per unit - Real nomPower = 555e6; - Real nomPhPhVoltRMS = 24e3; - Real nomFreq = 60; - Real nomFieldCurr = 1300; - Int poleNum = 2; - Real H = 3.7; - - Real Rs = 0.003; - Real Ll = 0.15; - Real Lmd = 1.6599; - Real Lmd0 = 1.6599; - Real Lmq = 1.61; - Real Lmq0 = 1.61; - Real Rfd = 0.0006; - Real Llfd = 0.1648; - Real Rkd = 0.0284; - Real Llkd = 0.1713; - Real Rkq1 = 0.0062; - Real Llkq1 = 0.7252; - Real Rkq2 = 0.0237; - Real Llkq2 = 0.125; - //Real Rkq2 = 0; - //Real Llkq2 = 0; - - Real Ld_s = 0.23; - Real Lq_s = 0.25; - - // Set up simulation - Real om = 2.0*M_PI*60.0; - Real tf = 3; - Real dt = 0.00001; - Int downSampling = 1; - - Real Ra = (Ld_s + Lq_s) / dt; - - // Declare circuit components - Component::Ptr gen = SynchronGeneratorVBRSmpl::make("EMT_VBRSimplified_", 0, 1, 2, - nomPower, nomPhPhVoltRMS, nomFreq, poleNum, nomFieldCurr, - Rs, Ll, Lmd, Lmd0, Lmq, Lmq0, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2, Llkq2, H, Logger::Level::info); - Real loadRes = 24e3*24e3/300e6; - Component::Ptr r1 = Resistor::make("r1", 0, DEPRECATEDGND, loadRes); - Component::Ptr r2 = Resistor::make("r2", 1, DEPRECATEDGND, loadRes); - Component::Ptr r3 = Resistor::make("r3", 2, DEPRECATEDGND, loadRes); - - SystemTopology system(60); - system.mComponents = { gen, r1, r2, r3 }; - - // Declare circuit components for resistance change - //Real breakerRes = 0.001; - Real breakerRes = 19.2 + 0.001; - Component::Ptr rBreaker1 = Resistor::make("rbreak1", 0, DEPRECATEDGND, breakerRes); - Component::Ptr rBreaker2 = Resistor::make("rbreak2", 1, DEPRECATEDGND, breakerRes); - Component::Ptr rBreaker3 = Resistor::make("rbreak3", 2, DEPRECATEDGND, breakerRes); - - - SystemTopology systemBreakerOn(60); - systemBreakerOn.mComponents = { gen, rBreaker1, rBreaker2, rBreaker3, r1, r2, r3 }; - - String mSimulationName = "EMT_SynchronGenerator_VBRSimplified_" + std::to_string(dt); - Simulation sim(mSimulationName, system, dt, tf, Domain::EMT); - sim.setLogDownsamplingRate(downSampling); - sim.addSystemTopology(systemBreakerOn); - - // Initialize generator - Real initActivePower = 300e6; - Real initReactivePower = 0; - Real initTerminalVolt = 24000 / sqrt(3) * sqrt(2); - Real initVoltAngle = -DPS_PI / 2; - Real mechPower = 300e6; - auto genPtr = std::dynamic_pointer_cast(gen); - genPtr->initialize(om, dt, initActivePower, initReactivePower, initTerminalVolt, initVoltAngle, mechPower); - - // Calculate initial values for circuit at generator connection point +// Simplified VBR model does not exist at the moment #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + // Define machine parameters in per unit + Real nomPower = 555e6; + Real nomPhPhVoltRMS = 24e3; + Real nomFreq = 60; + Real nomFieldCurr = 1300; + Int poleNum = 2; + Real H = 3.7; + + Real Rs = 0.003; + Real Ll = 0.15; + Real Lmd = 1.6599; + Real Lmd0 = 1.6599; + Real Lmq = 1.61; + Real Lmq0 = 1.61; + Real Rfd = 0.0006; + Real Llfd = 0.1648; + Real Rkd = 0.0284; + Real Llkd = 0.1713; + Real Rkq1 = 0.0062; + Real Llkq1 = 0.7252; + Real Rkq2 = 0.0237; + Real Llkq2 = 0.125; + //Real Rkq2 = 0; + //Real Llkq2 = 0; + + Real Ld_s = 0.23; + Real Lq_s = 0.25; + + // Set up simulation + Real om = 2.0*M_PI*60.0; + Real tf = 3; + Real dt = 0.00001; + Int downSampling = 1; + + Real Ra = (Ld_s + Lq_s) / dt; + + // Declare circuit components + Component::Ptr gen = SynchronGeneratorVBRSmpl::make("EMT_VBRSimplified_", 0, 1, 2, + nomPower, nomPhPhVoltRMS, nomFreq, poleNum, nomFieldCurr, + Rs, Ll, Lmd, Lmd0, Lmq, Lmq0, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2, Llkq2, H, Logger::Level::info); + Real loadRes = 24e3*24e3/300e6; + Component::Ptr r1 = Resistor::make("r1", 0, DEPRECATEDGND, loadRes); + Component::Ptr r2 = Resistor::make("r2", 1, DEPRECATEDGND, loadRes); + Component::Ptr r3 = Resistor::make("r3", 2, DEPRECATEDGND, loadRes); + + SystemTopology system(60); + system.mComponents = { gen, r1, r2, r3 }; + + // Declare circuit components for resistance change + Real breakerRes = 19.2 + 0.001; + Component::Ptr rBreaker1 = Resistor::make("rbreak1", 0, DEPRECATEDGND, breakerRes); + Component::Ptr rBreaker2 = Resistor::make("rbreak2", 1, DEPRECATEDGND, breakerRes); + Component::Ptr rBreaker3 = Resistor::make("rbreak3", 2, DEPRECATEDGND, breakerRes); + + + SystemTopology systemBreakerOn(60); + systemBreakerOn.mComponents = { gen, rBreaker1, rBreaker2, rBreaker3, r1, r2, r3 }; + + String mSimulationName = "EMT_SynchronGenerator_VBRSimplified_" + std::to_string(dt); + Simulation sim(mSimulationName, system, dt, tf, Domain::EMT); + sim.setLogDownsamplingRate(downSampling); + sim.addSystemTopology(systemBreakerOn); + + // Initialize generator + Real initActivePower = 300e6; + Real initReactivePower = 0; + Real initTerminalVolt = 24000 / sqrt(3) * sqrt(2); + Real initVoltAngle = -DPS_PI / 2; + Real mechPower = 300e6; + auto genPtr = std::dynamic_pointer_cast(gen); + genPtr->initialize(om, dt, initActivePower, initReactivePower, initTerminalVolt, initVoltAngle, mechPower); + + // Calculate initial values for circuit at generator connection point +#if 0 + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif - sim.setSwitchTime(0.1, 1); - sim.setSwitchTime(0.2, 0); - - sim.run(); + sim.setSwitchTime(0.1, 1); + sim.setSwitchTime(0.2, 0); - */ + sim.run(); +#endif return 0; } diff --git a/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_ThreePhaseFault.cpp b/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_ThreePhaseFault.cpp index 99c5911c17..599f18c551 100644 --- a/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_ThreePhaseFault.cpp +++ b/dpsim/examples/cxx/Components/Deprecated/EMT_SynchronGenerator_ThreePhaseFault.cpp @@ -12,7 +12,7 @@ using namespace DPsim; using namespace CPS::EMT::Ph3; int main(int argc, char *argv[]) { - // Define machine parameters in per unit + // Define machine parameters in per unit. Real nomPower = 555e6; Real nomPhPhVoltRMS = 24e3; Real nomFreq = 60; @@ -34,13 +34,14 @@ int main(int argc, char *argv[]) { Real Llkq1 = 0.7252; Real Rkq2 = 0.0237; Real Llkq2 = 0.125; - //Real Rkq2 = 0; - //Real Llkq2 = 0; - +#if 0 + Real Rkq2 = 0; + Real Llkq2 = 0; +#endif Real Ld_s = 0.23; Real Lq_s = 0.25; - // Set up simulation + // Set up simulation. Real tf, dt; Real om = 2.0 * M_PI * 60.0; tf = 0.3; @@ -49,7 +50,7 @@ int main(int argc, char *argv[]) { Real Ra = (Ld_s + Lq_s) / dt; - // Declare circuit components + // Declare circuit components. Component::Ptr gen = SynchronGeneratorDQ::make( "gen", 0, 1, 2, nomPower, nomPhPhVoltRMS, nomFreq, poleNum, nomFieldCurr, Rs, Ll, Lmd, Lmd0, Lmq, Lmq0, Rfd, Llfd, Rkd, Llkd, Rkq1, Llkq1, Rkq2, @@ -62,7 +63,7 @@ int main(int argc, char *argv[]) { SystemTopology system(60); system.mComponents = {gen, r1, r2, r3}; - // Declare circuit components for resistance change + // Declare circuit components for resistance change. Real breakerRes = 0.001; Component::Ptr rBreaker1 = Resistor::make("rbreak1", 0, DEPRECATEDGND, breakerRes); @@ -84,7 +85,7 @@ int main(int argc, char *argv[]) { sim.setLogDownsamplingRate(downSampling); sim.addSystemTopology(systemBreakerOn); - // Initialize generator + // Initialize generator. Real initActivePower = 300e6; Real initReactivePower = 0; Real initTerminalVolt = 24000 / sqrt(3) * sqrt(2); @@ -94,11 +95,11 @@ int main(int argc, char *argv[]) { genPtr->initialize(om, dt, initActivePower, initReactivePower, initTerminalVolt, initVoltAngle, mechPower); - // Calculate initial values for circuit at generator connection point + // Calculate initial values for circuit at generator connection point. #if 0 - Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); - Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); - Real initPowerFactor = acos(initActivePower / initApparentPower); + Real initApparentPower = sqrt(pow(initActivePower, 2) + pow(initReactivePower, 2)); + Real initTerminalCurr = initApparentPower / (3 * initTerminalVolt)* sqrt(2); + Real initPowerFactor = acos(initActivePower / initApparentPower); #endif sim.setSwitchTime(0.1, 1); diff --git a/dpsim/examples/cxx/cim_graphviz/cimviz.cpp b/dpsim/examples/cxx/cim_graphviz/cimviz.cpp index e1b1487d94..1861b430e7 100644 --- a/dpsim/examples/cxx/cim_graphviz/cimviz.cpp +++ b/dpsim/examples/cxx/cim_graphviz/cimviz.cpp @@ -21,12 +21,12 @@ static graph_t *G; #ifndef _WIN32 static void intr(int s) { - /* if interrupted we try to produce a partial rendering before exiting */ + // If interrupted we try to produce a partial rendering before exiting. if (G) gvRenderJobs(gvc, G); /* Note that we don't call gvFinalize() so that we don't start event-driven - * devices like -Tgtk or -Txlib */ + * devices like -Tgtk or -Txlib */ exit(gvFreeContext(gvc)); } #endif @@ -37,14 +37,14 @@ struct GVC_s { char *config_path; bool config_found; - /* gvParseArgs */ + // gvParseArgs char **input_filenames; }; int main(int argc, char *argv[]) { int ret, i; - argv[0] = (char *)"neato"; /* Default layout engine */ + argv[0] = (char *)"neato"; // Default layout engine. gvc = gvContext(); gvParseArgs(gvc, argc, argv); @@ -64,13 +64,13 @@ int main(int argc, char *argv[]) { if (i == 0) return 0; - /* The remaining code is identical to GraphVizs dot.c code */ + // The remaining code is identical to GraphVizs dot.c code. SystemTopology sys = reader.loadCIM(50, filenames); Graph::Graph graph = sys.topologyGraph(); G = graph.mGraph; - ret = gvLayoutJobs(gvc, G); /* take layout engine from command line */ + ret = gvLayoutJobs(gvc, G); // Take layout engine from command line. if (ret) goto out; diff --git a/dpsim/include/dpsim/Compat/getopt.h b/dpsim/include/dpsim/Compat/getopt.h index fe5a4b9415..68c9f0e7d8 100644 --- a/dpsim/include/dpsim/Compat/getopt.h +++ b/dpsim/include/dpsim/Compat/getopt.h @@ -1,3 +1,4 @@ +// editorconfig-checker-disable-file #ifndef __GETOPT_H__ /** * DISCLAIMER @@ -85,12 +86,14 @@ int optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #endif -//extern int optind; /* index of first non-option in argv */ -//extern int optopt; /* single option character, as parsed */ -//extern int opterr; /* flag to enable built-in diagnostics... */ -// /* (user may set to zero, to suppress) */ -// -//extern char *optarg; /* pointer to argument of current option */ +#if 0 +extern int optind; /* index of first non-option in argv */ +extern int optopt; /* single option character, as parsed */ +extern int opterr; /* flag to enable built-in diagnostics... */ + /* (user may set to zero, to suppress) */ + +extern char *optarg; /* pointer to argument of current option */ +#endif #define PRINT_ERROR ((opterr) && (*options != ':')) diff --git a/dpsim/include/dpsim/InterfaceWorker.h b/dpsim/include/dpsim/InterfaceWorker.h index 75e18d7462..e46267a968 100644 --- a/dpsim/include/dpsim/InterfaceWorker.h +++ b/dpsim/include/dpsim/InterfaceWorker.h @@ -30,32 +30,32 @@ class InterfaceWorker { virtual ~InterfaceWorker() = default; /** - * Function that will be called on loop in its separate thread. - * Should be used to read values from the environment and push them into `updatedAttrs` - * `updatedAttrs` will always be empty when this function is invoked - */ + * Function that will be called on loop in its separate thread. + * Should be used to read values from the environment and push them into `updatedAttrs` + * `updatedAttrs` will always be empty when this function is invoked + */ virtual void readValuesFromEnv( std::vector &updatedAttrs) = 0; /** - * Function that will be called on loop in its separate thread. - * Should be used to read values from `updatedAttrs` and write them to the environment - * The `updatedAttrs` list will not be cleared by the caller in between function calls - * When this function is called, `updatedAttrs` will include at least one value - */ + * Function that will be called on loop in its separate thread. + * Should be used to read values from `updatedAttrs` and write them to the environment + * The `updatedAttrs` list will not be cleared by the caller in between function calls + * When this function is called, `updatedAttrs` will include at least one value. + */ virtual void writeValuesToEnv( std::vector &updatedAttrs) = 0; /** - * Open the interface and set up the connection to the environment - * This is guaranteed to be called before any calls to `readValuesFromEnv` and `writeValuesToEnv` - */ + * Open the interface and set up the connection to the environment + * This is guaranteed to be called before any calls to `readValuesFromEnv` and `writeValuesToEnv` + */ virtual void open() = 0; /** - * Close the interface and all connections to the environment - * After this has been called, no further calls to `readValuesFromEnv` or `writeValuesToEnv` will occur - */ + * Close the interface and all connections to the environment + * After this has been called, no further calls to `readValuesFromEnv` or `writeValuesToEnv` will occur + */ virtual void close() = 0; }; } // namespace DPsim diff --git a/dpsim/include/dpsim/MNASolverFactory.h b/dpsim/include/dpsim/MNASolverFactory.h index 94835e1604..6cfc3c7d43 100644 --- a/dpsim/include/dpsim/MNASolverFactory.h +++ b/dpsim/include/dpsim/MNASolverFactory.h @@ -77,8 +77,9 @@ class MnaSolverFactory { switch (implementation) { /* TODO: have only one "solver" object of type MnaSolverDirect and only use setDirectLinearSolverImplementation in the switch-case. - * This is not done now, since MnaSolverDirect and MnaSolver are distinct classes - and someone might add another subclass of MnaSolver - * to the project (MnaSolverIterative?). It is planned to merge MnaSolverDirect and MnaSolver anyway, so this won't happen. */ + * This is not done now, since MnaSolverDirect and MnaSolver are distinct classes - and someone might add another subclass of MnaSolver + * to the project (MnaSolverIterative?). It is planned to merge MnaSolverDirect and MnaSolver anyway, so this won't happen. + */ case DirectLinearSolverImpl::SparseLU: { log->info("creating SparseLUAdapter solver implementation"); std::shared_ptr> sparseSolver = diff --git a/dpsim/include/dpsim/ODESolver.h b/dpsim/include/dpsim/ODESolver.h index 3d8baf2c58..f9e1c6c64c 100644 --- a/dpsim/include/dpsim/ODESolver.h +++ b/dpsim/include/dpsim/ODESolver.h @@ -55,18 +55,20 @@ class ODESolver : public Solver { // TODO: Variables for implicit solve? /// Template Jacobian Matrix (implicit solver) - /* SUNMatrix A = NULL; - /// Linear solver object (implicit solver) - SUNLinearSolver LS = NULL; */ +#if 0 + SUNMatrix A = NULL; + /// Linear solver object (implicit solver) + SUNLinearSolver LS = NULL; +#endif - /// reusable error-checking flag + /// Reusable error-checking flag int mFlag{0}; // Similar to DAE-Solver CPS::ODEInterface::StSpFn mStSpFunction; CPS::ODEInterface::JacFn mJacFunction; - /// use wrappers similar to DAE_Solver + /// Use wrappers similar to DAE_Solver static int StateSpaceWrapper(realtype t, N_Vector y, N_Vector ydot, void *user_data); int StateSpace(realtype t, N_Vector y, N_Vector ydot); diff --git a/dpsim/include/dpsim/RealTimeSimulation.h b/dpsim/include/dpsim/RealTimeSimulation.h index 5829f0497d..20ab812d2e 100644 --- a/dpsim/include/dpsim/RealTimeSimulation.h +++ b/dpsim/include/dpsim/RealTimeSimulation.h @@ -30,9 +30,9 @@ class RealTimeSimulation : public Simulation { CPS::Logger::Level logLevel = CPS::Logger::Level::info); /** Perform the main simulation loop in real time. - * - * @param startSynch If true, the simulation waits for the first external value before starting the timing. - */ + * + * @param startSynch If true, the simulation waits for the first external value before starting the timing. + */ void run(const Timer::StartClock::duration &startIn = std::chrono::seconds(1)); diff --git a/dpsim/src/KLUAdapter.cpp b/dpsim/src/KLUAdapter.cpp index ed79b4327c..ec3811f4be 100644 --- a/dpsim/src/KLUAdapter.cpp +++ b/dpsim/src/KLUAdapter.cpp @@ -61,13 +61,14 @@ void KLUAdapter::preprocessing( mVaryingColumns.push_back(changedEntry.second); } - // this call also works if mVaryingColumns, mVaryingRows are empty + // This call also works if mVaryingColumns, mVaryingRows are empty mSymbolic = klu_analyze_partial(n, Ap, Ai, &mVaryingColumns[0], &mVaryingRows[0], varying_entries, mPreordering, &mCommon); - /* store non-zero value of current preprocessed matrix. only used until - * to-do in refactorize-function is resolved. Can be removed then. */ + /* Store non-zero value of current preprocessed matrix. only used until + * to-do in refactorize-function is resolved. Can be removed then. + */ nnz = Eigen::internal::convert_index(systemMatrix.nonZeros()); } @@ -85,8 +86,9 @@ void KLUAdapter::factorize(SparseMatrix &systemMatrix) { Int varying_entries = Eigen::internal::convert_index(mChangedEntries.size()); - /* make sure that factorization path is not computed if there are no varying entries. - * Doing so should not be a problem, but it is safer to do it this way */ + /* Make sure that factorization path is not computed if there are no varying entries. + * Doing so should not be a problem, but it is safer to do it this way. + */ if (!(mVaryingColumns.empty()) && !(mVaryingRows.empty())) { if (mPartialRefactorizationMethod == DPsim::PARTIAL_REFACTORIZATION_METHOD::FACTORIZATION_PATH) { @@ -102,7 +104,7 @@ void KLUAdapter::factorize(SparseMatrix &systemMatrix) { } void KLUAdapter::refactorize(SparseMatrix &systemMatrix) { - /* TODO: remove if-else when zero<->non-zero issue during matrix stamping has been fixed. Also remove in partialRefactorize then. */ + // TODO: Remove if-else when zero<->non-zero issue during matrix stamping has been fixed. Also remove in partialRefactorize then. if (systemMatrix.nonZeros() != nnz) { preprocessing(systemMatrix, mChangedEntries); factorize(systemMatrix); @@ -153,16 +155,18 @@ Matrix KLUAdapter::solve(Matrix &rightSideVector) { // We should preallocate this buffer. Matrix x = rightSideVector; - /* number of right hands sides - * usually one, KLU can handle multiple right hand sides */ + /* Number of right hands sides + * usually one, KLU can handle multiple right hand sides. + */ Int rhsCols = Eigen::internal::convert_index(rightSideVector.cols()); - /* leading dimension, also called "n" */ + // Leading dimension, also called "n". Int rhsRows = Eigen::internal::convert_index(rightSideVector.rows()); /* tsolve refers to transpose solve. Input matrix is stored in compressed row format, - * KLU operates on compressed column format. This way, the transpose of the matrix is factored. - * This has to be taken into account only here during right-hand solving. */ + * KLU operates on compressed column format. This way, the transpose of the matrix is factored. + * This has to be taken into account only here during right-hand solving. + */ klu_tsolve(mSymbolic, mNumeric, rhsRows, rhsCols, x.const_cast_derived().data(), &mCommon); @@ -180,8 +184,9 @@ void KLUAdapter::printMatrixMarket(SparseMatrix &matrix, int counter) const { std::ofstream ofs; ofs.open(outputName); - /* TODO: add logger to DirectLinearSolver to use libfmt's more powerful logging tools. - * Then also move matrix printing (of LU matrices) here in order to avoid C-level printing. */ + /* TODO: Add logger to DirectLinearSolver to use libfmt's more powerful logging tools. + * Then also move matrix printing (of LU matrices) here in order to avoid C-level printing. + */ ofs.precision(14); ofs << "%%MatrixMarket matrix coordinate real general" << std::endl; ofs << n << " " << n << " " << nz << std::endl; @@ -211,7 +216,7 @@ void KLUAdapter::applyConfiguration() { SPDLOG_LOGGER_INFO(mSLog, "Matrix is scaled using " + mConfiguration.getScalingMethodString()); - // TODO: implement support for COLAMD (modifiy SuiteSparse) + // TODO: Implement support for COLAMD (modifiy SuiteSparse) switch (mConfiguration.getFillInReductionMethod()) { case FILL_IN_REDUCTION_METHOD::AMD: mPreordering = AMD_ORDERING; diff --git a/dpsim/src/ODESolver.cpp b/dpsim/src/ODESolver.cpp index 53a1ba2eb0..6d8c796aa1 100644 --- a/dpsim/src/ODESolver.cpp +++ b/dpsim/src/ODESolver.cpp @@ -39,52 +39,54 @@ void ODESolver::initialize() { }; // Causes numerical issues, better allocate in every step-> see step - /*mArkode_mem= ARKodeCreate(); - if (check_flag(mArkode_mem, "ARKodeCreate", 0)) - mFlag=1; +#if 0 + mArkode_mem= ARKodeCreate(); + if (check_flag(mArkode_mem, "ARKodeCreate", 0)) + mFlag=1; - mFlag = ARKodeSetUserData(mArkode_mem, this); - if (check_flag(&mFlag, "ARKodeSetUserData", 1)) - mFlag=1;*/ + mFlag = ARKodeSetUserData(mArkode_mem, this); + if (check_flag(&mFlag, "ARKodeSetUserData", 1)) + mFlag=1; /* Call ARKodeInit to initialize the integrator memory and specify the - right-hand side function in y'=f(t,y), the inital time T0, and - the initial dependent variable vector y(fluxes+mech. vars).*/ - /* if(mImplicitIntegration){ - mFlag = ARKodeInit(mArkode_mem, NULL, &ODESolver::StateSpaceWrapper, initial_time, mStates); - if (check_flag(&mFlag, "ARKodeInit", 1)) throw CPS::Exception(); - - // Initialize dense matrix data structure - A = SUNDenseMatrix(mProbDim, mProbDim); - if (check_flag((void *)A, "SUNDenseMatrix", 0)) throw CPS::Exception(); - - // Initialize linear solver - LS = SUNDenseLinearSolver(mStates, A); - if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) throw CPS::Exception(); - - // Attach matrix and linear solver - mFlag = ARKDlsSetLinearSolver(mArkode_mem, LS, A); - if (check_flag(&mFlag, "ARKDlsSetLinearSolver", 1)) throw CPS::Exception(); - - // Set Jacobian routine - mFlag = ARKDlsSetJacFn(mArkode_mem, &ODESolver::JacobianWrapper); - if (check_flag(&mFlag, "ARKDlsSetJacFn", 1)) throw CPS::Exception(); + * right-hand side function in y'=f(t,y), the inital time T0, and + * the initial dependent variable vector y(fluxes+mech. vars).*/ + if(mImplicitIntegration){ + mFlag = ARKodeInit(mArkode_mem, NULL, &ODESolver::StateSpaceWrapper, initial_time, mStates); + if (check_flag(&mFlag, "ARKodeInit", 1)) throw CPS::Exception(); + + // Initialize dense matrix data structure + A = SUNDenseMatrix(mProbDim, mProbDim); + if (check_flag((void *)A, "SUNDenseMatrix", 0)) throw CPS::Exception(); + + // Initialize linear solver + LS = SUNDenseLinearSolver(mStates, A); + if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) throw CPS::Exception(); + + // Attach matrix and linear solver + mFlag = ARKDlsSetLinearSolver(mArkode_mem, LS, A); + if (check_flag(&mFlag, "ARKDlsSetLinearSolver", 1)) throw CPS::Exception(); + + // Set Jacobian routine + mFlag = ARKDlsSetJacFn(mArkode_mem, &ODESolver::JacobianWrapper); + if (check_flag(&mFlag, "ARKDlsSetJacFn", 1)) throw CPS::Exception(); } else { - mFlag = ARKodeInit(mArkode_mem, &ODESolver::StateSpaceWrapper, NULL, initial_time, mStates); - if (check_flag(&mFlag, "ARKodeInit", 1)) throw CPS::Exception(); - }*/ + mFlag = ARKodeInit(mArkode_mem, &ODESolver::StateSpaceWrapper, NULL, initial_time, mStates); + if (check_flag(&mFlag, "ARKodeInit", 1)) throw CPS::Exception(); + } // Shifted to every step because of numerical issues // Specify Runge-Kutta Method/order - /*mFlag = ARKodeSetOrder(mArkode_mem, 4); - if (check_flag(&mFlag, "ARKodeOrderSet", 1)) - mFlag=1;*/ + mFlag = ARKodeSetOrder(mArkode_mem, 4); + if (check_flag(&mFlag, "ARKodeOrderSet", 1)) + mFlag=1; - /*mFlag = ARKodeSStolerances(mArkode_mem, reltol, abstol); - if (check_flag(&mFlag, "ARKodeSStolerances", 1)) - mFlag=1;*/ + mFlag = ARKodeSStolerances(mArkode_mem, reltol, abstol); + if (check_flag(&mFlag, "ARKodeSStolerances", 1)) + mFlag=1; +#endif } int ODESolver::StateSpaceWrapper(realtype t, N_Vector y, N_Vector ydot, @@ -134,8 +136,9 @@ Real ODESolver::step(Real initial_time) { mFlag = 1; /* Call ARKodeInit to initialize the integrator memory and specify the - right-hand side function in y'=f(t,y), the inital time T0, and - the initial dependent variable vector y(fluxes+mech. vars).*/ + * right-hand side function in y'=f(t,y), the inital time T0, and + * the initial dependent variable vector y(fluxes+mech. vars). + */ if (mImplicitIntegration) { mFlag = ARKodeInit(mArkode_mem, NULL, &ODESolver::StateSpaceWrapper, initial_time, mStates); diff --git a/dpsim/src/Simulation.cpp b/dpsim/src/Simulation.cpp index ce6834bed4..1a76c3b06c 100644 --- a/dpsim/src/Simulation.cpp +++ b/dpsim/src/Simulation.cpp @@ -223,35 +223,37 @@ Graph::Graph Simulation::dependencyGraph() { std::map avgTimes; std::map fillColors; +#if 0 /* The main SolveTasks of each Solver usually takes the - * largest amount of computing time. We exclude it from - * coloring for improving the spread of the color range - * for the remaining tasks. - */ - // auto isSolveTask = [](Task::Ptr task) -> Bool { - // const std::vector ignoreTasks = { - // #ifdef WITH_SUNDIALS - // std::type_index(typeid(ODESolver::SolveTask)), - // #endif - // std::type_index(typeid(MnaSolver::SolveTask)), - // std::type_index(typeid(MnaSolver::SolveTask)), - // std::type_index(typeid(DiakopticsSolver::SubnetSolveTask)), - // std::type_index(typeid(DiakopticsSolver::SubnetSolveTask)), - // std::type_index(typeid(DiakopticsSolver::SolveTask)), - // std::type_index(typeid(DiakopticsSolver::SolveTask)), - // std::type_index(typeid(NRpolarSolver::SolveTask)) - // }; - - // return std::find(ignoreTasks.begin(), ignoreTasks.end(), std::type_index(typeid(*task.get()))) != ignoreTasks.end(); - // }; - - // auto isIgnoredTask = [&isSolveTask](Task::Ptr task) -> Bool { - // return typeid(*task.get()) == typeid(Interface::PreStep) || sSolveTask(task); - // }; - - // auto isRootTask = [](Task::Ptr task) -> Bool { - // return typeid(*task.get()) == typeid(Scheduler::Root); - // }; + * largest amount of computing time. We exclude it from + * coloring for improving the spread of the color range + * for the remaining tasks. + */ + auto isSolveTask = [](Task::Ptr task) -> Bool { + const std::vector ignoreTasks = { +#ifdef WITH_SUNDIALS + std::type_index(typeid(ODESolver::SolveTask)), +#endif + std::type_index(typeid(MnaSolver::SolveTask)), + std::type_index(typeid(MnaSolver::SolveTask)), + std::type_index(typeid(DiakopticsSolver::SubnetSolveTask)), + std::type_index(typeid(DiakopticsSolver::SubnetSolveTask)), + std::type_index(typeid(DiakopticsSolver::SolveTask)), + std::type_index(typeid(DiakopticsSolver::SolveTask)), + std::type_index(typeid(NRpolarSolver::SolveTask)) + }; + + return std::find(ignoreTasks.begin(), ignoreTasks.end(), std::type_index(typeid(*task.get()))) != ignoreTasks.end(); + }; + + auto isIgnoredTask = [&isSolveTask](Task::Ptr task) -> Bool { + return typeid(*task.get()) == typeid(Interface::PreStep) || sSolveTask(task); + }; + + auto isRootTask = [](Task::Ptr task) -> Bool { + return typeid(*task.get()) == typeid(Scheduler::Root); + }; +#endif auto isScheduled = [this](Task::Ptr task) -> Bool { return !mTaskOutEdges[task].empty(); diff --git a/dpsim/src/Timer.cpp b/dpsim/src/Timer.cpp index 00f0f65a7d..13f5d47663 100644 --- a/dpsim/src/Timer.cpp +++ b/dpsim/src/Timer.cpp @@ -15,7 +15,7 @@ #ifdef HAVE_TIMERFD #include #include -#endif /* HAVE_TIMERFD */ +#endif // HAVE_TIMERFD using namespace DPsim; using CPS::SystemError; @@ -81,14 +81,14 @@ void Timer::start() { mTicks = 0; mOverruns = 0; - /* Determine offset between clocks */ + // Determine offset between clocks. auto rt = StartClock::now(); auto steady = IntervalClock::now(); /* This handles the offset between - * - IntervalClock (CLOCK_MONOTONIC aka std::chrono::steady_clock) and - * - StartClock (CLOCK_REALTIME aka std::chrono::system_clock) - */ + * - IntervalClock (CLOCK_MONOTONIC aka std::chrono::steady_clock) and + * - StartClock (CLOCK_REALTIME aka std::chrono::system_clock) + */ auto start = mStartAt > StartTimePoint() ? mStartAt.time_since_epoch() - rt.time_since_epoch() + steady.time_since_epoch() diff --git a/dpsim/src/pybind/main.cpp b/dpsim/src/pybind/main.cpp index 51d9c4e9ac..349dbedafe 100644 --- a/dpsim/src/pybind/main.cpp +++ b/dpsim/src/pybind/main.cpp @@ -37,11 +37,11 @@ using namespace pybind11::literals; PYBIND11_MODULE(dpsimpy, m) { m.doc() = R"pbdoc( - DPsim Python bindings - ----------------------- - The Python bindings provide access to most of the DPsim features implemented in C++. - It is possible to run powerflow, quasi-static, dynamic phasor and electromagnetic transient simulations - and to parameterize all components of the network from Python. + DPsim Python bindings + ----------------------- + The Python bindings provide access to most of the DPsim features implemented in C++. + It is possible to run powerflow, quasi-static, dynamic phasor and electromagnetic transient simulations + and to parameterize all components of the network from Python. )pbdoc"; //Enums From 63a754308df8f014ab1c76d443bcb337cddda8da Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Sun, 6 Apr 2025 08:06:50 +0200 Subject: [PATCH 067/168] fix(cmake): Show feature summary even if not Git info is available Signed-off-by: Steffen Vogel --- CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9f747bce6a..2504453be5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -304,10 +304,11 @@ if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) feature_summary(WHAT ALL VAR enabledFeaturesText) + message(STATUS "Building ${CMAKE_PROJECT_NAME}:") + message(STATUS "Feature summary for DPsim") + message(STATUS "${enabledFeaturesText}") + if(FOUND_GIT_VERSION) - message(STATUS "Building ${CMAKE_PROJECT_NAME}:") - message(STATUS "Feature summary for DPsim") - message(STATUS "${enabledFeaturesText}") message(STATUS " VERSION: ${DPSIM_VERSION}") message(STATUS " RELEASE: ${DPSIM_RELEASE}") message(STATUS " GIT_REV: ${DPSIM_GIT_REV}") From ab5f5088953f0458f09b55132056aceb7d3c5bd2 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 8 Apr 2025 09:12:25 +0200 Subject: [PATCH 068/168] fix(doc): Harmonize capitalization of Markdown filenames Signed-off-by: Steffen Vogel --- .../content/en/docs/Development/{Debugging.md => debugging.md} | 0 .../content/en/docs/Development/{Guidelines.md => guidelines.md} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename docs/hugo/content/en/docs/Development/{Debugging.md => debugging.md} (100%) rename docs/hugo/content/en/docs/Development/{Guidelines.md => guidelines.md} (100%) diff --git a/docs/hugo/content/en/docs/Development/Debugging.md b/docs/hugo/content/en/docs/Development/debugging.md similarity index 100% rename from docs/hugo/content/en/docs/Development/Debugging.md rename to docs/hugo/content/en/docs/Development/debugging.md diff --git a/docs/hugo/content/en/docs/Development/Guidelines.md b/docs/hugo/content/en/docs/Development/guidelines.md similarity index 100% rename from docs/hugo/content/en/docs/Development/Guidelines.md rename to docs/hugo/content/en/docs/Development/guidelines.md From f62afd26de247e12ecfbe03ee1f883b5c4c38127 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 8 Apr 2025 09:55:31 +0200 Subject: [PATCH 069/168] feat(pre-commit): Add markdownlint hook Signed-off-by: Steffen Vogel --- .pre-commit-config.yaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 728a652ea3..29266f40f6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -42,3 +42,9 @@ repos: hooks: - id: black - id: black-jupyter + + - repo: https://github.com/markdownlint/markdownlint + rev: "v0.13.0" + hooks: + - id: markdownlint + args: [-r, "~MD013,~MD033,~MD024"] From 70ea0fb3982e109c287e0e2a7d95a07204d8aa1f Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 8 Apr 2025 09:56:06 +0200 Subject: [PATCH 070/168] fix(style): Fix markdownlint warnings Signed-off-by: Steffen Vogel --- README.md | 3 +- .../content/en/docs/Concepts/dyn-phasors.md | 2 +- .../en/docs/Concepts/nodal-analysis.md | 5 +- .../content/en/docs/Concepts/powerflow.md | 124 +++++---- .../content/en/docs/Development/_index.md | 16 +- .../content/en/docs/Development/debugging.md | 141 ++++++----- .../content/en/docs/Development/guidelines.md | 8 +- .../content/en/docs/Getting started/build.md | 170 ++++++++----- .../en/docs/Getting started/install.md | 30 ++- .../en/docs/Getting started/real-time.md | 17 +- .../en/docs/Models/RLC-Elements/index.md | 235 ++++++++++-------- .../Models/Synchronous Generator/index.md | 59 +++-- .../en/docs/Models/Transformer/index.md | 3 +- docs/hugo/content/en/docs/Models/_index.md | 35 +-- docs/hugo/content/en/docs/Models/branches.md | 6 +- .../en/docs/Overview/Architecture/index.md | 4 +- .../en/docs/Overview/Attributes/index.md | 45 ++-- docs/hugo/content/en/docs/Overview/_index.md | 4 +- .../content/en/docs/Overview/interfaces.md | 12 +- .../content/en/docs/Overview/mnainterface.md | 9 +- .../content/en/docs/Overview/subcomponents.md | 67 ++--- docs/hugo/content/en/docs/Roadmap/index.md | 32 +-- docs/hugo/content/en/docs/Tasks/add-model.md | 54 ++-- .../en/docs/Tasks/create-simulation.md | 42 ++-- docs/hugo/content/en/docs/_index.md | 12 +- 25 files changed, 666 insertions(+), 469 deletions(-) diff --git a/README.md b/README.md index 34dfa37916..480f875087 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,8 @@ The project is released under the terms of the [MPL 2.0](https://mozilla.org/MPL [LF Energy Slack](https://slack.lfenergy.org/) - Chat with other users and developers and get help in the **#sogno** or **#sogno-dpsim** channel. -You can also send a direct message to +You can also send a direct message to: + - Markus Mirz - Jan Dinkelbach - Steffen Vogel diff --git a/docs/hugo/content/en/docs/Concepts/dyn-phasors.md b/docs/hugo/content/en/docs/Concepts/dyn-phasors.md index acd3663056..05604f7f8b 100644 --- a/docs/hugo/content/en/docs/Concepts/dyn-phasors.md +++ b/docs/hugo/content/en/docs/Concepts/dyn-phasors.md @@ -10,7 +10,7 @@ A few years later, dynamic phasors were also employed for power system simulatio In [Strunz2006](https://ieeexplore.ieee.org/document/4026700) the authors combine the dynamic phasor approach with the Electromagnetic Transients Program (EMTP) simulator concept which includes Modified Nodal Analysis (MNA). Further research topics include fault and stability analysis under unbalanced conditions as presented in [Stankovic2000](https://ieeexplore.ieee.org/document/871734) and also rotating machine models have been developed in dynamic phasors [Zhang 2007](https://ieeexplore.ieee.org/document/4282063). -## Bandpass Signals and Baseband Representation +# Bandpass Signals and Baseband Representation Although here, dynamic phasors are presented as a power system modelling tool, it should be noted that the concept is also known in other domains, for example, microwave and communications engineering [Maas2003](https://ieeexplore.ieee.org/document/9100822), [Suarez2009](https://ieeexplore.ieee.org/book/5236646), [Haykin2009](https://isbnsearch.org/isbn/9780471697909), [Proakis2001](https://isbnsearch.org/isbn/0131589326). In these domains, the approach is often denoted as base band representation or complex envelope. diff --git a/docs/hugo/content/en/docs/Concepts/nodal-analysis.md b/docs/hugo/content/en/docs/Concepts/nodal-analysis.md index 155befda57..b9b0c362a4 100644 --- a/docs/hugo/content/en/docs/Concepts/nodal-analysis.md +++ b/docs/hugo/content/en/docs/Concepts/nodal-analysis.md @@ -28,4 +28,7 @@ A circuit can be solved using Nodal Analysis as follows * Write $n-1$ KCL based equations in terms of node voltage variable. The resulting equations can be written in matrix form and have to be solved for $v$. -$$\boldsymbol{Y} \boldsymbol{v} = \boldsymbol{i}$$ + +```math +\boldsymbol{Y} \boldsymbol{v} = \boldsymbol{i} +``` diff --git a/docs/hugo/content/en/docs/Concepts/powerflow.md b/docs/hugo/content/en/docs/Concepts/powerflow.md index 9b4c1455ab..4d667ed606 100644 --- a/docs/hugo/content/en/docs/Concepts/powerflow.md +++ b/docs/hugo/content/en/docs/Concepts/powerflow.md @@ -8,7 +8,8 @@ The power flow problem is about the calculation of voltage magnitudes and angles The solution is obtained from a given set of voltage magnitudes and power levels for a specific model of the network configuration. The power flow solution exhibits the voltages and angles at all buses and real and reactive flows can be deduced from the same. -## Power System Model +# Power System Model + Power systems are modeled as a network of buses (nodes) and branches (lines). To a network bus, components such a generator, load, and transmission substation can be connected. Each bus in the network is fully described by the following four electrical quantities: @@ -21,39 +22,53 @@ Each bus in the network is fully described by the following four electrical quan There are three types of networks buses: VD bus, PV bus and PQ bus. Depending on the type of the bus, two of the four electrical quantities are specified as shown in the table below. -| Bus Type | Known | Unknown | -| --- | --- | --- | -| $VD$ | $\vert V_{k} \vert, \theta_{k}$ | $P_{k}, Q_{k}$ | -| $PV$ | $P_{k}, \vert V_{k} \vert$ | $Q_{k}, \theta_{k}$ | -| $PQ$ | $P_{k}, Q_{k}$ | $\vert V_{k} \vert, \theta_{k}$ | +| Bus Type | Known | Unknown | +| --- | --- | --- | +| $VD$ | $\vert V_{k} \vert, \theta_{k}$ | $P_{k}, Q_{k}$ | +| $PV$ | $P_{k}, \vert V_{k} \vert$ | $Q_{k}, \theta_{k}$ | +| $PQ$ | $P_{k}, Q_{k}$ | $\vert V_{k} \vert, \theta_{k}$ | + +# Single Phase Power Flow Problem -## Single Phase Power Flow Problem The power flow problem can be expressed by the goal to bring a mismatch function $\vec{f}$ to zero. The value of the mismatch function depends on a solution vector $\vec{x}$: -$$ \vec{f}(\vec{x}) = 0 $$ + +```math +\vec{f}(\vec{x}) = 0 +``` As $\vec{f}(\vec{x})$ will be nonlinear, the equation system will be solved with Newton-Raphson: -$$-\textbf{J}(\vec{x}) \Delta \vec{x} = \vec{f} (\vec{x})$$ +```math +-\textbf{J}(\vec{x}) \Delta \vec{x} = \vec{f} (\vec{x}) +``` where $\Delta \vec{x}$ is the correction of the solution vector and $\textbf{J}(\vec{x})$ is the Jacobian matrix. The solution vector $\vec{x}$ represents the voltage $\vec{V}$ by polar or cartesian quantities. The mismatch function $\vec{f}$ will either represent the power mismatch $\Delta \vec{S}$ in terms of -$$\left [ \begin{array}{c} \Delta \vec{P} \\ \Delta \vec{Q} \end{array} \right ]$$ +```math +\left [ \begin{array}{c} \Delta \vec{P} \\ \Delta \vec{Q} \end{array} \right ] +``` or the current mismatch $\Delta \vec{I}$ in terms of -$$\left [ \begin{array}{c} \Delta \vec{I_{real}} \\ \Delta \vec{I_{imag}} \end{array} \right ]$$ +```math +\left [ \begin{array}{c} \Delta \vec{I_{real}} \\ \Delta \vec{I_{imag}} \end{array} \right ] +``` where the vectors split the complex quantities into real and imaginary parts. Futhermore, the solution vector $\vec{x}$ will represent $\vec{V}$ either by polar coordinates -$$\left [ \begin{array}{c} \vec{\delta} \\ \vert \vec{V} \vert \end{array} \right ]$$ +```math +\left [ \begin{array}{c} \vec{\delta} \\ \vert \vec{V} \vert \end{array} \right ] +``` or rectangular coordinates -$$\left [ \begin{array}{c} \vec{V_{real}} \\ \vec{V_{imag}} \end{array} \right ]$$ +```math +\left [ \begin{array}{c} \vec{V_{real}} \\ \vec{V_{imag}} \end{array} \right ] +``` This results in four different formulations of the powerflow problem: @@ -64,23 +79,28 @@ This results in four different formulations of the powerflow problem: To solve the problem using NR, we need to formulate $\textbf{J} (\vec{x})$ and $\vec{f} (\vec{x})$ for each powerflow problem formulation. -### Powerflow Problem with Power Mismatch Function and Polar Coordinates +## Powerflow Problem with Power Mismatch Function and Polar Coordinates -#### Formulation of Mismatch Function +### Formulation of Mismatch Function The injected power at a node $k$ is given by: -$$S_{k} = V_{k} I _{k}^{*}$$ + +```math +S_{k} = V_{k} I _{k}^{*} +``` The current injection into any bus $k$ may be expressed as: -$$ + +```math I_{k} = \sum_{j=1}^{N} Y_{kj} V_{j} -$$ +``` Substitution yields: + ```math \begin{align} S_{k} &= V_{k} \left ( \sum_{j=1}^{N} Y_{kj} V_{j} \right )^{*} \nonumber \\ - &= V_{k} \sum_{j=1}^{N} Y_{kj}^{*} V_{j} ^{*} \nonumber + &= V_{k} \sum_{j=1}^{N} Y_{kj}^{*} V_{j} ^{*} \nonumber \end{align} ``` @@ -90,11 +110,11 @@ Then we may rewrite the last equation: ```math \begin{align} S_{k} &= V_{k} \sum_{j=1}^{N} Y_{kj}^{*} V_{j}^{*} \nonumber \\ - &= \vert V_{k} \vert \angle \theta_{k} \sum_{j=1}^{N} (G_{kj} + jB_{kj})^{*} ( \vert V_{j} \vert \angle \theta_{j})^{*} \nonumber \\ - &= \vert V_{k} \vert \angle \theta_{k} \sum_{j=1}^{N} (G_{kj} - jB_{kj}) ( \vert V_{j} \vert \angle - \theta_{j}) \nonumber \\ - &= \sum_{j=1} ^{N} \vert V_{k} \vert \angle \theta_{k} ( \vert V_{j} \vert \angle - \theta_{j}) (G_{kj} - jB_{kj}) \nonumber \\ - &= \sum_{j=1} ^{N} \left ( \vert V_{k} \vert \vert V_{j} \vert \angle (\theta_{k} - \theta_{j}) \right ) (G_{kj} - jB_{kj}) \nonumber \\ - &= \sum_{j=1} ^{N} \vert V_{k} \vert \vert V_{j} \vert \left ( cos(\theta_{k} - \theta_{j}) + jsin(\theta_{k} - \theta_{j}) \right ) (G_{kj} - jB_{kj}) + &= \vert V_{k} \vert \angle \theta_{k} \sum_{j=1}^{N} (G_{kj} + jB_{kj})^{*} ( \vert V_{j} \vert \angle \theta_{j})^{*} \nonumber \\ + &= \vert V_{k} \vert \angle \theta_{k} \sum_{j=1}^{N} (G_{kj} - jB_{kj}) ( \vert V_{j} \vert \angle - \theta_{j}) \nonumber \\ + &= \sum_{j=1} ^{N} \vert V_{k} \vert \angle \theta_{k} ( \vert V_{j} \vert \angle - \theta_{j}) (G_{kj} - jB_{kj}) \nonumber \\ + &= \sum_{j=1} ^{N} \left ( \vert V_{k} \vert \vert V_{j} \vert \angle (\theta_{k} - \theta_{j}) \right ) (G_{kj} - jB_{kj}) \nonumber \\ + &= \sum_{j=1} ^{N} \vert V_{k} \vert \vert V_{j} \vert \left ( cos(\theta_{k} - \theta_{j}) + jsin(\theta_{k} - \theta_{j}) \right ) (G_{kj} - jB_{kj}) \end{align} ``` @@ -116,12 +136,13 @@ We define the vector of unknown as the composite vector of unknown angles $\vec{ ```math \begin{align} \vec{x} = \left[ \begin{array}{c} \vec{\theta} \\ \vert \vec{V} \vert \\ \end{array} \right ] - = \left[ \begin{array}{c} \theta_{2} \\ \theta_{3} \\ \vdots \\ \theta_{N} \\ \vert V_{N_{PV+1}} \vert \\ \vert V_{N_{PV+2}} \vert \\ \vdots \\ \vert V_{N} \vert \end{array} \right] + = \left[ \begin{array}{c} \theta_{2} \\ \theta_{3} \\ \vdots \\ \theta_{N} \\ \vert V_{N_{PV+1}} \vert \\ \vert V_{N_{PV+2}} \vert \\ \vdots \\ \vert V_{N} \vert \end{array} \right] \end{align} ``` The right-hand sides of equations (2) and (3) depend on the elements of the unknown vector $\vec{x}$. Expressing this dependency more explicitly, we rewrite these equations as: + ```math \begin{align} P_{k} = P_{k} (\vec{x}) \Rightarrow P_{k}(\vec{x}) - P_{k} &= 0 \quad \quad k = 2,...,N \\ @@ -130,20 +151,23 @@ Q_{k} = Q_{k} (\vec{x}) \Rightarrow Q_{k} (\vec{x}) - Q_{k} &= 0 \quad \quad k = ``` We now define the mismatch vector $\vec{f} (\vec{x})$ as: + ```math \begin{align} \vec{f} (\vec{x}) = \left [ \begin{array}{c} f_{1}(\vec{x}) \\ \vdots \\ f_{N-1}(\vec{x}) \\ ------ \\ f_{N}(\vec{x}) \\ \vdots \\ f_{2N-N_{PV} -1}(\vec{x}) \end{array} \right ] - = \left [ \begin{array}{c} P_{2}(\vec{x}) - P_{2} \\ \vdots \\ P_{N}(\vec{x}) - P_{N} \\ --------- \\ Q_{N_{PV}+1}(\vec{x}) - Q_{N_{PV}+1} \\ \vdots \\ Q_{N}(\vec{x}) - Q_{N} \end{array} \right] - = \left [ \begin{array}{c} \Delta P_{2} \\ \vdots \\ \Delta P_{N} \\ ------ \\ \Delta Q_{N_{PV}+1} \\ \vdots \\ \Delta Q_{N} \end{array} \right ] - = \vec{0} + = \left [ \begin{array}{c} P_{2}(\vec{x}) - P_{2} \\ \vdots \\ P_{N}(\vec{x}) - P_{N} \\ --------- \\ Q_{N_{PV}+1}(\vec{x}) - Q_{N_{PV}+1} \\ \vdots \\ Q_{N}(\vec{x}) - Q_{N} \end{array} \right] + = \left [ \begin{array}{c} \Delta P_{2} \\ \vdots \\ \Delta P_{N} \\ ------ \\ \Delta Q_{N_{PV}+1} \\ \vdots \\ \Delta Q_{N} \end{array} \right ] + = \vec{0} \end{align} ``` + That is a system of nonlinear equations. This nonlinearity comes from the fact that $P_{k}$ and $Q_{k}$ have terms containing products of some of the unknowns and also terms containing trigonometric functions of some the unknowns. -#### Formulation of Jacobian +### Formulation of Jacobian As discussed in the previous section, the power flow problem will be solved using the Newton-Raphson method. Here, the Jacobian matrix is obtained by taking all first-order partial derivates of the power mismatch functions with respect to the voltage angles $\theta_{k}$ and magnitudes $\vert V_{k} \vert$ as: + ```math \begin{align} J_{jk}^{P \theta} &= \frac{\partial P_{j} (\vec{x} ) } {\partial \theta_{k}} = \vert V_{j} \vert \vert V_{k} \vert \left ( G_{jk} sin(\theta_{j} - \theta_{k}) - B_{jk} cos(\theta_{j} - \theta_{k} ) \right ) \\ @@ -158,19 +182,20 @@ J_{jj}^{QV} &= \frac{\partial Q_{j}(\vec{x})}{\partial \vert V_{j} \vert } = \fr ``` The linear system of equations that is solved in every Newton iteration can be written in matrix form as follows: + ```math \begin{align} -\left [ \begin{array}{cccccc} - \frac{\partial \Delta P_{2} }{\partial \theta_{2}} & \cdots & \frac{\partial \Delta P_{2} }{\partial \theta_{N}} & - \frac{\partial \Delta P_{2} }{\partial \vert V_{N_{G+1}} \vert} & \cdots & \frac{\partial \Delta P_{2} }{\partial \vert V_{N} \vert} \\ - \vdots & \ddots & \vdots & \vdots & \ddots & \vdots \\ - \frac{\partial \Delta P_{N} }{\partial \theta_{2}} & \cdots & \frac{\partial \Delta P_{N}}{\partial \theta_{N}} & - \frac{\partial \Delta P_{N}}{\partial \vert V_{N_{G+1}} \vert } & \cdots & \frac{\partial \Delta P_{N}}{\partial \vert V_{N} \vert} \\ - \frac{\partial \Delta Q_{N_{G+1}} }{\partial \theta_{2}} & \cdots & \frac{\partial \Delta Q_{N_{G+1}} }{\partial \theta_{N}} & - \frac{\partial \Delta Q_{N_{G+1}} }{\partial \vert V_{N_{G+1}} \vert } & \cdots & \frac{\partial \Delta Q_{N_{G+1}} }{\partial \vert V_{N} \vert} \\ - \vdots & \ddots & \vdots & \vdots & \ddots & \vdots \\ - \frac{\partial \Delta Q_{N}}{\partial \theta_{2}} & \cdots & \frac{\partial \Delta Q_{N}}{\partial \theta_{N}} & - \frac{\partial \Delta Q_{N}}{\partial \vert V_{N_{G+1}} \vert } & \cdots & \frac{\partial \Delta Q_{N}}{\partial \vert V_{N} \vert} + \frac{\partial \Delta P_{2} }{\partial \theta_{2}} & \cdots & \frac{\partial \Delta P_{2} }{\partial \theta_{N}} & + \frac{\partial \Delta P_{2} }{\partial \vert V_{N_{G+1}} \vert} & \cdots & \frac{\partial \Delta P_{2} }{\partial \vert V_{N} \vert} \\ + \vdots & \ddots & \vdots & \vdots & \ddots & \vdots \\ + \frac{\partial \Delta P_{N} }{\partial \theta_{2}} & \cdots & \frac{\partial \Delta P_{N}}{\partial \theta_{N}} & + \frac{\partial \Delta P_{N}}{\partial \vert V_{N_{G+1}} \vert } & \cdots & \frac{\partial \Delta P_{N}}{\partial \vert V_{N} \vert} \\ + \frac{\partial \Delta Q_{N_{G+1}} }{\partial \theta_{2}} & \cdots & \frac{\partial \Delta Q_{N_{G+1}} }{\partial \theta_{N}} & + \frac{\partial \Delta Q_{N_{G+1}} }{\partial \vert V_{N_{G+1}} \vert } & \cdots & \frac{\partial \Delta Q_{N_{G+1}} }{\partial \vert V_{N} \vert} \\ + \vdots & \ddots & \vdots & \vdots & \ddots & \vdots \\ + \frac{\partial \Delta Q_{N}}{\partial \theta_{2}} & \cdots & \frac{\partial \Delta Q_{N}}{\partial \theta_{N}} & + \frac{\partial \Delta Q_{N}}{\partial \vert V_{N_{G+1}} \vert } & \cdots & \frac{\partial \Delta Q_{N}}{\partial \vert V_{N} \vert} \end{array} \right ] \left [ \begin{array}{c} \Delta \theta_{2} \\ \vdots \\ \Delta \theta_{N} \\ \Delta \vert V_{N_{G+1}} \vert \\ \vdots \\ \Delta \vert V_{N} \vert \end{array} \right ] = \left [ \begin{array}{c} \Delta P_{2} \\ \vdots \\ \Delta P_{N} \\ \Delta Q_{N_{G+1}} \\ \vdots \\ \Delta Q_{N} \end{array} \right ] @@ -180,21 +205,22 @@ The linear system of equations that is solved in every Newton iteration can be w ## Solution of the Problem The solution update formula is given by: + ```math \begin{align} - \vec{x}^{(i+1)} = \vec{x}^{(i)} + \Delta \vec{x}^{(i)} = \vec{x}^{(i)} - \textbf{J}^{-1} \vec{f} (\vec{x}^{(i)}) + \vec{x}^{(i+1)} = \vec{x}^{(i)} + \Delta \vec{x}^{(i)} = \vec{x}^{(i)} - \textbf{J}^{-1} \vec{f} (\vec{x}^{(i)}) \end{align} ``` To sum up, the NR algorithm, for application to the power flow problem is: 1. Set the iteration counter to $i=1$. Use the initial solution $V_{i} = 1 \angle 0^{\circ}$ -2. Compute the mismatch vector $\vec{f}({\vec{x}})$ using the power flow equations -3. Perform the following stopping criterion tests: - * If $\vert \Delta P_{i} \vert < \epsilon_{P}$ for all type PQ and PV buses and - * If $\vert \Delta Q_{i} \vert < \epsilon_{Q}$ for all type PQ - * Then go to step 6 - * Otherwise, go to step 4. -4. Evaluate the Jacobian matrix $\textbf{J}^{(i)}$ and compute $\Delta \vec{x}^{(i)}$. -5. Compute the update solution vector $\vec{x}^{(i+1)}$. Return to step 3. -6. Stop. +1. Compute the mismatch vector $\vec{f}({\vec{x}})$ using the power flow equations +1. Perform the following stopping criterion tests: + * If $\vert \Delta P_{i} \vert < \epsilon_{P}$ for all type PQ and PV buses and + * If $\vert \Delta Q_{i} \vert < \epsilon_{Q}$ for all type PQ + * Then go to step 6 + * Otherwise, go to step 4. +1. Evaluate the Jacobian matrix $\textbf{J}^{(i)}$ and compute $\Delta \vec{x}^{(i)}$. +1. Compute the update solution vector $\vec{x}^{(i+1)}$. Return to step 3. +1. Stop. diff --git a/docs/hugo/content/en/docs/Development/_index.md b/docs/hugo/content/en/docs/Development/_index.md index 2070ce0bee..0053dcf5be 100644 --- a/docs/hugo/content/en/docs/Development/_index.md +++ b/docs/hugo/content/en/docs/Development/_index.md @@ -6,18 +6,18 @@ description: > How to extend DPsim. --- -## Environment +# Environment We recommend the following development tools: - Editor: [Visual Studio Code](https://code.visualstudio.com) - - Extensions: - - [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) - - [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) - - [CMake Tools](https://marketplace.visualstudio.com/items?itemName=vector-of-bool.cmake-tools) - - [Docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) - - [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - - [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) + - Extensions: + - [C/C++](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) + - [Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python) + - [CMake Tools](https://marketplace.visualstudio.com/items?itemName=vector-of-bool.cmake-tools) + - [Docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker) + - [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) + - [Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack) - [Docker](https://www.docker.com) - [CMake](https://cmake.org) - [Git](https://git-scm.com) diff --git a/docs/hugo/content/en/docs/Development/debugging.md b/docs/hugo/content/en/docs/Development/debugging.md index 6d75ec5c48..d4006801c8 100644 --- a/docs/hugo/content/en/docs/Development/debugging.md +++ b/docs/hugo/content/en/docs/Development/debugging.md @@ -3,50 +3,54 @@ title: "Debugging" linkTitle: "Debugging" --- -## Mixed Python C++ Debugging +# Mixed Python C++ Debugging -### Prerequisites +## Prerequisites Your vscode launch.json should have two configurations, one to launch the python process and one to attach gdb: - { - "version": "0.2.0", - "configurations": [ - { - "name": "Python: Current File", - "type": "python", - "request": "launch", - "program": "${file}", - "console": "integratedTerminal", - "stopOnEntry": true, - "env": {"PYTHONPATH": "${workspaceFolder}/build${pathSeparator}${env:PYTHONPATH}"} - }, - { - "name": "(gdb) Attach", - "type": "cppdbg", - "request": "attach", - "program": "/usr/bin/python", - "processId": "${command:pickProcess}", - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - } - ] - } +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "stopOnEntry": true, + "env": {"PYTHONPATH": "${workspaceFolder}/build${pathSeparator}${env:PYTHONPATH}"} + }, + { + "name": "(gdb) Attach", + "type": "cppdbg", + "request": "attach", + "program": "/usr/bin/python", + "processId": "${command:pickProcess}", + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} +``` The python debugger will stop on entry ("stopOnEntry": true). Make sure to adapt your PYTHONPATH variable if necessary. The C++ code has to be build in debug mode - cmake .. -DCMAKE_BUILD_TYPE=Debug +```shell +cmake .. -DCMAKE_BUILD_TYPE=Debug +``` -### Attaching C++ Debugger +## Attaching C++ Debugger - open the python example to be debugged - go to the debug menu and select / run the "Python: Current File" configuration @@ -59,45 +63,48 @@ The C++ code has to be build in debug mode You can automate this by using the vscode extension “Python C++ Debugger” and by adding this configuration to the launch.json above: - { - "name": "Python C++ Debugger", - "type": "pythoncpp", - "request": "launch", - "pythonConfig": "custom", - "pythonLaunchName": "Python: Current File", - "cppConfig": "default (gdb) Attach" - } +```json +{ + "name": "Python C++ Debugger", + "type": "pythoncpp", + "request": "launch", + "pythonConfig": "custom", + "pythonLaunchName": "Python: Current File", + "cppConfig": "default (gdb) Attach" +} +``` This will automatically run both debuggers and select the current process. It can take a while before the debugger hits the C++ breakpoints. - -## C++ Debugging +# C++ Debugging Use the following launch.json for vscode and set the program path: - { - "version": "0.2.0", - "configurations": [ - { - "name": "(gdb) Launch", - "type": "cppdbg", - "request": "launch", - "program": "${workspaceFolder}/dpsim/build/Examples/Cxx/example", - "args": [], - "stopAtEntry": true, - "cwd": "${workspaceFolder}", - "environment": [], - "externalConsole": false, - "MIMode": "gdb", - "setupCommands": [ - { - "description": "Enable pretty-printing for gdb", - "text": "-enable-pretty-printing", - "ignoreFailures": true - } - ] - } - ] - } +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/dpsim/build/Examples/Cxx/example", + "args": [], + "stopAtEntry": true, + "cwd": "${workspaceFolder}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} +``` diff --git a/docs/hugo/content/en/docs/Development/guidelines.md b/docs/hugo/content/en/docs/Development/guidelines.md index ecdcf238d5..df85d3a0e6 100644 --- a/docs/hugo/content/en/docs/Development/guidelines.md +++ b/docs/hugo/content/en/docs/Development/guidelines.md @@ -5,7 +5,7 @@ linkTitle: "Guidelines" This is a summary of general guidelines for the development of DPsim. -## Scaling of Voltages and Currents +# Scaling of Voltages and Currents Voltage quantities are expressed either as phase-to-phase RMS values (denominated as `RMS3PH`) or as phase-to-ground peak values (denominated as `PEAK1PH`): @@ -18,19 +18,19 @@ Current quantities are expressed either as `RMS` or as `PEAK` values: - Simulation quantities in both `SP` and `DP` domain (e.g. `mIntfCurrent` of `DP::Ph1::PiLine`) as `RMS` values - Simulation quantities in the `EMT` domain (e.g. `mIntfCurrent` of `EMT::Ph3::Transformer`) as `PEAK` values - -## Logging +# Logging Debug or trace should be the default log level for information that might be nice to have but not necessary for every simulation case. Calls to the logger that might occur during simulation must use spdlog macros, like SPDLOG_LOGGER_INFO. -## Creating New Releases +# Creating New Releases Although DPsim currently does not have any conventions on versioning, the periodic creation of new versions can help to mark significant changes and to analyze new portions of code using tools like SonarCloud. A new version of DPsim has to be indicated as follows: + - Create a new tag with an increased version number - Update setup.cfg - Update CMakeLists.txt diff --git a/docs/hugo/content/en/docs/Getting started/build.md b/docs/hugo/content/en/docs/Getting started/build.md index 7542bb9ea7..4d7bf6ae76 100644 --- a/docs/hugo/content/en/docs/Getting started/build.md +++ b/docs/hugo/content/en/docs/Getting started/build.md @@ -4,82 +4,109 @@ linkTitle: "Build" date: 2023-05-03 --- -## Docker based +# Docker based Clone the repository - $ git clone git@github.com:sogno-platform/dpsim.git +```shell +git clone git@github.com:sogno-platform/dpsim.git +``` or using https if you do not have an account - $ git clone https://github.com/sogno-platform/dpsim.git +```shell +git clone https://github.com/sogno-platform/dpsim.git +``` In the repository, there is a Docker file with all required dependencies - $ cd dpsim - $ docker build -t sogno/dpsim:dev -f Packaging/Docker/Dockerfile.dev . +```shell +cd dpsim +docker build -t sogno/dpsim:dev -f Packaging/Docker/Dockerfile.dev . +``` Alternatively, the image can be pulled from DockerHub like so - $ docker pull sogno/dpsim:dev +```shell +docker pull sogno/dpsim:dev +``` For OS specific instructions on how to install requirements, see the sections below. Next, run a Docker container - $ cd dpsim - $ docker run -it -p 8888:8888 -v $(pwd):/dpsim --privileged sogno/dpsim:dev bash +```shell +cd dpsim +docker run -it -p 8888:8888 -v $(pwd):/dpsim --privileged sogno/dpsim:dev bash +``` The option `-p` maps the port 8888 of the container to the docker host. This is required to access the jupyter lab instance inside the container. The option `--privileged` is required for debug builds. For Windows, you might need to specify the current directory with curly brackets - $ docker run -it -p 8888:8888 -v ${pwd}:/dpsim --privileged sogno/dpsim:dev bash +```shell +docker run -it -p 8888:8888 -v ${pwd}:/dpsim --privileged sogno/dpsim:dev bash +``` Now, you should be in an interactive session inside the docker container. The DPsim C++ and Python library without C++ examples or documentation can be built as follows - $ cd /dpsim - $ mkdir build && cd build - $ cmake .. - $ cmake --build . --target dpsimpy +```shell +cd /dpsim +mkdir build && cd build +cmake .. +cmake --build . --target dpsimpy +``` If you need other libraries that are not built by default, you need to target them specifically, for example if you need `dpsimpy´ and ´dpsimpyvillas´: - $ cmake --build . --target dpsimpy dpsimpyvillas +```shell +cmake --build . --target dpsimpy dpsimpyvillas +``` To build everything run - $ cmake --build . +```shell +cmake --build . +``` To use other libraries that are installed, use the relevant option defined in the CMakeList.txt files, for example for GSL below, and then build as usual: - $ cmake .. -DWITH_GSL=ON +```shell +cmake .. -DWITH_GSL=ON +``` If you would like to use the Python package, it has to be added to the path. The following command adds the dpsimpy C++/Python package as well as the dpsim pure Python package. - $ cd /dpsim/build - $ export PYTHONPATH=$(pwd):$(pwd)/../python/src/ +```shell +cd /dpsim/build +export PYTHONPATH=$(pwd):$(pwd)/../python/src/ +``` If you are using `conda` or other ways to develop with environments, please keep in mind that this will become specific for your setup. For this case, from within the environment already active: - $ cd /dpsim/build - $ conda develop $(pwd) && conda develop $(pwd)/Source/Python && conda develop $(pwd)/../Source/Python +```shell +cd /dpsim/build +conda develop $(pwd) && conda develop $(pwd)/Source/Python && conda develop $(pwd)/../Source/Python +``` -To run jupyter lab +To run JupyterLab - $ cd /dpsim - $ jupyter lab --ip="0.0.0.0" --allow-root --no-browser +```shell +cd /dpsim +jupyter lab --ip="0.0.0.0" --allow-root --no-browser +``` -To install dpsim run +To install DPsim run - $ cd /dpsim/build - $ sudo make install +```shell +cd /dpsim/build +sudo make install +``` - -## CMake for Linux +# CMake for Linux The most recent list of requirements can be found in the Dockerfiles. @@ -91,19 +118,21 @@ If you want to use these optional feature, you have to build them manually. Install Sundials - $ git clone --branch v3.1.1 https://github.com/LLNL/sundials.git - $ mkdir sundials/build - $ pushd sundials/build - $ cmake .. \ - -DBUILD_SHARED_LIBS=ON \ - -DBUILD_STATIC_LIBS=OFF \ - -DEXAMPLES_ENABLE_C=OFF - $ make -j$(nproc) install - $ popd +```shell +git clone --branch v3.1.1 https://github.com/LLNL/sundials.git +mkdir sundials/build +pushd sundials/build +cmake .. \ + -DBUILD_SHARED_LIBS=ON \ + -DBUILD_STATIC_LIBS=OFF \ + -DEXAMPLES_ENABLE_C=OFF +make -j$(nproc) install +popd +``` The following steps to clone, build and install are the same as for the Docker setup. -## CMake for Windows +# CMake for Windows Make sure that the required dependecies are installed: @@ -117,69 +146,84 @@ Clone the project as explained for Docker. Open a windows command prompt and navigate into the new DPsim folder. Generate a Visual Studio project with CMake and use it to build the project - $ mkdir build - $ cd build - $ cmake -G "Visual Studio 15 2017 Win64" .. +```shell +mkdir build +cd build +cmake -G "Visual Studio 15 2017 Win64" .. +``` Open Visual Studio and load the Visual Studio project from the build directory within the DPsim folder. You can either build the project from within Visual Studio or from the command line by running the following command in the windows command prompt - $ cmake --build . +```shell +cmake --build . +``` To install the Python package use Visual Studio and the Release configuration to build the DPsim Python module and then build the INSTALL project. -## CMake for macOS +# CMake for macOS -Make sure that the required dependecies are installed +Make sure that the required dependencies are installed - $ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" - $ brew install gcc9 git cmake graphviz python3 gsl eigen spdlog - $ sudo pip3 install numpy +```shell +/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" +brew install gcc9 git cmake graphviz python3 gsl eigen spdlog +sudo pip3 install numpy +``` Clone the source as explained for the Docker setup. Compile - $ mkdir build - $ cmake .. - $ make -j$(sysctl -n hw.ncpu) +```shell +mkdir build +cmake .. +make -j$(sysctl -n hw.ncpu) +``` To install the generated Python module to your system - $ sudo make install - +```shell +sudo make install +``` -## Python Package for pypi +# Python Package for pypi Follow the previous steps to set up the Docker container. To build the Python package run - $ python3 setup.py bdist_wheel +```shell +python3 setup.py bdist_wheel +``` -## Documentation +# Documentation -### Python +## Python Install [Sphinx](https://www.sphinx-doc.org/en/master/) or use the Docker image. Generate the Python documentation by running Sphinx via CMake: - $ mkdir -p build && cd build - $ cmake .. - $ make docs +```shell +mkdir -p build && cd build +cmake .. +make docs +``` The resulting documentation will be generated in `Documentation/html/`. -### C++ +## C++ Install [Doxygen](http://www.doxygen.nl/) or use the Docker image. Generate the C++ documentation by running Doxygen via CMake: - $ mkdir -p build && cd build - $ cmake .. - $ make docs_cxx +```shell +mkdir -p build && cd build +cmake .. +make docs_cxx +``` The resulting documentation will be generated in `Documentation/html/Cxx`. diff --git a/docs/hugo/content/en/docs/Getting started/install.md b/docs/hugo/content/en/docs/Getting started/install.md index 0724b13614..f4a1e9a1c9 100644 --- a/docs/hugo/content/en/docs/Getting started/install.md +++ b/docs/hugo/content/en/docs/Getting started/install.md @@ -8,45 +8,51 @@ DPsim is a Python module / C++ library for complex power system simulation. As a Python module, the easiest way to get to know DPsim is via [Jupyter Notebooks](https://jupyter-notebook-beginner-guide.readthedocs.io/en/latest/). -## Docker +# Docker First, you need to install [Docker](https://docs.docker.com/install/). Then, you could either build a docker image by yourself as described in the build instructions or download a prepared image from Docker Hub as described in the following. To start a Jupyter session, run a DPsim Docker container - $ docker run -p 8888:8888 sogno/dpsim +```shell +docker run -p 8888:8888 sogno/dpsim +``` -And access the session by opening the following link: http://localhost:8888/lab?token=3adaa57df44cea75e60c0169e1b2a98ae8f7de130481b5bc +And access the session by opening the following link: -## Python +# Python **Currently, the pypi packages are not maintained. Until we have updated the packages, please use the docker installation.** -### Prerequisites +## Prerequisites First, you need to make sure that Python is installed and your version is compatible. An easy way to install Python and all required packages is the [Anaconda distribution](https://www.anaconda.com/). To get started, install the latest installer for Python 3.x from the [downloads section](https://www.anaconda.com/download/). Then, run the Anaconda Prompt and create a new conda environment: - $ conda create -n dpsim python=3.6 +```shell +conda create -n dpsim python=3.6 +``` After creating the environment you need to make sure that it is activated. The current environment is displayed at the beginning of the command line in brackets. It should read *"(dpsim)..."*. In case it is not activated, run: - $ activate dpsim +```shell +activate dpsim +``` - -### Pip Package Installation +## Pip Package Installation Then, DPsim can be installed as a Python module: - $ pip install dpsim - +```shell +pip install dpsim +``` -## From Source +# From Source To build and install DPsim from the source files, please refer to the build section. diff --git a/docs/hugo/content/en/docs/Getting started/real-time.md b/docs/hugo/content/en/docs/Getting started/real-time.md index b0e279e832..78bdc262e0 100644 --- a/docs/hugo/content/en/docs/Getting started/real-time.md +++ b/docs/hugo/content/en/docs/Getting started/real-time.md @@ -12,12 +12,12 @@ This is due to operating system noise and other processes interfering with the s With proper tuning, we have achieved real-time time steps as low as 5 us synchronized to a FPGA using VILLASnode. Synchronizing the time step to an external source is only necessary, when very high time step accuracy, with maximum deviations in the nanoseconds, is required. - -## Operating System and Kernel +# Operating System and Kernel Using a Linux kernel with the `PREEMPT_RT` feature improves latency when issuing system calls and enables the FIFO scheduler that lets us avoid preemption during the real-time simulation. Most distributions offer a binary package for a `PREEMPT_RT` enabled kernel. For example on Rocky Linux: + ```bash sudo dnf --enablerepo=rt install kernel-rt kernel-rt-devel ``` @@ -25,22 +25,26 @@ sudo dnf --enablerepo=rt install kernel-rt kernel-rt-devel More aggressive tuning can involve isolating a set of cores for exclusive use by the real-time simulation. This way, the kernel will not schedule any processes on these cores. Add the kernel parameters `isolcpus` and `nohz_full` using, for example, `grubby`: + ```bash sudo grubby --update-kernel=ALL --args="isolcpus=9,11,13,15 nohz_full=9,11,13,15" ``` Something similar, but less invasive and non-permanent can be achieved using `tuna`: + ```bash sudo tuna isolate -c 9,11,13,15 ``` To avoid real-time throttling to cause overruns disable this feature: + ```bash sudo bash -c "echo -1 > /proc/sys/kernel/sched_rt_runtime_us" ``` + Note that this is not persistent when rebooting. -## Simulation Model Tuning +# Simulation Model Tuning Real time capable models cannot issue any system calls during simulation as the context switch to the kernel introduces unacceptable latencies. This means models cannot allocate memory, use mutexes or other interrupt-driven synchronization primitives, read or write data from files. @@ -50,7 +54,8 @@ Note however, that this logger pre-allocated the memory required for all of the Your machine may run out of memory, when the simulation is long or you log too many signals. You can increase the performance of your simulation by adding the `-flto` and `-march=native` compiler flags: -``` + +```diff diff --git a/CMakeLists.txt b/CMakeLists.txt index 8801cbe8d..4a2843269 100644 --- a/CMakeLists.txt @@ -66,9 +71,10 @@ index 8801cbe8d..4a2843269 100644 # Get version info and buildid from Git ``` -## Running a Real-Time Simulation +# Running a Real-Time Simulation Before running a simulation, you can run the following commands as root: + ```bash echo "evacuating cores" tuna isolate -c 9,11,13,15 @@ -86,6 +92,7 @@ systemctl stop chronyd As a reference, real-time simulation examples are provided in the `dpsim/examples/cxx` and `dpsim-villas/examples/cxx` folder of the DPsim repository. To benefit from the `PREEMPT_RT` feature and the isolated cores, the simulation has to be started using the `chrt` command to set the scheduling policy and priority, and the `taskset` command to pin the process to the isolated cores. + - [chrt man-page](http://man7.org/linux/man-pages/man1/chrt.1.html) - [taskset man-page](http://man7.org/linux/man-pages/man1/taskset.1.html) diff --git a/docs/hugo/content/en/docs/Models/RLC-Elements/index.md b/docs/hugo/content/en/docs/Models/RLC-Elements/index.md index 939f1a7439..6a0cb72884 100644 --- a/docs/hugo/content/en/docs/Models/RLC-Elements/index.md +++ b/docs/hugo/content/en/docs/Models/RLC-Elements/index.md @@ -4,70 +4,90 @@ linkTitle: "RLC-Elements" date: 2020-03-18 --- -## EMT Equations and Modified Nodal Analysis +# EMT Equations and Modified Nodal Analysis -### Inductance +## Inductance An inductance is described by -$$ - v_j(t) - v_k(t) = v_L(t) = L \frac{\mathrm{d} i_L(t)}{\mathrm{d}t} -$$ + +```math +v_j(t) - v_k(t) = v_L(t) = L \frac{\mathrm{d} i_L(t)}{\mathrm{d}t} +``` + Integration results in an equation to compute the current at time $t$ from a previous state at $t - \Delta t$. -$$ - i_L(t) = i_L(t - \Delta t) + \frac{1}{L} \ \int_{t - \Delta t}^{t} v_L(\tau) \ \mathrm{d} \tau -$$ + +```math +i_L(t) = i_L(t - \Delta t) + \frac{1}{L} \ \int_{t - \Delta t}^{t} v_L(\tau) \ \mathrm{d} \tau +``` + There are various methods to discretize this equation in order to solve it numerically. The trapezoidal rule, an implicit second-order method, is commonly applied for circuit simulation: -$$ - \int_{t - \Delta t}^{t} f(\tau) \ \mathrm{d} \tau \approx \frac{\Delta t}{2}(f(t) + f(t - \Delta t)) -$$ + +```math +\int_{t - \Delta t}^{t} f(\tau) \ \mathrm{d} \tau \approx \frac{\Delta t}{2}(f(t) + f(t - \Delta t)) +``` + Applying the trapezoidal rule to leads to -$$ - i_L(t) = i_L(t - \Delta t) + \frac{\Delta t}{2L}(v_L(t) + v_L(t - \Delta t)) -$$ + +```math +i_L(t) = i_L(t - \Delta t) + \frac{\Delta t}{2L}(v_L(t) + v_L(t - \Delta t)) +``` + This can be rewritten in terms of an equivalent conductance and current source and the number of time steps $k$ with size $\Delta t$. -$$ - i_L(k) = g_L v_L(k) + i_{L,equiv}(k-1) -$$ -$$ - i_{L,equiv}(k-1) = i_L(k-1) + \frac{\Delta t}{2L} v_L(k-1) -$$ -$$ - g_L = \frac{\Delta t}{2L} -$$ + +```math +i_L(k) = g_L v_L(k) + i_{L,equiv}(k-1) +``` + +```math +i_{L,equiv}(k-1) = i_L(k-1) + \frac{\Delta t}{2L} v_L(k-1) +``` + +```math +g_L = \frac{\Delta t}{2L} +``` Hence, components described by differential equations are transformed into a DC equivalent circuit as depicted in the figure below. ![inductance resistive companion](electrical_resistive_companion_inductance.svg) -### Capacitance +## Capacitance The same procedure can be applied to a capacitance. Integration on both side yields -$$ - i_C(t) = C \frac{\mathrm{d}}{\mathrm{d}t} \ v_C(t) -$$ -$$ - v_C(t) = v_C(t - \Delta t) + \frac{1}{C} \int_{t - \Delta t}^t i_C(\tau) \mathrm{d} \tau -$$ + +```math +i_C(t) = C \frac{\mathrm{d}}{\mathrm{d}t} \ v_C(t) +``` + +```math +v_C(t) = v_C(t - \Delta t) + \frac{1}{C} \int_{t - \Delta t}^t i_C(\tau) \mathrm{d} \tau +``` + Finally, the equivalent circuit is described by a current source and a conductance. -$$ - i_{C}(k) = g_{C} v_C(k) + i_{C,equiv}(k-1) -$$ -$$ - i_{C,equiv}(k-1) = -i_{C}(k-1) - g_C v_C(k-1) -$$ -$$ - g_{C} = \frac{2C}{\Delta t} -$$ + +```math +i_{C}(k) = g_{C} v_C(k) + i_{C,equiv}(k-1) +``` + +```math +i_{C,equiv}(k-1) = -i_{C}(k-1) - g_C v_C(k-1) +``` + +```math +g_{C} = \frac{2C}{\Delta t} +``` + This equation set is visualized in the figure below. ![capacitance resistive companion](electrical_resistive_companion_capacitance.svg) Hence, the vector of unknowns $\bm{x}$ and the source vector $\bm{b}$ become time dependent and this leads to the system description: -$$ - \bm{A} \bm{x}(t) = \bm{b}(t) -$$ + +```math +\bm{A} \bm{x}(t) = \bm{b}(t) +``` + To simulate the transient behavior of circuits, this linear equation has to be solved repeatedly. As long as the system topology and the time step is fixed, the system matrix is constant. @@ -77,8 +97,10 @@ The dynamic phasor concept can be integrated with nodal analysis. The overall procedure does not change but the system equations are rewritten using complex numbers and all variables need to be expressed in terms of dynamic phasors. Therefore, the resistive companion representations of inductances and capacitances have to be adapted as well. -### Inductance +## Inductance + In dynamic phasors the integration of the inductance equation yields + ```math \begin{align} \langle v_L \rangle(t) &= \Big \langle L \frac{\mathrm{d} i_L}{\mathrm{d}t} \Big \rangle(t) \nonumber \\ @@ -86,88 +108,107 @@ In dynamic phasors the integration of the inductance equation yields \end{align} ``` -$$ - \langle i_L \rangle(t) = \langle i_L \rangle(t - \Delta t) + \int_{t - \Delta t}^t \frac{1}{L} \langle v_L \rangle(\tau) - j \omega \ \langle i_L \rangle(\tau) \mathrm{d} \tau -$$ +```math +\langle i_L \rangle(t) = \langle i_L \rangle(t - \Delta t) + \int_{t - \Delta t}^t \frac{1}{L} \langle v_L \rangle(\tau) - j \omega \ \langle i_L \rangle(\tau) \mathrm{d} \tau +``` Applying the trapezoidal method leads to the finite difference equation: -$$ + +```math \begin{split} - \langle i_L \rangle(k) = \langle i_L \rangle(k-1) + \frac{\Delta t}{2} \bigg[ \frac{1}{L} (\langle v_L \rangle(k) + \langle v_L \rangle(k-1)) - - j \omega (\langle i_L \rangle(t) + \langle i_L \rangle(k-1) \bigg] + \langle i_L \rangle(k) = \langle i_L \rangle(k-1) + \frac{\Delta t}{2} \bigg[ \frac{1}{L} (\langle v_L \rangle(k) + \langle v_L \rangle(k-1)) + - j \omega (\langle i_L \rangle(t) + \langle i_L \rangle(k-1) \bigg] \end{split} -$$ +``` Solving this for $\langle i_L \rangle(k)$ results in the \ac{DP} equivalent circuit model: -$$ - \langle i_L \rangle(k) = \frac{a - jab}{1 + b^2} \langle v_L \rangle(k) + \langle i_{L,equiv} \rangle(k-1) -$$ + +```math +\langle i_L \rangle(k) = \frac{a - jab}{1 + b^2} \langle v_L \rangle(k) + \langle i_{L,equiv} \rangle(k-1) +``` + with -$$ - a = \frac{\Delta t}{2L}, \qquad b = \frac{\Delta t \omega}{2} -$$ -$$ - \langle i_{L,equiv} \rangle(k-1) = \frac{1 - b^2 - j2b}{1 + b^2} \langle i_L \rangle(k-1) + \frac{a - jab}{1 + b^2} \langle v_L \rangle(k-1) -$$ -### Capacitance +```math +a = \frac{\Delta t}{2L}, \qquad b = \frac{\Delta t \omega}{2} +``` + +```math +\langle i_{L,equiv} \rangle(k-1) = \frac{1 - b^2 - j2b}{1 + b^2} \langle i_L \rangle(k-1) + \frac{a - jab}{1 + b^2} \langle v_L \rangle(k-1) +``` + +## Capacitance Similarly, a capacitance is described by as follows -$$ - \langle i_C \rangle(k) = C \ \frac{\mathrm{d} \langle v_C \rangle}{\mathrm{d} t} + j \omega C \ \langle v_C \rangle(t) -$$ -$$ - v_C(t) = v_C(t- \Delta t) + \int_{t- \Delta t}^{t} \frac{1}{C} \ i_C(\tau) -j \omega \ v_C(\tau) \ \mathrm{d} \tau -$$ + +```math +\langle i_C \rangle(k) = C \ \frac{\mathrm{d} \langle v_C \rangle}{\mathrm{d} t} + j \omega C \ \langle v_C \rangle(t) +``` + +```math +v_C(t) = v_C(t- \Delta t) + \int_{t- \Delta t}^{t} \frac{1}{C} \ i_C(\tau) -j \omega \ v_C(\tau) \ \mathrm{d} \tau +``` Applying the trapezoidal rule for the capacitance equation leads to the finite difference equation: + ```math \begin{split} \langle v_C \rangle(k) = \langle v_C \rangle(k-1) + \frac{\Delta t}{2} \bigg[ \frac{1}{C} \ \langle i_C \rangle(k) - j \omega \ \langle v_C \rangle(k) \\ + \frac{1}{C} \ \langle i_C \rangle(k-1) - j \omega \ \langle v_C \rangle(k-1) \bigg] - \end{split} +\end{split} ``` The DP model for the capacitance is defined by -$$ - \langle i_C \rangle(k) = \frac{1+jb}{a} \ \langle v_C \rangle(k) + \langle i_{C,equiv} \rangle(k-1) -$$ + +```math +\langle i_C \rangle(k) = \frac{1+jb}{a} \ \langle v_C \rangle(k) + \langle i_{C,equiv} \rangle(k-1) +``` + with -$$ - a = \frac{\Delta t}{2C}, \qquad - b = \frac{\Delta t \omega}{2} -$$ -$$ - \langle i_{C,equiv} \rangle(k-1) = - \frac{1-jb}{a} \ \langle v_C \rangle(k-1) - \langle i_C \rangle(k-1) -$$ -### RL-series element +```math +a = \frac{\Delta t}{2C}, \qquad +b = \frac{\Delta t \omega}{2} +``` + +```math +\langle i_{C,equiv} \rangle(k-1) = - \frac{1-jb}{a} \ \langle v_C \rangle(k-1) - \langle i_C \rangle(k-1) +``` + +## RL-series element In dynamic phasors the integration of the inductance equation yields -$$ - \langle v \rangle(t) = L \frac{\mathrm{d}}{dt} \langle i \rangle(t) + j \omega L \ \langle i \rangle(t) + R \ \langle i \rangle(t) -$$ -$$ - \langle i \rangle(t) = \langle i \rangle(t - \Delta t) + \int_{t - \Delta t}^t \frac{1}{L} \langle v \rangle(\tau) - j \omega \ \langle i \rangle(\tau) - \frac{R}{L} \ \langle i \rangle(\tau) \mathrm{d} \tau -$$ + +```math +\langle v \rangle(t) = L \frac{\mathrm{d}}{dt} \langle i \rangle(t) + j \omega L \ \langle i \rangle(t) + R \ \langle i \rangle(t) +``` + +```math +\langle i \rangle(t) = \langle i \rangle(t - \Delta t) + \int_{t - \Delta t}^t \frac{1}{L} \langle v \rangle(\tau) - j \omega \ \langle i \rangle(\tau) - \frac{R}{L} \ \langle i \rangle(\tau) \mathrm{d} \tau +``` Applying the trapezoidal method leads to the finite difference equation: -$$ + +```math \begin{split} - \langle i \rangle(k) = \langle i \rangle(k-1) + \frac{\Delta t}{2} \bigg[ \frac{1}{L} (\langle v \rangle(k) + \langle v \rangle(k-1)) - - \left( j \omega + \frac{R}{L} \right) (\langle i \rangle(k) + \langle i \rangle(k-1)) \bigg] +\langle i \rangle(k) = \langle i \rangle(k-1) + \frac{\Delta t}{2} \bigg[ \frac{1}{L} (\langle v \rangle(k) + \langle v \rangle(k-1)) + - \left( j \omega + \frac{R}{L} \right) (\langle i \rangle(k) + \langle i \rangle(k-1)) \bigg] \end{split} -$$ +``` Solving this for $\langle i \rangle(k)$ results in the \ac{DP} equivalent circuit model: -$$ - \langle i \rangle(k) = \frac{a + Ra^2 - jab}{(1+Ra)^2 + b^2} \langle v \rangle(k) + \langle i_{equiv} \rangle(k-1) -$$ + +```math +\langle i \rangle(k) = \frac{a + Ra^2 - jab}{(1+Ra)^2 + b^2} \langle v \rangle(k) + \langle i_{equiv} \rangle(k-1) +``` + with -$$ - a = \frac{\Delta t}{2L}, \qquad b = \frac{\Delta t \omega}{2} -$$ -$$ - \langle i_{equiv} \rangle(k-1) = \frac{1 - b^2 - j2b + 2Ra + (Ra)^2 - j2Rab}{(1+Ra^2) + b^2} \langle i \rangle(k-1) + \frac{a + Ra^2 - jab}{(1+Ra)^2 + b^2} \langle v \rangle(k-1) -$$ + +```math +a = \frac{\Delta t}{2L}, \qquad b = \frac{\Delta t \omega}{2} +``` + +```math +\langle i_{equiv} \rangle(k-1) = \frac{1 - b^2 - j2b + 2Ra + (Ra)^2 - j2Rab}{(1+Ra^2) + b^2} \langle i \rangle(k-1) + \frac{a + Ra^2 - jab}{(1+Ra)^2 + b^2} \langle v \rangle(k-1) +``` diff --git a/docs/hugo/content/en/docs/Models/Synchronous Generator/index.md b/docs/hugo/content/en/docs/Models/Synchronous Generator/index.md index d711b19343..aca6e7a3cb 100644 --- a/docs/hugo/content/en/docs/Models/Synchronous Generator/index.md +++ b/docs/hugo/content/en/docs/Models/Synchronous Generator/index.md @@ -11,17 +11,19 @@ Two different synchronous machine models are currently available: The machine model is interfaced to the nodal analysis network solver through a current source, which only affects the source vector and not the system matrix [Wang2010](https://ieeexplore.ieee.org/document/5411963). -## Basic Equations +# Basic Equations The equations of the stator and rotor voltages are + ```math \begin{align} - \mathbf{v}_{abcs} &= \mathbf{R}_s \mathbf{i}_{abcs} + \frac{d}{dt} \boldsymbol{\lambda}_{abcs} \\ - \mathbf{v}_{dqr} &= \mathbf{R}_r \mathbf{i}_{dqr} + \frac{d}{dt} \boldsymbol{\lambda}_{dqr} + \mathbf{v}_{abcs} &= \mathbf{R}_s \mathbf{i}_{abcs} + \frac{d}{dt} \boldsymbol{\lambda}_{abcs} \\ + \mathbf{v}_{dqr} &= \mathbf{R}_r \mathbf{i}_{dqr} + \frac{d}{dt} \boldsymbol{\lambda}_{dqr} \end{align} ``` where + ```math \begin{align} \mathbf{v}_{abcs} &= @@ -67,20 +69,21 @@ where ``` The flux linkage equations are defined as + ```math \begin{equation} - \begin{bmatrix} - \boldsymbol{\lambda}_{abcs} \\ - \boldsymbol{\lambda}_{dqr} - \end{bmatrix} - = - \begin{bmatrix} - \mathbf{L}_s & \mathbf{L}_{rs} \\ - {(\mathbf{L}_{rs})}^{T} & \mathbf{L}_r - \end{bmatrix} - \begin{bmatrix} - \mathbf{i}_{abcs} \\ - \mathbf{i}_{dqr} + \begin{bmatrix} + \boldsymbol{\lambda}_{abcs} \\ + \boldsymbol{\lambda}_{dqr} + \end{bmatrix} + = + \begin{bmatrix} + \mathbf{L}_s & \mathbf{L}_{rs} \\ + {(\mathbf{L}_{rs})}^{T} & \mathbf{L}_r + \end{bmatrix} + \begin{bmatrix} + \mathbf{i}_{abcs} \\ + \mathbf{i}_{dqr} \end{bmatrix} \end{equation} ``` @@ -88,6 +91,7 @@ The flux linkage equations are defined as The inductance matrices are varying with the rotor position $\theta_r$ which varies with time. The mechanical equations are: + ```math \begin{align} \frac{d\theta_r}{dt} &= \omega_r \\ @@ -107,6 +111,7 @@ For stator referred variables, the base quantities for per unit are chosen as fo - $f_{base}$ rated frequency in Hz The synchronous generator equations in terms of per unit values in the rotor reference frame become: + ```math \begin{equation} \begin{bmatrix} @@ -132,7 +137,9 @@ The synchronous generator equations in terms of per unit values in the rotor ref \end{bmatrix} \end{equation} ``` + where + ```math \begin{align} \mathbf{v}_{dq0s} &= @@ -161,7 +168,9 @@ where \end{pmatrix}^T. \end{align} ``` + The flux linkages are: + ```math \begin{equation} \begin{pmatrix} @@ -179,7 +188,9 @@ The flux linkages are: \end{pmatrix} \end{equation} ``` + where + ```math \begin{align} \mathbf{L}_{dqss} &= @@ -213,7 +224,9 @@ where \end{bmatrix} \nonumber \\ \end{align} ``` + with + ```math \begin{align} L_{d} &= L_{ls} + L_{md} \nonumber \\ @@ -226,6 +239,7 @@ with ``` The mechanical equations in per unit become: + ```math \begin{align} T_e &= \lambda_{qs} i_{ds} - \lambda_{ds} i_{qs} \\ @@ -233,16 +247,20 @@ The mechanical equations in per unit become: \frac{1}{\omega_b} \frac{d \omega_r}{dt} &= \frac{1}{2H} (T_m - T_e). \end{align} ``` + For the simulation, fluxes are chosen as state variables. To avoid the calculation of currents from fluxes using the inverse of the inductance matrix, the equation set needs to be solved for the fluxes analytically. To simplify the calculations, dq axis magnetizing flux linkages are defined [Krause, Analysis of electric machinery and drive systems, 2002]: + ```math \begin{align} \lambda_{md} &= L_{md} \left( i_{ds} + i_{fd} + i_{kd} \right) \nonumber \\ \lambda_{mq} &= L_{mq} \left( i_{qs} + i_{kq1} + i_{kq2} \right) \end{align} ``` + Using the flux linkages results in a simpler equation set for the fluxes: + ```math \begin{align} \lambda_{ds} &= L_{ls} i_{ds} + L_{md} \left( i_{ds} + i_{fd} + i_{kd} \right) \nonumber \\ @@ -254,6 +272,7 @@ Using the flux linkages results in a simpler equation set for the fluxes: \lambda_{kq2} &= L_{ls} i_{kq2} + L_{mq} \left( i_{qs} + i_{kq1} + i_{kq2} \right) \end{align} ``` + ```math \begin{align} \lambda_{ds} &= L_{ls} i_{ds} + \lambda_{md} \nonumber \\ @@ -272,6 +291,7 @@ The fundamental dynamic phasors are similar to the dq0 quantities for symmetrica The network abc dynamic phasor quantities can be converted to dq0 dynamic phasors by applying the symmetrical components transformation and a rotation. The angle $\delta$ is the orientation of the dq0 reference frame relative to the abc frame. + ```math \begin{align} \langle i_{ds} \rangle_{0} &= \mathbf{Re} \left\{ \langle i_{p} \rangle_1 \ \mathrm{e}^{-j \delta} \right\} \nonumber \\ @@ -281,7 +301,9 @@ The angle $\delta$ is the orientation of the dq0 reference frame relative to the \langle i_{0s} \rangle_{1} &= \mathbf{Re} \left\{ \langle i_{z} \rangle_1 \right\} \end{align} ``` + The winding currents for positive and zero sequence components can be expressed as + ```math \begin{align} \langle i_{ds} \rangle_0 &= \frac{\langle \lambda_{ds} \rangle_0 - \langle \lambda_{md} \rangle_0 }{L_{ls}} \nonumber \\ @@ -293,6 +315,7 @@ The winding currents for positive and zero sequence components can be expressed \langle i_{kq2} \rangle_0 &= \frac{\langle \lambda_{kq2} \rangle_0 - \langle \lambda_{mq} \rangle_0}{L_{lkq2}}. \end{align} ``` + ```math \begin{align} \frac{d}{dt} \langle \lambda_{ds} \rangle_0 &= \langle v_{ds} \rangle_0 + \langle \omega_r \rangle_0 \langle \lambda_{qs} \rangle_0 + \frac{R_s}{L_{ls}} \left( \langle \lambda_{md} \rangle_0 - \langle \lambda_{ds} \rangle_0 \right) \nonumber \\ @@ -304,22 +327,28 @@ The winding currents for positive and zero sequence components can be expressed \frac{d}{dt} \langle \lambda_{kq2} \rangle_0 &= \frac{R_{kq2}}{L_{lkq2}} \left( \langle \lambda_{mq} \rangle_0 - \langle \lambda_{kq2} \rangle_0 \right). \end{align} ``` + In the dynamic phasor case, the equation for $\frac{d}{dt} \langle \lambda_{0s} \rangle_1$ has a frequency shift. To complete the state model, the magnetizing flux linkages are expressed as: + ```math \begin{align} \langle \lambda_{md} \rangle_0 &= L_{ad} \left( \frac{\langle \lambda_{ds} \rangle_0}{L_{ls}} + \frac{\langle \lambda_{fd} \rangle_0}{L_{lfd}} + \frac{\langle \lambda_{kd} \rangle_0}{L_{lkd}} \right) \nonumber \\ \langle \lambda_{mq} \rangle_0 &= L_{aq} \left( \frac{\langle \lambda_{qs} \rangle_0}{L_{ls}} + \frac{\langle \lambda_{kq1} \rangle_0}{L_{lkq1}} + \frac{\langle \lambda_{kq2} \rangle_0}{L_{lkq2}} \right) \end{align} ``` + where + ```math \begin{align} L_{ad} &= \left( \frac{1}{L_{md}} + \frac{1}{L_{ls}} + \frac{1}{L_{lfd}} + \frac{1}{L_{lkd}} \right) \nonumber \\ L_{aq} &= \left( \frac{1}{L_{mq}} + \frac{1}{L_{ls}} + \frac{1}{L_{lkq1}} + \frac{1}{L_{lkq2}} \right). \end{align} ``` + The mechanical equations in dynamic phasors are: + ```math \begin{align} T_e &= \langle \lambda_{qs} \rangle_0 \langle i_{ds} \rangle_0 - \langle \lambda_{ds} \rangle_0 \langle i_{qs} \rangle_0 \\ diff --git a/docs/hugo/content/en/docs/Models/Transformer/index.md b/docs/hugo/content/en/docs/Models/Transformer/index.md index 8762084cd4..56a331c27f 100644 --- a/docs/hugo/content/en/docs/Models/Transformer/index.md +++ b/docs/hugo/content/en/docs/Models/Transformer/index.md @@ -4,7 +4,8 @@ linkTitle: "Transformer" date: 2021-07-22 --- -## 2-Winding Transformer +# 2-Winding Transformer + The transformer model is composed of an RL-segment and an ideal transformer. The single line diagram is depicted in the figure below. diff --git a/docs/hugo/content/en/docs/Models/_index.md b/docs/hugo/content/en/docs/Models/_index.md index 2cbb1cb5fa..89f479905a 100644 --- a/docs/hugo/content/en/docs/Models/_index.md +++ b/docs/hugo/content/en/docs/Models/_index.md @@ -7,22 +7,23 @@ description: > --- The following models are currently available: + - Dynamic phasors - - inductor, capacitor, resistor - - current and voltage source - - load (PQ and Z type) - - pi-line - - transmission line (Bergeron) - - synchronous generator dq-frame full order (Kundur, Krause) - - inverter averaged - - inverter with harmonics (comparable to switched model) - - switch + - inductor, capacitor, resistor + - current and voltage source + - load (PQ and Z type) + - pi-line + - transmission line (Bergeron) + - synchronous generator dq-frame full order (Kundur, Krause) + - inverter averaged + - inverter with harmonics (comparable to switched model) + - switch - EMT - - inductor, capacitor, resistor - - current and voltage source - - load (Z type) - - pi-line - - transmission line (Bergeron) - - synchronous generator dq-frame full order (Kundur, Krause) - - inverter averaged - - switch + - inductor, capacitor, resistor + - current and voltage source + - load (Z type) + - pi-line + - transmission line (Bergeron) + - synchronous generator dq-frame full order (Kundur, Krause) + - inverter averaged + - switch diff --git a/docs/hugo/content/en/docs/Models/branches.md b/docs/hugo/content/en/docs/Models/branches.md index e3419eaeab..946237210b 100644 --- a/docs/hugo/content/en/docs/Models/branches.md +++ b/docs/hugo/content/en/docs/Models/branches.md @@ -4,8 +4,8 @@ linkTitle: "Branches" date: 2020-03-18 --- -## RX-Line +# RX-Line -## PI-Line +# PI-Line -## Transformer +# Transformer diff --git a/docs/hugo/content/en/docs/Overview/Architecture/index.md b/docs/hugo/content/en/docs/Overview/Architecture/index.md index da22567da7..30bce46db2 100644 --- a/docs/hugo/content/en/docs/Overview/Architecture/index.md +++ b/docs/hugo/content/en/docs/Overview/Architecture/index.md @@ -5,7 +5,7 @@ weight: 1 date: 2020-03-25 --- -## Modules and Dependencies +# Modules and Dependencies The figure below shows the main components of the DPsim library and their dependencies on other software projects. All functionality is implemented in the C++ core, which can be used standalone or together with the Python interface. @@ -35,7 +35,7 @@ Its main purpose will be offline simulation, for example, to provide reference r The component models depend mostly on the Eigen library. Even if components are used in combination with Sundials ODE / DAE solvers, we try to keep the specific functions required by these solvers independent of the Sundials package. -## Class Hierarchy +# Class Hierarchy The `Simulation` class holds references to instances of `Interface`, `Solver`, `Logger` and `SystemTopology`. For a simulation scenario, the minimum description would include a `SystemTopology` and a solver type. diff --git a/docs/hugo/content/en/docs/Overview/Attributes/index.md b/docs/hugo/content/en/docs/Overview/Attributes/index.md index 70c58aa223..8469ebb29c 100644 --- a/docs/hugo/content/en/docs/Overview/Attributes/index.md +++ b/docs/hugo/content/en/docs/Overview/Attributes/index.md @@ -18,7 +18,8 @@ Any simulation component or class which inherits from `IdentifiedObject` contain This list can be used to store all the attributes present in this component and later access them via a `String` instead of having to use the member variable directly. For reasons of code clarity and runtime safety, the member variables should still be used whenever possible. -## Creating and Storing Attributes +# Creating and Storing Attributes + Normally, a new attribute is created by using the `create` or `createDynamic` method of an `AttributeList` object. These two methods will create a new attribute of the given type and insert it into the `AttributeList` under the given name. After the name, `create` can take an additional parameter of type `T` which will be used as the initial value for this attribute. Afterwards, a pointer to the attribute is returned which can then be stored in a component's member variable. Usually this is done in the @@ -47,19 +48,20 @@ When a class has no access to an `AttributeList` object (for example the `Simula ```cpp // Simulation class -Simulation::Simulation(String name, Logger::Level logLevel) : - mName(AttributeStatic::make(name)), - mFinalTime(AttributeStatic::make(0.001)), - mTimeStep(AttributeStatic::make(0.001)), - mSplitSubnets(AttributeStatic::make(true)), - mSteadyStateInit(AttributeStatic::make(false)), - //... +Simulation::Simulation(String name, Logger::Level logLevel) : + mName(AttributeStatic::make(name)), + mFinalTime(AttributeStatic::make(0.001)), + mTimeStep(AttributeStatic::make(0.001)), + mSplitSubnets(AttributeStatic::make(true)), + mSteadyStateInit(AttributeStatic::make(false)), + //... { - // ... + // ... } ``` -## Working with Static Attributes +# Working with Static Attributes + As stated above, the value of a static attribute can only be changed through the attribute's `set`-method or by writing its value through a mutable reference obtained by calling `get`. This means that the value will not change between consecutive reads. Because of the performance benefits static attributes provide over dynamic attributes, attributes should be static whenever possible. @@ -73,6 +75,7 @@ Real& read3 = **attr; //read3 = 0.001 ``` The value of an attribute can be changed by either writing to the mutable reference obtained from `get`, or by calling the `set`-method: + ```cpp AttributeBase::Ptr attr = AttributeStatic::make(0.001); Real read1 = **attr; //read1 = 0.001 @@ -82,12 +85,14 @@ attr->set(0.003); Real read3 = **attr; //read3 = 0.003 ``` -## Working with Dynamic Attributes +# Working with Dynamic Attributes + In general, dynamic attributes can be accessed via the same `get` and `set`-methods described above for static attributes. However, dynamic attributes can additionally have **dependencies** on other attributes which affect the behavior of these methods. Usually, this is used to dynamically compute the attribute's value from the value of another attribute. In the simplest case, a dynamic attribute can be set to **reference** another (static or dynamic) attribute using the `setReference`-method. After this method has been called, the dynamic attribute's value will always reflect the value of the attribute it references: + ```cpp AttributeBase::Ptr attr1 = AttributeStatic::make(0.001); AttributeBase::Ptr attr2 = AttributeDynamic::make(); @@ -101,6 +106,7 @@ Real read2 = **attr2; //read2 = 0.002 When working with references between multiple dynamic attributes, the direction in which the references are defined can be important: References should always be set in such a way that the reference relationships form a one-way chain. Only the last attribute in such a reference chain (which itself does not reference anything) should be modified by external code (i.e. through mutable references or the `set`-method). This ensures that changes are always reflected in all attributes in the chain. For example, the following setup might lead to errors because it overwrites an existing reference: + ```cpp // Overwriting an existing reference relationship AttributeBase::Ptr A = AttributeDynamic::make(); @@ -130,18 +136,21 @@ C->setReference(B); // Current chain: C -> B -> A Aside from setting references, it is also possible to completely recompute a dynamic attribute's value every time it is read. This can for example be used to create attributes which reference a single matrix coefficient of another attribute, or which represent the magnitude or phase of a complex attribute. Dynamic attributes which depend on one other attribute in this way are also called **derived** attributes, and they can be created by calling one of the various `derive...` methods on the original attribute: + ```cpp AttributeBase::Ptr attr1 = AttributeStatic::make(Complex(3, 4)); AttributeBase::Ptr attr2 = attr1->deriveMag(); -Real read1 = **attr2; //read1 = 5 +Real read1 = **attr2; // read1 = 5 **attr1 = Complex(1, 0); -Real read2 = **attr2; //read2 = 1 +Real read2 = **attr2; // read2 = 1 ``` + There is also a general `derive`-method which can take a custom `getter` and `setter` lambda function for computing the derived attribute from its dependency. For more complex cases involving dependencies on multiple attributes, the `AttributeDynamic` class has a method called `addTask` which can be used to add arbitrary computation tasks which are executed when the attribute is read or written to. For more information, check the method comments in `Attribute.h`. -## Using Attributes for Logging and Interfacing +# Using Attributes for Logging and Interfacing + When setting up a simulation, there are some methods which require an instance of `AttributeBase::Ptr` as a parameter. Examples for this are the logger methods (e.g. `DataLogger::logAttribute`) and [interface]({{< ref "../interfaces.md" >}}) methods (e.g. `InterfaceVillas::exportAttribute`). To obtain the required attribute pointer, one can either directly access the public member variables of the component the attribute belongs to, or use the component's `attribute(String name)` method which will look up the attribute in the component's `AttributeList`: @@ -164,6 +173,7 @@ intf->exportAttribute(r1->mIntfVoltage->deriveCoeff(0, 0), 0, true); ``` When creating a simulation in Python, the component's member variables are usually not accessible, so the `attr`-method has to be used for all accesses: + ```python # dpsim-mqtt.py intf = dpsimpyvillas.InterfaceVillas(name='dpsim-mqtt', config=mqtt_config) @@ -171,7 +181,7 @@ intf.import_attribute(evs.attr('V_ref'), 0, True) intf.export_attribute(r12.attr('i_intf').derive_coeff(0, 0), 0) ``` -## Using Attributes to Schedule Tasks +# Using Attributes to Schedule Tasks Attributes are also used to determine dependencies of tasks on data, which is information required by the scheduler. For the usual `MNAPreStep` and `MNAPostStep` tasks, these dependencies are configured in the `mnaAddPreStepDependencies` and `mnaAddPostStepDependencies` methods: @@ -182,9 +192,10 @@ void DP::Ph1::Inductor::mnaAddPostStepDependencies( AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector ) { attributeDependencies.push_back(leftVector); - modifiedAttributes.push_back(mIntfVoltage); - modifiedAttributes.push_back(mIntfCurrent); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); } ``` + Here, the MNA post step depends on the solution vector of the system, `leftVector`, and modifies `mIntfVoltage` and `mIntfCurrent`. Therefore, this task needs to be scheduled after the system solution that computes `leftVector` and before tasks that require the voltage and current interface vectors of the inductance, e.g. the task logging these values. diff --git a/docs/hugo/content/en/docs/Overview/_index.md b/docs/hugo/content/en/docs/Overview/_index.md index 06e49d65bb..e754419a2a 100644 --- a/docs/hugo/content/en/docs/Overview/_index.md +++ b/docs/hugo/content/en/docs/Overview/_index.md @@ -12,11 +12,11 @@ Users interact with the C++ simulation kernel via Python bindings, which can be The DPsim simulation kernel is implemented in C++ and uses the Eigen linear algebra library. By using a system programming language like C++ and a highly optimized math library, optimal performance and real-time execution can be guaranteed. The integration into the [VILLASframework](https://github.com/VILLASframework/node) allows DPsim to be used in large-scale co-simulations. -## Licensing +# Licensing The project is released under the terms of the [MPL 2.0](https://mozilla.org/MPL/2.0/). -## Where should I go next? +# Where should I go next * [Getting Started]({{< ref "/docs/Getting Started/" >}} "Getting Started"): Get started with DPsim * [Examples]({{< ref "/docs/Examples/" >}} "Examples"): Check out some example code! diff --git a/docs/hugo/content/en/docs/Overview/interfaces.md b/docs/hugo/content/en/docs/Overview/interfaces.md index f1086cfa97..d8731b19da 100644 --- a/docs/hugo/content/en/docs/Overview/interfaces.md +++ b/docs/hugo/content/en/docs/Overview/interfaces.md @@ -10,7 +10,7 @@ Interfaces are subclasses of `Interface` and implement the methods `addExport` a This way, attributes that are imported are read from the interface before they are used in any DPsim component. Attributes that are exported are written to the interface after they are set by a DPsim component. -## Interfacing with VILLASnode +# Interfacing with VILLASnode > This feature requires the compilation of DPsim with the `WITH_VILLAS` feature flag. For use of the VILLASnode interface in python, the `dpsimpyvillas` target has to built in addition to the normal `dpsimpy` package. @@ -38,6 +38,7 @@ The attributes given as the first parameter to these methods are attributes belo As an example, for exporting and importing attributes via the MQTT protocol, the VILLASnode interfaces can be configured as follows: Using C++: + ```cpp // JSON configuration adhering to the VILLASnode documentation std::string mqttConfig = R"STRING({ @@ -61,6 +62,7 @@ intf->exportAttribute(r12->mIntfCurrent->deriveCoeff(0, 0), 1, true, "v ``` Using Python: + ```python # JSON configuration adhering to the VILLASnode documentation mqtt_config = '''{ @@ -83,8 +85,10 @@ intf.import_attribute(evs.attr('V_ref'), 0, True) intf.export_attribute(r12.attr('i_intf').derive_coeff(0, 0), 0) ``` -## Adding an Interface to the Simulation +# Adding an Interface to the Simulation + After a new interface has been created and configured, it can be added to a simulation using the `Simulation::addInterface` method: + ```cpp // Create and configure simulation RealTimeSimulation sim(simName); @@ -105,11 +109,13 @@ Note that the execution of these tasks might not necessarily coincide with the p This is because the interface internally spawns two new threads for exchanging data with the environment and then uses a **lock-free queue** for communication between these reader and writer threads, and the simulation. Because of this, time-intensive import or export operations will not block the main simulation thread unless this is explicitly configured in the interface's `importAttribute` and `exportAttribute` methods. -## Synchronizing the Simulation with the Environment +# Synchronizing the Simulation with the Environment + To allow for synchronizing the DPsim simulation with external services, the `Interface` class provides some additional configuration options in the `importAttribute` and `exportAttribute` methods. For imports, setting the `blockOnRead` parameter will completely halt the simulation at the start of every time step until a new value for this attribute was read from the environment. Additionally, the `syncOnSimulationStart` parameter can be set for every import to indicate that this attribute is used to synchronize the start of the simulation. When a simulation contains any interfaces importing attributes which have `syncOnSimulationStart` set, the `Simulation::sync` will be called before the first time step. This method will: + - write out all attributes configured for export to the environment - block until all attributes with `syncOnSimulationStart` set have been read from the environment at least once - write out all exported attributes again diff --git a/docs/hugo/content/en/docs/Overview/mnainterface.md b/docs/hugo/content/en/docs/Overview/mnainterface.md index d7a2d5a527..21eb04e1c3 100644 --- a/docs/hugo/content/en/docs/Overview/mnainterface.md +++ b/docs/hugo/content/en/docs/Overview/mnainterface.md @@ -26,9 +26,10 @@ virtual void mnaCompApplySystemMatrixStampHarm(SparseMatrixRow& systemMatrix, In virtual void mnaCompApplyRightSideVectorStampHarm(Matrix& sourceVector); virtual void mnaCompApplyRightSideVectorStampHarm(Matrix& sourceVector, Int freqIdx); ``` + `MNASimPowerComp` provides empty default implementations for all of these methods, so component classes are not forced to implement any of them. -## Controlling Common Base Class Behavior +# Controlling Common Base Class Behavior Child component classes can control the behavior of the base class through the constructor arguments of `MNASimPowerComp`. The two boolean variables `hasPreStep` and `hasPostStep` can be used to control whether the `MNAPreStep` and `MNAPostStep` tasks will be created and registered. @@ -40,10 +41,10 @@ If this behavior is not desired, e.g. for resistors which have no influence on t ```cpp void DP::Ph1::Resistor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { - updateMatrixNodeIndices(); + updateMatrixNodeIndices(); - **mRightVector = Matrix::Zero(0, 0); - //... + **mRightVector = Matrix::Zero(0, 0); + //... } ``` diff --git a/docs/hugo/content/en/docs/Overview/subcomponents.md b/docs/hugo/content/en/docs/Overview/subcomponents.md index 600cc1e532..936bbdeb1e 100644 --- a/docs/hugo/content/en/docs/Overview/subcomponents.md +++ b/docs/hugo/content/en/docs/Overview/subcomponents.md @@ -7,7 +7,8 @@ date: 2022-12-14 In DPsim, there are many components which can be broken down into individual subcomponents. Examples are the `PiLine`, consisting of an inductor, three resistors, and two capacitors, or the `NetworkInjection` which contains a voltage source. On the C++ class level, these subcomponents are represented by member variables within the larger component class. In this guide, all components which have subcomponents are called **composite components**. -## Creating Composite Components +# Creating Composite Components + While normal components are usually subclasses of `SimPowerComp` or `MNASimPowerComp`, there exists a special base class for composite components called `CompositePowerComp`. This class provides multiple methods and parameters for configuring how the subcomponents should be handled with respect to the `MNAPreStep` and `MNAPostStep` tasks. @@ -17,39 +18,41 @@ be set to automatically create and register a `MNAPreStep` or `MNAPostStep` task Additionally, all subcomponents should be registered as soon as they are created using the `addMNASubComponent`-method. This method takes multiple parameters defining how and in what order the subcomponent's pre- and post- steps should be called, as well as if the subcomponent should be stamped into the system `rightVector`: + ```cpp // DP_Ph1_PiLine.cpp DP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) - : Base::Ph1::PiLine(mAttributes), - // Call the constructor of CompositePowerComp and enable automatic pre- and post-step creation - CompositePowerComp(uid, name, true, true, logLevel) + : Base::Ph1::PiLine(mAttributes), + // Call the constructor of CompositePowerComp and enable automatic pre- and post-step creation + CompositePowerComp(uid, name, true, true, logLevel) { - //... + //... } void DP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { - //... - // Create series sub components - mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); + //... + // Create series sub components + mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); - // Setup mSubSeriesResistor... + // Setup mSubSeriesResistor... - // Register the resistor as a subcomponent. The resistor's pre- and post-step will be called before the pre- and post-step of the parent, - // and the resistor does not contribute to the `rightVector`. - addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + // Register the resistor as a subcomponent. The resistor's pre- and post-step will be called before the pre- and post-step of the parent, + // and the resistor does not contribute to the `rightVector`. + addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); - mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); + mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); - // Setup mSubSeriesInductor... + // Setup mSubSeriesInductor... - // Register the inductor as a subcomponent. The inductor's pre- and post-step will be called before the pre- and post-step of the parent, - // and the inductor does contribute to the `rightVector`. - addMNASubComponent(mSubSeriesInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - //... + // Register the inductor as a subcomponent. The inductor's pre- and post-step will be called before the pre- and post-step of the parent, + // and the inductor does contribute to the `rightVector`. + addMNASubComponent(mSubSeriesInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + //... } ``` -## Orchestrating MNA Method Calls +# Orchestrating MNA Method Calls + By choosing which methods to override in the composite component class, subcomponent handling can either be offloaded to the `CompositePowerComp` base class or manually implemented in the new component class. By default, `CompositePowerComp` provides all methods demanded by `MNAInterface` in such a way that the subcomponents' MNA-methods are properly called. To also allow for the composite component class to perform further actions in these MNA-methods, there exist multiple methods prefixed with `mnaParent`, e.g. `mnaParentPreStep` or `mnaParentAddPostStepDependencies`. @@ -63,21 +66,23 @@ so the subcomponent method calls have to be performed explicitly if desired. Giv ```cpp void DP::Ph1::PiLine::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { - // only add the dependencies of the composite component, the subcomponent's dependencies are handled by the base class - prevStepDependencies.push_back(mIntfCurrent); - prevStepDependencies.push_back(mIntfVoltage); - modifiedAttributes.push_back(mRightVector); + // Only add the dependencies of the composite component, the subcomponent's dependencies are handled by the base class + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); } ``` + ```cpp void DP::Ph1::PiLine::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { - // manually add pre-step dependencies of subcomponents - for (auto subComp : mSubcomponentsMNA) { - subComp->mnaAddPreStepDependencies(prevStepDependencies, attributeDependencies, modifiedAttributes); - } - // add pre-step dependencies of component itself - prevStepDependencies.push_back(mIntfCurrent); - prevStepDependencies.push_back(mIntfVoltage); - modifiedAttributes.push_back(mRightVector); + // Manually add pre-step dependencies of subcomponents + for (auto subComp : mSubcomponentsMNA) { + subComp->mnaAddPreStepDependencies(prevStepDependencies, attributeDependencies, modifiedAttributes); + } + + // Add pre-step dependencies of component itself + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); } ``` diff --git a/docs/hugo/content/en/docs/Roadmap/index.md b/docs/hugo/content/en/docs/Roadmap/index.md index 221130655e..d246a0eae2 100644 --- a/docs/hugo/content/en/docs/Roadmap/index.md +++ b/docs/hugo/content/en/docs/Roadmap/index.md @@ -8,28 +8,28 @@ Short-term planning for new features is done on the GitHub [Project board](https You can also check the [Issues List](https://github.com/sogno-platform/dpsim/issues) or the [Pull Requests](https://github.com/sogno-platform/dpsim/pulls) on GitHub. -### Under Development +# Under Development - Solver - - [ ] CUDA sparse implementation - - [ ] improve online system matrix computation and refactorization to support nonlinear elements in network solution (NICSLU integration) - - [x] merge DAE solver branch + - [ ] CUDA sparse implementation + - [ ] improve online system matrix computation and refactorization to support nonlinear elements in network solution (NICSLU integration) + - [x] merge DAE solver branch - Interfaces - - [x] reimplement python interface using pybind and expose more models / functionalities - - [x] add python based examples using the VILLASnode interface - - [x] support matpower / pypower format for static simulation + - [x] reimplement python interface using pybind and expose more models / functionalities + - [x] add python based examples using the VILLASnode interface + - [x] support matpower / pypower format for static simulation - Tests, Examples, CI - - [x] convert most of the examples to Python and test them against reference results in CI - - [x] convert more gitlab CI jobs to github actions - - [ ] add IEEE39 system to examples + - [x] convert most of the examples to Python and test them against reference results in CI + - [x] convert more gitlab CI jobs to github actions + - [ ] add IEEE39 system to examples - Models - - [x] VBR generator model - - [ ] SVC - - [ ] add tap-change to transfomer + - [x] VBR generator model + - [ ] SVC + - [ ] add tap-change to transfomer -### Ideas +# Ideas - Solver - - [ ] improve integration of diakoptics solver + - [ ] improve integration of diakoptics solver - Interfaces - - [ ] implement CIM reader in Python using new pybind interface and cimpy library + - [ ] implement CIM reader in Python using new pybind interface and cimpy library diff --git a/docs/hugo/content/en/docs/Tasks/add-model.md b/docs/hugo/content/en/docs/Tasks/add-model.md index 0c47fd8f55..18ea03e195 100644 --- a/docs/hugo/content/en/docs/Tasks/add-model.md +++ b/docs/hugo/content/en/docs/Tasks/add-model.md @@ -7,11 +7,11 @@ description: > Extending the simulator with new component or control models. --- -## Add a Component Model +# Add a Component Model In this section we will show the implementation of a new component model by means a three-phase dynamic phasor inductor model. -### C++ OOP +## C++ OOP DPsim implements component models in a sub project called CPowerSystems (CPS) that is located in the *models* folder. This folder is added to the DPsim CMake project. @@ -21,7 +21,7 @@ DPsim supports different types of solvers (MNA, DAE, NRP). Each solver requires certain member functions in the component class to be implemented. These functions are specified by the solver interface classes: ``MNAInterface.h``, ``DAEInterface.h``, etc. -### Directory / Namespace Structure +## Directory / Namespace Structure For the implementation of the new component, we add two new files @@ -33,40 +33,44 @@ The general structure looks as follows. Directories: - DPsim - | - |- Source - |- Include - \ models - |- Source - |- DP - |- EMT - |- Static - \ Signal - |- Include - |- DP - |- EMT - |- Static - \ Signal +```text +DPsim + | + |- Source + |- Include + \ models + |- Source + |- DP + |- EMT + |- Static + \ Signal + |- Include + |- DP + |- EMT + |- Static + \ Signal +``` Namespaces: - CPS::{DP,EMT,Static,Signal}::{Ph1,Ph3}::{Name} +```cpp +CPS::{DP,EMT,Static,Signal}::{Ph1,Ph3}::{Name} +``` -### Attributes +## Attributes Each components has a list of attributes, which has to be specified when creating the components class. TODO: explain attribute system -### Tasks for Pre/Post-step Functions +## Tasks for Pre/Post-step Functions TODO: add example task dependency graph -### Adding the new Component to DPsim +## Adding the new Component to DPsim After finishing the implementation of the new component, it needs to be added to the following files: -- ``models/Include/cps/Components.h`` -- ``models/Source/CMakeLists.txt`` -- ``Sources/Python/Module.cpp`` +- `models/Include/cps/Components.h` +- `models/Source/CMakeLists.txt` +- `Sources/Python/Module.cpp` diff --git a/docs/hugo/content/en/docs/Tasks/create-simulation.md b/docs/hugo/content/en/docs/Tasks/create-simulation.md index 5e1a1a7c75..523408fe67 100644 --- a/docs/hugo/content/en/docs/Tasks/create-simulation.md +++ b/docs/hugo/content/en/docs/Tasks/create-simulation.md @@ -8,33 +8,39 @@ description: > Here, we will show the implementation of a new simulation scenario defined in C++, which is using DPsim as a library. -## Directory Structure +# Directory Structure In the end, your directory structure should look like as follows: - my-project - |- CMakeLists.txt - |- source - |- my-scenario.cpp - |- dpsim (as submodule) +```text +my-project + |- CMakeLists.txt + |- source + |- my-scenario.cpp + |- dpsim (as submodule) +``` -## CMake File +# CMake File -Your CMakeLists could look like this: +Your `CMakeLists.txt` could look like this: - cmake_minimum_required(VERSION 3.5) - project(my-project CXX) +```cmake +cmake_minimum_required(VERSION 3.5) +project(my-project CXX) - add_subdirectory(dpsim) +add_subdirectory(dpsim) - add_executable(my-scenario source/my-scenario.cpp) - target_link_libraries(my-scenario dpsim) +add_executable(my-scenario source/my-scenario.cpp) +target_link_libraries(my-scenario dpsim) +``` -## Build the Project +# Build the Project The build process is similar to the one of DPsim: - $ cd my-project - $ mkdir build && cd build - $ cmake .. - $ make my-scenario +```shell +cd my-project +mkdir build && cd build +cmake .. +make my-scenario +``` diff --git a/docs/hugo/content/en/docs/_index.md b/docs/hugo/content/en/docs/_index.md index 1903e5849b..0dd1b6ec5c 100644 --- a/docs/hugo/content/en/docs/_index.md +++ b/docs/hugo/content/en/docs/_index.md @@ -17,25 +17,23 @@ DPsim is a solver library for dynamic power system simulation. - It can load models in the IEC61970 Common Information Model (CIM) / Common Grid Model Exchange Standard (CGMES) XML format. - It can be interfaced to a variety of protocols and interfaces via [VILLASnode](https://fein-aachen.org/projects/villas-node/). - -## Connect +# Connect Using or want to use DPsim? Find out more here: [LF Energy Slack](https://slack.lfenergy.org/) - Chat with other users and developers and get help in the **#sogno** or **#sogno-dpsim** channel. -You can also send a direct message to +You can also send a direct message to: + - Markus Mirz - Jan Dinkelbach - Steffen Vogel - -## Contribute +# Contribute If you want to get more involved by contributing to DPsim, please send us a Pull Request on [GitHub](https://github.com/sogno-platform/dpsim). - -## Publications +# Publications If you are using DPsim for your research, please cite one of the following papers in your publications: From 5105f7f287b2b43354e412c155da8edf4d5523c5 Mon Sep 17 00:00:00 2001 From: Georgii Tishenin Date: Wed, 16 Apr 2025 17:17:00 +0200 Subject: [PATCH 071/168] Declare nominal/base voltages as Real instead of Attribute Signed-off-by: Georgii Tishenin --- .../dpsim-models/Base/Base_Ph1_Transformer.h | 20 +++++------ .../SP/SP_Ph1_AvVoltageSourceInverterDQ.h | 9 +++-- .../include/dpsim-models/SP/SP_Ph1_Load.h | 6 ++-- .../dpsim-models/SP/SP_Ph1_NetworkInjection.h | 4 ++- .../include/dpsim-models/SP/SP_Ph1_PiLine.h | 9 +++-- .../include/dpsim-models/SP/SP_Ph1_RXLine.h | 9 +++-- .../SP/SP_Ph1_SynchronGenerator.h | 5 +-- .../dpsim-models/SP/SP_Ph1_Transformer.h | 5 ++- dpsim-models/src/DP/DP_Ph1_Transformer.cpp | 18 +++++----- .../SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp | 5 +-- dpsim-models/src/SP/SP_Ph1_Load.cpp | 15 ++++---- .../src/SP/SP_Ph1_NetworkInjection.cpp | 11 +++--- dpsim-models/src/SP/SP_Ph1_PiLine.cpp | 11 +++--- dpsim-models/src/SP/SP_Ph1_RXLine.cpp | 8 ++--- .../src/SP/SP_Ph1_SynchronGenerator.cpp | 8 +++-- dpsim-models/src/SP/SP_Ph1_Transformer.cpp | 34 ++++++++++++------- 16 files changed, 105 insertions(+), 72 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Base/Base_Ph1_Transformer.h b/dpsim-models/include/dpsim-models/Base/Base_Ph1_Transformer.h index acd208c52d..9bd2c89488 100644 --- a/dpsim-models/include/dpsim-models/Base/Base_Ph1_Transformer.h +++ b/dpsim-models/include/dpsim-models/Base/Base_Ph1_Transformer.h @@ -15,11 +15,13 @@ namespace CPS { namespace Base { namespace Ph1 { class Transformer { -public: +protected: /// Nominal voltage of primary side - const Attribute::Ptr mNominalVoltageEnd1; + Real mNominalVoltageEnd1; /// Nominal voltage of secondary side - const Attribute::Ptr mNominalVoltageEnd2; + Real mNominalVoltageEnd2; + +public: /// Rated Apparent Power [VA] const Attribute::Ptr mRatedPower; /// Complex transformer ratio @@ -30,20 +32,16 @@ class Transformer { const Attribute::Ptr mInductance; explicit Transformer(CPS::AttributeList::Ptr attributeList) - : mNominalVoltageEnd1( - attributeList->create("nominal_voltage_end1")), - mNominalVoltageEnd2( - attributeList->create("nominal_voltage_end2")), - mRatedPower(attributeList->create("S")), + : mRatedPower(attributeList->create("S")), mRatio(attributeList->create("ratio")), mResistance(attributeList->create("R")), - mInductance(attributeList->create("L")){}; + mInductance(attributeList->create("L")) {}; /// void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance) { - **mNominalVoltageEnd1 = nomVoltageEnd1; - **mNominalVoltageEnd2 = nomVoltageEnd2; + mNominalVoltageEnd1 = nomVoltageEnd1; + mNominalVoltageEnd2 = nomVoltageEnd2; **mRatio = std::polar(ratioAbs, ratioPhase); **mResistance = resistance; **mInductance = inductance; diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h index 481a915bc3..32c52e3423 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h @@ -25,6 +25,9 @@ class AvVoltageSourceInverterDQ : public CompositePowerComp, public Base::AvVoltageSourceInverterDQ, public SharedFactory { +private: + /// Nominal voltage + Real mVnom; protected: // ### General Parameters ### /// Nominal system angle @@ -65,8 +68,6 @@ class AvVoltageSourceInverterDQ // ### General Parameters ### /// Nominal frequency const Attribute::Ptr mOmegaN; - /// Nominal voltage - const Attribute::Ptr mVnom; /// Active power reference const Attribute::Ptr mPref; /// Reactive power reference @@ -127,6 +128,10 @@ class AvVoltageSourceInverterDQ Real gamma_qInit); void withControl(Bool controlOn) { mWithControl = controlOn; }; + // #### Powerflow section #### + /// Get nominal voltage + Real getNomVoltage() const; + // #### MNA section #### /// Initializes internal variables of the component void mnaParentInitialize(Real omega, Real timeStep, diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Load.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Load.h index 0a27f08750..e8749a6b46 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Load.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Load.h @@ -25,8 +25,6 @@ class Load : public CompositePowerComp, public SharedFactory, public PFSolverInterfaceBus { public: - /// Nominal voltage [V] - const Attribute::Ptr mNomVoltage; /// Active power [Watt] const Attribute::Ptr mActivePower; /// Reactive power [VAr] @@ -37,6 +35,8 @@ class Load : public CompositePowerComp, const Attribute::Ptr mReactivePowerPerUnit; private: + /// Nominal voltage [V] + Real mNomVoltage; /// base apparent power[VA] Real mBaseApparentPower; ///base omega [1/s] @@ -79,6 +79,8 @@ class Load : public CompositePowerComp, void updatePQ(Real time); // #### Powerflow section #### + /// Get nominal voltage + Real getNomVoltage() const; /// Calculates component's parameters in specified per-unit system void calculatePerUnitParameters(Real baseApparentPower, Real baseOmega); /// Modify powerflow bus type diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h index bf99c32006..ee8220b47f 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_NetworkInjection.h @@ -39,7 +39,7 @@ class NetworkInjection : public CompositePowerComp, // #### Powerflow section #### /// Base voltage [V] - const Attribute::Ptr mBaseVoltage; + Real mBaseVoltage; public: const Attribute::Ptr mVoltageRef; @@ -71,6 +71,8 @@ class NetworkInjection : public CompositePowerComp, // #### Powerflow section #### /// Set parameters relevant for PF solver void setParameters(Real vSetPointPerUnit); + // Get base voltage + Real getBaseVoltage() const; /// Set base voltage void setBaseVoltage(Real baseVoltage); /// Calculates component's parameters in specified per-unit system diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine.h index f99d2e5fb7..5bd3aa6993 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine.h @@ -28,10 +28,11 @@ class PiLine : public CompositePowerComp, public MNATearInterface, public SharedFactory, public PFSolverInterfaceBranch { -public: - ///base voltage [V] - const Attribute::Ptr mBaseVoltage; +private: + /// base voltage [V] + Real mBaseVoltage; +public: // #### Power flow results #### /// branch Current flow [A], coef(0) has data from node 0, coef(1) from node 1. const Attribute::Ptr mCurrent; @@ -106,6 +107,8 @@ class PiLine : public CompositePowerComp, void initializeFromNodesAndTerminals(Real frequency) override; // #### Powerflow section #### + /// Get base voltage + Real getBaseVoltage() const; /// Set base voltage void setBaseVoltage(Real baseVoltage); /// Calculates component's parameters in specified per-unit system diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_RXLine.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_RXLine.h index 37ac353e77..65735b3425 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_RXLine.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_RXLine.h @@ -22,6 +22,10 @@ class RXLine : public CompositePowerComp, public SharedFactory, public PFSolverInterfaceBranch, public Base::Ph1::PiLine { +private: + ///base voltage [V] + Real mBaseVoltage; + protected: /// CHECK: Which of these really need to be member variables? ///Capacitance of the line in [F] @@ -59,8 +63,6 @@ class RXLine : public CompositePowerComp, std::shared_ptr mInitialResistor; public: - ///base voltage [V] - const Attribute::Ptr mBaseVoltage; ///Inductance of the line in [H] /// CHECK: Why does this not use the base class' attribute mSeriesInd? const Attribute::Ptr mInductance; @@ -100,9 +102,10 @@ class RXLine : public CompositePowerComp, void transformParametersToPerUnitSystem(); // #### Powerflow section #### + /// Get base voltage + Real getBaseVoltage() const; /// Stamps admittance matrix void pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow &Y) override; - /// updates branch current and power flow, input pu value, update with real value void updateBranchFlow(VectorComp ¤t, VectorComp &powerflow); /// stores nodal injection power in this line object diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGenerator.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGenerator.h index 30ad1c09f9..332bb0cb15 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGenerator.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_SynchronGenerator.h @@ -20,6 +20,8 @@ class SynchronGenerator : public SimPowerComp, public SharedFactory, public PFSolverInterfaceBus { private: + /// Base voltage [V] + Real mBaseVoltage; /// Base apparent power[VA] Real mBaseApparentPower; @@ -30,8 +32,6 @@ class SynchronGenerator : public SimPowerComp, const Attribute::Ptr mSetPointReactivePower; /// Voltage set point of the machine [V] const Attribute::Ptr mSetPointVoltage; - /// Base voltage [V] - const Attribute::Ptr mBaseVoltage; /// Active power set point of the machine [pu] const Attribute::Ptr mSetPointActivePowerPerUnit; /// Reactive power set point of the machine [pu] @@ -51,6 +51,7 @@ class SynchronGenerator : public SimPowerComp, PowerflowBusType powerflowBusType, Real setPointReactivepower = 0); // #### Powerflow section #### + Real getBaseVoltage() const; /// Set base voltage void setBaseVoltage(Real baseVoltage); /// Initializes component from power flow data diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer.h index 99b6642453..65b9f63ba6 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer.h @@ -134,7 +134,10 @@ class Transformer : public CompositePowerComp, void initializeFromNodesAndTerminals(Real frequency) override; // #### Powerflow section #### - /// Set base voltage + /// Get nominal voltage at end 1 + Real getNominalVoltageEnd1() const; + /// Get nominal voltage at end 2 + Real getNominalVoltageEnd2() const; void setBaseVoltage(Real baseVoltage); /// Initializes component from power flow data void calculatePerUnitParameters(Real baseApparentPower, Real baseOmega); diff --git a/dpsim-models/src/DP/DP_Ph1_Transformer.cpp b/dpsim-models/src/DP/DP_Ph1_Transformer.cpp index b8b1084731..60f4d9003d 100644 --- a/dpsim-models/src/DP/DP_Ph1_Transformer.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Transformer.cpp @@ -30,7 +30,7 @@ DP::Ph1::Transformer::Transformer(String uid, String name, /// DEPRECATED: Delete method SimPowerComp::Ptr DP::Ph1::Transformer::clone(String name) { auto copy = Transformer::make(name, mLogLevel); - copy->setParameters(**mNominalVoltageEnd1, **mNominalVoltageEnd2, + copy->setParameters(mNominalVoltageEnd1, mNominalVoltageEnd2, std::abs(**mRatio), std::arg(**mRatio), **mResistance, **mInductance); return copy; @@ -47,7 +47,7 @@ void DP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, SPDLOG_LOGGER_INFO( mSLog, "Nominal Voltage End 1={} [V] Nominal Voltage End 2={} [V]", - **mNominalVoltageEnd1, **mNominalVoltageEnd2); + mNominalVoltageEnd1, mNominalVoltageEnd2); SPDLOG_LOGGER_INFO( mSLog, "Resistance={} [Ohm] Inductance={} [Ohm] (referred to primary side)", @@ -81,14 +81,14 @@ void DP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { std::shared_ptr> tmp = mTerminals[0]; mTerminals[0] = mTerminals[1]; mTerminals[1] = tmp; - Real tmpVolt = **mNominalVoltageEnd1; - **mNominalVoltageEnd1 = **mNominalVoltageEnd2; - **mNominalVoltageEnd2 = tmpVolt; + Real tmpVolt = mNominalVoltageEnd1; + mNominalVoltageEnd1 = mNominalVoltageEnd2; + mNominalVoltageEnd2 = tmpVolt; SPDLOG_LOGGER_INFO(mSLog, "Switching terminals to have first terminal at " "higher voltage side. Updated parameters: "); SPDLOG_LOGGER_INFO( mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]", - **mNominalVoltageEnd1, **mNominalVoltageEnd2); + mNominalVoltageEnd1, mNominalVoltageEnd2); SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", std::abs(**mRatio), std::arg(**mRatio)); } @@ -130,7 +130,7 @@ void DP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { Real qSnub = Q_SNUB_TRANSFORMER * **mRatedPower; // A snubber conductance is added on the higher voltage side - mSnubberResistance1 = std::pow(std::abs(**mNominalVoltageEnd1), 2) / pSnub; + mSnubberResistance1 = std::pow(std::abs(mNominalVoltageEnd1), 2) / pSnub; mSubSnubResistor1 = std::make_shared(**mName + "_snub_res1", mLogLevel); mSubSnubResistor1->setParameters(mSnubberResistance1); @@ -144,7 +144,7 @@ void DP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); // A snubber conductance is added on the lower voltage side - mSnubberResistance2 = std::pow(std::abs(**mNominalVoltageEnd2), 2) / pSnub; + mSnubberResistance2 = std::pow(std::abs(mNominalVoltageEnd2), 2) / pSnub; mSubSnubResistor2 = std::make_shared(**mName + "_snub_res2", mLogLevel); mSubSnubResistor2->setParameters(mSnubberResistance2); @@ -167,7 +167,7 @@ void DP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { // A snubber capacitance is added to lower voltage side mSnubberCapacitance2 = - qSnub / std::pow(std::abs(**mNominalVoltageEnd2), 2) / omega; + qSnub / std::pow(std::abs(mNominalVoltageEnd2), 2) / omega; mSubSnubCapacitor2 = std::make_shared(**mName + "_snub_cap2", mLogLevel); mSubSnubCapacitor2->setParameters(mSnubberCapacitance2); diff --git a/dpsim-models/src/SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp b/dpsim-models/src/SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp index cc0d5cf31b..653a5c2eea 100644 --- a/dpsim-models/src/SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp +++ b/dpsim-models/src/SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp @@ -14,7 +14,6 @@ SP::Ph1::AvVoltageSourceInverterDQ::AvVoltageSourceInverterDQ( String uid, String name, Logger::Level logLevel, Bool withTrafo) : CompositePowerComp(uid, name, true, true, logLevel), mOmegaN(mAttributes->create("Omega_nom")), - mVnom(mAttributes->create("vnom")), mPref(mAttributes->create("P_ref")), mQref(mAttributes->create("Q_ref")), mVcd(mAttributes->create("Vc_d", 0)), @@ -107,7 +106,7 @@ void SP::Ph1::AvVoltageSourceInverterDQ::setParameters(Real sysOmega, mPowerControllerVSI->setParameters(Pref, Qref); **mOmegaN = sysOmega; - **mVnom = sysVoltNom; + mVnom = sysVoltNom; **mPref = Pref; **mQref = Qref; } @@ -295,6 +294,8 @@ void SP::Ph1::AvVoltageSourceInverterDQ::initializeFromNodesAndTerminals( SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization from powerflow finished ---"); } +Real SP::Ph1::AvVoltageSourceInverterDQ::getNomVoltage() const { return mVnom; } + void SP::Ph1::AvVoltageSourceInverterDQ::mnaParentInitialize( Real omega, Real timeStep, Attribute::Ptr leftVector) { mTimeStep = timeStep; diff --git a/dpsim-models/src/SP/SP_Ph1_Load.cpp b/dpsim-models/src/SP/SP_Ph1_Load.cpp index ef4b8ccddf..4c25f2805e 100644 --- a/dpsim-models/src/SP/SP_Ph1_Load.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Load.cpp @@ -20,9 +20,8 @@ SP::Ph1::Load::Load(String uid, String name, Logger::Level logLevel) mActivePower(mAttributes->createDynamic( "P")), //Made dynamic so it can be imported through InterfaceVillas mReactivePower(mAttributes->createDynamic( - "Q")), //Made dynamic so it can be imported through InterfaceVillas - mNomVoltage(mAttributes->create("V_nom")) { - + "Q")) //Made dynamic so it can be imported through InterfaceVillas +{ SPDLOG_LOGGER_INFO(mSLog, "Create {} of type {}", **mName, this->type()); mSLog->flush(); **mIntfVoltage = MatrixComp::Zero(1, 1); @@ -34,18 +33,20 @@ void SP::Ph1::Load::setParameters(Real activePower, Real reactivePower, Real nominalVoltage) { **mActivePower = activePower; **mReactivePower = reactivePower; - **mNomVoltage = nominalVoltage; + mNomVoltage = nominalVoltage; SPDLOG_LOGGER_INFO( mSLog, "Active Power={} [W] Reactive Power={} [VAr] Nominal Voltage={} [V]", - **mActivePower, **mReactivePower, **mNomVoltage); + **mActivePower, **mReactivePower, mNomVoltage); mSLog->flush(); mParametersSet = true; } // #### Powerflow section #### +Real SP::Ph1::Load::getNomVoltage() const { return mNomVoltage; } + void SP::Ph1::Load::calculatePerUnitParameters(Real baseApparentPower, Real baseOmega) { SPDLOG_LOGGER_INFO(mSLog, "#### Calculate Per Unit Parameters for {}", @@ -107,7 +108,7 @@ void SP::Ph1::Load::initializeFromNodesAndTerminals(Real frequency) { // instantiate subResistor for active power consumption if (**mActivePower != 0) { - mResistance = std::pow(**mNomVoltage, 2) / **mActivePower; + mResistance = std::pow(mNomVoltage, 2) / **mActivePower; mConductance = 1.0 / mResistance; mSubResistor = std::make_shared( **mUID + "_res", **mName + "_res", Logger::Level::off); @@ -120,7 +121,7 @@ void SP::Ph1::Load::initializeFromNodesAndTerminals(Real frequency) { } if (**mReactivePower != 0) - mReactance = std::pow(**mNomVoltage, 2) / **mReactivePower; + mReactance = std::pow(mNomVoltage, 2) / **mReactivePower; else mReactance = 0; diff --git a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp index 48f8ffd330..c7af01de61 100644 --- a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp +++ b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp @@ -15,7 +15,6 @@ SP::Ph1::NetworkInjection::NetworkInjection(String uid, String name, : CompositePowerComp(uid, name, true, true, logLevel), mVoltageRef(mAttributes->createDynamic("V_ref")), mSrcFreq(mAttributes->createDynamic("f_src")), - mBaseVoltage(mAttributes->create("base_Voltage")), mVoltageSetPoint(mAttributes->create("V_set")), mVoltageSetPointPerUnit(mAttributes->create("V_set_pu", 1.0)), mActivePowerInjection(mAttributes->create("p_inj")), @@ -92,17 +91,21 @@ void SP::Ph1::NetworkInjection::setParameters(Complex initialPhasor, Logger::realToString(baseFrequency)); } +Real SP::Ph1::NetworkInjection::getBaseVoltage() const{ + return mBaseVoltage; +} + void SP::Ph1::NetworkInjection::setBaseVoltage(Real baseVoltage) { - **mBaseVoltage = baseVoltage; + mBaseVoltage = baseVoltage; } void SP::Ph1::NetworkInjection::calculatePerUnitParameters( Real baseApparentPower, Real baseOmega) { SPDLOG_LOGGER_INFO(mSLog, "#### Calculate Per Unit Parameters for {}", **mName); - SPDLOG_LOGGER_INFO(mSLog, "Base Voltage={} [V]", **mBaseVoltage); + SPDLOG_LOGGER_INFO(mSLog, "Base Voltage={} [V]", mBaseVoltage); - **mVoltageSetPointPerUnit = **mVoltageSetPoint / **mBaseVoltage; + **mVoltageSetPointPerUnit = **mVoltageSetPoint / mBaseVoltage; SPDLOG_LOGGER_INFO(mSLog, "Voltage Set-Point ={} [pu]", **mVoltageSetPointPerUnit); diff --git a/dpsim-models/src/SP/SP_Ph1_PiLine.cpp b/dpsim-models/src/SP/SP_Ph1_PiLine.cpp index acb6cad204..3c2a83898c 100644 --- a/dpsim-models/src/SP/SP_Ph1_PiLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_PiLine.cpp @@ -13,7 +13,6 @@ using namespace CPS; SP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) : Base::Ph1::PiLine(mAttributes), CompositePowerComp(uid, name, false, true, logLevel), - mBaseVoltage(mAttributes->create("base_Voltage")), mCurrent(mAttributes->create("current_vector")), mActivePowerBranch(mAttributes->create("p_branch_vector")), mReactivePowerBranch(mAttributes->create("q_branch_vector")), @@ -77,8 +76,10 @@ SimPowerComp::Ptr SP::Ph1::PiLine::clone(String name) { } // #### Powerflow section #### +Real SP::Ph1::PiLine::getBaseVoltage() const { return mBaseVoltage; } + void SP::Ph1::PiLine::setBaseVoltage(Real baseVoltage) { - **mBaseVoltage = baseVoltage; + mBaseVoltage = baseVoltage; } void SP::Ph1::PiLine::calculatePerUnitParameters(Real baseApparentPower, @@ -90,15 +91,15 @@ void SP::Ph1::PiLine::calculatePerUnitParameters(Real baseApparentPower, SPDLOG_LOGGER_INFO(mSLog, "Base Power={} [VA] Base Omega={} [1/s]", baseApparentPower, baseOmega); - mBaseImpedance = (**mBaseVoltage * **mBaseVoltage) / mBaseApparentPower; + mBaseImpedance = (mBaseVoltage * mBaseVoltage) / mBaseApparentPower; mBaseAdmittance = 1.0 / mBaseImpedance; mBaseInductance = mBaseImpedance / mBaseOmega; mBaseCapacitance = 1.0 / mBaseOmega / mBaseImpedance; mBaseCurrent = baseApparentPower / - (**mBaseVoltage * + (mBaseVoltage * sqrt(3)); // I_base=(S_threephase/3)/(V_line_to_line/sqrt(3)) SPDLOG_LOGGER_INFO(mSLog, "Base Voltage={} [V] Base Impedance={} [Ohm]", - **mBaseVoltage, mBaseImpedance); + mBaseVoltage, mBaseImpedance); mSeriesResPerUnit = **mSeriesRes / mBaseImpedance; mSeriesIndPerUnit = **mSeriesInd / mBaseInductance; diff --git a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp index 1e9dd342d0..74c01f0b61 100644 --- a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp @@ -15,7 +15,6 @@ SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage, Logger::Level logLevel) : Base::Ph1::PiLine(mAttributes), CompositePowerComp(uid, name, true, true, logLevel), - mBaseVoltage(mAttributes->create("base_Voltage", baseVoltage)), mInductance(mAttributes->create("L_series")), mActivePowerInjection(mAttributes->create("p_inj")), mReactivePowerInjection(mAttributes->create("q_inj")), @@ -41,7 +40,6 @@ SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage, SP::Ph1::RXLine::RXLine(String uid, String name, Logger::Level logLevel) : Base::Ph1::PiLine(mAttributes), CompositePowerComp(uid, name, true, true, logLevel), - mBaseVoltage(mAttributes->create("base_Voltage")), mInductance(mAttributes->create("L_series")), mActivePowerInjection(mAttributes->create("p_inj")), mReactivePowerInjection(mAttributes->create("q_inj")), @@ -58,11 +56,11 @@ SP::Ph1::RXLine::RXLine(String uid, String name, Logger::Level logLevel) void SP::Ph1::RXLine::setPerUnitSystem(Real baseApparentPower, Real baseOmega) { mBaseApparentPower = baseApparentPower; mBaseOmega = baseOmega; - mBaseImpedance = (**mBaseVoltage * **mBaseVoltage) / mBaseApparentPower; + mBaseImpedance = (mBaseVoltage * mBaseVoltage) / mBaseApparentPower; mBaseAdmittance = 1.0 / mBaseImpedance; mBaseInductance = mBaseImpedance / mBaseOmega; /// I_base = S_base / V_line - mBaseCurrent = baseApparentPower / (**mBaseVoltage * sqrt(3)); + mBaseCurrent = baseApparentPower / (mBaseVoltage * sqrt(3)); #if 0 mLog.Log(Logger::Level::INFO) << "#### Set Per Unit System for " << **mName << std::endl; @@ -80,6 +78,8 @@ void SP::Ph1::RXLine::setPerUnitSystem(Real baseApparentPower, Real baseOmega) { #endif } +Real SP::Ph1::RXLine::getBaseVoltage() const { return mBaseVoltage; } + void SP::Ph1::RXLine::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow &Y) { updateMatrixNodeIndices(); int bus1 = this->matrixNodeIndex(0); diff --git a/dpsim-models/src/SP/SP_Ph1_SynchronGenerator.cpp b/dpsim-models/src/SP/SP_Ph1_SynchronGenerator.cpp index c5c5684fff..933d48cc20 100644 --- a/dpsim-models/src/SP/SP_Ph1_SynchronGenerator.cpp +++ b/dpsim-models/src/SP/SP_Ph1_SynchronGenerator.cpp @@ -13,7 +13,6 @@ using namespace CPS; SP::Ph1::SynchronGenerator::SynchronGenerator(String uid, String name, Logger::Level logLevel) : SimPowerComp(uid, name, logLevel), - mBaseVoltage(mAttributes->create("base_Voltage")), mSetPointActivePower(mAttributes->create("P_set")), mSetPointReactivePower(mAttributes->create("Q_set")), mSetPointVoltage(mAttributes->create("V_set")), @@ -45,8 +44,11 @@ void SP::Ph1::SynchronGenerator::setParameters( } // #### Powerflow section #### + +Real SP::Ph1::SynchronGenerator::getBaseVoltage() const { return mBaseVoltage; } + void SP::Ph1::SynchronGenerator::setBaseVoltage(Real baseVoltage) { - **mBaseVoltage = baseVoltage; + mBaseVoltage = baseVoltage; } void SP::Ph1::SynchronGenerator::calculatePerUnitParameters( @@ -60,7 +62,7 @@ void SP::Ph1::SynchronGenerator::calculatePerUnitParameters( **mSetPointActivePowerPerUnit = **mSetPointActivePower / mBaseApparentPower; **mSetPointReactivePowerPerUnit = **mSetPointReactivePower / mBaseApparentPower; - **mSetPointVoltagePerUnit = **mSetPointVoltage / **mBaseVoltage; + **mSetPointVoltagePerUnit = **mSetPointVoltage / mBaseVoltage; SPDLOG_LOGGER_INFO(mSLog, "Active Power Set Point={} [pu] Voltage Set Point={} [pu]", **mSetPointActivePowerPerUnit, **mSetPointVoltagePerUnit); diff --git a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp index e94606355e..3f3a77c64d 100644 --- a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp @@ -49,7 +49,7 @@ void SP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, SPDLOG_LOGGER_INFO( mSLog, "Nominal Voltage End 1={} [V] Nominal Voltage End 2={} [V]", - **mNominalVoltageEnd1, **mNominalVoltageEnd2); + mNominalVoltageEnd1, mNominalVoltageEnd2); SPDLOG_LOGGER_INFO( mSLog, "Resistance={} [Ohm] Inductance={} [H] (referred to primary side)", **mResistance, **mInductance); @@ -78,7 +78,7 @@ void SP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, /// DEPRECATED: Delete method SimPowerComp::Ptr SP::Ph1::Transformer::clone(String name) { auto copy = Transformer::make(name, mLogLevel); - copy->setParameters(**mNominalVoltageEnd1, **mNominalVoltageEnd2, + copy->setParameters(mNominalVoltageEnd1, mNominalVoltageEnd2, **mRatedPower, std::abs(**mRatio), std::arg(**mRatio), **mResistance, **mInductance); return copy; @@ -100,14 +100,14 @@ void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { std::shared_ptr> tmp = mTerminals[0]; mTerminals[0] = mTerminals[1]; mTerminals[1] = tmp; - Real tmpVolt = **mNominalVoltageEnd1; - **mNominalVoltageEnd1 = **mNominalVoltageEnd2; - **mNominalVoltageEnd2 = tmpVolt; + Real tmpVolt = mNominalVoltageEnd1; + mNominalVoltageEnd1 = mNominalVoltageEnd2; + mNominalVoltageEnd2 = tmpVolt; SPDLOG_LOGGER_INFO(mSLog, "Switching terminals to have first terminal at " "higher voltage side. Updated parameters: "); SPDLOG_LOGGER_INFO( mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]", - **mNominalVoltageEnd1, **mNominalVoltageEnd2); + mNominalVoltageEnd1, mNominalVoltageEnd2); SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", mRatioAbs, mRatioPhase); } @@ -149,7 +149,7 @@ void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { Real qSnub = Q_SNUB_TRANSFORMER * **mRatedPower; // A snubber conductance is added on the higher voltage side - mSnubberResistance1 = std::pow(std::abs(**mNominalVoltageEnd1), 2) / pSnub; + mSnubberResistance1 = std::pow(std::abs(mNominalVoltageEnd1), 2) / pSnub; mSubSnubResistor1 = std::make_shared(**mName + "_snub_res1", mLogLevel); mSubSnubResistor1->setParameters(mSnubberResistance1); @@ -158,13 +158,13 @@ void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { mSLog, "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]", node(0)->name(), Logger::realToString(mSnubberResistance1)); - mSubSnubResistor1->setBaseVoltage(**mNominalVoltageEnd1); + mSubSnubResistor1->setBaseVoltage(mNominalVoltageEnd1); addMNASubComponent(mSubSnubResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); // A snubber conductance is added on the lower voltage side - mSnubberResistance2 = std::pow(std::abs(**mNominalVoltageEnd2), 2) / pSnub; + mSnubberResistance2 = std::pow(std::abs(mNominalVoltageEnd2), 2) / pSnub; mSubSnubResistor2 = std::make_shared(**mName + "_snub_res2", mLogLevel); mSubSnubResistor2->setParameters(mSnubberResistance2); @@ -173,7 +173,7 @@ void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { mSLog, "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]", node(1)->name(), Logger::realToString(mSnubberResistance2)); - mSubSnubResistor2->setBaseVoltage(**mNominalVoltageEnd2); + mSubSnubResistor2->setBaseVoltage(mNominalVoltageEnd2); addMNASubComponent(mSubSnubResistor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); @@ -189,7 +189,7 @@ void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { // A snubber capacitance is added to lower voltage side mSnubberCapacitance2 = - qSnub / std::pow(std::abs(**mNominalVoltageEnd2), 2) / mNominalOmega; + qSnub / std::pow(std::abs(mNominalVoltageEnd2), 2) / mNominalOmega; mSubSnubCapacitor2 = std::make_shared(**mName + "_snub_cap2", mLogLevel); mSubSnubCapacitor2->setParameters(mSnubberCapacitance2); @@ -198,7 +198,7 @@ void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { mSLog, "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]", node(1)->name(), Logger::realToString(mSnubberCapacitance2)); - mSubSnubCapacitor2->setBaseVoltage(**mNominalVoltageEnd2); + mSubSnubCapacitor2->setBaseVoltage(mNominalVoltageEnd2); addMNASubComponent(mSubSnubCapacitor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); @@ -230,6 +230,14 @@ void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { // #### Powerflow section #### +Real SP::Ph1::Transformer::getNominalVoltageEnd1() const { + return mNominalVoltageEnd1; +} + +Real SP::Ph1::Transformer::getNominalVoltageEnd2() const { + return mNominalVoltageEnd2; +} + void SP::Ph1::Transformer::setBaseVoltage(Real baseVoltage) { // Note: to be consistent set base voltage to higher voltage (and impedance values must be referred to high voltage side) // TODO: use attribute setter for setting base voltage @@ -264,7 +272,7 @@ void SP::Ph1::Transformer::calculatePerUnitParameters(Real baseApparentPower, mLeakagePerUnit = Complex(mResistancePerUnit, 1. * mInductancePerUnit); SPDLOG_LOGGER_INFO(mSLog, "Leakage Impedance={} [pu] ", mLeakagePerUnit); - mRatioAbsPerUnit = mRatioAbs / **mNominalVoltageEnd1 * **mNominalVoltageEnd2; + mRatioAbsPerUnit = mRatioAbs / mNominalVoltageEnd1 * mNominalVoltageEnd2; SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [pu]", mRatioAbsPerUnit); // Calculate per unit parameters of subcomps From 00bd29e86571a154d9d75c0c51ef79100fd80b56 Mon Sep 17 00:00:00 2001 From: Georgii Tishenin Date: Wed, 16 Apr 2025 17:17:46 +0200 Subject: [PATCH 072/168] PFSolver: get base voltages using getter functions Signed-off-by: Georgii Tishenin --- dpsim/src/PFSolver.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/dpsim/src/PFSolver.cpp b/dpsim/src/PFSolver.cpp index 73297ed001..c4026ee483 100644 --- a/dpsim/src/PFSolver.cpp +++ b/dpsim/src/PFSolver.cpp @@ -269,8 +269,7 @@ void PFSolver::determineNodeBaseVoltages() { if (std::shared_ptr vsi = std::dynamic_pointer_cast< CPS::SP::Ph1::AvVoltageSourceInverterDQ>(comp)) { - baseVoltage_ = - Math::abs(vsi->attributeTyped("vnom")->get()); + baseVoltage_ = vsi->getNomVoltage(); SPDLOG_LOGGER_INFO( mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", @@ -278,7 +277,7 @@ void PFSolver::determineNodeBaseVoltages() { break; } else if (std::shared_ptr rxline = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = rxline->attributeTyped("base_Voltage")->get(); + baseVoltage_ = rxline->getBaseVoltage(); SPDLOG_LOGGER_INFO( mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", @@ -286,7 +285,7 @@ void PFSolver::determineNodeBaseVoltages() { break; } else if (std::shared_ptr line = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = line->attributeTyped("base_Voltage")->get(); + baseVoltage_ = line->getBaseVoltage(); SPDLOG_LOGGER_INFO( mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", @@ -296,16 +295,14 @@ void PFSolver::determineNodeBaseVoltages() { std::dynamic_pointer_cast( comp)) { if (trans->terminal(0)->node()->name() == node->name()) { - baseVoltage_ = - trans->attributeTyped("nominal_voltage_end1")->get(); + baseVoltage_ = trans->getNominalVoltageEnd1(); SPDLOG_LOGGER_INFO( mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", baseVoltage_, trans->name(), node->name()); break; } else if (trans->terminal(1)->node()->name() == node->name()) { - baseVoltage_ = - trans->attributeTyped("nominal_voltage_end2")->get(); + baseVoltage_ = trans->getNominalVoltageEnd2(); SPDLOG_LOGGER_INFO( mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", @@ -315,7 +312,7 @@ void PFSolver::determineNodeBaseVoltages() { } else if (std::shared_ptr gen = std::dynamic_pointer_cast( comp)) { - baseVoltage_ = gen->attributeTyped("base_Voltage")->get(); + baseVoltage_ = gen->getBaseVoltage(); SPDLOG_LOGGER_INFO( mSLog, "Choose base voltage {}V of {} to convert pu-solution of {}.", @@ -323,7 +320,7 @@ void PFSolver::determineNodeBaseVoltages() { break; } else if (std::shared_ptr load = std::dynamic_pointer_cast(comp)) { - baseVoltage_ = load->attributeTyped("V_nom")->get(); + baseVoltage_ = load->getNomVoltage(); SPDLOG_LOGGER_INFO( mSLog, "Choose base voltage of {} V to convert pu-solution of {}.", baseVoltage_, load->name(), node->name()); @@ -331,7 +328,7 @@ void PFSolver::determineNodeBaseVoltages() { } else if (std::shared_ptr extnet = std::dynamic_pointer_cast( comp)) { - baseVoltage_ = extnet->attributeTyped("base_Voltage")->get(); + baseVoltage_ = extnet->getBaseVoltage(); SPDLOG_LOGGER_INFO( mSLog, "Choose base voltage of {}V to convert pu-solution of {}.", baseVoltage_, extnet->name(), node->name()); From 1d7380398ffedde50b5f63cfb5fa64922d14b74e Mon Sep 17 00:00:00 2001 From: Georgii Tishenin Date: Wed, 16 Apr 2025 17:51:29 +0200 Subject: [PATCH 073/168] Fix formatting to comply with clang-format Signed-off-by: Georgii Tishenin --- .../include/dpsim-models/Base/Base_Ph1_Transformer.h | 2 +- .../dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h | 1 + dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp | 4 +--- dpsim-models/src/SP/SP_Ph1_Transformer.cpp | 6 +++--- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Base/Base_Ph1_Transformer.h b/dpsim-models/include/dpsim-models/Base/Base_Ph1_Transformer.h index 9bd2c89488..742deaf58b 100644 --- a/dpsim-models/include/dpsim-models/Base/Base_Ph1_Transformer.h +++ b/dpsim-models/include/dpsim-models/Base/Base_Ph1_Transformer.h @@ -35,7 +35,7 @@ class Transformer { : mRatedPower(attributeList->create("S")), mRatio(attributeList->create("ratio")), mResistance(attributeList->create("R")), - mInductance(attributeList->create("L")) {}; + mInductance(attributeList->create("L")){}; /// void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h index 32c52e3423..a914470af6 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_AvVoltageSourceInverterDQ.h @@ -28,6 +28,7 @@ class AvVoltageSourceInverterDQ private: /// Nominal voltage Real mVnom; + protected: // ### General Parameters ### /// Nominal system angle diff --git a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp index c7af01de61..d06227a02e 100644 --- a/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp +++ b/dpsim-models/src/SP/SP_Ph1_NetworkInjection.cpp @@ -91,9 +91,7 @@ void SP::Ph1::NetworkInjection::setParameters(Complex initialPhasor, Logger::realToString(baseFrequency)); } -Real SP::Ph1::NetworkInjection::getBaseVoltage() const{ - return mBaseVoltage; -} +Real SP::Ph1::NetworkInjection::getBaseVoltage() const { return mBaseVoltage; } void SP::Ph1::NetworkInjection::setBaseVoltage(Real baseVoltage) { mBaseVoltage = baseVoltage; diff --git a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp index 3f3a77c64d..bee05f78e4 100644 --- a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp @@ -78,9 +78,9 @@ void SP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, /// DEPRECATED: Delete method SimPowerComp::Ptr SP::Ph1::Transformer::clone(String name) { auto copy = Transformer::make(name, mLogLevel); - copy->setParameters(mNominalVoltageEnd1, mNominalVoltageEnd2, - **mRatedPower, std::abs(**mRatio), std::arg(**mRatio), - **mResistance, **mInductance); + copy->setParameters(mNominalVoltageEnd1, mNominalVoltageEnd2, **mRatedPower, + std::abs(**mRatio), std::arg(**mRatio), **mResistance, + **mInductance); return copy; } From bdea128812ab45139e7b48c4e6b0dcc652924b59 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 4 Apr 2025 08:33:55 +0200 Subject: [PATCH 074/168] feat(nix): Add Nix packaging Signed-off-by: Steffen Vogel --- flake.lock | 82 +++++++++++++++++++ flake.nix | 60 ++++++++++++++ packaging/Nix/cimpp.nix | 47 +++++++++++ packaging/Nix/dpsim.nix | 118 ++++++++++++++++++++++++++++ packaging/Nix/dpsimpy.nix | 118 ++++++++++++++++++++++++++++ packaging/Nix/readerwriterqueue.nix | 24 ++++++ packaging/Nix/shell.nix | 19 +++++ packaging/Nix/suitesparse.nix | 14 ++++ packaging/Nix/sundials.nix | 19 +++++ 9 files changed, 501 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 packaging/Nix/cimpp.nix create mode 100644 packaging/Nix/dpsim.nix create mode 100644 packaging/Nix/dpsimpy.nix create mode 100644 packaging/Nix/readerwriterqueue.nix create mode 100644 packaging/Nix/shell.nix create mode 100644 packaging/Nix/suitesparse.nix create mode 100644 packaging/Nix/sundials.nix diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..65e31ad9c5 --- /dev/null +++ b/flake.lock @@ -0,0 +1,82 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1742800061, + "narHash": "sha256-oDJGK1UMArK52vcW9S5S2apeec4rbfNELgc50LqiPNs=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1750f3c1c89488e2ffdd47cab9d05454dddfb734", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "villas-node": "villas-node" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "villas-node": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1743649879, + "narHash": "sha256-XqPw+lYpg5qvGPscjYqKfMexk0xlMKpm6nF/hRnVAlY=", + "owner": "VILLASframework", + "repo": "node", + "rev": "d56124e7934c319f9d3fca8ad862b20f29ebdb8e", + "type": "github" + }, + "original": { + "owner": "VILLASframework", + "repo": "node", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..b4dae14c5d --- /dev/null +++ b/flake.nix @@ -0,0 +1,60 @@ +{ + description = "DPsim - Solver library for dynamic power system simulation"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + villas-node = { + url = "github:VILLASframework/node"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = + { + self, + nixpkgs, + flake-utils, + villas-node, + }: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { + inherit system; + + # Required for old sundials version + config.permittedInsecurePackages = [ "python-2.7.18.8" ]; + + overlays = [ + villas-node.overlays.default + + (final: prev: { + readerwriterqueue = final.callPackage ./packaging/Nix/readerwriterqueue.nix { }; + cimpp = final.callPackage ./packaging/Nix/cimpp.nix { }; + suitesparse-dpsim = prev.callPackage ./packaging/Nix/suitesparse.nix { }; + sundials321 = prev.callPackage ./packaging/Nix/sundials.nix { }; + dpsim = pkgs.callPackage ./packaging/Nix/dpsim.nix { }; + dpsimpy = pkgs.callPackage ./packaging/Nix/dpsimpy.nix { }; + }) + ]; + }; + in + { + packages = { + default = pkgs.dpsim; + + inherit (pkgs) + dpsim + dpsimpy + readerwriterqueue + cimpp + ; + }; + + devShells = { + default = pkgs.callPackage ./packaging/Nix/shell.nix { }; + }; + } + ); +} diff --git a/packaging/Nix/cimpp.nix b/packaging/Nix/cimpp.nix new file mode 100644 index 0000000000..55b41a7f92 --- /dev/null +++ b/packaging/Nix/cimpp.nix @@ -0,0 +1,47 @@ +{ + fetchFromGitHub, + stdenv, + lib, + cmake, + libxml2, + fetchurl, + + # Options + cimVersion ? "CGMES_2.4.15_16FEB2016", +}: +let + libxml2_2914 = + (libxml2.overrideAttrs ( + finalAttrs: prevAttrs: { + version = "2.9.14"; + src = fetchurl { + url = "mirror://gnome/sources/libxml2/${lib.versions.majorMinor finalAttrs.version}/libxml2-${finalAttrs.version}.tar.xz"; + hash = "sha256-YNdKJX0czsBHXnScui8hVZ5IE577pv8oIkNXx8eY3+4"; + }; + patches = [ ]; + } + )).override + { pythonSupport = false; }; +in +stdenv.mkDerivation { + name = "libcimpp"; + src = fetchFromGitHub { + owner = "sogno-platform"; + repo = "libcimpp"; + # rev = "release/v2.2.0"; + rev = "1b11d5c17bedf0ae042628b42ecb4e49df70b2f6"; + hash = "sha256-RBcV7HlgrKML03E/J9IGIkbKAK23KAXuFJOSXTFZ/i4="; + fetchSubmodules = true; + }; + + nativeBuildInputs = [ cmake ]; + + cmakeFlags = [ + "-DUSE_CIM_VERSION=${cimVersion}" + "-DBUILD_SHARED_LIBS=ON" + ]; + + enableParallelBuilding = true; + + buildInputs = [ libxml2_2914 ]; +} diff --git a/packaging/Nix/dpsim.nix b/packaging/Nix/dpsim.nix new file mode 100644 index 0000000000..5acd981ac9 --- /dev/null +++ b/packaging/Nix/dpsim.nix @@ -0,0 +1,118 @@ +{ + lib, + stdenv, + + makeFontsConf, + + cimpp, + cmake, + doxygen, + eigen, + fmt, + graphviz, + gsl, + nlohmann_json, + pkg-config, + python312, + python312Packages, + readerwriterqueue, + spdlog, + sphinx, + sundials321, + suitesparse-dpsim, + villas-node, + freefont_ttf, + + cudatoolkit, + magma, + + # Options + withExamples ? false, + withAllExtras ? true, + withOpenMP ? withAllExtras, + withCIMpp ? withAllExtras, + withDocumentation ? withAllExtras, + withVILLAS ? withAllExtras, + withGSL ? withAllExtras, + withGraphviz ? withAllExtras, + withPybind ? withAllExtras, + withSundials ? withAllExtras, + withSuiteSparse ? withAllExtras, + withMNASolverPlugin ? withAllExtras, +}: +stdenv.mkDerivation { + name = "dpsim"; + src = ../..; + + nativeBuildInputs = + [ + cmake + pkg-config + ] + ++ lib.optionals withDocumentation [ + doxygen + sphinx + python312Packages.sphinx-rtd-theme + ]; + + buildInputs = + [ + eigen + fmt + spdlog + nlohmann_json + readerwriterqueue + + # TODO: Add these dependencies + # cudatoolkit + # magma + ] + ++ lib.optional withCIMpp cimpp + ++ lib.optional withVILLAS villas-node + ++ lib.optional withGSL gsl + ++ lib.optional withGraphviz graphviz + ++ lib.optional withSundials sundials321 + ++ lib.optional withSuiteSparse suitesparse-dpsim + ++ lib.optionals withPybind [ + python312 + python312Packages.pybind11 + ]; + + enableParallelBuilding = true; + + cmakeFlags = [ + # LTO is currently broken in Nixpkgs (https://github.com/NixOS/nixpkgs/issues/384599) + "-DWITH_LTO=OFF" + + "-DBUILD_SHARED_LIBS=ON" + + # Feature flags + "-DWITH_OPENMP=${if withOpenMP then "ON" else "OFF"}" + "-DWITH_CIM=${if withCIMpp then "ON" else "OFF"}" + "-DWITH_VILLAS=${if withVILLAS then "ON" else "OFF"}" + "-DWITH_GSL=${if withGSL then "ON" else "OFF"}" + "-DWITH_MNASOLVER_PLUGIN=${if withMNASolverPlugin then "ON" else "OFF"}" + + "-DDPSIM_BUILD_EXAMPLES=${if withExamples then "ON" else "OFF"}" + "-DDPSIM_BUILD_DOC=${if withDocumentation then "ON" else "OFF"}" + + # We can not fetch external code within the Nix sandbox + # Instead we packaged those dependencies as separate Nix derivations. + "-DFETCH_EIGEN=OFF" + "-DFETCH_SUITESPARSE=OFF" + "-DFETCH_SPDLOG=OFF" + "-DFETCH_CIMPP=OFF" + "-DFETCH_PYBIND=OFF" + "-DFETCH_GRID_DATA=OFF" + "-DFETCH_FILESYSTEM=OFF" + "-DFETCH_JSON=OFF" + "-DFETCH_READERWRITERQUEUE=OFF" + ]; + + FONTCONFIG_FILE = makeFontsConf { fontDirectories = [ freefont_ttf ]; }; + + # For building docs diagrams + preBuild = '' + export XDG_CACHE_HOME="$(mktemp -d)" + ''; +} diff --git a/packaging/Nix/dpsimpy.nix b/packaging/Nix/dpsimpy.nix new file mode 100644 index 0000000000..0332dc35b8 --- /dev/null +++ b/packaging/Nix/dpsimpy.nix @@ -0,0 +1,118 @@ +{ + lib, + + patchelf, + + cimpp, + cmake, + eigen, + fmt, + gsl, + nlohmann_json, + pkg-config, + python312, + python312Packages, + readerwriterqueue, + spdlog, + sundials321, + graphviz, + suitesparse-dpsim, + villas-node, + + cudatoolkit, + magma, + + # Options + withAllExtras ? true, + withOpenMP ? withAllExtras, + withCIMpp ? withAllExtras, + withVILLAS ? withAllExtras, + withGSL ? withAllExtras, + withGraphviz ? withAllExtras, + withPybind ? withAllExtras, + withSundials ? withAllExtras, + withSuiteSparse ? withAllExtras, + withMNASolverPlugin ? withAllExtras, +}: +with python312Packages; +buildPythonPackage { + name = "dpsimpy"; + src = ../..; + + nativeBuildInputs = [ + cmake + pkg-config + ]; + + pyproject = true; + + build-system = [ + setuptools + setuptools-scm + ]; + + dependencies = [ pytest-runner ]; + + buildInputs = + [ + eigen + fmt + spdlog + nlohmann_json + readerwriterqueue + + # TODO: Add these dependencies + # cudatoolkit + # magma + ] + ++ lib.optional withCIMpp cimpp + ++ lib.optional withVILLAS villas-node + ++ lib.optional withGSL gsl + ++ lib.optional withGraphviz graphviz + ++ lib.optional withSundials sundials321 + ++ lib.optional withSuiteSparse suitesparse-dpsim + ++ lib.optionals withPybind [ + python312 + python312Packages.pybind11 + ]; + + enableParallelBuilding = true; + dontUseCmakeConfigure = true; + + preBuild = '' + pypaBuildFlags+="-C--global-option=build_ext -C--global-option=--parallel=$NIX_BUILD_CORES" + ''; + + env = { + # NIX_DEBUG = "7"; + CMAKE_OPTS = builtins.concatStringsSep " " [ + # LTO is currently broken in Nixpkgs (https://github.com/NixOS/nixpkgs/issues/384599) + "-DWITH_LTO=OFF" + + "-DBUILD_SHARED_LIBS=ON" + + # Feature flags + "-DWITH_OPENMP=${if withOpenMP then "ON" else "OFF"}" + "-DWITH_CIM=${if withCIMpp then "ON" else "OFF"}" + "-DWITH_VILLAS=${if withVILLAS then "ON" else "OFF"}" + "-DWITH_GSL=${if withGSL then "ON" else "OFF"}" + "-DWITH_MNASOLVER_PLUGIN=${if withMNASolverPlugin then "ON" else "OFF"}" + + "-DDPSIM_BUILD_EXAMPLES=OFF" + + # We can not fetch external code within the Nix sandbox + # Instead we packaged those dependencies as separate Nix derivations. + "-DFETCH_EIGEN=OFF" + "-DFETCH_SUITESPARSE=OFF" + "-DFETCH_SPDLOG=OFF" + "-DFETCH_CIMPP=OFF" + "-DFETCH_PYBIND=OFF" + "-DFETCH_GRID_DATA=OFF" + "-DFETCH_FILESYSTEM=OFF" + "-DFETCH_JSON=OFF" + "-DFETCH_READERWRITERQUEUE=OFF" + + "-DCMAKE_SKIP_BUILD_RPATH=ON" + ]; + }; +} diff --git a/packaging/Nix/readerwriterqueue.nix b/packaging/Nix/readerwriterqueue.nix new file mode 100644 index 0000000000..7df5773cd4 --- /dev/null +++ b/packaging/Nix/readerwriterqueue.nix @@ -0,0 +1,24 @@ +{ + fetchFromGitHub, + stdenv, + cmake, +}: +stdenv.mkDerivation { + name = "readerwriterqueue"; + src = fetchFromGitHub { + owner = "cameron314"; + repo = "readerwriterqueue"; + rev = "16b48ae1148284e7b40abf72167206a4390a4592"; + hash = "sha256-m4cUIXiDFxTguDZ7d0svjlOSkUNYY0bbUp3t7adBwOo"; + }; + + enableParallelBuilding = true; + + nativeBuildInputs = [ cmake ]; + + cmakeFlags = [ "-DCMAKE_INSTALL_LIBDIR=lib" ]; + + # postInstall = '' + # cmake --install . --prefix "''${!outputDev}" --component Devel + # ''; +} diff --git a/packaging/Nix/shell.nix b/packaging/Nix/shell.nix new file mode 100644 index 0000000000..5e4e0a1b3c --- /dev/null +++ b/packaging/Nix/shell.nix @@ -0,0 +1,19 @@ +{ + mkShell, + dpsim, + python3, + pre-commit, + clang-tools, + ruby +}: +mkShell { + inputsFrom = [ dpsim ]; + + packages = [ + (python3.withPackages (ps: with ps; [ numpy ])) + + pre-commit + ruby # Required for pre-commit + clang-tools + ]; +} diff --git a/packaging/Nix/suitesparse.nix b/packaging/Nix/suitesparse.nix new file mode 100644 index 0000000000..3188759ee3 --- /dev/null +++ b/packaging/Nix/suitesparse.nix @@ -0,0 +1,14 @@ +{ fetchFromGitHub, suitesparse }: +suitesparse.overrideAttrs (oldAttrs: { + version = "5.10.6-dpsim"; + src = fetchFromGitHub { + owner = "dpsim-simulator"; + repo = "SuiteSparse"; + rev = "release-v5.10.6"; + hash = "sha256-KUUfy8eT+xj/GFAsGOvkTfQevNyUwH1rJcDOW5hO9mw"; + }; + + postPatch = '' + substituteInPlace ./KLU/Source/klu_print.c --replace 'KLU_dumpKLU' '// KLU_dumpKLU' + ''; +}) diff --git a/packaging/Nix/sundials.nix b/packaging/Nix/sundials.nix new file mode 100644 index 0000000000..5b0721a75d --- /dev/null +++ b/packaging/Nix/sundials.nix @@ -0,0 +1,19 @@ +{ + fetchFromGitHub, + sundials, + python2, +}: +(sundials.overrideAttrs ( + finalAttrs: prevAttrs: { + version = "3.2.1"; + src = fetchFromGitHub { + owner = "LLNL"; + repo = "sundials"; + rev = "v${finalAttrs.version}"; + hash = "sha256-5fVgxFEzhzw7rAENpt2+8qGR0pe00nntSFnyArmafzU"; + }; + + doCheck = false; + } +)).override + { python = python2; } From dba705e4b5b264119e4fc03644407fccb60956eb Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 8 Apr 2025 08:16:49 +0200 Subject: [PATCH 075/168] feat(ci): Add GitHub CI workflow for building DPsim with Nix Signed-off-by: Steffen Vogel --- .github/workflows/build_nix.yaml | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 .github/workflows/build_nix.yaml diff --git a/.github/workflows/build_nix.yaml b/.github/workflows/build_nix.yaml new file mode 100644 index 0000000000..47e1c7c4f5 --- /dev/null +++ b/.github/workflows/build_nix.yaml @@ -0,0 +1,33 @@ +name: Build with Nix + +on: + push: + branches: + - master + pull_request: + +## Build ## + +jobs: + build: + name: Build with Nix + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Install Nix + uses: cachix/install-nix-action@v31 + with: + nix_path: nixpkgs=channel:nixos-unstable + + - name: Setup Nix cache + uses: cachix/cachix-action@v14 + with: + name: dpsim + authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}" + + - name: Build dpsim + run: nix build .#dpsim From 1db38c558215dc752052e390d2cc0912b386ae5e Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Tue, 8 Apr 2025 09:11:31 +0200 Subject: [PATCH 076/168] feat(doc): Add documentation for using Nix package manager Signed-off-by: Steffen Vogel --- .../content/en/docs/Getting started/build.md | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/hugo/content/en/docs/Getting started/build.md b/docs/hugo/content/en/docs/Getting started/build.md index 4d7bf6ae76..1276740afd 100644 --- a/docs/hugo/content/en/docs/Getting started/build.md +++ b/docs/hugo/content/en/docs/Getting started/build.md @@ -198,6 +198,34 @@ To build the Python package run python3 setup.py bdist_wheel ``` +## Nix + +DPsim can be fully build using [Nix](https://nixos.org/), a declarative package manager for building software reproducible. + +The following steps require a working single-user or multi-user installation of Nix, but not necessarily NixOS. + +DPsim uses Nix's experimental Flake feature which needs to be activated: + +```shell +echo "experimental-features=nix-command flakes" > ~/.config/nix/nix.conf +``` + +Building DPsim, including all its dependencies can be done by running: + +```shell +nix build github:sogno-platform/dpsim +``` + +The build result will be available within the `result` folder of your current directory. + +For development purposes, a local development environment can be setup by you running: + +```shell +nix develop github:sogno-platform/dpsim +``` + +Please note, that the Flake reference above (`github:sogno-platform/dpsim`) can be substituted by a local path (`.`), in case you have locally checked out the DPsim repo. + # Documentation ## Python From b48c3a11d0ec5ea1060524493735c142451d236c Mon Sep 17 00:00:00 2001 From: Georgii Tishenin Date: Fri, 18 Apr 2025 18:13:24 +0200 Subject: [PATCH 077/168] remove commented out code in dpsim/ Signed-off-by: Georgii Tishenin --- dpsim/include/dpsim/Compat/getopt.h | 9 ------ dpsim/include/dpsim/ODESolver.h | 8 ----- dpsim/src/ODESolver.cpp | 50 ----------------------------- dpsim/src/Simulation.cpp | 38 ---------------------- 4 files changed, 105 deletions(-) diff --git a/dpsim/include/dpsim/Compat/getopt.h b/dpsim/include/dpsim/Compat/getopt.h index 68c9f0e7d8..2cf6d158b4 100644 --- a/dpsim/include/dpsim/Compat/getopt.h +++ b/dpsim/include/dpsim/Compat/getopt.h @@ -86,15 +86,6 @@ int optreset; /* reset getopt */ char *optarg; /* argument associated with option */ #endif -#if 0 -extern int optind; /* index of first non-option in argv */ -extern int optopt; /* single option character, as parsed */ -extern int opterr; /* flag to enable built-in diagnostics... */ - /* (user may set to zero, to suppress) */ - -extern char *optarg; /* pointer to argument of current option */ -#endif - #define PRINT_ERROR ((opterr) && (*options != ':')) #define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ diff --git a/dpsim/include/dpsim/ODESolver.h b/dpsim/include/dpsim/ODESolver.h index f9e1c6c64c..81a795db6b 100644 --- a/dpsim/include/dpsim/ODESolver.h +++ b/dpsim/include/dpsim/ODESolver.h @@ -53,14 +53,6 @@ class ODESolver : public Solver { /// Scalar absolute tolerance realtype abstol = RCONST(1.0e-10); - // TODO: Variables for implicit solve? - /// Template Jacobian Matrix (implicit solver) -#if 0 - SUNMatrix A = NULL; - /// Linear solver object (implicit solver) - SUNLinearSolver LS = NULL; -#endif - /// Reusable error-checking flag int mFlag{0}; diff --git a/dpsim/src/ODESolver.cpp b/dpsim/src/ODESolver.cpp index 6d8c796aa1..eaaf8af833 100644 --- a/dpsim/src/ODESolver.cpp +++ b/dpsim/src/ODESolver.cpp @@ -37,56 +37,6 @@ void ODESolver::initialize() { double tmp1[], double tmp2[], double tmp3[]) { dummy->odeJacobian(t, y, fy, J, tmp1, tmp2, tmp3); }; - - // Causes numerical issues, better allocate in every step-> see step -#if 0 - mArkode_mem= ARKodeCreate(); - if (check_flag(mArkode_mem, "ARKodeCreate", 0)) - mFlag=1; - - mFlag = ARKodeSetUserData(mArkode_mem, this); - if (check_flag(&mFlag, "ARKodeSetUserData", 1)) - mFlag=1; - - /* Call ARKodeInit to initialize the integrator memory and specify the - * right-hand side function in y'=f(t,y), the inital time T0, and - * the initial dependent variable vector y(fluxes+mech. vars).*/ - if(mImplicitIntegration){ - mFlag = ARKodeInit(mArkode_mem, NULL, &ODESolver::StateSpaceWrapper, initial_time, mStates); - if (check_flag(&mFlag, "ARKodeInit", 1)) throw CPS::Exception(); - - // Initialize dense matrix data structure - A = SUNDenseMatrix(mProbDim, mProbDim); - if (check_flag((void *)A, "SUNDenseMatrix", 0)) throw CPS::Exception(); - - // Initialize linear solver - LS = SUNDenseLinearSolver(mStates, A); - if (check_flag((void *)LS, "SUNDenseLinearSolver", 0)) throw CPS::Exception(); - - // Attach matrix and linear solver - mFlag = ARKDlsSetLinearSolver(mArkode_mem, LS, A); - if (check_flag(&mFlag, "ARKDlsSetLinearSolver", 1)) throw CPS::Exception(); - - // Set Jacobian routine - mFlag = ARKDlsSetJacFn(mArkode_mem, &ODESolver::JacobianWrapper); - if (check_flag(&mFlag, "ARKDlsSetJacFn", 1)) throw CPS::Exception(); - } - else { - mFlag = ARKodeInit(mArkode_mem, &ODESolver::StateSpaceWrapper, NULL, initial_time, mStates); - if (check_flag(&mFlag, "ARKodeInit", 1)) throw CPS::Exception(); - } - - // Shifted to every step because of numerical issues - - // Specify Runge-Kutta Method/order - mFlag = ARKodeSetOrder(mArkode_mem, 4); - if (check_flag(&mFlag, "ARKodeOrderSet", 1)) - mFlag=1; - - mFlag = ARKodeSStolerances(mArkode_mem, reltol, abstol); - if (check_flag(&mFlag, "ARKodeSStolerances", 1)) - mFlag=1; -#endif } int ODESolver::StateSpaceWrapper(realtype t, N_Vector y, N_Vector ydot, diff --git a/dpsim/src/Simulation.cpp b/dpsim/src/Simulation.cpp index 1a76c3b06c..f27d7e2922 100644 --- a/dpsim/src/Simulation.cpp +++ b/dpsim/src/Simulation.cpp @@ -223,38 +223,6 @@ Graph::Graph Simulation::dependencyGraph() { std::map avgTimes; std::map fillColors; -#if 0 - /* The main SolveTasks of each Solver usually takes the - * largest amount of computing time. We exclude it from - * coloring for improving the spread of the color range - * for the remaining tasks. - */ - auto isSolveTask = [](Task::Ptr task) -> Bool { - const std::vector ignoreTasks = { -#ifdef WITH_SUNDIALS - std::type_index(typeid(ODESolver::SolveTask)), -#endif - std::type_index(typeid(MnaSolver::SolveTask)), - std::type_index(typeid(MnaSolver::SolveTask)), - std::type_index(typeid(DiakopticsSolver::SubnetSolveTask)), - std::type_index(typeid(DiakopticsSolver::SubnetSolveTask)), - std::type_index(typeid(DiakopticsSolver::SolveTask)), - std::type_index(typeid(DiakopticsSolver::SolveTask)), - std::type_index(typeid(NRpolarSolver::SolveTask)) - }; - - return std::find(ignoreTasks.begin(), ignoreTasks.end(), std::type_index(typeid(*task.get()))) != ignoreTasks.end(); - }; - - auto isIgnoredTask = [&isSolveTask](Task::Ptr task) -> Bool { - return typeid(*task.get()) == typeid(Interface::PreStep) || sSolveTask(task); - }; - - auto isRootTask = [](Task::Ptr task) -> Bool { - return typeid(*task.get()) == typeid(Scheduler::Root); - }; -#endif - auto isScheduled = [this](Task::Ptr task) -> Bool { return !mTaskOutEdges[task].empty(); }; @@ -309,12 +277,6 @@ Graph::Graph Simulation::dependencyGraph() { n->set("style", "rounded,filled,bold"); n->set("shape", "rectangle"); - // if (isSolveTask(task)) { - // n->set("fillcolor", "orange"); - // } - // if (isRootTask(task)) { - // n->set("fillcolor", "springgreen1"); - // } if (isScheduled(task)) { if (avgTimeWorst > Scheduler::TaskTime(0)) { auto grad = (float)avgTimes[task].count() / avgTimeWorst.count(); From 70de405506772b976e8b7b2db85ae56819794f7d Mon Sep 17 00:00:00 2001 From: Georgii Tishenin Date: Fri, 18 Apr 2025 18:13:59 +0200 Subject: [PATCH 078/168] remove commented out code in dpsim-models/ Signed-off-by: Georgii Tishenin --- dpsim-models/include/dpsim-models/Attribute.h | 24 --- dpsim-models/include/dpsim-models/CSVReader.h | 12 -- .../EMT_Ph3_AvVoltSourceInverterStateSpace.h | 18 -- .../include/dpsim-models/EMT/EMT_Ph3_PiLine.h | 8 - dpsim-models/src/CIM/Reader.cpp | 13 -- dpsim-models/src/CSVReader.cpp | 194 ------------------ dpsim-models/src/DP/DP_Ph1_Resistor.cpp | 19 -- dpsim-models/src/DP/DP_Ph3_Capacitor.cpp | 46 ----- dpsim-models/src/DP/DP_Ph3_Inductor.cpp | 35 +--- .../src/DP/DP_Ph3_SynchronGeneratorDQ.cpp | 51 +---- dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp | 48 +---- ...EMT_Ph3_AvVoltSourceInverterStateSpace.cpp | 16 -- dpsim-models/src/SP/SP_Ph1_RXLine.cpp | 33 --- dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp | 27 +-- dpsim-models/src/SP/SP_Ph3_Capacitor.cpp | 23 --- dpsim-models/src/SP/SP_Ph3_Inductor.cpp | 20 -- dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp | 50 +---- dpsim-models/src/Signal/Exciter.cpp | 18 -- 18 files changed, 8 insertions(+), 647 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Attribute.h b/dpsim-models/include/dpsim-models/Attribute.h index 3207a0ee53..14da779a9c 100644 --- a/dpsim-models/include/dpsim-models/Attribute.h +++ b/dpsim-models/include/dpsim-models/Attribute.h @@ -90,30 +90,6 @@ template class AttributePointer { bool isNull() const { return mPtr == nullptr; } - // These (implicit) comparison operators are disabled to avoid accidentally comparing pointers instead of attribute values. - // When a pointer comparison is necessary, this can be done via the `getPtr` method or by using the `AttributeCmp` and `AttributeEq` structs. -#if 0 - template - bool operator<(const AttributePointer& rhs) const noexcept { - return this->mPtr < rhs.getPtr(); - } - - template - bool operator>(const AttributePointer& rhs) const noexcept { - return this->mPtr > rhs.getPtr(); - } - - template - bool operator==(const AttributePointer& rhs) const noexcept { - return this->mPtr == rhs.getPtr(); - } - - template - bool operator!=(const AttributePointer& rhs) const noexcept { - return this->mPtr != rhs.getPtr(); - } -#endif - private: std::shared_ptr mPtr; }; diff --git a/dpsim-models/include/dpsim-models/CSVReader.h b/dpsim-models/include/dpsim-models/CSVReader.h index 3b45f3db4c..06d255d8f5 100644 --- a/dpsim-models/include/dpsim-models/CSVReader.h +++ b/dpsim-models/include/dpsim-models/CSVReader.h @@ -75,18 +75,6 @@ class CSVReader { Real end_time = -1, Real scale_factor = 1, CSVReader::DataFormat format = CSVReader::DataFormat::SECONDS); -#if 0 - void assignLoadProfilePF(std::vector>& loads, - Real start_time = -1, Real time_step = 1, Real end_time = -1, Real scale_factor= 1, - CSVReader::Mode mode = CSVReader::Mode::AUTO, - CSVReader::DataFormat format = CSVReader::DataFormat::SECONDS); - - void assignLoadProfileSP(std::vector>& loads, - Real start_time = -1, Real time_step = 1, Real end_time = -1, Real scale_factor= 1, - CSVReader::Mode mode = CSVReader::Mode::AUTO, - CSVReader::DataFormat format = CSVReader::DataFormat::SECONDS); -#endif - void assignLoadProfileDP( std::vector> &loads, diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.h index 635fb3a261..d1f8bee5b1 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.h @@ -72,15 +72,6 @@ class AvVoltSourceInverterStateSpace protected: Matrix mIfabc = Matrix::Zero(3, 1); -#if 0 - Real mIfa; - Real mIfb; - Real mIfc; - - Real mVca; - Real mVcb; - Real mVcc; -#endif // Norton equivalant voltage source Matrix mEquivCurrent = Matrix::Zero(3, 1); @@ -113,15 +104,6 @@ class AvVoltSourceInverterStateSpace void initializeStates(Real omega, Real timeStep, Attribute::Ptr leftVector); -#if 0 - // Initialize with parameters. - void initialize(Real theta, Real phi_pll, Real p, Real q, Real phi_d, Real phi_q, - Real gamma_d, Real gamma_q, Real i_fd, Real i_fq, Real v_cd, Real v_cq); - - void initStates(Real initOmegaPLL, Real initPhiPLL, Real initP, Real initQ, - Real initPhid, Real initPhiQ, Real initGamma_d, Real initGamma_q, Real initVcabc, Real initIfabc); -#endif - void updateStates(); void setParameters(Real sysOmega, Complex sysVoltNom, Real Pref, Real Qref, diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h index 3cc9e8f615..d63f8452c3 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h @@ -75,14 +75,6 @@ class PiLine : public CompositePowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; - -#if 0 - MNAInterface::List mnaTearGroundComponents(); - void mnaTearInitialize(Real omega, Real timeStep); - void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix); - void mnaTearApplyVoltageStamp(Matrix& voltageVector); - void mnaTearPostStep(Matrix voltage, Matrix current); -#endif }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/src/CIM/Reader.cpp b/dpsim-models/src/CIM/Reader.cpp index 27867fa271..2189e527f9 100644 --- a/dpsim-models/src/CIM/Reader.cpp +++ b/dpsim-models/src/CIM/Reader.cpp @@ -341,19 +341,6 @@ Reader::mapEnergyConsumer(CIMPP::EnergyConsumer *consumer) { auto load = std::make_shared(consumer->mRID, consumer->name, mComponentLogLevel); - // TODO: Use EnergyConsumer.P and EnergyConsumer.Q if available, overwrite if existent SvPowerFlow data -#if 0 - Real p = 0; - Real q = 0; - if (consumer->p.value){ - p = unitValue(consumer->p.value,UnitMultiplier::M); - } - if (consumer->q.value){ - q = unitValue(consumer->q.value,UnitMultiplier::M); - } - load->setParameters(p, q, 0); -#endif - // P and Q values will be set according to SvPowerFlow data load->modifyPowerFlowBusType( PowerflowBusType:: diff --git a/dpsim-models/src/CSVReader.cpp b/dpsim-models/src/CSVReader.cpp index aa95162b12..32ef715a49 100644 --- a/dpsim-models/src/CSVReader.cpp +++ b/dpsim-models/src/CSVReader.cpp @@ -163,200 +163,12 @@ std::vector CSVReader::readLoadProfileDP(fs::path file, Real start_time, load_profileDP.push_back(pq); if (end_time > 0 && presentTime > end_time) break; -#if 0 - while (presentTime + time_step < Int(presentTime) + 1) { - presentTime += time_step; - p_data.push_back(p_data.back()); - } -#endif presentTime = Int(presentTime) + 1; } std::cout << "CSV loaded." << std::endl; return load_profileDP; } -#if 0 -void CSVReader::assignLoadProfileSP(std::vector>& loads, - Real start_time, Real time_step, Real end_time, Real scale_factor, - CSVReader::Mode mode, CSVReader::DataFormat format) { - - switch (mode) { - case CSVReader::Mode::AUTO: { - for (auto load : loads) { - if(!load->isLoad()) - continue; - String load_name = load->name(); - for (auto file : mFileList) { - String file_name = file.filename().string(); - // Changing file name and load name to upper case for later matching - for (auto & c : load_name) c = toupper(c); - for (auto & c : file_name) c = toupper(c); - // Strip off all non-alphanumeric characters - load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); - file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); - if (std::stoi(file_name) == std::stoi(load_name)) { - load->mLoadProfile = readLoadProfileDP(file, start_time, time_step, end_time, scale_factor, format); - SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); - } - } - } - - break; - } - case CSVReader::Mode::MANUAL: { - Int LP_assigned_counter = 0; - Int LP_not_assigned_counter = 0; - SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); - for (auto load : loads) { - std::map::iterator file = mAssignPattern.find(load->name()); - if (file == mAssignPattern.end()) { - - SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); - LP_not_assigned_counter++; - continue; - } - for(auto path: mFileList){ - if(path.string().find(file->second)!= std::string::npos){ - load->mLoadProfile = readLoadProfileDP(path, start_time, time_step, end_time, scale_factor); - SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); - LP_assigned_counter++; - } - - } - } - SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); - break; - } - default: { - throw std::invalid_argument( - "Load profile assign mode error"); - break; - } - } -} - -void CSVReader::assignLoadProfilePF(std::vector>& loads, - Real start_time, Real time_step, Real end_time, Real scale_factor, - CSVReader::Mode mode, CSVReader::DataFormat format) { - - switch (mode) { - case CSVReader::Mode::AUTO: { - for (auto load : loads) { - if(!load->isLoad()) - continue; - String load_name = load->name(); - for (auto file : mFileList) { - String file_name = file.filename().string(); - // Changing file name and load name to upper case for later matching - for (auto & c : load_name) c = toupper(c); - for (auto & c : file_name) c = toupper(c); - // Strip off all non-alphanumeric characters - load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); - file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); - if (std::stoi(file_name) == std::stoi(load_name)) { - load->mPFAvVoltageSourceInverter->mLoadProfile = readLoadProfile(fs::path(mPath + file->second + ".csv"), start_time, time_step, end_time); - load->mPFAvVoltageSourceInverter->use_profile = true; - SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); - } - } - } - - break; - } - case CSVReader::Mode::MANUAL: { - Int LP_assigned_counter = 0; - Int LP_not_assigned_counter = 0; - SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); - for (auto load : loads) { - std::map::iterator file = mAssignPattern.find(load->name()); - if (file == mAssignPattern.end()) { - - SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); - LP_not_assigned_counter++; - continue; - } - for(auto path: mFileList){ - if(path.string().find(file->second)!= std::string::npos){ - load->mPFAvVoltageSourceInverter->mLoadProfile = readLoadProfile(fs::path(mPath + file->second + ".csv"), start_time, time_step, end_time); - load->mPFAvVoltageSourceInverter->use_profile = true; - SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); - LP_assigned_counter++; - } - - } - } - SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); - break; - } - default: { - throw std::invalid_argument( - "Load profile assign mode error"); - break; - } - } -} - -// TODO: profile handling currently not supported by average inverter in DP1ph -void CSVReader::assignLoadProfileDP(std::vector>& loads, - Real start_time, Real time_step, Real end_time, Real scale_factor, - CSVReader::Mode mode, CSVReader::DataFormat format) { - - switch (mode) { - case CSVReader::Mode::AUTO: { - for (auto load : loads) { - if(!load->isLoad()) - continue; - String load_name = load->name(); - for (auto file : mFileList) { - String file_name = file.filename().string(); - // Changing file name and load name to upper case for later matching - for (auto & c : load_name) c = toupper(c); - for (auto & c : file_name) c = toupper(c); - // Strip off all non-alphanumeric characters - load_name.erase(remove_if(load_name.begin(), load_name.end(), [](char c) { return !isalnum(c); }), load_name.end()); - file_name.erase(remove_if(file_name.begin(), file_name.end(), [](char c) { return !isalnum(c); }), file_name.end()); - if (std::stoi(file_name) == std::stoi(load_name)) { - load->mLoadProfile = readLoadProfileDP(file, start_time, time_step, end_time, scale_factor, format); - SPDLOG_LOGGER_INFO(mSLog, "Assigned {} to {}", file.filename().string(), load->name()); - } - } - } - - break; - } - case CSVReader::Mode::MANUAL: { - Int LP_assigned_counter = 0; - Int LP_not_assigned_counter = 0; - SPDLOG_LOGGER_INFO(mSLog, "Assigning load profiles with user defined pattern ..."); - for (auto load : loads) { - std::map::iterator file = mAssignPattern.find(load->name()); - if (file == mAssignPattern.end()) { - - SPDLOG_LOGGER_INFO(mSLog, "{} has no profile given.", load->name()); - LP_not_assigned_counter++; - continue; - } - for(auto path: mFileList){ - if(path.string().find(file->second)!= std::string::npos){ - load->mLoadProfile = readLoadProfileDP(path, start_time, time_step, end_time, scale_factor); - SPDLOG_LOGGER_INFO(mSLog, "Assigned {}.csv to {}", file->second, load->name()); - LP_assigned_counter++; - } - - } - } - SPDLOG_LOGGER_INFO(mSLog, "Assigned profiles for {} loads, {} not assigned.", LP_assigned_counter, LP_not_assigned_counter); - break; - } - default: { - throw std::invalid_argument( - "Load profile assign mode error"); - break; - } - } -} -#endif - PowerProfile CSVReader::readLoadProfile(fs::path file, Real start_time, Real time_step, Real end_time, CSVReader::DataFormat format) { @@ -463,12 +275,6 @@ std::vector CSVReader::readPQData(fs::path file, Real start_time, p_data.push_back(std::stod((*row_).get(0)) * 1000); if (end_time > 0 && presentTime > end_time) break; -#if 0 - while (presentTime + time_step < Int(presentTime) + 1) { - presentTime += time_step; - p_data.push_back(p_data.back()); - } -#endif presentTime = Int(presentTime) + 1; } std::cout << "CSV loaded." << std::endl; diff --git a/dpsim-models/src/DP/DP_Ph1_Resistor.cpp b/dpsim-models/src/DP/DP_Ph1_Resistor.cpp index 148c52b8f8..f9ecabcd08 100644 --- a/dpsim-models/src/DP/DP_Ph1_Resistor.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Resistor.cpp @@ -174,22 +174,6 @@ void DP::Ph1::Resistor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { void DP::Ph1::Resistor::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], std::vector &off) { - /* New state vector definintion: - * state[0]=node0_voltage - * state[1]=node1_voltage - * .... - * state[n]=noden_voltage - * state[n+1]=component0_voltage - * state[n+2]=component0_inductance (not yet implemented) - * ... - * state[m-1]=componentm_voltage - * state[m]=componentm_inductance - * ... - * state[x] = nodal_equation_1 - * state[x+1] = nodal_equation_2 - * ... - */ - int Pos1 = matrixNodeIndex(0); int Pos2 = matrixNodeIndex(1); int c_offset = off[0] + off[1]; // Current offset for component @@ -199,9 +183,6 @@ void DP::Ph1::Resistor::daeResidual(double ttime, const double state[], c_offset + Pos2 + 1; // Current offset for second nodal equation resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor -#if 0 - resid[c_offset+1] = ; // TODO : add inductance equation -#endif resid[n_offset_1] += 1.0 / **mResistance * state[c_offset]; resid[n_offset_2] += 1.0 / **mResistance * state[c_offset]; off[1] += 1; diff --git a/dpsim-models/src/DP/DP_Ph3_Capacitor.cpp b/dpsim-models/src/DP/DP_Ph3_Capacitor.cpp index 1ff468107a..a857aca65c 100644 --- a/dpsim-models/src/DP/DP_Ph3_Capacitor.cpp +++ b/dpsim-models/src/DP/DP_Ph3_Capacitor.cpp @@ -54,16 +54,6 @@ void DP::Ph3::Capacitor::initializeFromNodesAndTerminals(Real frequency) { **mIntfCurrent = susceptance * **mIntfVoltage; SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialize from power flow ---"); - // << "Impedance: " << impedance << std::endl - // << "Voltage across: " << std::abs((**mIntfVoltage)(0,0)) - // << "<" << Math::phaseDeg((**mIntfVoltage)(0,0)) << std::endl - // << "Current: " << std::abs((**mIntfCurrent)(0,0)) - // << "<" << Math::phaseDeg((**mIntfCurrent)(0,0)) << std::endl - // << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - // << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl - // << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - // << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl - // << "--- Power flow initialization finished ---" << std::endl; } void DP::Ph3::Capacitor::initVars(Real omega, Real timeStep) { @@ -83,11 +73,6 @@ void DP::Ph3::Capacitor::initVars(Real omega, Real timeStep) { Complex(equivCondReal(2, 1), equivCondImag(2, 1)), Complex(equivCondReal(2, 2), equivCondImag(2, 2)); - // Since equivCondReal == a.inverse() and -#if 0 - Matrix mPrevVoltCoeffReal = a.inverse(); - Matrix mPrevVoltCoeffImag = -b * a.inverse(); -#endif Matrix mPrevVoltCoeffReal = equivCondReal; Matrix mPrevVoltCoeffImag = -b * equivCondReal; @@ -109,34 +94,6 @@ void DP::Ph3::Capacitor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); initVars(omega, timeStep); -#if 0 - Matrix equivCondReal = 2.0 * mCapacitance / timeStep; - Matrix equivCondImag = omega * mCapacitance; - mEquivCond << - Complex(equivCondReal(0, 0), equivCondImag(0, 0)), - Complex(equivCondReal(1, 0), equivCondImag(1, 0)), - Complex(equivCondReal(2, 0), equivCondImag(2, 0)); - - // TODO: Something is wrong here -- from Ph1_Capacitor - Matrix prevVoltCoeffReal = 2.0 * mCapacitance / timeStep; - Matrix prevVoltCoeffImag = - omega * mCapacitance; - mPrevVoltCoeff = Matrix::Zero(3, 1); - mPrevVoltCoeff << - Complex(prevVoltCoeffReal(0, 0), prevVoltCoeffImag(0, 0)), - Complex(prevVoltCoeffReal(1, 0), prevVoltCoeffImag(1, 0)), - Complex(prevVoltCoeffReal(2, 0), prevVoltCoeffImag(2, 0)); - - mEquivCurrent = -**mIntfCurrent + -mPrevVoltCoeff.cwiseProduct( **mIntfVoltage);*/ - // No need to update current now - //**mIntfCurrent = mEquivCond.cwiseProduct(**mIntfVoltage) + mEquivCurrent; - - mLog.info() << "\n--- MNA Initialization ---" << std::endl - << "Initial voltage " << Math::abs((**mIntfVoltage)(0,0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0,0)) << std::endl - << "Initial current " << Math::abs((**mIntfCurrent)(0,0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0,0)) << std::endl - << "--- MNA initialization finished ---" << std::endl; -#endif } void DP::Ph3::Capacitor::mnaCompApplySystemMatrixStamp( @@ -147,9 +104,6 @@ void DP::Ph3::Capacitor::mnaCompApplySystemMatrixStamp( } void DP::Ph3::Capacitor::mnaCompApplyRightSideVectorStamp(Matrix &rightVector) { - //mCureqr = mCurrr + mGcr * mDeltavr + mGci * mDeltavi; - //mCureqi = mCurri + mGcr * mDeltavi - mGci * mDeltavr; - mEquivCurrent = -**mIntfCurrent + -mPrevVoltCoeff * **mIntfVoltage; if (terminalNotGrounded(0)) { diff --git a/dpsim-models/src/DP/DP_Ph3_Inductor.cpp b/dpsim-models/src/DP/DP_Ph3_Inductor.cpp index 1a7fad29fe..57474f6983 100644 --- a/dpsim-models/src/DP/DP_Ph3_Inductor.cpp +++ b/dpsim-models/src/DP/DP_Ph3_Inductor.cpp @@ -54,16 +54,6 @@ void DP::Ph3::Inductor::initializeFromNodesAndTerminals(Real frequency) { //TODO SPDLOG_LOGGER_INFO(mSLog, "--- Initialize according to power flow ---"); - // << "in phase A: " << std::endl - // << "Voltage across: " << std::abs((**mIntfVoltage)(0,0)) - // << "<" << Math::phaseDeg((**mIntfVoltage)(0,0)) << std::endl - // << "Current: " << std::abs((**mIntfCurrent)(0,0)) - // << "<" << Math::phaseDeg((**mIntfCurrent)(0,0)) << std::endl - // << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - // << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl - // << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - // << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl - // << "--- Power flow initialization finished ---" << std::endl; } void DP::Ph3::Inductor::initVars(Real omega, Real timeStep) { @@ -89,8 +79,6 @@ void DP::Ph3::Inductor::initVars(Real omega, Real timeStep) { // TODO: check if this is correct or if it should be only computed before the step mEquivCurrent = mEquivCond * **mIntfVoltage + mPrevCurrFac * **mIntfCurrent; - // no need to update this now - //**mIntfCurrent = mEquivCond.cwiseProduct(**mIntfVoltage) + mEquivCurrent; } void DP::Ph3::Inductor::mnaCompInitialize(Real omega, Real timeStep, @@ -100,9 +88,6 @@ void DP::Ph3::Inductor::mnaCompInitialize(Real omega, Real timeStep, SPDLOG_LOGGER_INFO(mSLog, "Initial voltage {}", Math::abs((**mIntfVoltage)(0, 0))); - // << "<" << Math::phaseDeg((**mIntfVoltage)(0,0)) << std::endl - // << "Initial current " << Math::abs((**mIntfCurrent)(0,0)) - // << "<" << Math::phaseDeg((**mIntfCurrent)(0,0)) << std::endl; } void DP::Ph3::Inductor::mnaCompApplySystemMatrixStamp( @@ -197,22 +182,8 @@ void DP::Ph3::Inductor::mnaTearInitialize(Real omega, Real timeStep) { initVars(omega, timeStep); } -void DP::Ph3::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { -#if 0 - Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx, mEquivCond.cwiseInverse()(0,0)); -#endif -} +void DP::Ph3::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) {} -void DP::Ph3::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) { -#if 0 - mEquivCurrent = mEquivCond * (**mIntfVoltage)(0,0) + mPrevCurrFac * (**mIntfCurrent)(0,0); - Math::addToVectorElement(voltageVector, mTearIdx, mEquivCurrent .cwiseProduct( mEquivCond.cwiseInverse())); -#endif -} +void DP::Ph3::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) {} -void DP::Ph3::Inductor::mnaTearPostStep(Complex voltage, Complex current) { -#if 0 - **mIntfVoltage = voltage; - **mIntfCurrent = mEquivCond * voltage + mEquivCurrent; -#endif -} +void DP::Ph3::Inductor::mnaTearPostStep(Complex voltage, Complex current) {} diff --git a/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQ.cpp b/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQ.cpp index a5829feab9..b2e8f547ca 100644 --- a/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQ.cpp +++ b/dpsim-models/src/DP/DP_Ph3_SynchronGeneratorDQ.cpp @@ -193,53 +193,6 @@ MatrixComp DP::Ph3::SynchronGeneratorDQ::dq0ToAbcTransform(Real theta, return abcCompVector; } -void DP::Ph3::SynchronGeneratorDQ::trapezoidalFluxStates() { -#if 0 - // Calculation of rotational speed with euler - if (mHasTurbineGovernor == true) - mMechTorque = mTurbineGovernor.step(mOmMech, 1, 300e6 / 555e6, mTimeStep); - - mElecTorque = (mPsid*mIq - mPsiq*mId); - mOmMech = mOmMech + mTimeStep * (1 / (2 * mH) * (mMechTorque - mElecTorque)); - - //Calculation of flux - Matrix A = (mResistanceMat*mReactanceMat - mOmMech*mOmegaFluxMat); - Matrix B = Matrix::Identity(7, 7); - - if (numMethod == NumericalMethod::Trapezoidal_flux) - Fluxes = Math::StateSpaceTrapezoidal(Fluxes, A, B, mTimeStep*mBase_OmElec, dqVoltages); - else - Fluxes = Math::StateSpaceEuler(Fluxes, A, B, mTimeStep*mBase_OmElec, dqVoltages); - - // Calculation of currents based on inverse of inductance matrix - mId = ((mLlfd*mLlkd + mLmd*(mLlfd + mLlkd))*mPsid - mLmd*mLlkd*mPsifd - mLlfd*mLmd*mPsikd) / detLd; - mIfd = (mLlkd*mLmd*mPsid - (mLl*mLlkd + mLmd*(mLl + mLlkd))*mPsifd + mLmd*mLl*mPsikd) / detLd; - mIkd = (mLmd*mLlfd*mPsid + mLmd*mLl*mPsifd - (mLmd*(mLlfd + mLl) + mLl*mLlfd)*mPsikd) / detLd; - mIq = ((mLlkq1*mLlkq2 + mLmq*(mLlkq1 + mLlkq2))*mPsiq - mLmq*mLlkq2*mPsikq1 - mLmq*mLlkq1*mPsikq2) / detLq; - mIkq1 = (mLmq*mLlkq2*mPsiq - (mLmq*(mLlkq2 + mLl) + mLl*mLlkq2)*mPsikq1 + mLmq*mLl*mPsikq2) / detLq; - mIkq2 = (mLmq*mLlkq1*mPsiq + mLmq*mLl*mPsikq1 - (mLmq*(mLlkq1 + mLl) + mLl*mLlkq1)*mPsikq2) / detLq; - mI0 = -mPsi0 / mLl; -#endif -} +void DP::Ph3::SynchronGeneratorDQ::trapezoidalFluxStates() {} -void DP::Ph3::SynchronGeneratorDQ::trapezoidalCurrentStates() { -#if 0 - Matrix A = (mReactanceMat*mResistanceMat); - Matrix B = mReactanceMat; - Matrix C = Matrix::Zero(7, 1); - C(0, 0) = -mOmMech*mPsid; - C(1, 0) = mOmMech*mPsiq; - C = mReactanceMat*C; - - dqCurrents = Math::StateSpaceTrapezoidal(dqCurrents, A, B, C, mTimeStep*mOmMech, dqVoltages); - - //Calculation of currents based on inverse of inductance matrix - mPsiq = -(mLl + mLmq)*mIq + mLmq*mIkq1 + mLmq*mIkq2; - mPsid = -(mLl + mLmd)*mId + mLmd*mIfd + mLmd*mIkd; - mPsi0 = -mLl*mI0; - mPsikq1 = -mLmq*mIq + (mLlkq1 + mLmq)*mIkq1 + mLmq*mIkq2; - mPsikq2 = -mLmq*mIq + mLmq*mIkq1 + (mLlkq2 + mLmq)*mIkq2; - mPsifd = -mLmd*mId + (mLlfd + mLmd)*mIfd + mLmd*mIkd; - mPsikd = -mLmd*mId + mLmd*mIfd + (mLlkd + mLmd)*mIkd; -#endif -} +void DP::Ph3::SynchronGeneratorDQ::trapezoidalCurrentStates() {} diff --git a/dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp b/dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp index 0b29712c20..b69897154e 100644 --- a/dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp +++ b/dpsim-models/src/DP/DP_Ph3_VoltageSource.cpp @@ -35,15 +35,6 @@ void DP::Ph3::VoltageSource::setParameters(Complex voltageRef) { void DP::Ph3::VoltageSource::initializeFromNodesAndTerminals(Real frequency) { if (**mVoltageRef == Complex(0, 0)) **mVoltageRef = initialSingleVoltage(1) - initialSingleVoltage(0); - -#if 0 - mLog.info() << "--- Initialize according to power flow ---" << std::endl; - mLog.info() << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - << "<" << std::arg(initialSingleVoltage(0)) << std::endl; - mLog.info() << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - << "<" << std::arg(initialSingleVoltage(1)) << std::endl; - mLog.info() << "Voltage across: " << std::abs(mVoltageRef->get()) << "<" << std::arg(mVoltageRef->get()) << std::endl; -#endif } void DP::Ph3::VoltageSource::mnaCompInitialize( @@ -108,18 +99,6 @@ void DP::Ph3::VoltageSource::mnaCompApplySystemMatrixStamp( mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), matrixNodeIndex(1, 2), Complex(1, 0)); } - -#if 0 - mLog.info() << "--- System matrix stamp ---" << std::endl; - if (terminalNotGrounded(0)) { - mLog.info() << "Add " << Complex(-1, 0) << " to " << matrixNodeIndex(0) << "," << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << std::endl; - mLog.info() << "Add " << Complex(-1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << "," << matrixNodeIndex(0) << std::endl; - } - if (terminalNotGrounded(1)) { - mLog.info() << "Add " << Complex(1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << "," << matrixNodeIndex(1) << std::endl; - mLog.info() << "Add " << Complex(1, 0) << " to " << matrixNodeIndex(1) << "," << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << std::endl; - } -#endif } void DP::Ph3::VoltageSource::mnaCompApplyRightSideVectorStamp( @@ -133,8 +112,6 @@ void DP::Ph3::VoltageSource::mnaCompApplyRightSideVectorStamp( Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), (**mIntfVoltage)(2, 0)); - - //mLog.debug() << "Add " << (**mIntfVoltage)(0,0) << " to source vector " << mVirtualNodes[0]->matrixNodeIndex(PhaseType::A) << std::endl; } void DP::Ph3::VoltageSource::updateVoltage(Real time) { @@ -192,30 +169,7 @@ void DP::Ph3::VoltageSource::mnaCompUpdateCurrent(const Matrix &leftVector) { void DP::Ph3::VoltageSource::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], - std::vector &off) { - /* New state vector definintion: - * state[0]=node0_voltage - * state[1]=node1_voltage - * .... - * state[n]=noden_voltage - * state[n+1]=component0_voltage - * state[n+2]=component0_inductance (not yet implemented) - * ... - * state[m-1]=componentm_voltage - * state[m]=componentm_inductance - */ - - //int Pos1 = matrixNodeIndex(0); - //int Pos2 = matrixNodeIndex(1); - //int c_offset = off[0] + off[1]; //current offset for component - //int n_offset_1 = c_offset + Pos1 + 1;// current offset for first nodal equation - //int n_offset_2 = c_offset + Pos2 + 1;// current offset for second nodal equation - //resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor - ////resid[++c_offset] = ; //TODO : add inductance equation - //resid[n_offset_1] += std::real(current()); - //resid[n_offset_2] += std::real(current()); - //off[1] += 1; -} + std::vector &off) {} Complex DP::Ph3::VoltageSource::daeInitialize() { (**mIntfVoltage)(0, 0) = **mVoltageRef; diff --git a/dpsim-models/src/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp b/dpsim-models/src/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp index 0064030ab9..185ba8aa11 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp @@ -148,14 +148,6 @@ void EMT::Ph3::AvVoltSourceInverterStateSpace::initializeStates( **mGamma_q = 0.006339; **mVcabc = initVgabc; mIfabc = Matrix::Zero(3, 1); -#if 0 - mVca = initVcabc(0, 0); - mVcb = initVcabc(1, 0); - mVcc = initVcabc(2, 0); - mIfa = initIfabc(0, 0); - mIfb = initIfabc(1, 0); - mIfc = initIfabc(2, 0); -#endif mStates << **mThetaPLL, **mPhiPLL, **mP, **mQ, **mPhi_d, **mPhi_q, **mGamma_d, **mGamma_q, **mVcabc, mIfabc; @@ -183,14 +175,6 @@ void EMT::Ph3::AvVoltSourceInverterStateSpace::updateStates() { **mGamma_d = newStates(7, 0); **mVcabc = newStates.block(8, 0, 3, 1); mIfabc = newStates.block(11, 0, 3, 1); -#if 0 - mIfa = newStates(8, 1); - mIfb = newStates(9, 1); - mIfc = newStates(10, 1); - mVca = newStates(11, 1); - mVcb = newStates(12, 1); - mVcc = newStates(13, 1); -#endif mStates = newStates; mU = newU; diff --git a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp index 74c01f0b61..f22722b06b 100644 --- a/dpsim-models/src/SP/SP_Ph1_RXLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_RXLine.cpp @@ -30,11 +30,6 @@ SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage, **mCurrent = MatrixComp::Zero(2, 1); **mActivePowerBranch = Matrix::Zero(2, 1); **mReactivePowerBranch = Matrix::Zero(2, 1); -#if 0 - mLog.Log(Logger::Level::DEBUG) << "Create " << this->type() << " " << name - << " R=" << resistance << " L=" << inductance - << std::endl; -#endif } SP::Ph1::RXLine::RXLine(String uid, String name, Logger::Level logLevel) @@ -59,23 +54,10 @@ void SP::Ph1::RXLine::setPerUnitSystem(Real baseApparentPower, Real baseOmega) { mBaseImpedance = (mBaseVoltage * mBaseVoltage) / mBaseApparentPower; mBaseAdmittance = 1.0 / mBaseImpedance; mBaseInductance = mBaseImpedance / mBaseOmega; - /// I_base = S_base / V_line mBaseCurrent = baseApparentPower / (mBaseVoltage * sqrt(3)); -#if 0 - mLog.Log(Logger::Level::INFO) << "#### Set Per Unit System for " << **mName << std::endl; - mLog.Log(Logger::Level::INFO) << " Base Voltage= " << mBaseVoltage << " [V] " << " Base Impedance= " << mBaseImpedance << " [Ohm] " << std::endl; -#endif - mSeriesResPerUnit = **mSeriesRes / mBaseImpedance; mSeriesIndPerUnit = **mInductance / mBaseInductance; - -#if 0 - mLog.Log(Logger::Level::INFO) << "Series Resistance Per Unit= " << " " << mSeriesResPerUnit << " [Ohm] " - << " Series Inductance Per Unit= " << " " << mSeriesIndPerUnit << " [H] " - << std::endl; - mLog.Log(Logger::Level::INFO) << "r " << mSeriesResPerUnit << std::endl << " x: " << mBaseOmega * mInductance / mBaseImpedance<matrixNodeIndex(0); int bus2 = this->matrixNodeIndex(1); - // Dimension check - // TODO: FIX -#if 0 - if (bus1 > (n - 1) || bus2 > (n - 1)) { - std::stringstream ss; - ss << "Line>>" << this->getName() << ": Wrong Y dimension: " << n; - throw std::invalid_argument(ss.str()); - //std::cout << "Line>>" << Name << ": Wrong Y dimension: " << n << endl; - return; - } -#endif - //create the element admittance matrix Complex y = Complex(1, 0) / Complex(mSeriesResPerUnit, 1. * mSeriesIndPerUnit); @@ -128,9 +98,6 @@ void SP::Ph1::RXLine::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow &Y) { Y.coeffRef(bus1, bus2) += mY_element.coeff(0, 1); Y.coeffRef(bus2, bus1) += mY_element.coeff(1, 0); Y.coeffRef(bus2, bus2) += mY_element.coeff(1, 1); - - //mLog.Log(Logger::Level::INFO) << "#### Y matrix stamping: " << std::endl; - //mLog.Log(Logger::Level::INFO) << mY_element << std::endl; } void SP::Ph1::RXLine::updateBranchFlow(VectorComp ¤t, diff --git a/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp b/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp index 34e57d36fb..54920c08e2 100644 --- a/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp +++ b/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp @@ -206,32 +206,7 @@ void SP::Ph1::VoltageSource::mnaCompUpdateCurrent(const Matrix &leftVector) { void SP::Ph1::VoltageSource::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], - std::vector &off) { - /* New state vector definintion: - * state[0]=node0_voltage - * state[1]=node1_voltage - * .... - * state[n]=noden_voltage - * state[n+1]=component0_voltage - * state[n+2]=component0_inductance (not yet implemented) - * ... - * state[m-1]=componentm_voltage - * state[m]=componentm_inductance - */ - -#if 0 - int Pos1 = matrixNodeIndex(0); - int Pos2 = matrixNodeIndex(1); - int c_offset = off[0] + off[1]; //current offset for component - int n_offset_1 = c_offset + Pos1 + 1;// current offset for first nodal equation - int n_offset_2 = c_offset + Pos2 + 1;// current offset for second nodal equation - resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor - //resid[++c_offset] = ; //TODO : add inductance equation - resid[n_offset_1] += std::real(current()); - resid[n_offset_2] += std::real(current()); - off[1] += 1; -#endif -} + std::vector &off) {} Complex SP::Ph1::VoltageSource::daeInitialize() { (**mIntfVoltage)(0, 0) = mSrcSig->getSignal(); diff --git a/dpsim-models/src/SP/SP_Ph3_Capacitor.cpp b/dpsim-models/src/SP/SP_Ph3_Capacitor.cpp index 3fa2c06e20..62ff54e7ed 100644 --- a/dpsim-models/src/SP/SP_Ph3_Capacitor.cpp +++ b/dpsim-models/src/SP/SP_Ph3_Capacitor.cpp @@ -47,34 +47,11 @@ void SP::Ph3::Capacitor::initializeFromNodesAndTerminals(Real frequency) { Complex(cos(2. / 3. * M_PI), sin(2. / 3. * M_PI)); **mIntfCurrent = mSusceptance * **mIntfVoltage; - // TODO: add updated logger -#if 0 - mLog.info() << "\n--- Initialize from power flow ---" << std::endl - << "Impedance: " << impedance << std::endl - << "Voltage across: " << std::abs((**mIntfVoltage)(0, 0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl - << "Current: " << std::abs((**mIntfCurrent)(0, 0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl - << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl - << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl - << "--- Power flow initialization finished ---" << std::endl; -#endif } void SP::Ph3::Capacitor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); - // TODO add updated logger -#if 0 -mLog.info() << "\n--- MNA Initialization ---" << std::endl - << "Initial voltage " << Math::abs((**mIntfVoltage)(0, 0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl - << "Initial current " << Math::abs((**mIntfCurrent)(0, 0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl - << "--- MNA initialization finished ---" << std::endl; -#endif } void SP::Ph3::Capacitor::mnaCompApplySystemMatrixStamp( diff --git a/dpsim-models/src/SP/SP_Ph3_Inductor.cpp b/dpsim-models/src/SP/SP_Ph3_Inductor.cpp index ab002d3213..b2c498826f 100644 --- a/dpsim-models/src/SP/SP_Ph3_Inductor.cpp +++ b/dpsim-models/src/SP/SP_Ph3_Inductor.cpp @@ -49,31 +49,11 @@ void SP::Ph3::Inductor::initializeFromNodesAndTerminals(Real frequency) { **mIntfCurrent = mSusceptance * **mIntfVoltage; SPDLOG_LOGGER_INFO(mSLog, "--- Initialize according to power flow ---"); -#if 0 - mLog.info() << "--- Initialize according to power flow ---" << std::endl - << "in phase A: " << std::endl - << "Voltage across: " << std::abs((**mIntfVoltage)(0, 0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl - << "Current: " << std::abs((**mIntfCurrent)(0, 0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl - << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - << "<" << Math::phaseDeg(initialSingleVoltage(0)) << std::endl - << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - << "<" << Math::phaseDeg(initialSingleVoltage(1)) << std::endl - << "--- Power flow initialization finished ---" << std::endl; -#endif } void SP::Ph3::Inductor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); - // TODO -#if 0 - mLog.info() << "Initial voltage " << Math::abs((**mIntfVoltage)(0, 0)) - << "<" << Math::phaseDeg((**mIntfVoltage)(0, 0)) << std::endl - << "Initial current " << Math::abs((**mIntfCurrent)(0, 0)) - << "<" << Math::phaseDeg((**mIntfCurrent)(0, 0)) << std::endl; -#endif } void SP::Ph3::Inductor::mnaCompApplySystemMatrixStamp( diff --git a/dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp b/dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp index 15f751c1d7..5a5e0a58c1 100644 --- a/dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp +++ b/dpsim-models/src/SP/SP_Ph3_VoltageSource.cpp @@ -36,15 +36,6 @@ void SP::Ph3::VoltageSource::initializeFromNodesAndTerminals(Real frequency) { if (**mVoltageRef == Complex(0, 0)) **mVoltageRef = initialSingleVoltage(1) - initialSingleVoltage(0); - -#if 0 - mLog.info() << "--- Initialize according to power flow ---" << std::endl; - mLog.info() << "Terminal 0 voltage: " << std::abs(initialSingleVoltage(0)) - << "<" << std::arg(initialSingleVoltage(0)) << std::endl; - mLog.info() << "Terminal 1 voltage: " << std::abs(initialSingleVoltage(1)) - << "<" << std::arg(initialSingleVoltage(1)) << std::endl; - mLog.info() << "Voltage across: " << std::abs(mVoltageRef->get()) << "<" << std::arg(mVoltageRef->get()) << std::endl; -#endif } void SP::Ph3::VoltageSource::mnaCompInitialize( @@ -109,18 +100,6 @@ void SP::Ph3::VoltageSource::mnaCompApplySystemMatrixStamp( mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), matrixNodeIndex(1, 2), Complex(1, 0)); } - -#if 0 - mLog.info() << "--- System matrix stamp ---" << std::endl; - if (terminalNotGrounded(0)) { - mLog.info() << "Add " << Complex(-1, 0) << " to " << matrixNodeIndex(0) << "," << mVirtualNodes[0]->matrixNodeIndex() << std::endl; - mLog.info() << "Add " << Complex(-1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex() << "," << matrixNodeIndex(0) << std::endl; - } - if (terminalNotGrounded(1)) { - mLog.info() << "Add " << Complex(1, 0) << " to " << mVirtualNodes[0]->matrixNodeIndex() << "," << matrixNodeIndex(1) << std::endl; - mLog.info() << "Add " << Complex(1, 0) << " to " << matrixNodeIndex(1) << "," << mVirtualNodes[0]->matrixNodeIndex() << std::endl; - } -#endif } void SP::Ph3::VoltageSource::mnaCompApplyRightSideVectorStamp( @@ -134,8 +113,6 @@ void SP::Ph3::VoltageSource::mnaCompApplyRightSideVectorStamp( Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), (**mIntfVoltage)(2, 0)); - - //mLog.debug() << "Add " << (**mIntfVoltage)(0,0) << " to source vector " << mVirtualNodes[0]->matrixNodeIndex() << std::endl; } void SP::Ph3::VoltageSource::updateVoltage(Real time) { @@ -194,32 +171,7 @@ void SP::Ph3::VoltageSource::mnaCompUpdateCurrent(const Matrix &leftVector) { void SP::Ph3::VoltageSource::daeResidual(double ttime, const double state[], const double dstate_dt[], double resid[], - std::vector &off) { - /* New state vector definintion: - * state[0]=node0_voltage - * state[1]=node1_voltage - * .... - * state[n]=noden_voltage - * state[n+1]=component0_voltage - * state[n+2]=component0_inductance (not yet implemented) - * ... - * state[m-1]=componentm_voltage - * state[m]=componentm_inductance - */ - -#if 0 - int Pos1 = matrixNodeIndex(0); - int Pos2 = matrixNodeIndex(1); - int c_offset = off[0] + off[1]; //current offset for component - int n_offset_1 = c_offset + Pos1 + 1;// current offset for first nodal equation - int n_offset_2 = c_offset + Pos2 + 1;// current offset for second nodal equation - resid[c_offset] = (state[Pos2] - state[Pos1]) - state[c_offset]; // Voltage equation for Resistor - //resid[++c_offset] = ; //TODO : add inductance equation - resid[n_offset_1] += std::real(current()); - resid[n_offset_2] += std::real(current()); - off[1] += 1; -#endif -} + std::vector &off) {} Complex SP::Ph3::VoltageSource::daeInitialize() { (**mIntfVoltage)(0, 0) = **mVoltageRef; diff --git a/dpsim-models/src/Signal/Exciter.cpp b/dpsim-models/src/Signal/Exciter.cpp index b44b8631fa..27c462d927 100644 --- a/dpsim-models/src/Signal/Exciter.cpp +++ b/dpsim-models/src/Signal/Exciter.cpp @@ -57,7 +57,6 @@ void Signal::Exciter::initialize(Real Vh_init, Real Ef_init) { **mEf = Ef_init; // mVse is the ceiling function in PSAT - // mVse = mEf * (0.33 * (exp(0.1 * abs(mEf)) - 1.)); **mVse = **mEf * (0.33 * exp(0.1 * abs(**mEf))); // mVis = vr2 in PSAT @@ -98,7 +97,6 @@ Real Signal::Exciter::step(Real mVd, Real mVq, Real dt) { **mVm = Math::StateSpaceEuler(mVm_prev, -1 / mTr, 1 / mTr, dt, **mVh); // Stabilizing feedback equation - // mVse = mEf * (0.33 * (exp(0.1 * abs(mEf)) - 1.)); **mVse = mEf_prev * (0.33 * exp(0.1 * abs(mEf_prev))); **mVis = Math::StateSpaceEuler(mVis_prev, -1 / mTf, -mKf / mTf / mTf, dt, mEf_prev); @@ -118,19 +116,3 @@ Real Signal::Exciter::step(Real mVd, Real mVq, Real dt) { return **mEf; } - -#if 0 -// Saturation function according to Viviane thesis -Real Signal::Exciter::saturation_fcn1(Real mVd, Real mVq, Real Vref, Real dt) { - if (mEf <= 2.3) - mVse = (0.1 / 2.3)*mEf; - else - mVse = (0.33 / 3.1)*mEf; - mVse = mVse*mEf; -} - -// Saturation function according to PSAT -Real Signal::Exciter::saturation_fcn2() { - return mA * (exp(mB * abs(mEf)) - 1); -} -#endif From 2240d35ea542ec47198a39bb65652d9728f35033 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 17 Apr 2025 17:42:42 +0200 Subject: [PATCH 079/168] cppcheck: Catch exception in Timer destructor Signed-off-by: Leonardo Carreras --- dpsim/src/Timer.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/dpsim/src/Timer.cpp b/dpsim/src/Timer.cpp index 13f5d47663..02a2f78895 100644 --- a/dpsim/src/Timer.cpp +++ b/dpsim/src/Timer.cpp @@ -35,7 +35,11 @@ Timer::Timer(int flags) Timer::~Timer() { if (mState == State::running) - stop(); + try { + stop(); + } catch (SystemError &e) { + std::cerr << "ERROR: The timer was not stopped properly: " << std::endl; + } #ifdef HAVE_TIMERFD close(mTimerFd); From 313afd8006e0a670dcea80364ce65119cef73d38 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 17 Apr 2025 17:43:39 +0200 Subject: [PATCH 080/168] cppcheck: Pass the new iterator when deleting the current component Signed-off-by: Leonardo Carreras --- dpsim-models/src/SystemTopology.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/dpsim-models/src/SystemTopology.cpp b/dpsim-models/src/SystemTopology.cpp index b62ffa1835..03c932b43f 100644 --- a/dpsim-models/src/SystemTopology.cpp +++ b/dpsim-models/src/SystemTopology.cpp @@ -244,9 +244,12 @@ void SystemTopology::reset() { } void SystemTopology::removeComponent(const String &name) { - for (auto it = mComponents.begin(); it != mComponents.end(); ++it) { + for (auto it = mComponents.begin(); it != mComponents.end();) { if ((*it)->name() == name) { - mComponents.erase(it); + it = mComponents.erase( + it); // safe: returns next valid iterator when erasing + } else { + ++it; } } } From 3ba7acf63db558343652594f613eabf87d37e5a7 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 17 Apr 2025 17:53:08 +0200 Subject: [PATCH 081/168] Dockerfiles: Fedora v42 with metadata and villas updated Signed-off-by: Leonardo Carreras --- packaging/Docker/Dockerfile | 8 ++++---- packaging/Docker/Dockerfile.dev | 18 ++++++++++-------- packaging/Docker/Dockerfile.dev-minimal | 15 +++++++-------- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/packaging/Docker/Dockerfile b/packaging/Docker/Dockerfile index 2a28ad662c..263f96cd64 100644 --- a/packaging/Docker/Dockerfile +++ b/packaging/Docker/Dockerfile @@ -4,10 +4,10 @@ ARG BASE_IMAGE=sogno/dpsim:dev FROM ${BASE_IMAGE} LABEL \ - org.opencontainers.image.title = "DPsim" \ - org.opencontainers.image.licenses = "MPL 2.0" \ - org.opencontainers.image.url = "http://dpsim.fein-aachen.org/" \ - org.opencontainers.image.source = "https://github.com/sogno-platform/dpsim" + org.opencontainers.image.title="DPsim" \ + org.opencontainers.image.licenses="MPL 2.0" \ + org.opencontainers.image.url="http://dpsim.fein-aachen.org/" \ + org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" COPY . /dpsim/ RUN rm -rf /dpsim/build && mkdir /dpsim/build diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index 770742d020..ed9c714efc 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -1,8 +1,8 @@ -FROM fedora:36 AS base +FROM fedora:42 AS base ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 ARG CIMPP_COMMIT=1b11d5c17bedf0ae042628b42ecb4e49df70b2f6 -ARG VILLAS_VERSION=18cdd2a6364d05fbf413ca699616cd324abfcb54 +ARG VILLAS_VERSION=825237cb11f687169a9455ecaa97b5dc6cbce26e ARG CMAKE_OPTS ARG MAKE_OPTS=-j4 @@ -22,7 +22,10 @@ RUN dnf -y install \ rpmdevtools rpm-build \ make cmake pkgconfig \ python3-pip \ - cppcheck + cppcheck \ + flex bison \ + protobuf-compiler protobuf-c-compiler \ + clang-tools-extra # Tools needed for developement RUN dnf -y install \ @@ -71,9 +74,8 @@ RUN dnf -y install \ protobuf-c-devel # Python dependencies -ADD requirements.txt . -RUN pip3 install --upgrade wheel build setuptools packaging -RUN pip3 install -r requirements.txt +COPY requirements.txt . +RUN pip3 install --upgrade wheel build setuptools packaging && pip3 install -r requirements.txt # Install CIMpp from source RUN cd /tmp && \ @@ -89,14 +91,14 @@ RUN cd /tmp && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/libcimpp -# Install VILLASnode from source +# Install VILLASnode from source (with fpga support) RUN cd /tmp && \ git clone --recurse-submodules https://github.com/VILLASframework/node.git villas-node && \ mkdir -p villas-node/build && cd villas-node/build && \ git checkout ${VILLAS_VERSION} && \ cmake ${CMAKE_OPTS} .. \ -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ - -DDOWNLOAD_GO=OFF && \ + -DCMAKE_BUILD_TYPE=Release && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node diff --git a/packaging/Docker/Dockerfile.dev-minimal b/packaging/Docker/Dockerfile.dev-minimal index 08c6bd01e0..55b32b3f24 100644 --- a/packaging/Docker/Dockerfile.dev-minimal +++ b/packaging/Docker/Dockerfile.dev-minimal @@ -1,10 +1,10 @@ -FROM fedora:36 +FROM fedora:42 LABEL \ - org.opencontainers.image.title = "DPsim" \ - org.opencontainers.image.licenses = "MPL 2.0" \ - org.opencontainers.image.url = "http://dpsim.fein-aachen.org/" \ - org.opencontainers.image.source = "https://github.com/sogno-platform/dpsim" + org.opencontainers.image.title="DPsim" \ + org.opencontainers.image.licenses="MPL 2.0" \ + org.opencontainers.image.url="http://dpsim.fein-aachen.org/" \ + org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" RUN dnf -y update @@ -22,8 +22,7 @@ RUN dnf --refresh -y install \ spdlog-devel # Python dependencies -ADD requirements.txt . -RUN pip3 install --upgrade wheel build setuptools packaging -RUN pip3 install -r requirements.txt +COPY requirements.txt . +RUN pip3 install --upgrade wheel build setuptools packaging && pip3 install -r requirements.txt EXPOSE 8888 From 69552382ffce15f3c8b43f03a3c676c6a94f7705 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 17 Apr 2025 18:42:43 +0200 Subject: [PATCH 082/168] Add a logger to the Timer Signed-off-by: Leonardo Carreras --- dpsim/include/dpsim/Timer.h | 8 +++++++- dpsim/src/Timer.cpp | 23 ++++++++++++++++------- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/dpsim/include/dpsim/Timer.h b/dpsim/include/dpsim/Timer.h index 4008d9b8ad..2f0cf09c69 100644 --- a/dpsim/include/dpsim/Timer.h +++ b/dpsim/include/dpsim/Timer.h @@ -10,6 +10,7 @@ #include +#include #include namespace DPsim { @@ -42,10 +43,15 @@ class Timer { long long mTicks; int mFlags; + /// Timer log level + CPS::Logger::Level mLogLevel; + /// Logger + CPS::Logger::Log mSLog; + public: enum Flags : int { fail_on_overrun = 1 }; - Timer(int flags = 0); + Timer(int flags = 0, CPS::Logger::Level logLevel = CPS::Logger::Level::debug); ~Timer(); diff --git a/dpsim/src/Timer.cpp b/dpsim/src/Timer.cpp index 02a2f78895..b8c564c313 100644 --- a/dpsim/src/Timer.cpp +++ b/dpsim/src/Timer.cpp @@ -20,16 +20,18 @@ using namespace DPsim; using CPS::SystemError; -Timer::Timer(int flags) - : mState(stopped), mOverruns(0), mTicks(0), mFlags(flags) { +Timer::Timer(int flags, CPS::Logger::Level logLevel) + : mState(stopped), mOverruns(0), mTicks(0), mFlags(flags), + mLogLevel(logLevel) { #ifdef HAVE_TIMERFD mTimerFd = timerfd_create(CLOCK_MONOTONIC, 0); if (mTimerFd < 0) { + SPDLOG_LOGGER_ERROR(mSLog, "Failed to create timerfd"); throw SystemError("Failed to create timerfd"); } #else - std::cerr << "WARNING: No high resolution timer available. Clock might drift!" - << std::endl; + SPDLOG_LOGGER_WARN(mSLog, + "No high resolution timer available. Clock might drift!"); #endif } @@ -38,7 +40,9 @@ Timer::~Timer() { try { stop(); } catch (SystemError &e) { - std::cerr << "ERROR: The timer was not stopped properly: " << std::endl; + SPDLOG_LOGGER_ERROR(mSLog, + "The timer was not stopped properly. The simulation " + "behaviour is not guaranteed anymore."); } #ifdef HAVE_TIMERFD @@ -54,6 +58,7 @@ void Timer::sleep() { bytes = read(mTimerFd, &ticks, sizeof(ticks)); if (bytes < 0) { + SPDLOG_LOGGER_ERROR(mSLog, "Read from timerfd failed"); throw SystemError("Read from timerfd failed"); } #else @@ -73,9 +78,13 @@ void Timer::sleep() { mTicks += ticks; if (overruns > 0) { - //SPDLOG_LOGGER_WARN(mSLog, "Timer overrun of {} timesteps at {}", overruns, mTime); - if (mFlags & Flags::fail_on_overrun) + SPDLOG_LOGGER_WARN(mSLog, "Timer overrun of {} timesteps at {}", overruns, + mTicks); + if (mFlags & Flags::fail_on_overrun) { + SPDLOG_LOGGER_ERROR(mSLog, "The overrun has made the simulation to fail " + "because the flag is active"); throw OverrunException{overruns}; + } } } From d3929342062404293987ced6c8bd51f93a81741b Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Sun, 20 Apr 2025 15:13:49 +0200 Subject: [PATCH 083/168] Add libre to Dockerfile fix one of the real-time errors using villas Signed-off-by: Leonardo Carreras --- packaging/Docker/Dockerfile.dev | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index ed9c714efc..a44c95d25d 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -71,7 +71,8 @@ RUN dnf -y install \ libconfig-devel \ libnl3-devel \ protobuf-devel \ - protobuf-c-devel + protobuf-c-devel \ + libre-devel # Python dependencies COPY requirements.txt . From 72fec2485d6d5f6a05305c3b6a0c009cb73b4d1b Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Sun, 20 Apr 2025 20:49:54 +0200 Subject: [PATCH 084/168] Fix KLU Adapter: varying entry index passed without checkend for empty Signed-off-by: Leonardo Carreras --- dpsim/src/KLUAdapter.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/dpsim/src/KLUAdapter.cpp b/dpsim/src/KLUAdapter.cpp index ec3811f4be..81fbd91b5e 100644 --- a/dpsim/src/KLUAdapter.cpp +++ b/dpsim/src/KLUAdapter.cpp @@ -62,9 +62,22 @@ void KLUAdapter::preprocessing( } // This call also works if mVaryingColumns, mVaryingRows are empty - mSymbolic = - klu_analyze_partial(n, Ap, Ai, &mVaryingColumns[0], &mVaryingRows[0], - varying_entries, mPreordering, &mCommon); + int *colPtr = mVaryingColumns.empty() ? nullptr : &mVaryingColumns[0]; + int *rowPtr = mVaryingRows.empty() ? nullptr : &mVaryingRows[0]; + + mSymbolic = klu_analyze_partial(n, Ap, Ai, colPtr, rowPtr, varying_entries, + mPreordering, &mCommon); + + if (mVaryingColumns.empty()) { + SPDLOG_LOGGER_INFO( + mSLog, + "KLUAdapter: No variable COLUMN entries passed to klu_analyze_partial"); + } + if (mVaryingRows.empty()) { + SPDLOG_LOGGER_INFO( + mSLog, + "KLUAdapter: No variable ROW entries passed to klu_analyze_partial"); + } /* Store non-zero value of current preprocessed matrix. only used until * to-do in refactorize-function is resolved. Can be removed then. From d22dcea731df1cc239b1c3ff147705e80f5934a0 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 21 Apr 2025 13:28:32 +0200 Subject: [PATCH 085/168] Fix initialization of logger in Timer Signed-off-by: Leonardo Carreras --- dpsim/src/Timer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/dpsim/src/Timer.cpp b/dpsim/src/Timer.cpp index b8c564c313..73c9390878 100644 --- a/dpsim/src/Timer.cpp +++ b/dpsim/src/Timer.cpp @@ -23,6 +23,7 @@ using CPS::SystemError; Timer::Timer(int flags, CPS::Logger::Level logLevel) : mState(stopped), mOverruns(0), mTicks(0), mFlags(flags), mLogLevel(logLevel) { + mSLog = CPS::Logger::get("Timer"); #ifdef HAVE_TIMERFD mTimerFd = timerfd_create(CLOCK_MONOTONIC, 0); if (mTimerFd < 0) { From c10572cd05e7222395356fd47808471ec1755316 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 12 May 2025 00:05:25 +0200 Subject: [PATCH 086/168] fix undeclared destructors Signed-off-by: Leonardo Carreras --- dpsim/include/dpsim/DataLoggerInterface.h | 2 ++ dpsim/include/dpsim/Interface.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/dpsim/include/dpsim/DataLoggerInterface.h b/dpsim/include/dpsim/DataLoggerInterface.h index 393f77a53a..7b17e5f97c 100644 --- a/dpsim/include/dpsim/DataLoggerInterface.h +++ b/dpsim/include/dpsim/DataLoggerInterface.h @@ -28,6 +28,8 @@ class DataLoggerInterface { DataLoggerInterface() : mAttributes(){}; + virtual ~DataLoggerInterface() = default; + // Start the logger. After starting the number of columns should not be changed. virtual void start() = 0; // Stops the logger. Afterwards it should not be used anymore. diff --git a/dpsim/include/dpsim/Interface.h b/dpsim/include/dpsim/Interface.h index f4b3c473bf..2a8d6c6436 100644 --- a/dpsim/include/dpsim/Interface.h +++ b/dpsim/include/dpsim/Interface.h @@ -27,6 +27,8 @@ class Interface : public SharedFactory { mLog = CPS::Logger::get("Interface", logLevel); }; + virtual ~Interface() = default; + virtual void open() = 0; virtual void close() = 0; From 87173edd2abd03c1df37094fdc64a42217c135d7 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 12 May 2025 00:05:52 +0200 Subject: [PATCH 087/168] fix undeclared temporary variables (sonarcloud) Signed-off-by: Leonardo Carreras --- dpsim/src/pybind/Attributes.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/dpsim/src/pybind/Attributes.cpp b/dpsim/src/pybind/Attributes.cpp index a2bf8c1822..8acbc6729f 100644 --- a/dpsim/src/pybind/Attributes.cpp +++ b/dpsim/src/pybind/Attributes.cpp @@ -33,7 +33,9 @@ void addAttributes(py::module_ m) { CPS::AttributeBase>(m, "AttributeReal") .def("get", &CPS::Attribute::get) .def("set", &CPS::Attribute::set) - .def("derive_scaled", &CPS::Attribute::deriveScaled); + .def("derive_scaled", + py::overload_cast( + &CPS::Attribute::template deriveScaled)); py::class_, CPS::AttributePointer>, @@ -48,11 +50,22 @@ void addAttributes(py::module_ m) { CPS::AttributeBase>(m, "AttributeComplex") .def("get", &CPS::Attribute::get) .def("set", &CPS::Attribute::set) - .def("derive_real", &CPS::Attribute::deriveReal) - .def("derive_imag", &CPS::Attribute::deriveImag) - .def("derive_mag", &CPS::Attribute::deriveMag) - .def("derive_phase", &CPS::Attribute::derivePhase) - .def("derive_scaled", &CPS::Attribute::deriveScaled); + .def("derive_real", + py::overload_cast<>( + &CPS::Attribute::template deriveReal<>)) + .def("derive_imag", + py::overload_cast<>( + &CPS::Attribute::template deriveImag<>)) + .def("derive_mag", + py::overload_cast<>( + &CPS::Attribute::template deriveMag<>)) + .def("derive_phase", + py::overload_cast<>( + &CPS::Attribute::template derivePhase<>)) + .def("derive_scaled", + py::overload_cast( + &CPS::Attribute::template deriveScaled< + CPS::Complex>)); py::class_, CPS::AttributePointer>, From a65ed48873791f1a6485e2bc8cf5d64a8e08ee50 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 12 May 2025 00:07:01 +0200 Subject: [PATCH 088/168] fix fedora container error in mosquito install and update villas version Signed-off-by: Leonardo Carreras --- packaging/Docker/Dockerfile.dev | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index a44c95d25d..74ca75c460 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -2,7 +2,7 @@ FROM fedora:42 AS base ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 ARG CIMPP_COMMIT=1b11d5c17bedf0ae042628b42ecb4e49df70b2f6 -ARG VILLAS_VERSION=825237cb11f687169a9455ecaa97b5dc6cbce26e +ARG VILLAS_VERSION=4df38d26d425117e538ad74bef27e62e353aadc3 ARG CMAKE_OPTS ARG MAKE_OPTS=-j4 @@ -66,7 +66,8 @@ RUN dnf -y install \ libwebsockets-devel # Install optional VILLASnode dependencies -RUN dnf -y install \ +RUN dnf -y remove systemd-standalone-tmpfiles || true && \ + dnf -y install \ mosquitto-devel \ libconfig-devel \ libnl3-devel \ From 49c8121e43433b634f3c88a203252984868e2b9d Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 12 May 2025 00:07:29 +0200 Subject: [PATCH 089/168] fix rocky container and update villas version Signed-off-by: Leonardo Carreras --- packaging/Docker/Dockerfile.dev-rocky | 55 ++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/packaging/Docker/Dockerfile.dev-rocky b/packaging/Docker/Dockerfile.dev-rocky index 6de7efc427..493dde36d0 100644 --- a/packaging/Docker/Dockerfile.dev-rocky +++ b/packaging/Docker/Dockerfile.dev-rocky @@ -2,6 +2,7 @@ FROM rockylinux:9 ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 ARG CIMPP_COMMIT=1b11d5c17bedf0ae042628b42ecb4e49df70b2f6 +ARG VILLAS_VERSION=4df38d26d425117e538ad74bef27e62e353aadc3 ARG CMAKE_OPTS ARG MAKE_OPTS=-j4 @@ -40,7 +41,9 @@ RUN dnf -y install \ wget \ libarchive \ openblas-devel \ - gcc-gfortran + gcc-gfortran \ + coreutils-single \ + glib2-devel # Dependencies RUN dnf --refresh -y install \ @@ -61,7 +64,16 @@ RUN dnf -y install \ jansson-devel \ mosquitto-devel \ libjpeg-devel \ - zlib-devel + zlib-devel \ + protobuf-c-devel \ + protobuf-devel \ + libmodbus-devel \ + librdkafka-devel \ + zeromq-devel \ + libusb-devel \ + lua-devel \ + nanomsg-devel \ + git-svn # CUDARPC and dependencies RUN dnf install -y \ @@ -90,6 +102,14 @@ RUN dnf -y install \ qt5-qtbase qt5-qtsvg RUN pip3 install gprof2dot +# Build & Install sundials +RUN cd /tmp && \ + git clone --branch v3.2.1 --recurse-submodules --depth 1 https://github.com/LLNL/sundials.git && \ + mkdir -p sundials/build && cd sundials/build && \ + cmake ${CMAKE_OPTS} .. \ + -DCMAKE_BUILD_TYPE=Release && \ + make ${MAKE_OPTS} install + # Install CIMpp from source RUN cd /tmp && \ git clone https://github.com/sogno-platform/libcimpp.git && \ @@ -116,17 +136,32 @@ RUN cd /tmp && \ -DBUILD_SHARED_LIBS=on && \ make ${MAKE_OPTS} install && rm -rf /tmp/magma-2.6.0 +# Install VILLASnode and deps from source +ENV CMAKE_OPTS="${CMAKE_OPTS} \ + -DCMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc \ + -DCMAKE_CUDA_ARCHITECTURES=60;61;70;75" + +RUN cd /tmp && \ + git clone --recurse-submodules https://github.com/VILLASframework/node.git villas-node && \ + cd villas-node && \ + git checkout ${VILLAS_VERSION} && \ + env MAKE_OPTS="" DEPS_NONINTERACTIVE=1 bash packaging/deps.sh && \ + mkdir -p build && cd build && \ + cmake ${CMAKE_OPTS} .. \ + -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ + -DCMAKE_CUDA_FLAGS="-Xcompiler=-Wall,-Werror" && \ + make ${MAKE_OPTS} install && \ + rm -rf /tmp/villas-node + # CIMpp and VILLASnode are installed here ENV LD_LIBRARY_PATH="/usr/local/lib64:${LD_LIBRARY_PATH}" -# # Python dependencies -# ADD requirements.txt . -# RUN pip3 install --upgrade wheel build setuptools packaging -# RUN pip3 install -r requirements.txt +# This is a hack: the VILLASnode build system does not install the libraries in the correct location for OpenDSS +RUN echo "/usr/local/openDSSC/bin" > /etc/ld.so.conf.d/opendssc.conf && \ + ldconfig -# # Remove this part in the future and use dedicated Jupyter Dockerfile -# # Activate Jupyter extensions -# RUN dnf -y --refresh install npm -# RUN pip3 install jupyter jupyter_contrib_nbextensions nbconvert nbformat +# Python dependencies +COPY requirements.txt requirements.txt +RUN pip3 install --upgrade wheel build setuptools packaging && pip3 install -r requirements.txt EXPOSE 8888 From 9f6da1fcb96ce7bc6536e1879fd59d445830d88a Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 12 May 2025 00:07:56 +0200 Subject: [PATCH 090/168] activate pybind in clang compilation using rocky Signed-off-by: Leonardo Carreras --- .github/workflows/build_test_linux_rocky.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_test_linux_rocky.yaml b/.github/workflows/build_test_linux_rocky.yaml index 7bf8ce1777..1f97e9e2cb 100644 --- a/.github/workflows/build_test_linux_rocky.yaml +++ b/.github/workflows/build_test_linux_rocky.yaml @@ -60,7 +60,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{ github.workspace }}/build - run: cmake $GITHUB_WORKSPACE -DFETCH_SPDLOG=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang -DWITH_PYBIND=OFF + run: cmake $GITHUB_WORKSPACE -DFETCH_SPDLOG=ON -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang - name: Build every target shell: bash From 412b488dc6049c94bb5f159122255435a41b2a68 Mon Sep 17 00:00:00 2001 From: Anas Bahr Date: Thu, 3 Jul 2025 23:25:26 +0200 Subject: [PATCH 091/168] Add coverage option to CMakeLists.txt Signed-off-by: Anas Bahr --- CMakeLists.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2504453be5..d6a919b346 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,15 @@ set(PROJECT_HOMEPAGE_URL "https://dpsim.fein-aachen.org/") set(PROJECT_VCS_URL "https://github.com/sogno-platform/dpsim") # Build options + +option(COVERAGE "Enable code coverage reporting" OFF) + +if(COVERAGE AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") + message(STATUS "Enabling code coverage") + add_compile_options(--coverage -O0 -g) + add_link_options(--coverage) +endif() + option(FETCH_EIGEN "Fetch Eigen3 as module" OFF) option(FETCH_SUITESPARSE "Fetch SuiteSparse as module" ON) option(FETCH_SPDLOG "Fetch spdlog as module" OFF) From 80aed44b3a0dcc58eedfaad6b72eaad943dfe8d7 Mon Sep 17 00:00:00 2001 From: Anas Bahr Date: Fri, 4 Jul 2025 00:01:31 +0200 Subject: [PATCH 092/168] Update yaml file for code coverage Signed-off-by: Anas Bahr --- .../workflows/build_test_linux_fedora.yaml | 38 ++++++++++++++++--- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_test_linux_fedora.yaml b/.github/workflows/build_test_linux_fedora.yaml index a0ee5f3818..e05410560b 100644 --- a/.github/workflows/build_test_linux_fedora.yaml +++ b/.github/workflows/build_test_linux_fedora.yaml @@ -31,7 +31,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{ github.workspace }}/build - run: cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 $GITHUB_WORKSPACE + run: cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 -DCOVERAGE=ON $GITHUB_WORKSPACE - name: Build dpsimpy and test examples shell: bash @@ -67,7 +67,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{ github.workspace }}/build - run: cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 $GITHUB_WORKSPACE + run: cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 -DCOVERAGE=ON $GITHUB_WORKSPACE - name: Build every target shell: bash @@ -113,16 +113,15 @@ jobs: - name: Install parallel testing shell: bash - run: pip install pytest-xdist + run: pip install pytest pytest-xdist pytest-cov nbformat nbconvert - name: Run pytest shell: bash working-directory: ${{ github.workspace }} env: PYTHONPATH: "${{ github.workspace }}/build" - run: | - cp -r python/src/dpsim build/ - pytest -v examples/Notebooks -n auto + run: pytest -n auto --cov --cov-branch --cov-report=xml examples/Notebooks/ + continue-on-error: true - name: Archive notebook outputs uses: actions/upload-artifact@v4 @@ -130,6 +129,33 @@ jobs: name: pytest-output-${{ github.sha }} path: outputs/ + - name: Install lcov + run: sudo dnf install -y lcov + + - name: Generate lcov report + run: | + lcov --capture --directory . --output-file coverage.info --rc lcov_branch_coverage=1 --ignore-errors mismatch + lcov --remove coverage.info '/usr/*' '*/test/*' --output-file coverage.cleaned.info + lcov --list coverage.cleaned.info + continue-on-error: true + + - name: Upload coverage artifacts + uses: actions/upload-artifact@v4 + with: + name: coverage-fedora--${{ github.sha }} + path: | + build/coverage.info + build/coverage_report/ + build/**/*.gc* + ${{ github.workspace }}/src/**/*.cpp + + + - name: Upload coverage report + uses: codecov/codecov-action@v5 + with: + token: ${{ secrets.CODECOV_TOKEN }} + slug: sogno-platform/dpsim + compare-notebook-results: name: Compare Notebook results runs-on: ubuntu-latest From ed6dd4ab25d3d782737e825bc0ef671a87e71f41 Mon Sep 17 00:00:00 2001 From: Florian Oppermann <58732614+Haifischbecken@users.noreply.github.com> Date: Fri, 4 Jul 2025 14:02:59 +0200 Subject: [PATCH 093/168] Add codecove badge Signed-off-by: Florian Oppermann <58732614+Haifischbecken@users.noreply.github.com> --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 480f875087..731536113e 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ [![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0) +[![codecov](https://codecov.io/gh/sogno-platform/dpsim/graph/badge.svg?token=FLUOQ8U7MH)](https://codecov.io/gh/sogno-platform/dpsim) + DPsim is a solver library for dynamic power system simulation. - It supports both the electromagnetic transient (EMT) and dynamic phasor (DP) domain for dynamic simulation. From 1a60014d3cd83f6e1abff7ec720c1089ab1cd62a Mon Sep 17 00:00:00 2001 From: Georgii Tishenin Date: Mon, 7 Jul 2025 12:29:32 +0200 Subject: [PATCH 094/168] Do not continue on error in "Run pytest" and "Generate lcov report" steps Signed-off-by: Georgii Tishenin --- .github/workflows/build_test_linux_fedora.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_test_linux_fedora.yaml b/.github/workflows/build_test_linux_fedora.yaml index e05410560b..9dfa72949e 100644 --- a/.github/workflows/build_test_linux_fedora.yaml +++ b/.github/workflows/build_test_linux_fedora.yaml @@ -120,8 +120,9 @@ jobs: working-directory: ${{ github.workspace }} env: PYTHONPATH: "${{ github.workspace }}/build" - run: pytest -n auto --cov --cov-branch --cov-report=xml examples/Notebooks/ - continue-on-error: true + run: | + cp -r python/src/dpsim build/ + pytest -n auto --cov --cov-branch --cov-report=xml examples/Notebooks/ - name: Archive notebook outputs uses: actions/upload-artifact@v4 @@ -135,9 +136,8 @@ jobs: - name: Generate lcov report run: | lcov --capture --directory . --output-file coverage.info --rc lcov_branch_coverage=1 --ignore-errors mismatch - lcov --remove coverage.info '/usr/*' '*/test/*' --output-file coverage.cleaned.info + lcov --remove coverage.info '/usr/*' --output-file coverage.cleaned.info lcov --list coverage.cleaned.info - continue-on-error: true - name: Upload coverage artifacts uses: actions/upload-artifact@v4 From 73e20cb0bc68b56613c3312c9e8b694fc701ab60 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Fri, 26 Aug 2022 15:04:16 +0200 Subject: [PATCH 095/168] Implement new Dockerfile for binder. Signed-off-by: Steffen Vogel Signed-off-by: Andres Acosta --- .gitmodules | 3 + Dockerfile | 128 +++++++++++++++++++++++++++++++++ apt.txt | 7 ++ examples/Notebooks/MSP-lecture | 1 + 4 files changed, 139 insertions(+) create mode 100644 .gitmodules create mode 100644 Dockerfile create mode 100644 apt.txt create mode 160000 examples/Notebooks/MSP-lecture diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..26a8b7153b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "examples/Notebooks/MSP-lecture"] + path = examples/Notebooks/MSP-lecture + url = https://git.rwth-aachen.de/acs/public/teaching/msp/notebooks.git diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..1ad47f3ad7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,128 @@ +FROM fedora:36 AS base + +ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 +ARG VILLAS_VERSION=411b0ad49e2629ad41c6918d2a6c51e9a72220b4 + +ARG CMAKE_OPTS +ARG MAKE_OPTS=-j4 + +ARG NotebookApp.default_url +ARG ip +ARG port + +LABEL \ + org.opencontainers.image.title="DPsim" \ + org.opencontainers.image.licenses="MPL 2.0" \ + org.opencontainers.image.url="http://dpsim.fein-aachen.org/" \ + org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" + +RUN dnf -y update + +# Toolchain +RUN dnf -y install \ + gcc gcc-c++ clang \ + git \ + rpmdevtools rpm-build \ + make cmake pkgconfig \ + python3-pip \ + cppcheck + +# Tools needed for developement +RUN dnf -y install \ + doxygen graphviz \ + gdb \ + procps-ng + +# Dependencies +RUN dnf --refresh -y install \ + python3-devel \ + eigen3-devel \ + libxml2-devel \ + graphviz-devel \ + spdlog-devel \ + fmt-devel + +# Install some debuginfos +RUN dnf -y debuginfo-install \ + python3 + +# Build & Install sundials +RUN cd /tmp && \ + git clone --branch v3.2.1 --recurse-submodules --depth 1 https://github.com/LLNL/sundials.git && \ + mkdir -p sundials/build && cd sundials/build && \ + cmake ${CMAKE_OPTS} .. \ + -DCMAKE_BUILD_TYPE=Release && \ + make ${MAKE_OPTS} install + +# CIMpp and VILLASnode are installed here +ENV LD_LIBRARY_PATH="/usr/local/lib64:${LD_LIBRARY_PATH}" + +# Install minimal VILLASnode dependencies +RUN dnf -y install \ + openssl-devel \ + libuuid-devel \ + libcurl-devel \ + jansson-devel \ + libwebsockets-devel + +# Install optional VILLASnode dependencies +RUN dnf -y install \ + mosquitto-devel \ + libconfig-devel \ + libnl3-devel + +# Python dependencies +ADD requirements.txt . +RUN pip3 install --upgrade wheel build +RUN pip3 install -r requirements.txt + +# Install CIMpp from source +RUN cd /tmp && \ + git clone --recurse-submodules --depth 1 https://github.com/cim-iec/libcimpp.git && \ + mkdir -p libcimpp/build && cd libcimpp/build && \ + cmake ${CMAKE_OPTS} ..\ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ + -DUSE_CIM_VERSION=${CIM_VERSION} \ + -DBUILD_ARABICA_EXAMPLES=OFF && \ + make ${MAKE_OPTS} install && \ + rm -rf /tmp/libcimpp + +# Install VILLASnode from source +RUN cd /tmp && \ + git clone --recurse-submodules https://github.com/VILLASframework/node.git villas-node && \ + mkdir -p villas-node/build && cd villas-node/build && \ + git checkout ${VILLAS_VERSION} && \ + cmake ${CMAKE_OPTS} .. \ + -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ + -DDOWNLOAD_GO=OFF && \ + make ${MAKE_OPTS} install && \ + rm -rf /tmp/villas-node + +RUN pip3 install --no-cache \ + jupyter \ + jupyterlab \ + jupyter_contrib_nbextensions \ + nbconvert \ + nbformat + +ARG NB_USER=jovyan +ARG NB_UID=1000 +ENV USER ${NB_USER} +ENV NB_UID ${NB_UID} +ENV HOME /home/${NB_USER} + +RUN adduser \ + --comment "Default user" \ + --uid ${NB_UID} \ + ${NB_USER} + +COPY . ${HOME}/dpsim +USER root +RUN chown -R ${NB_UID} ${HOME} +USER ${NB_USER} +RUN rm -rf ${HOME}/dpsim/build && mkdir ${HOME}/dpsim/build +WORKDIR ${HOME}/dpsim + +RUN python3 -m build --wheel +RUN python3 -m pip install ./dist/dpsim* diff --git a/apt.txt b/apt.txt new file mode 100644 index 0000000000..0bea444c05 --- /dev/null +++ b/apt.txt @@ -0,0 +1,7 @@ +gcc +gcc-c++ +clang +make +cmake +pkgconfig +cppcheck diff --git a/examples/Notebooks/MSP-lecture b/examples/Notebooks/MSP-lecture new file mode 160000 index 0000000000..628f946f48 --- /dev/null +++ b/examples/Notebooks/MSP-lecture @@ -0,0 +1 @@ +Subproject commit 628f946f481cd92f9ff9c1e37d2ebf9ca7f7102a From 4d8c1af2111184534fec293fa2c9ef34520b5467 Mon Sep 17 00:00:00 2001 From: Andres Acosta Date: Sun, 22 Dec 2024 17:26:09 +0100 Subject: [PATCH 096/168] Improvements to Index Notebook and binder Dockerfile. Signed-off-by: Andres Acosta Co-authored-by: Steffen Vogel --- .gitmodules | 3 - Dockerfile | 106 +-------------------------------- README.md | 6 ++ apt.txt | 7 --- examples/Index.ipynb | 9 ++- examples/Notebooks/MSP-lecture | 1 - 6 files changed, 16 insertions(+), 116 deletions(-) delete mode 100644 .gitmodules delete mode 100644 apt.txt delete mode 160000 examples/Notebooks/MSP-lecture diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 26a8b7153b..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "examples/Notebooks/MSP-lecture"] - path = examples/Notebooks/MSP-lecture - url = https://git.rwth-aachen.de/acs/public/teaching/msp/notebooks.git diff --git a/Dockerfile b/Dockerfile index 1ad47f3ad7..106a65ef00 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,111 +1,11 @@ -FROM fedora:36 AS base +# sogno/dpsim:dev is built by dpsim-git/packaging/Docker/Dockerfile.dev +ARG BASE_IMAGE=sogno/dpsim:dev -ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 -ARG VILLAS_VERSION=411b0ad49e2629ad41c6918d2a6c51e9a72220b4 - -ARG CMAKE_OPTS -ARG MAKE_OPTS=-j4 +FROM ${BASE_IMAGE} ARG NotebookApp.default_url ARG ip ARG port - -LABEL \ - org.opencontainers.image.title="DPsim" \ - org.opencontainers.image.licenses="MPL 2.0" \ - org.opencontainers.image.url="http://dpsim.fein-aachen.org/" \ - org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" - -RUN dnf -y update - -# Toolchain -RUN dnf -y install \ - gcc gcc-c++ clang \ - git \ - rpmdevtools rpm-build \ - make cmake pkgconfig \ - python3-pip \ - cppcheck - -# Tools needed for developement -RUN dnf -y install \ - doxygen graphviz \ - gdb \ - procps-ng - -# Dependencies -RUN dnf --refresh -y install \ - python3-devel \ - eigen3-devel \ - libxml2-devel \ - graphviz-devel \ - spdlog-devel \ - fmt-devel - -# Install some debuginfos -RUN dnf -y debuginfo-install \ - python3 - -# Build & Install sundials -RUN cd /tmp && \ - git clone --branch v3.2.1 --recurse-submodules --depth 1 https://github.com/LLNL/sundials.git && \ - mkdir -p sundials/build && cd sundials/build && \ - cmake ${CMAKE_OPTS} .. \ - -DCMAKE_BUILD_TYPE=Release && \ - make ${MAKE_OPTS} install - -# CIMpp and VILLASnode are installed here -ENV LD_LIBRARY_PATH="/usr/local/lib64:${LD_LIBRARY_PATH}" - -# Install minimal VILLASnode dependencies -RUN dnf -y install \ - openssl-devel \ - libuuid-devel \ - libcurl-devel \ - jansson-devel \ - libwebsockets-devel - -# Install optional VILLASnode dependencies -RUN dnf -y install \ - mosquitto-devel \ - libconfig-devel \ - libnl3-devel - -# Python dependencies -ADD requirements.txt . -RUN pip3 install --upgrade wheel build -RUN pip3 install -r requirements.txt - -# Install CIMpp from source -RUN cd /tmp && \ - git clone --recurse-submodules --depth 1 https://github.com/cim-iec/libcimpp.git && \ - mkdir -p libcimpp/build && cd libcimpp/build && \ - cmake ${CMAKE_OPTS} ..\ - -DBUILD_SHARED_LIBS=ON \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ - -DUSE_CIM_VERSION=${CIM_VERSION} \ - -DBUILD_ARABICA_EXAMPLES=OFF && \ - make ${MAKE_OPTS} install && \ - rm -rf /tmp/libcimpp - -# Install VILLASnode from source -RUN cd /tmp && \ - git clone --recurse-submodules https://github.com/VILLASframework/node.git villas-node && \ - mkdir -p villas-node/build && cd villas-node/build && \ - git checkout ${VILLAS_VERSION} && \ - cmake ${CMAKE_OPTS} .. \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ - -DDOWNLOAD_GO=OFF && \ - make ${MAKE_OPTS} install && \ - rm -rf /tmp/villas-node - -RUN pip3 install --no-cache \ - jupyter \ - jupyterlab \ - jupyter_contrib_nbextensions \ - nbconvert \ - nbformat - ARG NB_USER=jovyan ARG NB_UID=1000 ENV USER ${NB_USER} diff --git a/README.md b/README.md index 731536113e..3106bae0fa 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,12 @@ DPsim is a solver library for dynamic power system simulation. - It can load models in the IEC61970 CIM / CGMES XML format. - It can be interfaced to a variety of protocols and interfaces via [VILLASnode](https://fein-aachen.org/projects/villas-node/). +## Getting started using Binder + +Click the badge below to explore the interactive Jupyter notebooks in your browser: + +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/sogno-platform/dpsim/mybinder?labpath=examples%2FNotebooks%2FQuickstart+Guide.ipynb) + ## Documentation The [documentation](https://dpsim.fein-aachen.org/) has build / installation instructions, links to examples and explains the concepts implemented in DPsim as well as its architecture. diff --git a/apt.txt b/apt.txt deleted file mode 100644 index 0bea444c05..0000000000 --- a/apt.txt +++ /dev/null @@ -1,7 +0,0 @@ -gcc -gcc-c++ -clang -make -cmake -pkgconfig -cppcheck diff --git a/examples/Index.ipynb b/examples/Index.ipynb index 6e61e5522d..f53a3155c0 100644 --- a/examples/Index.ipynb +++ b/examples/Index.ipynb @@ -15,8 +15,13 @@ "## Examples\n", "\n", "Welcome to the examples collection of DPsim. These examples are a good way to start using DPsim. \\\n", - "They cover DPsim's feature from [simple circuits](./Notebooks/Circuits/CS_R2CL.ipynb) and to more complex benchmarks models like the [IEEE/WSCC 9-bus system](./Notebooks/Grids/WSCC_9-bus_dyn_switch_python.ipynb). \\\n", - "A good place to start is the [Quickstart Guide](./Notebooks/Quickstart%20Guide.ipynb).\n", + "They cover DPsim's feature from [simple circuits](./Notebooks/Circuits/CS_R2CL.ipynb) and to more complex benchmarks models like the [IEEE/WSCC 9-bus system](./Notebooks/Grids/DP_WSCC9bus_SGTrStab_Switch.ipynb). \\\n", + "A good place to start is the [Quickstart Guide](./Notebooks/Quickstart%20Guide.ipynb). \\\n", + "Below you will find a list of representative examples.\n", + " - [Infinite bus system with Fault](./Notebooks/Circuits/DP_SP_SynGenTrStab_SMIB_Fault.ipynb) Shows how to implement the Kundur's SMIB system with a balanced fault from scratch and simulates it using Dynamic Phasors\n", + " - [Three bus system in steady state](./Notebooks/Circuits/DP_SP_SynGenTrStab_3Bus_SteadyState.ipynb) Shows how to implement a power system with multiple buses and generators from scratch and simulates it in dynamic steady state\n", + " - [Dynamic Simulation from CIM model](./Notebooks/Grids/DP_CIGRE_MV_withDG_withLoadStep.ipynb) Demonstrates how to implement a dynamic simulation by importing a grid model defined by the Common Information Model (CIM) specification\n", + " - [Power flow from MATPOWER model](./Notebooks/matpower-case9.ipynb) Demonstrates how to implement a power flow by importing a grid model defined in [MATPOWER](https://matpower.org/)\n", "\n", "## Project Website\n", "\n", diff --git a/examples/Notebooks/MSP-lecture b/examples/Notebooks/MSP-lecture deleted file mode 160000 index 628f946f48..0000000000 --- a/examples/Notebooks/MSP-lecture +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 628f946f481cd92f9ff9c1e37d2ebf9ca7f7102a From 24b45d7af81b4909d4fb58364d71dec2d844e064 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 31 Jan 2025 12:16:40 +0100 Subject: [PATCH 097/168] Update binder badge in README and adapt Dockerfile for local Binder deployment. Signed-off-by: pipeacosta Signed-off-by: Florian Oppermann --- Dockerfile | 14 ++++++++------ README.md | 2 +- examples/Index.ipynb | 3 +-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Dockerfile b/Dockerfile index 106a65ef00..f3e6f600d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,16 +8,18 @@ ARG ip ARG port ARG NB_USER=jovyan ARG NB_UID=1000 -ENV USER ${NB_USER} -ENV NB_UID ${NB_UID} -ENV HOME /home/${NB_USER} +ENV USER=${NB_USER} +ENV NB_UID=${NB_UID} +ENV HOME=/home/${NB_USER} RUN adduser \ - --comment "Default user" \ - --uid ${NB_UID} \ - ${NB_USER} + --comment "Default user" \ + --uid ${NB_UID} \ + ${NB_USER} COPY . ${HOME}/dpsim +ENV PATH="${HOME}/.local/bin:${PATH}" +RUN python3 -m pip install notebook jupyterlab jupyterhub USER root RUN chown -R ${NB_UID} ${HOME} USER ${NB_USER} diff --git a/README.md b/README.md index 3106bae0fa..d3b61b8bba 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ DPsim is a solver library for dynamic power system simulation. Click the badge below to explore the interactive Jupyter notebooks in your browser: -[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/sogno-platform/dpsim/mybinder?labpath=examples%2FNotebooks%2FQuickstart+Guide.ipynb) +[![Binder](https://2i2c.mybinder.org/badge_logo.svg)](https://2i2c.mybinder.org/v2/gh/sogno-platform/dpsim/mybinder?urlpath=%2Fdoc%2Ftree%2Fexamples%2FIndex.ipynb) ## Documentation diff --git a/examples/Index.ipynb b/examples/Index.ipynb index f53a3155c0..37f01409f8 100644 --- a/examples/Index.ipynb +++ b/examples/Index.ipynb @@ -16,8 +16,7 @@ "\n", "Welcome to the examples collection of DPsim. These examples are a good way to start using DPsim. \\\n", "They cover DPsim's feature from [simple circuits](./Notebooks/Circuits/CS_R2CL.ipynb) and to more complex benchmarks models like the [IEEE/WSCC 9-bus system](./Notebooks/Grids/DP_WSCC9bus_SGTrStab_Switch.ipynb). \\\n", - "A good place to start is the [Quickstart Guide](./Notebooks/Quickstart%20Guide.ipynb). \\\n", - "Below you will find a list of representative examples.\n", + "A good place to start is the [Quickstart Guide](./Notebooks/Quickstart%20Guide.ipynb). Below you will find a list of representative examples.\n", " - [Infinite bus system with Fault](./Notebooks/Circuits/DP_SP_SynGenTrStab_SMIB_Fault.ipynb) Shows how to implement the Kundur's SMIB system with a balanced fault from scratch and simulates it using Dynamic Phasors\n", " - [Three bus system in steady state](./Notebooks/Circuits/DP_SP_SynGenTrStab_3Bus_SteadyState.ipynb) Shows how to implement a power system with multiple buses and generators from scratch and simulates it in dynamic steady state\n", " - [Dynamic Simulation from CIM model](./Notebooks/Grids/DP_CIGRE_MV_withDG_withLoadStep.ipynb) Demonstrates how to implement a dynamic simulation by importing a grid model defined by the Common Information Model (CIM) specification\n", From 8f8e6efa9ca8ca374c7c13b5d95f5a300e3b36c1 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 4 Jul 2025 17:23:59 +0200 Subject: [PATCH 098/168] Add job for building the binder Dockerfile. Signed-off-by: pipeacosta --- .github/workflows/container.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index c38c36cc40..cd3784f13d 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -103,3 +103,23 @@ jobs: file: packaging/Docker/Dockerfile.manylinux push: true tags: sogno/dpsim:manylinux + + create-docker-binder: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Login to Docker Hub + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USER }} + password: ${{ secrets.DOCKERHUB_SECRET }} + + - name: Build and push + id: docker_build_release + uses: docker/build-push-action@v5 + with: + file: Dockerfile + push: true + tags: sogno/dpsim:binder From 9fbae0424c53b63debbdecb0736b685658422182 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sat, 5 Jul 2025 11:56:17 +0200 Subject: [PATCH 099/168] Move Dockerfile to new .binder folder. Signed-off-by: pipeacosta --- Dockerfile => .binder/Dockerfile | 0 .github/workflows/container.yaml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename Dockerfile => .binder/Dockerfile (100%) diff --git a/Dockerfile b/.binder/Dockerfile similarity index 100% rename from Dockerfile rename to .binder/Dockerfile diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index cd3784f13d..0bd470d519 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -120,6 +120,6 @@ jobs: id: docker_build_release uses: docker/build-push-action@v5 with: - file: Dockerfile + file: .binder/Dockerfile push: true tags: sogno/dpsim:binder From 43b4363a2e1bb1ee51fa72873705cdcc27a76310 Mon Sep 17 00:00:00 2001 From: Andres Acosta Date: Mon, 7 Jul 2025 16:05:56 +0200 Subject: [PATCH 100/168] Modify Binder badge to point to master branch. Signed-off-by: Andres Acosta --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d3b61b8bba..87cad62e63 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ DPsim is a solver library for dynamic power system simulation. Click the badge below to explore the interactive Jupyter notebooks in your browser: -[![Binder](https://2i2c.mybinder.org/badge_logo.svg)](https://2i2c.mybinder.org/v2/gh/sogno-platform/dpsim/mybinder?urlpath=%2Fdoc%2Ftree%2Fexamples%2FIndex.ipynb) +[![Binder](https://2i2c.mybinder.org/badge_logo.svg)](https://2i2c.mybinder.org/v2/gh/sogno-platform/dpsim/HEAD?urlpath=%2Fdoc%2Ftree%2Fexamples%2FIndex.ipynb) ## Documentation From a4045a168121696735b9c17c9840f79637e46674 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Fri, 29 Aug 2025 18:41:18 +0200 Subject: [PATCH 101/168] Fix the profiling workflow There are errors in the workflow, in particular with the reference to the used tag when running. Additionally, the tags and names of the test examples were organized and matched. Signed-off-by: Leonardo Carreras --- .../build_test_linux_rocky_profiling.yaml | 70 +++++++++---------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/.github/workflows/build_test_linux_rocky_profiling.yaml b/.github/workflows/build_test_linux_rocky_profiling.yaml index 476a0151ae..c63ac3ec26 100644 --- a/.github/workflows/build_test_linux_rocky_profiling.yaml +++ b/.github/workflows/build_test_linux_rocky_profiling.yaml @@ -3,68 +3,64 @@ name: Build & Profile RockyLinux on: workflow_dispatch: -## Build ## - jobs: profiling: name: Build with Profiling options runs-on: ubuntu-latest container: sogno/dpsim:dev-rocky steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - - name: Create Build Environment - run: mkdir build + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive - - name: Cache build directory - uses: actions/cache@v4 - with: - path: ${{ github.workspace }}/build - key: build-cache-rocky-profiling-${{ github.ref }} + - name: Create Build Environment + run: mkdir build - - name: Configure CMake - shell: bash - working-directory: ${{ github.workspace }}/build - run: cmake $GITHUB_WORKSPACE -DWITH_PROFILING=ON -DWITH_ASAN=ON -DWITH_CUDA=OFF -DFETCH_SPDLOG=ON + - name: Cache build directory + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}/build + key: build-cache-rocky-profiling-${{ github.ref }} - - name: Build every target - shell: bash - working-directory: ${{ github.workspace }}/build - run: cmake --build . --parallel $(nproc) + - name: Configure CMake + shell: bash + working-directory: ${{ github.workspace }}/build + run: cmake $GITHUB_WORKSPACE -DWITH_PROFILING=ON -DWITH_ASAN=ON -DWITH_CUDA=OFF -DFETCH_SPDLOG=ON + - name: Build every target + shell: bash + working-directory: ${{ github.workspace }}/build + run: cmake --build . --parallel $(nproc) -## Tests ## test-examples-1: - name: Test Examples 1/4 + name: Test Examples 1/4 - WSCC_9bus_mult_coupled needs: [profiling] - uses: sogno-platform/dpsim/.github/workflows/run_and_profile_example.yaml@${{github.ref}} + uses: sogno-platform/dpsim/.github/workflows/run_and_profile_example.yaml@main with: - path: ./build/dpsim/examples/cxx/WSCC_9bus_mult_decoupled - name: WSCC_9bus_mult_decoupled + path: ./build/dpsim/examples/cxx/WSCC_9bus_mult_coupled + name: WSCC_9bus_mult_coupled test-examples-2: - name: Test Examples 2/4 + name: Test Examples 2/4 - WSCC_9bus_mult_decoupled needs: [profiling] - uses: sogno-platform/dpsim/.github/workflows/run_and_profile_example.yaml@${{github.ref}} + uses: sogno-platform/dpsim/.github/workflows/run_and_profile_example.yaml@main with: - path: ./build/dpsim/examples/cxx/WSCC_9bus_mult_coupled - name: WSCC_9bus_mult_coupled + path: ./build/dpsim/examples/cxx/WSCC_9bus_mult_decoupled + name: WSCC_9bus_mult_decoupled test-examples-3: - name: Test Examples 3/4 + name: Test Examples 3/4 - EMT_WSCC_9bus_split_decoupled needs: [profiling] - uses: sogno-platform/dpsim/.github/workflows/run_and_profile_example.yaml@${{github.ref}} + uses: sogno-platform/dpsim/.github/workflows/run_and_profile_example.yaml@main with: path: ./build/dpsim/examples/cxx/EMT_WSCC_9bus_split_decoupled - name: WSCC_9bus_split_decoupled + name: EMT_WSCC_9bus_split_decoupled test-examples-4: - name: Test Examples 4/4 + name: Test Examples 4/4 - DP_WSCC_9bus_split_decoupled needs: [profiling] - uses: sogno-platform/dpsim/.github/workflows/run_and_profile_example.yaml@${{github.ref}} + uses: sogno-platform/dpsim/.github/workflows/run_and_profile_example.yaml@main with: path: ./build/dpsim/examples/cxx/DP_WSCC_9bus_split_decoupled - name: WSCC_9bus_split_decoupled + name: DP_WSCC_9bus_split_decoupled From 036745fb0a388f31a0eb2e447846a359cdb14ae0 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Fri, 29 Aug 2025 18:49:11 +0200 Subject: [PATCH 102/168] Fix the realtime datalogger There is a segmentation fault coming from the way the attributes are accessed for some cases. Additionally, now the model is added to DPsim.h and a more verbose behaviour is implemented when saving the memory dump. Signed-off-by: Leonardo Carreras --- dpsim/include/DPsim.h | 1 + dpsim/src/RealTimeDataLogger.cpp | 35 +++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/dpsim/include/DPsim.h b/dpsim/include/DPsim.h index 1ddb1d424e..599cd8b844 100644 --- a/dpsim/include/DPsim.h +++ b/dpsim/include/DPsim.h @@ -11,6 +11,7 @@ #include #ifndef _MSC_VER +#include #include #endif diff --git a/dpsim/src/RealTimeDataLogger.cpp b/dpsim/src/RealTimeDataLogger.cpp index 797c6fca1a..9f3c6101d9 100644 --- a/dpsim/src/RealTimeDataLogger.cpp +++ b/dpsim/src/RealTimeDataLogger.cpp @@ -4,12 +4,14 @@ * SPDX-FileCopyrightText: 2024 Niklas Eiling * SPDX-License-Identifier: Apache-2.0 */ -#include "dpsim-models/Attribute.h" + #include +#include -#include #include -#include + +#include +#include using namespace DPsim; @@ -41,6 +43,11 @@ void RealTimeDataLogger::start() { } void RealTimeDataLogger::stop() { + auto log = CPS::Logger::get("RealTimeDataLogger", CPS::Logger::Level::off, + CPS::Logger::Level::info); + log->info("Stopping real-time data logger. Writing memory to file {}", + mFilename.string()); + auto mLogFile = std::ofstream(mFilename, std::ios_base::out | std::ios_base::trunc); if (!mLogFile.is_open()) { @@ -59,6 +66,8 @@ void RealTimeDataLogger::stop() { mLogFile << '\n'; } mLogFile.close(); + log->info("Finished writing real-time data log to file {}.", + mFilename.string()); } void RealTimeDataLogger::log(Real time, Int timeStepCount) { @@ -76,15 +85,21 @@ void RealTimeDataLogger::log(Real time, Int timeStepCount) { mAttributeData[mCurrentRow][0] = time; mCurrentAttribute = 1; - for (auto it : mAttributes) { + for (auto &it : mAttributes) { + auto base = it.second.getPtr(); // std::shared_ptr + if (it.second->getType() == typeid(Real)) { - mAttributeData[mCurrentRow][mCurrentAttribute++] = - **std::dynamic_pointer_cast>>( - it.second.getPtr()); + auto attr = std::dynamic_pointer_cast>(base); + if (!attr) { /* skip */ + continue; + } + mAttributeData[mCurrentRow][mCurrentAttribute++] = attr->get(); } else if (it.second->getType() == typeid(Int)) { - mAttributeData[mCurrentRow][mCurrentAttribute++] = - **std::dynamic_pointer_cast>>( - it.second.getPtr()); + auto attr = std::dynamic_pointer_cast>(base); + if (!attr) { /* skip */ + continue; + } + mAttributeData[mCurrentRow][mCurrentAttribute++] = attr->get(); } } } From 6a599125973321b7b4490cffc1745ea48e388915 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Fri, 29 Aug 2025 21:43:39 +0200 Subject: [PATCH 103/168] Add capability to create folders needed to set the file path Signed-off-by: Leonardo Carreras --- dpsim/include/dpsim/RealTimeDataLogger.h | 1 + dpsim/src/RealTimeDataLogger.cpp | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/dpsim/include/dpsim/RealTimeDataLogger.h b/dpsim/include/dpsim/RealTimeDataLogger.h index 3b9bf77107..cc2402a305 100644 --- a/dpsim/include/dpsim/RealTimeDataLogger.h +++ b/dpsim/include/dpsim/RealTimeDataLogger.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include diff --git a/dpsim/src/RealTimeDataLogger.cpp b/dpsim/src/RealTimeDataLogger.cpp index 9f3c6101d9..648b40a36b 100644 --- a/dpsim/src/RealTimeDataLogger.cpp +++ b/dpsim/src/RealTimeDataLogger.cpp @@ -48,6 +48,16 @@ void RealTimeDataLogger::stop() { log->info("Stopping real-time data logger. Writing memory to file {}", mFilename.string()); + const auto parent = mFilename.parent_path(); + if (!parent.empty()) { + std::error_code ec; + std::filesystem::create_directories(parent, ec); + if (ec) { + throw std::runtime_error("Cannot create log directory '" + + parent.string() + "': " + ec.message()); + } + } + auto mLogFile = std::ofstream(mFilename, std::ios_base::out | std::ios_base::trunc); if (!mLogFile.is_open()) { @@ -66,7 +76,7 @@ void RealTimeDataLogger::stop() { mLogFile << '\n'; } mLogFile.close(); - log->info("Finished writing real-time data log to file {}.", + log->info("Finished writing real-time data log to file {}", mFilename.string()); } From 6a111185374285d1970cae5017af99130b1ebf3b Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Fri, 29 Aug 2025 21:43:47 +0200 Subject: [PATCH 104/168] Add pybind bindings Signed-off-by: Leonardo Carreras --- dpsim/src/pybind/main.cpp | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/dpsim/src/pybind/main.cpp b/dpsim/src/pybind/main.cpp index 349dbedafe..e6129e4c9e 100644 --- a/dpsim/src/pybind/main.cpp +++ b/dpsim/src/pybind/main.cpp @@ -323,6 +323,60 @@ PYBIND11_MODULE(dpsimpy, m) { logger.logAttribute(names, comp.attribute(attr)); }); + py::class_>(m, + "RealTimeDataLogger") + + .def(py::init([](py::object filename, DPsim::Real final_time, + DPsim::Real time_step) { + py::object fspath = + py::module_::import("os").attr("fspath")(filename); + std::string s = py::cast(fspath); + std::filesystem::path p(s); + return std::make_shared(p, final_time, + time_step); + }), + "filename"_a, "final_time"_a, "time_step"_a) + + .def(py::init([](py::object filename, std::size_t row_number) { + py::object fspath = + py::module_::import("os").attr("fspath")(filename); + std::string s = py::cast(fspath); + std::filesystem::path p(s); + return std::make_shared(p, row_number); + }), + "filename"_a, "row_number"_a) + + .def("log_attribute", + py::overload_cast( + &DPsim::DataLoggerInterface::logAttribute), + "name"_a, "attr"_a, "max_cols"_a = 0, "max_rows"_a = 0) + + .def("log_attribute", + py::overload_cast &, + CPS::AttributeBase::Ptr>( + &DPsim::DataLoggerInterface::logAttribute), + "names"_a, "attr"_a) + + .def( + "log_attribute", + [](DPsim::RealTimeDataLogger &logger, const CPS::String &name, + const CPS::String &attr, const CPS::IdentifiedObject &comp, + CPS::UInt rowsMax, CPS::UInt colsMax) { + logger.logAttribute(name, comp.attribute(attr), rowsMax, colsMax); + }, + "name"_a, "attr"_a, "comp"_a, "rows_max"_a = 0, "cols_max"_a = 0) + + .def( + "log_attribute", + [](DPsim::RealTimeDataLogger &logger, + const std::vector &names, const CPS::String &attr, + const CPS::IdentifiedObject &comp) { + logger.logAttribute(names, comp.attribute(attr)); + }, + "names"_a, "attr"_a, "comp"_a); + py::class_>( m, "IdentifiedObject") .def("name", &CPS::IdentifiedObject::name) From 357ddaee7ae1df296b2b3ba63b8eaab240331a9e Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Fri, 29 Aug 2025 21:44:12 +0200 Subject: [PATCH 105/168] Add example notebook for tests Signed-off-by: Leonardo Carreras --- .../Features/RealtimeDatalogger.ipynb | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 examples/Notebooks/Features/RealtimeDatalogger.ipynb diff --git a/examples/Notebooks/Features/RealtimeDatalogger.ipynb b/examples/Notebooks/Features/RealtimeDatalogger.ipynb new file mode 100644 index 0000000000..be4431eda5 --- /dev/null +++ b/examples/Notebooks/Features/RealtimeDatalogger.ipynb @@ -0,0 +1,158 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# In-memory logging for realtime applications" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " DPsim integrates a datalogger for realtime applications. It pre-allocates memory to run without writing to a file until the simulation is finished.\n", + "\n", + " For normal simulations it also increases the speed of the execution." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Example 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We start by defining a very simple simulation:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import dpsimpy\n", + "\n", + "# Parameters\n", + "duration = 1\n", + "timestep = 0.001\n", + "name = \"ExampleDatalogger1\"\n", + "log_path = \"./logs/\" + name + \".csv\"\n", + "attributes = 4 # real and imaginary for a voltage and a currrent\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.dp.SimNode.gnd\n", + "n1 = dpsimpy.dp.SimNode(\"n1\")\n", + "\n", + "# Components\n", + "v1 = dpsimpy.dp.ph1.VoltageSource(\"v_1\")\n", + "v1.set_parameters(V_ref=complex(345, 0), f_src=50)\n", + "v1.connect([gnd, n1])\n", + "r1 = dpsimpy.dp.ph1.Resistor(\"r1\")\n", + "r1.connect([gnd, n1])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [gnd, n1], [v1, r1])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We setup now a Realtime Datalogger" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "logger = dpsimpy.RealTimeDataLogger(log_path, duration, timestep)\n", + "logger.log_attribute(\"n1.v\", \"v\", n1)\n", + "logger.log_attribute(\"r1.i\", \"i_intf\", r1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we setup a simple simulation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sim = dpsimpy.RealTimeSimulation(name, dpsimpy.LogLevel.debug)\n", + "sim.set_system(sys)\n", + "sim.set_domain(dpsimpy.Domain.DP)\n", + "sim.set_time_step(timestep)\n", + "sim.set_final_time(duration)\n", + "sim.add_logger(logger)\n", + "sim.run(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Check that all went good" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "\n", + "# Read the CSV\n", + "df = pd.read_csv(log_path)\n", + "\n", + "# Expected dimensions\n", + "expected_rows = int(duration / timestep + 0.5) # timesteps + 1\n", + "expected_cols = 1 + attributes # time + attributes\n", + "\n", + "# Assertions\n", + "assert df.shape[0] == expected_rows, f\"Expected {expected_rows} rows, got {df.shape[0]}\"\n", + "assert (\n", + " df.shape[1] == expected_cols\n", + "), f\"Expected {expected_cols} columns, got {df.shape[1]}\"\n", + "\n", + "print(\"OK:\", df.shape)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.3" + }, + "tests": { + "skip": true + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From 779885f22166aad99f555343b6f5b4d1286f52ba Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 2 Sep 2025 18:30:02 +0200 Subject: [PATCH 106/168] Toggle skip test to false in metadata Signed-off-by: Leonardo Carreras --- examples/Notebooks/Features/RealtimeDatalogger.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Notebooks/Features/RealtimeDatalogger.ipynb b/examples/Notebooks/Features/RealtimeDatalogger.ipynb index be4431eda5..3548656b08 100644 --- a/examples/Notebooks/Features/RealtimeDatalogger.ipynb +++ b/examples/Notebooks/Features/RealtimeDatalogger.ipynb @@ -150,7 +150,7 @@ "version": "3.12.3" }, "tests": { - "skip": true + "skip": false } }, "nbformat": 4, From 84f19d518abe800704f4d2f59db8d4a6931e51ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 4 Sep 2025 15:39:57 +0000 Subject: [PATCH 107/168] chore(deps): Bump pypa/gh-action-pypi-publish in /.github/workflows Bumps [pypa/gh-action-pypi-publish](https://github.com/pypa/gh-action-pypi-publish) from 1.12.4 to 1.13.0. - [Release notes](https://github.com/pypa/gh-action-pypi-publish/releases) - [Commits](https://github.com/pypa/gh-action-pypi-publish/compare/v1.12.4...v1.13.0) --- updated-dependencies: - dependency-name: pypa/gh-action-pypi-publish dependency-version: 1.13.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- .github/workflows/publish_to_pypi.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index e029c723c3..a4e4462288 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -74,11 +74,11 @@ jobs: path: dist/ - name: Publish distribution to Test PyPI - uses: pypa/gh-action-pypi-publish@v1.12.4 + uses: pypa/gh-action-pypi-publish@v1.13.0 with: repository-url: https://test.pypi.org/legacy/ skip-existing: true - name: Publish distribution to PyPI if: startsWith(github.ref, 'refs/tags') - uses: pypa/gh-action-pypi-publish@v1.12.4 + uses: pypa/gh-action-pypi-publish@v1.13.0 From ad8f4fbe931f765ed8c6f2036077a5fb55d87821 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 7 Oct 2025 23:38:47 +0200 Subject: [PATCH 108/168] Bump villas and update cimpp installation method in containers Signed-off-by: Leonardo Carreras --- packaging/Docker/Dockerfile.dev | 149 ++++++++++----------- packaging/Docker/Dockerfile.dev-debian | 146 ++++++++++---------- packaging/Docker/Dockerfile.dev-minimal | 31 ++--- packaging/Docker/Dockerfile.dev-rocky | 7 +- packaging/Docker/Dockerfile.manylinux | 15 ++- packaging/Docker/Dockerfile.rpm | 51 ++++--- packaging/Shell/install-fedora-deps-dev.sh | 2 +- packaging/Shell/install-fedora-deps.sh | 4 +- packaging/Shell/install-ubuntu-deps.sh | 4 +- 9 files changed, 216 insertions(+), 193 deletions(-) diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index 74ca75c460..2f34d973ad 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -1,8 +1,9 @@ FROM fedora:42 AS base ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 -ARG CIMPP_COMMIT=1b11d5c17bedf0ae042628b42ecb4e49df70b2f6 -ARG VILLAS_VERSION=4df38d26d425117e538ad74bef27e62e353aadc3 +ARG LIBCIMPP_VERSION=2.2.0 +ARG CIMPP_COMMIT=051ee4c311572fe92b30120b897d22deb253e162 +ARG VILLAS_VERSION=5606793aaee2d1eeb663180d3e52718fa8bd5931 ARG CMAKE_OPTS ARG MAKE_OPTS=-j4 @@ -13,38 +14,42 @@ LABEL \ org.opencontainers.image.url="http://dpsim.fein-aachen.org/" \ org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" -RUN dnf -y update - -# Toolchain -RUN dnf -y install \ - gcc gcc-c++ clang \ - git \ - rpmdevtools rpm-build \ - make cmake pkgconfig \ - python3-pip \ - cppcheck \ - flex bison \ - protobuf-compiler protobuf-c-compiler \ - clang-tools-extra - -# Tools needed for developement -RUN dnf -y install \ - doxygen graphviz \ - gdb \ - procps-ng - -# Dependencies -RUN dnf --refresh -y install \ - python3-devel \ - eigen3-devel \ - libxml2-devel \ - graphviz-devel \ - spdlog-devel \ - fmt-devel - -# Install some debuginfos -RUN dnf -y debuginfo-install \ - python3 +RUN set -eux; \ + dnf -y update; \ + dnf -y remove systemd-standalone-tmpfiles || true; \ + dnf -y --refresh install \ + gcc gcc-c++ clang \ + git \ + rpmdevtools rpm-build \ + make cmake pkgconfig \ + python3-pip \ + curl \ + cppcheck \ + flex bison \ + protobuf-compiler protobuf-c-compiler \ + clang-tools-extra \ + doxygen graphviz \ + gdb \ + procps-ng \ + python3-devel \ + eigen3-devel \ + libxml2-devel \ + graphviz-devel \ + spdlog-devel \ + fmt-devel \ + openssl-devel \ + libuuid-devel \ + libcurl-devel \ + jansson-devel \ + libwebsockets-devel \ + mosquitto-devel \ + libconfig-devel \ + libnl3-devel \ + protobuf-devel \ + protobuf-c-devel \ + libre-devel; \ + dnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum # Build & Install sundials RUN cd /tmp && \ @@ -57,41 +62,28 @@ RUN cd /tmp && \ # CIMpp and VILLASnode are installed here ENV LD_LIBRARY_PATH="/usr/local/lib64:${LD_LIBRARY_PATH}" -# Install minimal VILLASnode dependencies -RUN dnf -y install \ - openssl-devel \ - libuuid-devel \ - libcurl-devel \ - jansson-devel \ - libwebsockets-devel - -# Install optional VILLASnode dependencies -RUN dnf -y remove systemd-standalone-tmpfiles || true && \ - dnf -y install \ - mosquitto-devel \ - libconfig-devel \ - libnl3-devel \ - protobuf-devel \ - protobuf-c-devel \ - libre-devel - # Python dependencies COPY requirements.txt . -RUN pip3 install --upgrade wheel build setuptools packaging && pip3 install -r requirements.txt - -# Install CIMpp from source -RUN cd /tmp && \ - git clone https://github.com/sogno-platform/libcimpp.git && \ - mkdir -p libcimpp/build && cd libcimpp/build && \ - git checkout ${CIMPP_COMMIT} && \ - git submodule update --init && \ - cmake ${CMAKE_OPTS} ..\ - -DBUILD_SHARED_LIBS=ON \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ - -DUSE_CIM_VERSION=${CIM_VERSION} \ - -DBUILD_ARABICA_EXAMPLES=OFF && \ - make ${MAKE_OPTS} install && \ - rm -rf /tmp/libcimpp +RUN pip3 install --no-cache-dir --upgrade wheel build setuptools packaging && \ + pip3 install --no-cache-dir -r requirements.txt && \ + pip3 cache purge + +# Install libcimpp from prebuilt RPMs +RUN set -eux; \ + case "${CIM_VERSION}" in \ + CGMES_2.4.15_16FEB2016|CGMES_2.4.15_27JAN2020|CGMES_2.4.13_18DEC2013) \ + libcimpp_pkg="libcimpp_${CIM_VERSION}-${LIBCIMPP_VERSION}-Linux.rpm" ;; \ + *) \ + echo "Unsupported CIM_VERSION '${CIM_VERSION}' for prebuilt libcimpp package" >&2; \ + exit 1 ;; \ + esac; \ + libcimpp_url="https://github.com/sogno-platform/libcimpp/releases/download/release%2Fv${LIBCIMPP_VERSION}/${libcimpp_pkg}"; \ + curl -sSL "${libcimpp_url}" -o /tmp/libcimpp.rpm; \ + dnf -y install /tmp/libcimpp.rpm; \ + rm -f /tmp/libcimpp.rpm; \ + ldconfig; \ + dnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum # Install VILLASnode from source (with fpga support) RUN cd /tmp && \ @@ -104,17 +96,18 @@ RUN cd /tmp && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node -# Remove this part in the future and use dedicated Jupyter Dockerfile -# Activate Jupyter extensions -RUN dnf -y --refresh install \ - npm - -RUN pip3 install \ - jupyter \ - jupyterlab \ - jupyter_contrib_nbextensions \ - nbconvert \ - nbformat +RUN set -eux; \ + dnf -y --refresh install npm; \ + pip3 install --no-cache-dir \ + jupyter \ + jupyterlab \ + jupyter_contrib_nbextensions \ + nbconvert \ + nbformat; \ + pip3 cache purge; \ + dnf -y remove npm; \ + dnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum EXPOSE 8888 diff --git a/packaging/Docker/Dockerfile.dev-debian b/packaging/Docker/Dockerfile.dev-debian index f49bc69746..bb4a0fd615 100644 --- a/packaging/Docker/Dockerfile.dev-debian +++ b/packaging/Docker/Dockerfile.dev-debian @@ -1,44 +1,48 @@ FROM debian:11 ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 -ARG CIMPP_COMMIT=1b11d5c17bedf0ae042628b42ecb4e49df70b2f6 -ARG VILLAS_VERSION=18cdd2a6364d05fbf413ca699616cd324abfcb54 +ARG LIBCIMPP_VERSION=2.2.0 +ARG VILLAS_VERSION=5606793aaee2d1eeb663180d3e52718fa8bd5931 ARG CMAKE_OPTS ARG MAKE_OPTS=-j4 LABEL \ - org.opencontainers.image.title = "DPsim" \ - org.opencontainers.image.licenses = "MPL 2.0" \ - org.opencontainers.image.url = "http://dpsim.fein-aachen.org/" \ - org.opencontainers.image.source = "https://github.com/sogno-platform/dpsim" - -RUN apt-get -y update - -# Toolchain -RUN apt-get -y install \ - gcc g++ clang \ - git \ - make cmake pkg-config \ - python3-pip \ - wget - -# Tools needed for developement -RUN apt-get -y install \ - doxygen graphviz \ - gdb - -# Dependencies -RUN apt-get -y install \ - python3-dev \ - libeigen3-dev \ - libxml2-dev \ - libgraphviz-dev \ - libgsl-dev \ - libspdlog-dev \ - pybind11-dev \ - libspdlog-dev \ - libfmt-dev + org.opencontainers.image.title="DPsim" \ + org.opencontainers.image.licenses="MPL 2.0" \ + org.opencontainers.image.url="http://dpsim.fein-aachen.org/" \ + org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" + +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends \ + gcc g++ clang \ + git \ + make cmake pkg-config \ + python3-pip \ + wget \ + doxygen graphviz \ + gdb \ + python3-dev \ + libeigen3-dev \ + libxml2-dev \ + libgraphviz-dev \ + libgsl-dev \ + libspdlog-dev \ + pybind11-dev \ + libfmt-dev \ + libssl-dev \ + uuid-dev \ + libcurl4-gnutls-dev \ + libjansson-dev \ + libwebsockets-dev \ + libmosquitto-dev \ + libconfig-dev \ + libnl-3-dev \ + protobuf-dev \ + libprotobuf-c-dev; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* # Build & Install sundials RUN cd /tmp && \ @@ -46,23 +50,8 @@ RUN cd /tmp && \ mkdir -p sundials/build && cd sundials/build && \ cmake ${CMAKE_OPTS} .. \ -DCMAKE_BUILD_TYPE=Release && \ - make ${MAKE_OPTS} install - -## Install minimal VILLASnode dependencies -RUN apt-get -y install \ - libssl-dev \ - uuid-dev \ - libcurl4-gnutls-dev \ - libjansson-dev \ - libwebsockets-dev - -## Install optional VILLASnode dependencies -RUN apt-get -y install \ - libmosquitto-dev \ - libconfig-dev \ - libnl-3-dev \ - protobuf-dev \ - libprotobuf-c-dev + make ${MAKE_OPTS} install && \ + rm -rf /tmp/sundials ## Install libiec61850 from source RUN cd /tmp && \ @@ -76,22 +65,28 @@ RUN cd /tmp && \ rm -rf /tmp/libiec61850-1.3.3 ## Python dependencies -ADD requirements.txt . -RUN pip3 install -r requirements.txt - -## Install CIMpp from source -RUN cd /tmp && \ - git clone https://github.com/sogno-platform/libcimpp.git && \ - mkdir -p libcimpp/build && cd libcimpp/build && \ - git checkout ${CIMPP_COMMIT} && \ - git submodule update --init && \ - cmake ${CMAKE_OPTS} .. \ - -DBUILD_SHARED_LIBS=ON \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib \ - -DUSE_CIM_VERSION=${CIM_VERSION} \ - -DBUILD_ARABICA_EXAMPLES=OFF && \ - make ${MAKE_OPTS} install && \ - rm -rf /tmp/libcimpp +COPY requirements.txt . +RUN pip3 install --no-cache-dir --upgrade wheel build setuptools packaging && \ + pip3 install --no-cache-dir -r requirements.txt && \ + pip3 cache purge + +## Install libcimpp from prebuilt Debian packages +RUN set -eux; \ + case "${CIM_VERSION}" in \ + CGMES_2.4.15_16FEB2016|CGMES_2.4.15_27JAN2020|CGMES_2.4.13_18DEC2013) \ + libcimpp_pkg="libcimpp_${CIM_VERSION}-${LIBCIMPP_VERSION}-Linux.deb" ;; \ + *) \ + echo "Unsupported CIM_VERSION '${CIM_VERSION}' for prebuilt libcimpp package" >&2; \ + exit 1 ;; \ + esac; \ + libcimpp_url="https://github.com/sogno-platform/libcimpp/releases/download/release%2Fv${LIBCIMPP_VERSION}/${libcimpp_pkg}"; \ + wget -qO /tmp/libcimpp.deb "${libcimpp_url}"; \ + apt-get update; \ + apt-get install -y --no-install-recommends /tmp/libcimpp.deb; \ + rm -f /tmp/libcimpp.deb; \ + ldconfig; \ + apt-get clean; \ + rm -rf /var/lib/apt/lists/* ## Install VILLASnode from source RUN cd /tmp && \ @@ -101,19 +96,28 @@ RUN cd /tmp && \ cmake ${CMAKE_OPTS} .. \ -DCMAKE_INSTALL_LIBDIR=/usr/local/lib \ -DDOWNLOAD_GO=OFF && \ - make install && \ + make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node # Remove this part in the future and use dedicated Jupyter Dockerfile # Activate Jupyter extensions -RUN apt-get -y install \ - npm +RUN set -eux; \ + apt-get update; \ + apt-get install -y --no-install-recommends npm; \ + rm -rf /var/lib/apt/lists/* -RUN pip3 install \ +RUN pip3 install --no-cache-dir \ jupyter \ jupyterlab \ jupyter_contrib_nbextensions \ nbconvert \ - nbformat + nbformat && \ + pip3 cache purge + +RUN set -eux; \ + apt-get purge -y npm && \ + apt-get autoremove -y && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* EXPOSE 8888 diff --git a/packaging/Docker/Dockerfile.dev-minimal b/packaging/Docker/Dockerfile.dev-minimal index 55b32b3f24..27c52490e7 100644 --- a/packaging/Docker/Dockerfile.dev-minimal +++ b/packaging/Docker/Dockerfile.dev-minimal @@ -6,23 +6,24 @@ LABEL \ org.opencontainers.image.url="http://dpsim.fein-aachen.org/" \ org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" -RUN dnf -y update - -# Toolchain -RUN dnf -y install \ - gcc gcc-c++ \ - git \ - make cmake pkgconfig \ - python3-pip - -# Dependencies -RUN dnf --refresh -y install \ - python3-devel \ - eigen3-devel \ - spdlog-devel +RUN set -eux; \ + dnf -y update; \ + dnf -y remove systemd-standalone-tmpfiles || true; \ + dnf -y --refresh install \ + gcc gcc-c++ \ + git \ + make cmake pkgconfig \ + python3-pip \ + python3-devel \ + eigen3-devel \ + spdlog-devel; \ + dnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum # Python dependencies COPY requirements.txt . -RUN pip3 install --upgrade wheel build setuptools packaging && pip3 install -r requirements.txt +RUN pip3 install --no-cache-dir --upgrade wheel build setuptools packaging && \ + pip3 install --no-cache-dir -r requirements.txt && \ + pip3 cache purge EXPOSE 8888 diff --git a/packaging/Docker/Dockerfile.dev-rocky b/packaging/Docker/Dockerfile.dev-rocky index 493dde36d0..4f546d3259 100644 --- a/packaging/Docker/Dockerfile.dev-rocky +++ b/packaging/Docker/Dockerfile.dev-rocky @@ -1,8 +1,8 @@ FROM rockylinux:9 ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 -ARG CIMPP_COMMIT=1b11d5c17bedf0ae042628b42ecb4e49df70b2f6 -ARG VILLAS_VERSION=4df38d26d425117e538ad74bef27e62e353aadc3 +ARG CIMPP_COMMIT=051ee4c311572fe92b30120b897d22deb253e162 +ARG VILLAS_VERSION=5606793aaee2d1eeb663180d3e52718fa8bd5931 ARG CMAKE_OPTS ARG MAKE_OPTS=-j4 @@ -145,9 +145,10 @@ RUN cd /tmp && \ git clone --recurse-submodules https://github.com/VILLASframework/node.git villas-node && \ cd villas-node && \ git checkout ${VILLAS_VERSION} && \ - env MAKE_OPTS="" DEPS_NONINTERACTIVE=1 bash packaging/deps.sh && \ + env MAKE_OPTS="" DEPS_NONINTERACTIVE=1 DEPS_SKIP=libxil bash packaging/deps.sh && \ mkdir -p build && cd build && \ cmake ${CMAKE_OPTS} .. \ + -DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS -fpermissive" \ -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 \ -DCMAKE_CUDA_FLAGS="-Xcompiler=-Wall,-Werror" && \ make ${MAKE_OPTS} install && \ diff --git a/packaging/Docker/Dockerfile.manylinux b/packaging/Docker/Dockerfile.manylinux index 9279240c82..2ae98fc7e3 100644 --- a/packaging/Docker/Dockerfile.manylinux +++ b/packaging/Docker/Dockerfile.manylinux @@ -6,8 +6,8 @@ FROM quay.io/pypa/manylinux_2_28_x86_64 ARG CIM_VERSION=CGMES_2.4.15_16FEB2016 -ARG CIMPP_COMMIT=1b11d5c17bedf0ae042628b42ecb4e49df70b2f6 -ARG VILLAS_VERSION=84df28645077e05e5115f92ef328d688400b35b9 +ARG CIMPP_COMMIT=051ee4c311572fe92b30120b897d22deb253e162 +ARG VILLAS_VERSION=5606793aaee2d1eeb663180d3e52718fa8bd5931 ARG CMAKE_OPTS ARG MAKE_OPTS=-j4 @@ -31,7 +31,9 @@ RUN dnf install -y \ make cmake pkgconfig libtool \ autoconf automake autogen libtool flex bison \ python3-pip \ - cppcheck + cppcheck \ + ninja-build \ + meson # Tools needed for development RUN dnf -y install \ @@ -98,7 +100,11 @@ RUN dnf install -y \ protobuf-devel \ nanomsg-devel \ zeromq-devel \ - graphviz-devel + graphviz-devel \ + git-svn \ + subversion \ + subversion-perl \ + perl-Memoize # Install VILLASnode from source RUN cd /tmp && \ @@ -108,6 +114,7 @@ RUN cd /tmp && \ DEPS_SKIP=criterion,ethercat \ MAKE_OPTS="" \ CMAKE_OPTS=-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \ + NINJA=/usr/bin/ninja-build \ bash packaging/deps.sh && \ mkdir -p build && cd build && \ cmake ${CMAKE_OPTS} .. \ diff --git a/packaging/Docker/Dockerfile.rpm b/packaging/Docker/Dockerfile.rpm index 84b8ab6a8a..7647dd7937 100644 --- a/packaging/Docker/Dockerfile.rpm +++ b/packaging/Docker/Dockerfile.rpm @@ -16,27 +16,44 @@ RUN cmake ${CMAKE_OPTS} .. \ -DCPACK_GENERATOR=RPM RUN make ${MAKE_OPTS} package -FROM fedora:36 +FROM fedora:42 LABEL \ - org.opencontainers.image.title = "DPsim" \ - org.opencontainers.image.licenses = "MPL 2.0" \ - org.opencontainers.image.url = "http://dpsim.fein-aachen.org/" \ - org.opencontainers.image.source = "https://github.com/sogno-platform/dpsim" + org.opencontainers.image.title="DPsim" \ + org.opencontainers.image.licenses="MPL 2.0" \ + org.opencontainers.image.url="http://dpsim.fein-aachen.org/" \ + org.opencontainers.image.source="https://github.com/sogno-platform/dpsim" + +RUN set -eux; \ + dnf -y update; \ + dnf -y remove systemd-standalone-tmpfiles || true; \ + dnf -y --refresh install \ + python3-pip \ + findutils; \ + dnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum COPY --from=builder /dpsim/build/*.rpm /tmp -RUN dnf -y install /tmp/*.rpm - -ADD requirements.txt . -RUN pip3 install -r requirements.txt - -# Remove this part in the future and use dedicated Jupyter Dockerfile -# Activate Jupyter extensions -ADD requirements-jupyter.txt . -RUN pip3 install -r requirements-jupyter.txt -RUN dnf -y --refresh install npm -RUN jupyter nbextension enable --py widgetsnbextension -RUN jupyter labextension install @jupyter-widgets/jupyterlab-manager +RUN set -eux; \ + dnf -y install /tmp/*.rpm; \ + rm -f /tmp/*.rpm; \ + dnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum + +COPY requirements.txt . +COPY requirements-jupyter.txt . +RUN pip3 install --no-cache-dir --upgrade wheel build setuptools packaging && \ + pip3 install --no-cache-dir -r requirements.txt && \ + pip3 install --no-cache-dir -r requirements-jupyter.txt && \ + pip3 cache purge + +RUN set -eux; \ + dnf -y --refresh install npm; \ + jupyter nbextension enable --py widgetsnbextension; \ + jupyter labextension install @jupyter-widgets/jupyterlab-manager; \ + dnf -y remove npm; \ + dnf clean all; \ + rm -rf /var/cache/dnf /var/cache/yum # Copy example materials RUN mkdir dpsim diff --git a/packaging/Shell/install-fedora-deps-dev.sh b/packaging/Shell/install-fedora-deps-dev.sh index 1bf74946c8..4c608f046d 100644 --- a/packaging/Shell/install-fedora-deps-dev.sh +++ b/packaging/Shell/install-fedora-deps-dev.sh @@ -1,7 +1,7 @@ #!/bin/bash CIM_VERSION=${CIM_VERSION:-CGMES_2.4.15_16FEB2016} -VILLAS_VERSION=${VILLAS_VERSION:-66569cf9c43d2d7a4626b9a84321c4e340d3fe18} +VILLAS_VERSION=${VILLAS_VERSION:-5606793aaee2d1eeb663180d3e52718fa8bd5931} MAKE_PROCS=${MAKE_PROCS:-$(nproc)} MAKE_OPTS+="-j${MAKE_PROCS}" diff --git a/packaging/Shell/install-fedora-deps.sh b/packaging/Shell/install-fedora-deps.sh index 24e98ffd99..5c6e135392 100644 --- a/packaging/Shell/install-fedora-deps.sh +++ b/packaging/Shell/install-fedora-deps.sh @@ -1,7 +1,7 @@ #!/bin/bash CIM_VERSION=${CIM_VERSION:-CGMES_2.4.15_16FEB2016} -VILLAS_VERSION=${VILLAS_VERSION:-66569cf9c43d2d7a4626b9a84321c4e340d3fe18} +VILLAS_VERSION=${VILLAS_VERSION:-5606793aaee2d1eeb663180d3e52718fa8bd5931} MAKE_PROCS=${MAKE_PROCS:-$(nproc)} MAKE_OPTS+="-j${MAKE_PROCS}" @@ -72,6 +72,6 @@ cd /tmp && \ mkdir -p villas-node/build && cd villas-node/build && \ git checkout ${VILLAS_VERSION} && \ cmake ${CMAKE_OPTS} .. \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 && \ + -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node diff --git a/packaging/Shell/install-ubuntu-deps.sh b/packaging/Shell/install-ubuntu-deps.sh index 3ec1c2a23b..42e3e87fb8 100644 --- a/packaging/Shell/install-ubuntu-deps.sh +++ b/packaging/Shell/install-ubuntu-deps.sh @@ -1,7 +1,7 @@ #!/bin/bash CIM_VERSION=${CIM_VERSION:-CGMES_2.4.15_16FEB2016} -VILLAS_VERSION=${VILLAS_VERSION:-66569cf9c43d2d7a4626b9a84321c4e340d3fe18} +VILLAS_VERSION=${VILLAS_VERSION:-5606793aaee2d1eeb663180d3e52718fa8bd5931} MAKE_PROCS=${MAKE_PROCS:-$(nproc)} MAKE_OPTS+="-j${MAKE_PROCS}" @@ -58,6 +58,6 @@ cd /tmp && \ mkdir -p villas-node/build && cd villas-node/build && \ git checkout ${VILLAS_VERSION} && \ cmake ${CMAKE_OPTS} .. \ - -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 && \ + -DCMAKE_INSTALL_LIBDIR=/usr/local/lib64 && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node From 261f2e415e202c088a9b0a67a2192559522e5ba9 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 7 Oct 2025 23:40:58 +0200 Subject: [PATCH 109/168] Update cmake fetch and finding of libcimpp and fix dependent files and CIMReader Signed-off-by: Leonardo Carreras --- CMakeLists.txt | 16 +- cmake/FetchCIMpp.cmake | 54 ++++- cmake/FindCIMpp.cmake | 152 +++++++++--- .../include/dpsim-models/CIM/Reader.h | 18 ++ dpsim-models/src/CIM/Reader.cpp | 221 ++++++++++-------- dpsim-models/src/CMakeLists.txt | 2 +- dpsim/CMakeLists.txt | 2 +- dpsim/examples/cxx/CMakeLists.txt | 2 +- .../examples/cxx/cim_graphviz/CMakeLists.txt | 2 +- 9 files changed, 319 insertions(+), 150 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d6a919b346..fe778bd9b3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,13 +114,15 @@ include(CheckSymbolExists) check_symbol_exists(timerfd_create sys/timerfd.h HAVE_TIMERFD) check_symbol_exists(getopt_long getopt.h HAVE_GETOPT) if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - add_compile_options(-Ofast) + if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") + # Clang 18+ deprecates -Ofast; use the equivalent O3 fast-math combo instead. + add_compile_options(-O3 -ffast-math) + else() + add_compile_options(-Ofast) + endif() - # On Clang -Ofast enables -ffast-math which in turn enables -ffinite-math-only. - # This option causes all calls to functions checking for infinity or NaN to raise - # a warning (e.g. std::isnan). - # As we also set -Werror, these warnings are causing the build to fail. - # With this compiler option, we explicitly silence this warning. + # On Clang -ffast-math enables -ffinite-math-only which triggers warnings for + # infinity/NaN checks. Silence those when supported so -Werror stays usable. check_cxx_compiler_flag("-Wno-nan-infinity-disabled" CXX_SUPPORTS_WNAN_INFINITY_DISABLED) if(CXX_SUPPORTS_WNAN_INFINITY_DISABLED) add_compile_options(-Wno-nan-infinity-disabled) @@ -297,7 +299,7 @@ endif() if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) include(FeatureSummary) - add_feature_info(CIM WITH_CIM "Loading Common Information Model (CIM) files") + add_feature_info(CIM WITH_CIM "Loading Common Information Model (CIM) library") add_feature_info(CUDA WITH_CUDA "CUDA-based parallelization") add_feature_info(Graphviz WITH_GRAPHVIZ "Graphviz graphs") add_feature_info(GSL WITH_GSL "GNU Scientific library") diff --git a/cmake/FetchCIMpp.cmake b/cmake/FetchCIMpp.cmake index 4a504571f3..e121aa0113 100644 --- a/cmake/FetchCIMpp.cmake +++ b/cmake/FetchCIMpp.cmake @@ -1,13 +1,26 @@ -if(NOT CIM_VERSION) +# cmake_minimum_required handled by your top-level CMakeLists +# Requires CMake >= 3.14 for FetchContent_MakeAvailable + +set(CIM_VERSION "${CIM_VERSION}" CACHE STRING "CIM version (e.g. CGMES_2.4.15_16FEB2016 or 16v29a)") +if(NOT CIM_VERSION OR CIM_VERSION STREQUAL "") set(CIM_VERSION "CGMES_2.4.15_16FEB2016") endif() -# Allow overriding the commit hash externally -if(NOT DEFINED CIMPP_COMMIT) - set(CIMPP_COMMIT "1b11d5c17bedf0ae042628b42ecb4e49df70b2f6") # Default commit +set(CIMPP_COMMIT "${CIMPP_COMMIT}" CACHE STRING "libcimpp git commit to fetch") +if(NOT DEFINED CIMPP_COMMIT OR CIMPP_COMMIT STREQUAL "") + if(WIN32) + # Windows builds currently rely on the older commit; update once validated there. + set(CIMPP_COMMIT "1b11d5c17bedf0ae042628b42ecb4e49df70b2f6") + else() + # Linux and other platforms use the newer known-good commit. + set(CIMPP_COMMIT "051ee4c311572fe92b30120b897d22deb253e162") + endif() endif() -message(STATUS "CIM Version: ${CIM_VERSION}") +message(STATUS "[CIMpp] CIM Version: ${CIM_VERSION}") +message(STATUS "[CIMpp] Commit: ${CIMPP_COMMIT}") + +set(CGMES_BUILD OFF) if(CIM_VERSION STREQUAL "16v29a") set(USE_CIM_VERSION "IEC61970_16v29a") @@ -16,15 +29,40 @@ elseif(CIM_VERSION STREQUAL "CGMES_2.4.15_16FEB2016") set(CGMES_BUILD ON) endif() -set(CIMPP_BUILD_DOC OFF) +set(CIM_VERSION "${CIM_VERSION}" CACHE STRING "" FORCE) +set(CGMES_BUILD "${CGMES_BUILD}" CACHE BOOL "" FORCE) +set(CIMPP_BUILD_DOC OFF CACHE BOOL "Build libcimpp docs (disabled)" FORCE) include(FetchContent) + FetchContent_Declare(cimpp-module GIT_REPOSITORY https://github.com/sogno-platform/libcimpp.git - GIT_PROGRESS TRUE GIT_TAG ${CIMPP_COMMIT} + GIT_PROGRESS TRUE ) FetchContent_MakeAvailable(cimpp-module) -set(CIMpp_FOUND TRUE) +set(_candidates CIMPP::cimpp cimpp libcimpp) +set(_cimpp_target "") +foreach(tgt IN LISTS _candidates) + if(TARGET ${tgt}) + set(_cimpp_target ${tgt}) + break() + endif() +endforeach() + +if(_cimpp_target STREQUAL "") + message(FATAL_ERROR "[CIMpp] Fetched libcimpp but no library target was found (checked: ${_candidates}).") +endif() + +if(NOT TARGET CIMPP::cimpp) + if(_cimpp_target STREQUAL "CIMPP::cimpp") + else() + add_library(CIMPP::cimpp ALIAS ${_cimpp_target}) + endif() +endif() + +set(CIMpp_FOUND TRUE CACHE BOOL "Fetched CIMpp successfully" FORCE) +set(CIMPP_CGMES_BUILD ${CGMES_BUILD} CACHE BOOL "Is this a CGMES build?" FORCE) +set(CIMPP_USE_VERSION "${USE_CIM_VERSION}" CACHE STRING "Resolved internal CIM version tag" FORCE) diff --git a/cmake/FindCIMpp.cmake b/cmake/FindCIMpp.cmake index 08bb17aec3..dce5663751 100644 --- a/cmake/FindCIMpp.cmake +++ b/cmake/FindCIMpp.cmake @@ -1,47 +1,139 @@ -if(NOT CIM_VERSION) +cmake_minimum_required(VERSION 3.12) + +set(CIM_VERSION "${CIM_VERSION}" CACHE STRING "CIM version (e.g. CGMES_2.4.15_16FEB2016)") +set(CIMPP_ROOT "${CIMPP_ROOT}" CACHE PATH "CIMpp install prefix (/usr, /usr/local, /opt/cimpp)") + +if(NOT CIM_VERSION OR CIM_VERSION STREQUAL "") set(CIM_VERSION "CGMES_2.4.15_16FEB2016") + message(STATUS "[CIMpp] CIM_VERSION not provided, defaulting to ${CIM_VERSION}") +else() + message(STATUS "[CIMpp] CIM_VERSION provided: ${CIM_VERSION}") endif() -message(STATUS "CIM Version: ${CIM_VERSION}") +if(NOT CIMPP_ROOT OR CIMPP_ROOT STREQUAL "") + set(CIMPP_ROOT "/usr/local") + message(STATUS "[CIMpp] CIMPP_ROOT not provided, defaulting to ${CIMPP_ROOT}") +else() + message(STATUS "[CIMpp] CIMPP_ROOT provided: ${CIMPP_ROOT}") +endif() -if(CIM_VERSION STREQUAL "16v29a") - set(USE_CIM_VERSION "IEC61970_16v29a") -elseif(CIM_VERSION STREQUAL "CGMES_2.4.15_16FEB2016") - set(USE_CIM_VERSION "CGMES_2.4.15_16FEB2016") +# Detect CGMES builds and expose a flag +set(CGMES_BUILD OFF) +if(CIM_VERSION MATCHES "^CGMES_") set(CGMES_BUILD ON) endif() -find_path(CIMPP_INCLUDE_DIR - NAMES CIMModel.hpp +# Hints +set(_hints ${CIMPP_ROOT} $ENV{CIMPP_ROOT} /usr /usr/local) +list(FILTER _hints EXCLUDE REGEX "^$") + +# version: .../include/cimpp/ +find_path(CIMPP_VER_INCLUDE_DIR + NAMES Line.hpp + HINTS ${_hints} PATH_SUFFIXES include/cimpp/${CIM_VERSION} - include/cimpp/${USE_CIM_VERSION} -) + include/cimpp) -find_library(CIMPP_LIBRARY - NAMES - cimpp${CIM_VERSION} - cimpp${USE_CIM_VERSION} +# src: .../include/cimpp/src +find_path(CIMPP_SRC_INCLUDE_DIR + NAMES CIMFile.hpp + HINTS ${_hints} PATH_SUFFIXES - lib/static - lib/cimpp -) + include/cimpp + include/cimpp/${CIM_VERSION} + include/cimpp/src + include/cimpp/${CIM_VERSION}/src) -set(CIMPP_LIBRARIES - ${CIMPP_LIBRARY} - ${ARABICA_LIBRARY} -) +# static: .../include/cimpp/static +find_path(CIMPP_STATIC_INCLUDE_DIR + NAMES BaseClass.hpp + HINTS ${_hints} + PATH_SUFFIXES + include/cimpp/${CIM_VERSION} + include/cimpp/${CIM_VERSION}/static + include/cimpp/static + include/cimpp) -set(CIMPP_INCLUDE_DIRS - ${CIMPP_INCLUDE_DIR} - ${ARABICA_INCLUDE_DIR} -) +# static/IEC61970: .../include/cimpp/static/IEC61970 +find_path(CIMPP_STATIC_IEC61970_INCLUDE_DIR + NAMES IEC61970CIMVersion.h + HINTS ${_hints} + PATH_SUFFIXES + include/cimpp/${CIM_VERSION}/IEC61970 + include/cimpp/${CIM_VERSION}/static/IEC61970 + include/cimpp/static/IEC61970 + include/cimpp/IEC61970) + +# ---- Library (search specific directories only) +set(_cimpp_library_dirs "") +foreach(_root IN LISTS _hints) + if(_root) + list(APPEND _cimpp_library_dirs + "${_root}/lib" + "${_root}/lib64" + "${_root}/lib/x86_64-linux-gnu") + endif() +endforeach() +list(APPEND _cimpp_library_dirs "/lib" "/lib64" "/lib/x86_64-linux-gnu") +list(REMOVE_DUPLICATES _cimpp_library_dirs) + +find_library(CIMPP_LIBRARY + NAMES cimpp${CIM_VERSION} cimppCGMES_2.4.15_16FEB2016 cimpp + PATHS ${_cimpp_library_dirs} + NO_DEFAULT_PATH) +# ---- Revalidate discovered paths (avoid cached empty or stale results) +macro(_cimpp_recheck _var) + if(${_var} AND NOT EXISTS "${${_var}}") + unset(${_var} CACHE) + set(${_var} "") + endif() +endmacro() + +_cimpp_recheck(CIMPP_SRC_INCLUDE_DIR) +_cimpp_recheck(CIMPP_VER_INCLUDE_DIR) +_cimpp_recheck(CIMPP_STATIC_INCLUDE_DIR) +_cimpp_recheck(CIMPP_STATIC_IEC61970_INCLUDE_DIR) +_cimpp_recheck(CIMPP_LIBRARY) + +# ---- Validate include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(CIMpp DEFAULT_MSG CIMPP_LIBRARY CIMPP_INCLUDE_DIR) +find_package_handle_standard_args(CIMpp + REQUIRED_VARS + CIMPP_LIBRARY + CIMPP_SRC_INCLUDE_DIR + CIMPP_VER_INCLUDE_DIR + CIMPP_STATIC_INCLUDE_DIR + CIMPP_STATIC_IEC61970_INCLUDE_DIR + FAIL_MESSAGE "Set CIMPP_ROOT and CIM_VERSION so that the include paths are found.") -mark_as_advanced(CIMPP_LIBRARY CIMPP_INCLUDE_DIR) +if(NOT TARGET CIMPP::cimpp) + add_library(CIMPP::cimpp UNKNOWN IMPORTED) + set(_incs + "${CIMPP_SRC_INCLUDE_DIR}" + "${CIMPP_VER_INCLUDE_DIR}" + "${CIMPP_STATIC_INCLUDE_DIR}" + "${CIMPP_STATIC_IEC61970_INCLUDE_DIR}") + foreach(_inc IN LISTS _incs) + if(_inc STREQUAL "" OR NOT EXISTS "${_inc}") + list(REMOVE_ITEM _incs "${_inc}") + endif() + endforeach() + list(REMOVE_DUPLICATES _incs) + if(NOT CIMPP_LIBRARY OR _incs STREQUAL "") + message(WARNING "[CIMpp] Skipping CIMPP::cimpp target because include paths or library are missing") + unset(CIMPP_LIBRARY CACHE) + set(CIMPP_LIBRARY "") + else() + set_target_properties(CIMPP::cimpp PROPERTIES + IMPORTED_LOCATION "${CIMPP_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${_incs}") + endif() +endif() -add_library(libcimpp INTERFACE) -target_link_libraries(libcimpp INTERFACE ${CIMPP_LIBRARIES}) -target_include_directories(libcimpp INTERFACE ${CIMPP_INCLUDE_DIRS}) +message(STATUS "[CIMpp] src = ${CIMPP_SRC_INCLUDE_DIR}") +message(STATUS "[CIMpp] version = ${CIMPP_VER_INCLUDE_DIR}") +message(STATUS "[CIMpp] static = ${CIMPP_STATIC_INCLUDE_DIR}") +message(STATUS "[CIMpp] IEC61970 = ${CIMPP_STATIC_IEC61970_INCLUDE_DIR}") +message(STATUS "[CIMpp] lib = ${CIMPP_LIBRARY}") diff --git a/dpsim-models/include/dpsim-models/CIM/Reader.h b/dpsim-models/include/dpsim-models/CIM/Reader.h index 71f6032ea1..b8c4cef03b 100644 --- a/dpsim-models/include/dpsim-models/CIM/Reader.h +++ b/dpsim-models/include/dpsim-models/CIM/Reader.h @@ -10,6 +10,8 @@ #include #include +#include +#include #include #include @@ -54,6 +56,22 @@ class ConductingEquipment; namespace CPS { namespace CIM { +template +struct has_value_member : std::false_type {}; + +template +struct has_value_member().value)>> + : std::true_type {}; + +template const auto &cimString(const T &field) { + if constexpr (has_value_member::value) { + return field.value; + } else { + return field; + } +} + class InvalidTopology {}; class Reader { diff --git a/dpsim-models/src/CIM/Reader.cpp b/dpsim-models/src/CIM/Reader.cpp index 2189e527f9..9c4816578f 100644 --- a/dpsim-models/src/CIM/Reader.cpp +++ b/dpsim-models/src/CIM/Reader.cpp @@ -16,6 +16,8 @@ using namespace CPS; using namespace CPS::CIM; + +using CIMPP::String; using CIMPP::UnitMultiplier; Reader::Reader(String name, Logger::Level logLevel, @@ -176,8 +178,8 @@ void Reader::parseFiles() { dynamic_cast(obj)) { // Check if object is already in equipment list - if (mPowerflowEquipment.find(idObj->mRID) == - mPowerflowEquipment.end()) { + const auto &rid = cimString(idObj->mRID); + if (mPowerflowEquipment.find(rid) == mPowerflowEquipment.end()) { TopologicalPowerComp::Ptr comp = mapComponent(obj); if (comp) mPowerflowEquipment.insert(std::make_pair(comp->uid(), comp)); @@ -240,12 +242,13 @@ void Reader::processSvVoltage(CIMPP::SvVoltage *volt) { mSLog, "SvVoltage references missing Topological Node, ignoring"); return; } - auto search = mPowerflowNodes.find(node->mRID); + const auto &nodeRid = cimString(node->mRID); + auto search = mPowerflowNodes.find(nodeRid); if (search == mPowerflowNodes.end()) { SPDLOG_LOGGER_WARN(mSLog, "SvVoltage references Topological Node {}" " missing from mTopNodes, ignoring", - node->mRID); + nodeRid); return; } @@ -260,27 +263,29 @@ void Reader::processSvVoltage(CIMPP::SvVoltage *volt) { << volt->angle.value << std::endl; } Real voltagePhase = volt->angle.value * PI / 180; - mPowerflowNodes[node->mRID]->setInitialVoltage( + mPowerflowNodes[nodeRid]->setInitialVoltage( std::polar(voltageAbs, voltagePhase)); SPDLOG_LOGGER_INFO( mSLog, "Node {} MatrixNodeIndex {}: {} V, {} deg", - mPowerflowNodes[node->mRID]->uid(), - mPowerflowNodes[node->mRID]->matrixNodeIndex(), - std::abs(mPowerflowNodes[node->mRID]->initialSingleVoltage()), - std::arg(mPowerflowNodes[node->mRID]->initialSingleVoltage()) * 180 / PI); + mPowerflowNodes[nodeRid]->uid(), + mPowerflowNodes[nodeRid]->matrixNodeIndex(), + std::abs(mPowerflowNodes[nodeRid]->initialSingleVoltage()), + std::arg(mPowerflowNodes[nodeRid]->initialSingleVoltage()) * 180 / PI); } void Reader::processSvPowerFlow(CIMPP::SvPowerFlow *flow) { CIMPP::Terminal *term = flow->Terminal; - mPowerflowTerminals[term->mRID]->setPower( + const auto &terminalRid = cimString(term->mRID); + + mPowerflowTerminals[terminalRid]->setPower( Complex(Reader::unitValue(flow->p.value, UnitMultiplier::M), Reader::unitValue(flow->q.value, UnitMultiplier::M))); - SPDLOG_LOGGER_WARN(mSLog, "Terminal {}: {} W + j {} Var", term->mRID, - mPowerflowTerminals[term->mRID]->singleActivePower(), - mPowerflowTerminals[term->mRID]->singleReactivePower()); + SPDLOG_LOGGER_WARN(mSLog, "Terminal {}: {} W + j {} Var", terminalRid, + mPowerflowTerminals[terminalRid]->singleActivePower(), + mPowerflowTerminals[terminalRid]->singleReactivePower()); } SystemTopology Reader::systemTopology() { @@ -327,18 +332,21 @@ Matrix::Index Reader::mapTopologicalNode(String mrid) { TopologicalPowerComp::Ptr Reader::mapEnergyConsumer(CIMPP::EnergyConsumer *consumer) { - SPDLOG_LOGGER_INFO(mSLog, " Found EnergyConsumer {}", consumer->name); + const auto &consumerName = cimString(consumer->name); + const auto &consumerRid = cimString(consumer->mRID); + + SPDLOG_LOGGER_INFO(mSLog, " Found EnergyConsumer {}", consumerName); if (mDomain == Domain::EMT) { if (mPhase == PhaseType::ABC) { - return std::make_shared(consumer->mRID, consumer->name, + return std::make_shared(consumerRid, consumerName, mComponentLogLevel); } else { SPDLOG_LOGGER_INFO(mSLog, " RXLoad for EMT not implemented yet"); - return std::make_shared(consumer->mRID, consumer->name, + return std::make_shared(consumerRid, consumerName, mComponentLogLevel); } } else if (mDomain == Domain::SP) { - auto load = std::make_shared(consumer->mRID, consumer->name, + auto load = std::make_shared(consumerRid, consumerName, mComponentLogLevel); // P and Q values will be set according to SvPowerFlow data @@ -348,18 +356,21 @@ Reader::mapEnergyConsumer(CIMPP::EnergyConsumer *consumer) { return load; } else { if (mUseProtectionSwitches) - return std::make_shared( - consumer->mRID, consumer->name, mComponentLogLevel); + return std::make_shared(consumerRid, consumerName, + mComponentLogLevel); else - return std::make_shared(consumer->mRID, consumer->name, + return std::make_shared(consumerRid, consumerName, mComponentLogLevel); } } TopologicalPowerComp::Ptr Reader::mapACLineSegment(CIMPP::ACLineSegment *line) { + const auto &lineName = cimString(line->name); + const auto &lineRid = cimString(line->mRID); + SPDLOG_LOGGER_INFO(mSLog, " Found ACLineSegment {} r={} x={} bch={} gch={}", - line->name, (float)line->r.value, (float)line->x.value, + lineName, (float)line->r.value, (float)line->x.value, (float)line->bch.value, (float)line->gch.value); Real resistance = line->r.value; @@ -386,25 +397,25 @@ TopologicalPowerComp::Ptr Reader::mapACLineSegment(CIMPP::ACLineSegment *line) { Matrix cond_3ph = CPS::Math::singlePhaseParameterToThreePhase(conductance); - auto cpsLine = std::make_shared(line->mRID, line->name, + auto cpsLine = std::make_shared(lineRid, lineName, mComponentLogLevel); cpsLine->setParameters(res_3ph, ind_3ph, cap_3ph, cond_3ph); return cpsLine; } else { SPDLOG_LOGGER_INFO(mSLog, " PiLine for EMT not implemented yet"); - auto cpsLine = std::make_shared(line->mRID, line->name, + auto cpsLine = std::make_shared(lineRid, lineName, mComponentLogLevel); cpsLine->setParameters(resistance, inductance, capacitance, conductance); return cpsLine; } } else if (mDomain == Domain::SP) { - auto cpsLine = std::make_shared(line->mRID, line->name, + auto cpsLine = std::make_shared(lineRid, lineName, mComponentLogLevel); cpsLine->setParameters(resistance, inductance, capacitance, conductance); cpsLine->setBaseVoltage(baseVoltage); return cpsLine; } else { - auto cpsLine = std::make_shared(line->mRID, line->name, + auto cpsLine = std::make_shared(lineRid, lineName, mComponentLogLevel); cpsLine->setParameters(resistance, inductance, capacitance, conductance); return cpsLine; @@ -413,14 +424,16 @@ TopologicalPowerComp::Ptr Reader::mapACLineSegment(CIMPP::ACLineSegment *line) { TopologicalPowerComp::Ptr Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) { + const auto &transRid = cimString(trans->mRID); if (trans->PowerTransformerEnd.size() != 2) { SPDLOG_LOGGER_WARN( mSLog, "PowerTransformer {} does not have exactly two windings, ignoring", - trans->name); + cimString(trans->name)); return nullptr; } - SPDLOG_LOGGER_INFO(mSLog, "Found PowerTransformer {}", trans->name); + SPDLOG_LOGGER_INFO(mSLog, "Found PowerTransformer {}", + cimString(trans->name)); // assign transformer ends CIMPP::PowerTransformerEnd *end1 = nullptr, *end2 = nullptr; @@ -434,7 +447,8 @@ Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) { } // setting default values for non-set resistances and reactances - SPDLOG_LOGGER_INFO(mSLog, " PowerTransformerEnd_1 {}", end1->name); + SPDLOG_LOGGER_INFO(mSLog, " PowerTransformerEnd_1 {}", + cimString(end1->name)); SPDLOG_LOGGER_INFO(mSLog, " Srated={} Vrated={}", (float)end1->ratedS.value, (float)end1->ratedU.value); try { @@ -455,7 +469,8 @@ Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) { "default value of X={}", (float)end1->x.value); } - SPDLOG_LOGGER_INFO(mSLog, " PowerTransformerEnd_2 {}", end2->name); + SPDLOG_LOGGER_INFO(mSLog, " PowerTransformerEnd_2 {}", + cimString(end2->name)); SPDLOG_LOGGER_INFO(mSLog, " Srated={} Vrated={}", (float)end2->ratedS.value, (float)end2->ratedU.value); try { @@ -482,7 +497,7 @@ Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) { mSLog, " PowerTransformerEnds of {} come with distinct rated power values. " "Using rated power of PowerTransformerEnd_1.", - trans->name); + cimString(trans->name)); } Real ratedPower = unitValue(end1->ratedS.value, UnitMultiplier::M); Real voltageNode1 = unitValue(end1->ratedU.value, UnitMultiplier::k); @@ -541,7 +556,8 @@ Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) { CPS::Math::singlePhaseParameterToThreePhase(inductance); Bool withResistiveLosses = resistance > 0; auto transformer = std::make_shared( - trans->mRID, trans->name, mComponentLogLevel, withResistiveLosses); + transRid, cimString(trans->name), mComponentLogLevel, + withResistiveLosses); transformer->setParameters(voltageNode1, voltageNode2, ratedPower, ratioAbs, ratioPhase, resistance_3ph, inductance_3ph); @@ -552,7 +568,7 @@ Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) { } } else if (mDomain == Domain::SP) { auto transformer = std::make_shared( - trans->mRID, trans->name, mComponentLogLevel); + transRid, cimString(trans->name), mComponentLogLevel); transformer->setParameters(voltageNode1, voltageNode2, ratedPower, ratioAbs, ratioPhase, resistance, inductance); Real baseVolt = voltageNode1 >= voltageNode2 ? voltageNode1 : voltageNode2; @@ -561,7 +577,8 @@ Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) { } else { Bool withResistiveLosses = resistance > 0; auto transformer = std::make_shared( - trans->mRID, trans->name, mComponentLogLevel, withResistiveLosses); + transRid, cimString(trans->name), mComponentLogLevel, + withResistiveLosses); transformer->setParameters(voltageNode1, voltageNode2, ratedPower, ratioAbs, ratioPhase, resistance, inductance); return transformer; @@ -570,7 +587,10 @@ Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) { TopologicalPowerComp::Ptr Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { - SPDLOG_LOGGER_INFO(mSLog, " Found Synchronous machine {}", machine->name); + const auto &machineName = cimString(machine->name); + const auto &machineRid = cimString(machine->mRID); + + SPDLOG_LOGGER_INFO(mSLog, " Found Synchronous machine {}", machineName); if (mDomain == Domain::DP) { SPDLOG_LOGGER_INFO(mSLog, " Create generator in DP domain."); @@ -591,7 +611,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { if (CIMPP::SynchronousMachineTimeConstantReactance *genDyn = dynamic_cast( obj)) { - if (genDyn->SynchronousMachine->mRID == machine->mRID) { + if (cimString(genDyn->SynchronousMachine->mRID) == machineRid) { // stator Real Rs = genDyn->statorResistance.value; Real Ll = genDyn->statorLeakageReactance.value; @@ -621,7 +641,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG(mSLog, " GeneratorType is TransientStability."); auto gen = DP::Ph1::SynchronGeneratorTrStab::make( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setStandardParametersPU(ratedPower, ratedVoltage, mFrequency, Ld_t, H); return gen; @@ -629,7 +649,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator6aOrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s); @@ -638,7 +658,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator6bOrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s); @@ -647,7 +667,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator5OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s, 0.0); @@ -656,7 +676,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator4OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t); @@ -665,7 +685,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator3OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Td0_t); @@ -674,7 +694,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator4OrderPCM."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t); @@ -683,7 +703,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator4OrderTPM."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t); @@ -692,7 +712,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator6OrderPCM."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s); @@ -704,7 +724,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { } else if (mGeneratorType == GeneratorType::IdealVoltageSource) { SPDLOG_LOGGER_DEBUG(mSLog, " GeneratorType is IdealVoltageSource."); return std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); } else if (mGeneratorType == GeneratorType::None) { throw SystemError("GeneratorType is None. Specify!"); } else { @@ -727,7 +747,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { if (CIMPP::SynchronousMachineTimeConstantReactance *genDyn = dynamic_cast( obj)) { - if (genDyn->SynchronousMachine->mRID == machine->mRID) { + if (cimString(genDyn->SynchronousMachine->mRID) == machineRid) { // stator Real Rs = genDyn->statorResistance.value; Real Ll = genDyn->statorLeakageReactance.value; @@ -757,7 +777,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG(mSLog, " GeneratorType is TransientStability."); auto gen = SP::Ph1::SynchronGeneratorTrStab::make( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setStandardParametersPU(ratedPower, ratedVoltage, mFrequency, Ld_t, H); return gen; @@ -765,7 +785,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator6aOrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s); @@ -774,7 +794,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator6bOrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s); @@ -783,7 +803,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator5OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s, 0.0); @@ -792,7 +812,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator4OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t); @@ -801,7 +821,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator3OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Td0_t); @@ -816,7 +836,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { if (CIMPP::GeneratingUnit *genUnit = dynamic_cast(obj)) { for (auto syncGen : genUnit->RotatingMachine) { - if (syncGen->mRID == machine->mRID) { + if (cimString(syncGen->mRID) == machineRid) { // Check whether relevant input data are set, otherwise set default values Real setPointActivePower = 0; Real setPointVoltage = 0; @@ -829,7 +849,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { } catch (ReadingUninitializedField *e) { std::cerr << "Uninitalized setPointActivePower for GeneratingUnit " - << machine->name << ". Using default value of " + << machineName << ". Using default value of " << setPointActivePower << std::endl; } if (machine->RegulatingControl) { @@ -840,7 +860,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { setPointVoltage); } else { std::cerr << "Uninitalized setPointVoltage for GeneratingUnit " - << machine->name << ". Using default value of " + << machineName << ". Using default value of " << setPointVoltage << std::endl; } try { @@ -851,12 +871,12 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { } catch (ReadingUninitializedField *e) { std::cerr << "Uninitalized maximumReactivePower for GeneratingUnit " - << machine->name << ". Using default value of " + << machineName << ". Using default value of " << maximumReactivePower << std::endl; } auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setParameters( unitValue(machine->ratedS.value, UnitMultiplier::M), unitValue(machine->ratedU.value, UnitMultiplier::k), @@ -869,9 +889,9 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { } } SPDLOG_LOGGER_INFO(mSLog, "no corresponding initial power for {}", - machine->name); + machineName); return std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); } else if (mGeneratorType == GeneratorType::None) { throw SystemError("GeneratorType is None. Specify!"); } else { @@ -894,7 +914,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { if (CIMPP::SynchronousMachineTimeConstantReactance *genDyn = dynamic_cast( obj)) { - if (genDyn->SynchronousMachine->mRID == machine->mRID) { + if (cimString(genDyn->SynchronousMachine->mRID) == machineRid) { // stator Real Rs = genDyn->statorResistance.value; @@ -924,7 +944,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { if (mGeneratorType == GeneratorType::FullOrder) { SPDLOG_LOGGER_DEBUG(mSLog, " GeneratorType is FullOrder."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setParametersOperationalPerUnit( ratedPower, ratedVoltage, mFrequency, poleNum, nomFieldCurr, Rs, Ld, Lq, Ld_t, Lq_t, Ld_s, Lq_s, Ll, Td0_t, Tq0_t, Td0_s, @@ -933,7 +953,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { } else if (mGeneratorType == GeneratorType::FullOrderVBR) { SPDLOG_LOGGER_DEBUG(mSLog, " GeneratorType is FullOrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setBaseAndOperationalPerUnitParameters( ratedPower, ratedVoltage, mFrequency, poleNum, nomFieldCurr, Rs, Ld, Lq, Ld_t, Lq_t, Ld_s, Lq_s, Ll, Td0_t, Tq0_t, Td0_s, @@ -944,7 +964,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { mSLog, " GeneratorType is SynchronGenerator6aOrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s); @@ -954,7 +974,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { mSLog, " GeneratorType is SynchronGenerator6bOrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s); @@ -963,7 +983,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator5OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit( ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s, 0.0); @@ -972,7 +992,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator4OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Lq_t, Td0_t, Tq0_t); @@ -981,7 +1001,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { SPDLOG_LOGGER_DEBUG( mSLog, " GeneratorType is SynchronGenerator3OrderVBR."); auto gen = std::make_shared( - machine->mRID, machine->name, mComponentLogLevel); + machineRid, machineName, mComponentLogLevel); gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t, Td0_t); @@ -993,12 +1013,12 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { } else if (mGeneratorType == GeneratorType::IdealVoltageSource) { SPDLOG_LOGGER_DEBUG(mSLog, " GeneratorType is IdealVoltageSource."); return std::make_shared( - machine->mRID, machine->name, mComponentLogLevel, + machineRid, machineName, mComponentLogLevel, GeneratorType::IdealVoltageSource); } else if (mGeneratorType == GeneratorType::IdealCurrentSource) { SPDLOG_LOGGER_DEBUG(mSLog, " GeneratorType is IdealCurrentSource."); return std::make_shared( - machine->mRID, machine->name, mComponentLogLevel, + machineRid, machineName, mComponentLogLevel, GeneratorType::IdealCurrentSource); } else if (mGeneratorType == GeneratorType::None) { throw SystemError("GeneratorType is None. Specify!"); @@ -1012,7 +1032,7 @@ Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) { TopologicalPowerComp::Ptr Reader::mapExternalNetworkInjection(CIMPP::ExternalNetworkInjection *extnet) { SPDLOG_LOGGER_INFO(mSLog, "Found External Network Injection {}", - extnet->name); + cimString(extnet->name)); Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(extnet); @@ -1070,7 +1090,7 @@ Reader::mapExternalNetworkInjection(CIMPP::ExternalNetworkInjection *extnet) { TopologicalPowerComp::Ptr Reader::mapEquivalentShunt(CIMPP::EquivalentShunt *shunt) { - SPDLOG_LOGGER_INFO(mSLog, "Found shunt {}", shunt->name); + SPDLOG_LOGGER_INFO(mSLog, "Found shunt {}", cimString(shunt->name)); Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(shunt); @@ -1090,7 +1110,7 @@ Real Reader::determineBaseVoltageAssociatedWithEquipment( if (CIMPP::BaseVoltage *baseVolt = dynamic_cast(obj)) { for (auto comp : baseVolt->ConductingEquipment) { - if (comp->name == equipment->name) { + if (cimString(comp->name) == cimString(equipment->name)) { baseVoltage = unitValue(baseVolt->nominalVoltage.value, UnitMultiplier::k); } @@ -1103,7 +1123,8 @@ Real Reader::determineBaseVoltageAssociatedWithEquipment( if (CIMPP::TopologicalNode *topNode = dynamic_cast(obj)) { for (auto term : topNode->Terminal) { - if (term->ConductingEquipment->name == equipment->name) { + if (cimString(term->ConductingEquipment->name) == + cimString(equipment->name)) { baseVoltage = unitValue(topNode->BaseVoltage->nominalVoltage.value, UnitMultiplier::k); } @@ -1119,75 +1140,73 @@ template void Reader::processTopologicalNode(CIMPP::TopologicalNode *topNode) { // Add this node to global node list and assign simulation node incrementally. int matrixNodeIndex = Int(mPowerflowNodes.size()); - mPowerflowNodes[topNode->mRID] = SimNode::make( - topNode->mRID, topNode->name, matrixNodeIndex, mPhase); + const auto &nodeRid = cimString(topNode->mRID); + mPowerflowNodes[nodeRid] = SimNode::make( + nodeRid, cimString(topNode->name), matrixNodeIndex, mPhase); if (mPhase == PhaseType::ABC) { SPDLOG_LOGGER_INFO( - mSLog, "TopologicalNode {} phase A as simulation node {} ", - topNode->mRID, - mPowerflowNodes[topNode->mRID]->matrixNodeIndex(PhaseType::A)); + mSLog, "TopologicalNode {} phase A as simulation node {} ", nodeRid, + mPowerflowNodes[nodeRid]->matrixNodeIndex(PhaseType::A)); SPDLOG_LOGGER_INFO( - mSLog, "TopologicalNode {} phase B as simulation node {}", - topNode->mRID, - mPowerflowNodes[topNode->mRID]->matrixNodeIndex(PhaseType::B)); + mSLog, "TopologicalNode {} phase B as simulation node {}", nodeRid, + mPowerflowNodes[nodeRid]->matrixNodeIndex(PhaseType::B)); SPDLOG_LOGGER_INFO( - mSLog, "TopologicalNode {} phase C as simulation node {}", - topNode->mRID, - mPowerflowNodes[topNode->mRID]->matrixNodeIndex(PhaseType::C)); + mSLog, "TopologicalNode {} phase C as simulation node {}", nodeRid, + mPowerflowNodes[nodeRid]->matrixNodeIndex(PhaseType::C)); } else SPDLOG_LOGGER_INFO(mSLog, "TopologicalNode id: {}, name: {} as simulation node {}", - topNode->mRID, topNode->name, - mPowerflowNodes[topNode->mRID]->matrixNodeIndex()); + nodeRid, cimString(topNode->name), + mPowerflowNodes[nodeRid]->matrixNodeIndex()); for (auto term : topNode->Terminal) { // Insert Terminal if it does not exist in the map and add reference to node. // This could be optimized because the Terminal is searched twice. - auto cpsTerm = SimTerminal::make(term->mRID); - mPowerflowTerminals.insert(std::make_pair(term->mRID, cpsTerm)); - cpsTerm->setNode(std::dynamic_pointer_cast>( - mPowerflowNodes[topNode->mRID])); + const auto &termRid = cimString(term->mRID); + auto cpsTerm = SimTerminal::make(termRid); + mPowerflowTerminals.insert(std::make_pair(termRid, cpsTerm)); + cpsTerm->setNode( + std::dynamic_pointer_cast>(mPowerflowNodes[nodeRid])); if (!term->sequenceNumber.initialized) term->sequenceNumber = 1; - SPDLOG_LOGGER_INFO(mSLog, " Terminal {}, sequenceNumber {}", term->mRID, + SPDLOG_LOGGER_INFO(mSLog, " Terminal {}, sequenceNumber {}", termRid, (int)term->sequenceNumber); // Try to process Equipment connected to Terminal. CIMPP::ConductingEquipment *equipment = term->ConductingEquipment; if (!equipment) { SPDLOG_LOGGER_WARN(mSLog, "Terminal {} has no Equipment, ignoring!", - term->mRID); + termRid); } else { // Insert Equipment if it does not exist in the map and add reference to Terminal. // This could be optimized because the Equipment is searched twice. - if (mPowerflowEquipment.find(equipment->mRID) == - mPowerflowEquipment.end()) { + const auto &equipmentRid = cimString(equipment->mRID); + if (mPowerflowEquipment.find(equipmentRid) == mPowerflowEquipment.end()) { TopologicalPowerComp::Ptr comp = mapComponent(equipment); if (comp) { - mPowerflowEquipment.insert(std::make_pair(equipment->mRID, comp)); + mPowerflowEquipment.insert(std::make_pair(equipmentRid, comp)); } else { - SPDLOG_LOGGER_WARN(mSLog, "Could not map equipment {}", - equipment->mRID); + SPDLOG_LOGGER_WARN(mSLog, "Could not map equipment {}", equipmentRid); continue; } } - auto pfEquipment = mPowerflowEquipment.at(equipment->mRID); + auto pfEquipment = mPowerflowEquipment.at(equipmentRid); if (pfEquipment == nullptr) { SPDLOG_LOGGER_ERROR(mSLog, "Equipment {} is null in equipment list", - equipment->mRID); + equipmentRid); throw SystemError("Equipment is null in equipment list."); } std::dynamic_pointer_cast>(pfEquipment) ->setTerminalAt(std::dynamic_pointer_cast>( - mPowerflowTerminals[term->mRID]), + mPowerflowTerminals[termRid]), term->sequenceNumber - 1); SPDLOG_LOGGER_INFO(mSLog, " Added Terminal {} to Equipment {}", - term->mRID, equipment->mRID); + termRid, equipmentRid); } } } diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index 5ff995162f..db23ea808d 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -158,7 +158,7 @@ list(APPEND MODELS_SOURCES if(WITH_CIM) list(APPEND MODELS_SOURCES CIM/Reader.cpp) - list(APPEND MODELS_LIBRARIES libcimpp) + list(APPEND MODELS_LIBRARIES CIMPP::cimpp) endif() if(WITH_GRAPHVIZ) diff --git a/dpsim/CMakeLists.txt b/dpsim/CMakeLists.txt index ef0a3d1c7c..37ae751479 100644 --- a/dpsim/CMakeLists.txt +++ b/dpsim/CMakeLists.txt @@ -11,7 +11,7 @@ set(DPSIM_INCLUDE_DIRS add_subdirectory(src) if(WITH_PYBIND) - set(DPSIMPY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/Include/dpsim/pybind) + set(DPSIMPY_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include/dpsim/pybind) add_subdirectory(src/pybind) endif() diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index 99eea261a6..8fc377730e 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -165,7 +165,7 @@ if(WITH_RT) endif() if(WITH_CIM) - list(APPEND LIBRARIES libcimpp) + list(APPEND LIBRARIES CIMPP::cimpp) set(CIM_SOURCES CIM/WSCC-9bus_CIM.cpp diff --git a/dpsim/examples/cxx/cim_graphviz/CMakeLists.txt b/dpsim/examples/cxx/cim_graphviz/CMakeLists.txt index 4a81584785..940c0c5c1e 100644 --- a/dpsim/examples/cxx/cim_graphviz/CMakeLists.txt +++ b/dpsim/examples/cxx/cim_graphviz/CMakeLists.txt @@ -1,4 +1,4 @@ if(WITH_GRAPHVIZ AND WITH_CIM) add_executable(cimviz cimviz.cpp) - target_link_libraries(cimviz PUBLIC dpsim-models libcimpp ${GRAPHVIZ_LIBRARIES}) + target_link_libraries(cimviz PUBLIC dpsim-models CIMPP::cimpp ${GRAPHVIZ_LIBRARIES}) endif() From 81b56632619f4076b5f2dd25f9148ef88f7b5706 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 7 Oct 2025 23:41:38 +0200 Subject: [PATCH 110/168] Update nix build and github actions container workflow Signed-off-by: Leonardo Carreras --- .github/workflows/container.yaml | 1 + flake.lock | 26 ++++++++++++++++++++------ flake.nix | 23 ++++++++++------------- packaging/Nix/cimpp.nix | 4 ++-- 4 files changed, 33 insertions(+), 21 deletions(-) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index 0bd470d519..c5a0799c84 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -105,6 +105,7 @@ jobs: tags: sogno/dpsim:manylinux create-docker-binder: + needs: create-docker-fedora-dev runs-on: ubuntu-latest steps: - name: Checkout diff --git a/flake.lock b/flake.lock index 65e31ad9c5..65cfa8ea78 100644 --- a/flake.lock +++ b/flake.lock @@ -34,6 +34,22 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1759070547, + "narHash": "sha256-JVZl8NaVRYb0+381nl7LvPE+A774/dRpif01FKLrYFQ=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "647e5c14cbd5067f44ac86b74f014962df460840", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "flake-utils": "flake-utils", @@ -58,16 +74,14 @@ }, "villas-node": { "inputs": { - "nixpkgs": [ - "nixpkgs" - ] + "nixpkgs": "nixpkgs_2" }, "locked": { - "lastModified": 1743649879, - "narHash": "sha256-XqPw+lYpg5qvGPscjYqKfMexk0xlMKpm6nF/hRnVAlY=", + "lastModified": 1759121869, + "narHash": "sha256-RQJ02SVEq5l+MGe3++SIgrzZDJm/zHRwIGMnMoUBpUU=", "owner": "VILLASframework", "repo": "node", - "rev": "d56124e7934c319f9d3fca8ad862b20f29ebdb8e", + "rev": "5606793aaee2d1eeb663180d3e52718fa8bd5931", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index b4dae14c5d..d9feac72d5 100644 --- a/flake.nix +++ b/flake.nix @@ -2,11 +2,10 @@ description = "DPsim - Solver library for dynamic power system simulation"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; villas-node = { url = "github:VILLASframework/node"; - inputs.nixpkgs.follows = "nixpkgs"; }; }; @@ -25,22 +24,20 @@ # Required for old sundials version config.permittedInsecurePackages = [ "python-2.7.18.8" ]; - overlays = [ - villas-node.overlays.default - - (final: prev: { + (final: prev: let + villasPkg = villas-node.packages.${system}.villas-node; + in { readerwriterqueue = final.callPackage ./packaging/Nix/readerwriterqueue.nix { }; - cimpp = final.callPackage ./packaging/Nix/cimpp.nix { }; - suitesparse-dpsim = prev.callPackage ./packaging/Nix/suitesparse.nix { }; - sundials321 = prev.callPackage ./packaging/Nix/sundials.nix { }; - dpsim = pkgs.callPackage ./packaging/Nix/dpsim.nix { }; - dpsimpy = pkgs.callPackage ./packaging/Nix/dpsimpy.nix { }; + cimpp = final.callPackage ./packaging/Nix/cimpp.nix { }; + suitesparse-dpsim = prev.callPackage ./packaging/Nix/suitesparse.nix { }; + sundials321 = prev.callPackage ./packaging/Nix/sundials.nix { }; + dpsim = final.callPackage ./packaging/Nix/dpsim.nix { villas-node=villasPkg; }; + dpsimpy = final.callPackage ./packaging/Nix/dpsimpy.nix { }; }) ]; }; - in - { + in { packages = { default = pkgs.dpsim; diff --git a/packaging/Nix/cimpp.nix b/packaging/Nix/cimpp.nix index 55b41a7f92..0f56657e89 100644 --- a/packaging/Nix/cimpp.nix +++ b/packaging/Nix/cimpp.nix @@ -29,8 +29,8 @@ stdenv.mkDerivation { owner = "sogno-platform"; repo = "libcimpp"; # rev = "release/v2.2.0"; - rev = "1b11d5c17bedf0ae042628b42ecb4e49df70b2f6"; - hash = "sha256-RBcV7HlgrKML03E/J9IGIkbKAK23KAXuFJOSXTFZ/i4="; + rev = "051ee4c311572fe92b30120b897d22deb253e162"; + hash = "sha256-jyeiySIOPceH1/ZHRYsp1LczTlXuIapkMtCqlq2lZM0="; fetchSubmodules = true; }; From 1aead96712f912dd170748e2956643e11fa1c80f Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 14 Oct 2025 21:07:18 +0200 Subject: [PATCH 111/168] Implement suggestions regarding cmake, nix and dockerfiles Signed-off-by: Leonardo Carreras --- CMakeLists.txt | 13 +++---------- flake.nix | 2 +- packaging/Docker/Dockerfile.dev | 1 + packaging/Docker/Dockerfile.dev-rocky | 1 + 4 files changed, 6 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fe778bd9b3..2d817bd6ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -115,19 +115,12 @@ check_symbol_exists(timerfd_create sys/timerfd.h HAVE_TIMERFD) check_symbol_exists(getopt_long getopt.h HAVE_GETOPT) if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # Clang 18+ deprecates -Ofast; use the equivalent O3 fast-math combo instead. - add_compile_options(-O3 -ffast-math) + # Clang 18+ deprecates -Ofast; use the equivalent O3 instead. + add_compile_options(-O3) else() add_compile_options(-Ofast) endif() - # On Clang -ffast-math enables -ffinite-math-only which triggers warnings for - # infinity/NaN checks. Silence those when supported so -Werror stays usable. - check_cxx_compiler_flag("-Wno-nan-infinity-disabled" CXX_SUPPORTS_WNAN_INFINITY_DISABLED) - if(CXX_SUPPORTS_WNAN_INFINITY_DISABLED) - add_compile_options(-Wno-nan-infinity-disabled) - endif() - if(WITH_MARCH_NATIVE) add_compile_options(-march=native) endif() @@ -299,7 +292,7 @@ endif() if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME) include(FeatureSummary) - add_feature_info(CIM WITH_CIM "Loading Common Information Model (CIM) library") + add_feature_info(CIM WITH_CIM "Common Information Model (CIM) support") add_feature_info(CUDA WITH_CUDA "CUDA-based parallelization") add_feature_info(Graphviz WITH_GRAPHVIZ "Graphviz graphs") add_feature_info(GSL WITH_GSL "GNU Scientific library") diff --git a/flake.nix b/flake.nix index d9feac72d5..2c6ee9c104 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "DPsim - Solver library for dynamic power system simulation"; inputs = { - nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; flake-utils.url = "github:numtide/flake-utils"; villas-node = { url = "github:VILLASframework/node"; diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index 2f34d973ad..8cb173b290 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -96,6 +96,7 @@ RUN cd /tmp && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node +# Remove this part in the future and use dedicated Jupyter Dockerfile RUN set -eux; \ dnf -y --refresh install npm; \ pip3 install --no-cache-dir \ diff --git a/packaging/Docker/Dockerfile.dev-rocky b/packaging/Docker/Dockerfile.dev-rocky index 4f546d3259..d32aab94a2 100644 --- a/packaging/Docker/Dockerfile.dev-rocky +++ b/packaging/Docker/Dockerfile.dev-rocky @@ -145,6 +145,7 @@ RUN cd /tmp && \ git clone --recurse-submodules https://github.com/VILLASframework/node.git villas-node && \ cd villas-node && \ git checkout ${VILLAS_VERSION} && \ + # libxil is currently not working in the VILLASnode installer script, skip and use submodule for FPGA support env MAKE_OPTS="" DEPS_NONINTERACTIVE=1 DEPS_SKIP=libxil bash packaging/deps.sh && \ mkdir -p build && cd build && \ cmake ${CMAKE_OPTS} .. \ From 8bfea730112af1495ba20ae775348a9908c62442 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 20 Oct 2025 14:48:49 +0200 Subject: [PATCH 112/168] Disable code coverage in linux-fedora-examples on workflow Signed-off-by: Leonardo Carreras --- .github/workflows/build_test_linux_fedora.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_test_linux_fedora.yaml b/.github/workflows/build_test_linux_fedora.yaml index 9dfa72949e..9e0d9aa16b 100644 --- a/.github/workflows/build_test_linux_fedora.yaml +++ b/.github/workflows/build_test_linux_fedora.yaml @@ -67,7 +67,7 @@ jobs: - name: Configure CMake shell: bash working-directory: ${{ github.workspace }}/build - run: cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 -DCOVERAGE=ON $GITHUB_WORKSPACE + run: cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 $GITHUB_WORKSPACE - name: Build every target shell: bash From d5d12fe97c4a7b80da597d7358f880cd907e832c Mon Sep 17 00:00:00 2001 From: shikhin Date: Sat, 18 Oct 2025 20:53:19 +0530 Subject: [PATCH 113/168] Updated loggers to use SPD_LOG_LOGGER macros Signed-off-by: shikhin --- .../src/EMT/EMT_Ph3_ControlledCurrentSource.cpp | 8 ++++---- dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp | 6 ++++-- dpsim-villas/examples/cxx/Fpga9BusHil.cpp | 7 +++++-- .../examples/cxx/FpgaCosim3PhInfiniteBus.cpp | 8 +++++--- dpsim-villas/examples/cxx/FpgaCosimulation.cpp | 8 ++++++-- dpsim-villas/examples/cxx/FpgaExample.cpp | 7 +++++-- dpsim-villas/src/InterfaceWorkerVillas.cpp | 8 ++++---- dpsim/include/dpsim/MNASolverFactory.h | 14 +++++++------- dpsim/src/MNASolverPlugin.cpp | 2 +- dpsim/src/RealTimeDataLogger.cpp | 16 +++++++++------- dpsim/src/Simulation.cpp | 6 +++--- 11 files changed, 53 insertions(+), 37 deletions(-) diff --git a/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp b/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp index ec410b520f..b0f335f61b 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp @@ -28,10 +28,10 @@ SimPowerComp::Ptr EMT::Ph3::ControlledCurrentSource::clone(String name) { void EMT::Ph3::ControlledCurrentSource::setParameters(Matrix currentRef) { **mCurrentRef = currentRef; - - mSLog->info("\nCurrent reference phasor [I]: {:s}", - Logger::matrixCompToString(currentRef)); - + SPDLOG_LOGGER_INFO( + mSLog, "\nCurrent reference phasor [I]: {:s}", + Logger::matrixCompToString(currentRef) + ); mParametersSet = true; } diff --git a/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp b/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp index dc63f3c9b1..647873a815 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp @@ -39,10 +39,12 @@ void EMT::Ph3::CurrentSource::setParameters(MatrixComp currentRef, **mCurrentRef = currentRef; mSrcFreq->setReference(mSrcSig->mFreq); - mSLog->info("\nCurrent reference phasor [I]: {:s}" + SPDLOG_LOGGER_INFO( + mSLog, "\nCurrent reference phasor [I]: {:s}" "\nFrequency [Hz]: {:s}", Logger::matrixCompToString(currentRef), - Logger::realToString(srcFreq)); + Logger::realToString(srcFreq) + ); mParametersSet = true; } diff --git a/dpsim-villas/examples/cxx/Fpga9BusHil.cpp b/dpsim-villas/examples/cxx/Fpga9BusHil.cpp index 0961f31540..c81879112c 100644 --- a/dpsim-villas/examples/cxx/Fpga9BusHil.cpp +++ b/dpsim-villas/examples/cxx/Fpga9BusHil.cpp @@ -85,7 +85,10 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - DPsim::Logger::get("FpgaExample")->debug("Config for Node:\n{}", config); + SPDLOG_LOGGER_DEBUG( + DPsim::Logger::get("FpgaExample"), + "Config for Node:\n{}", + config); return config; } @@ -302,7 +305,7 @@ int main(int argc, char *argv[]) { sim.run(); - CPS::Logger::get("FpgaExample")->info("Simulation finished."); + SPDLOG_LOGGER_INFO(CPS::Logger::get("FpgaExample"), "Simulation finished."); sim.logStepTimes("FpgaExample"); topo.first.renderToFile("Fpga9BusHil.svg"); } diff --git a/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp b/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp index cc1c36d554..05adbb7cf2 100644 --- a/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp +++ b/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp @@ -133,8 +133,10 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - DPsim::Logger::get("FpgaCosim3PhInfiniteBus") - ->debug("Config for Node:\n{}", config); + SPDLOG_LOGGER_DEBUG( + DPsim::Logger::get("FpgaCosim3PhInfiniteBus"), + "Config for Node:\n{}", + config); return config; } @@ -250,7 +252,7 @@ int main(int argc, char *argv[]) { } sim.run(); - CPS::Logger::get("FpgaCosim3PhInfiniteBus")->info("Simulation finished."); + SPDLOG_LOGGER_INFO(CPS::Logger::get("FpgaCosim3PhInfiniteBus"), "Simulation finished."); sim.logStepTimes("FpgaCosim3PhInfiniteBus"); // std::ofstream of("task_dependencies.svg"); diff --git a/dpsim-villas/examples/cxx/FpgaCosimulation.cpp b/dpsim-villas/examples/cxx/FpgaCosimulation.cpp index 79bea5b4d2..723f98926d 100644 --- a/dpsim-villas/examples/cxx/FpgaCosimulation.cpp +++ b/dpsim-villas/examples/cxx/FpgaCosimulation.cpp @@ -129,7 +129,11 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - DPsim::Logger::get("FpgaExample")->debug("Config for Node:\n{}", config); + SPDLOG_LOGGER_DEBUG( + DPsim::Logger::get("FpgaExample"), + "Config for Node:\n{}", + config + ); return config; } @@ -231,7 +235,7 @@ int main(int argc, char *argv[]) { } sim.run(); - CPS::Logger::get("FpgaCosimulation")->info("Simulation finished."); + SPDLOG_LOGGER_INFO(CPS::Logger::get("FpgaCosimulation"), "Simulation finished."); sim.logStepTimes("FpgaCosimulation"); // std::ofstream of("task_dependencies.svg"); diff --git a/dpsim-villas/examples/cxx/FpgaExample.cpp b/dpsim-villas/examples/cxx/FpgaExample.cpp index 9abbf1b621..b6f027f5a4 100644 --- a/dpsim-villas/examples/cxx/FpgaExample.cpp +++ b/dpsim-villas/examples/cxx/FpgaExample.cpp @@ -92,7 +92,10 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - DPsim::Logger::get("FpgaExample")->debug("Config for Node:\n{}", config); + SPDLOG_LOGGER_DEBUG( + DPsim::Logger::get("FpgaExample"), + "Config for Node:\n{}", + config); return config; } @@ -278,7 +281,7 @@ int main(int argc, char *argv[]) { } sim.run(); - CPS::Logger::get("FpgaExample")->info("Simulation finished."); + SPDLOG_LOGGER_INFO(CPS::Logger::get("FpgaExample"), "Simulation finished."); sim.logStepTimes("FpgaExample"); //std::ofstream of("task_dependencies.svg"); diff --git a/dpsim-villas/src/InterfaceWorkerVillas.cpp b/dpsim-villas/src/InterfaceWorkerVillas.cpp index faf35681c0..26c144adb5 100644 --- a/dpsim-villas/src/InterfaceWorkerVillas.cpp +++ b/dpsim-villas/src/InterfaceWorkerVillas.cpp @@ -520,7 +520,7 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, mImports.emplace_back( [idx, log](Sample *smp) -> AttributeBase::Ptr { if (idx >= smp->length) { - log->error("incomplete data received from InterfaceVillas"); + SPDLOG_LOGGER_ERROR(log, "incomplete data received from InterfaceVillas"); return nullptr; } return AttributePointer( @@ -533,7 +533,7 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, mImports.emplace_back( [idx, log](Sample *smp) -> AttributeBase::Ptr { if (idx >= smp->length) { - log->error("incomplete data received from InterfaceVillas"); + SPDLOG_LOGGER_ERROR(log, "incomplete data received from InterfaceVillas"); return nullptr; } return AttributePointer( @@ -546,7 +546,7 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, mImports.emplace_back( [idx, log](Sample *smp) -> AttributeBase::Ptr { if (idx >= smp->length) { - log->error("incomplete data received from InterfaceVillas"); + SPDLOG_LOGGER_ERROR(log, "incomplete data received from InterfaceVillas"); return nullptr; } return AttributePointer( @@ -559,7 +559,7 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, mImports.emplace_back( [idx, log](Sample *smp) -> AttributeBase::Ptr { if (idx >= smp->length) { - log->error("incomplete data received from InterfaceVillas"); + SPDLOG_LOGGER_ERROR(log, "incomplete data received from InterfaceVillas"); return nullptr; } return AttributePointer( diff --git a/dpsim/include/dpsim/MNASolverFactory.h b/dpsim/include/dpsim/MNASolverFactory.h index 6cfc3c7d43..8377b85ebb 100644 --- a/dpsim/include/dpsim/MNASolverFactory.h +++ b/dpsim/include/dpsim/MNASolverFactory.h @@ -81,7 +81,7 @@ class MnaSolverFactory { * to the project (MnaSolverIterative?). It is planned to merge MnaSolverDirect and MnaSolver anyway, so this won't happen. */ case DirectLinearSolverImpl::SparseLU: { - log->info("creating SparseLUAdapter solver implementation"); + SPDLOG_LOGGER_INFO(log, "creating SparseLUAdapter solver implementation"); std::shared_ptr> sparseSolver = std::make_shared>(name, domain, logLevel); sparseSolver->setDirectLinearSolverImplementation( @@ -89,7 +89,7 @@ class MnaSolverFactory { return sparseSolver; } case DirectLinearSolverImpl::DenseLU: { - log->info("creating DenseLUAdapter solver implementation"); + SPDLOG_LOGGER_INFO(log, "creating DenseLUAdapter solver implementation"); std::shared_ptr> denseSolver = std::make_shared>(name, domain, logLevel); denseSolver->setDirectLinearSolverImplementation( @@ -98,7 +98,7 @@ class MnaSolverFactory { } #ifdef WITH_KLU case DirectLinearSolverImpl::KLU: { - log->info("creating KLUAdapter solver implementation"); + SPDLOG_LOGGER_INFO(log, "creating KLUAdapter solver implementation"); std::shared_ptr> kluSolver = std::make_shared>(name, domain, logLevel); kluSolver->setDirectLinearSolverImplementation( @@ -108,7 +108,7 @@ class MnaSolverFactory { #endif #ifdef WITH_CUDA case DirectLinearSolverImpl::CUDADense: { - log->info("creating GpuDenseAdapter solver implementation"); + SPDLOG_LOGGER_INFO(log, "creating GpuDenseAdapter solver implementation"); std::shared_ptr> gpuDenseSolver = std::make_shared>(name, domain, logLevel); gpuDenseSolver->setDirectLinearSolverImplementation( @@ -117,7 +117,7 @@ class MnaSolverFactory { } #ifdef WITH_CUDA_SPARSE case DirectLinearSolverImpl::CUDASparse: { - log->info("creating GpuSparseAdapter solver implementation"); + SPDLOG_LOGGER_INFO(log, "creating GpuSparseAdapter solver implementation"); std::shared_ptr> gpuSparseSolver = std::make_shared>(name, domain, logLevel); gpuSparseSolver->setDirectLinearSolverImplementation( @@ -127,7 +127,7 @@ class MnaSolverFactory { #endif #ifdef WITH_MAGMA case DirectLinearSolverImpl::CUDAMagma: { - log->info("creating GpuMagmaAdapter solver implementation"); + SPDLOG_LOGGER_INFO(log, "creating GpuMagmaAdapter solver implementation"); std::shared_ptr> gpuMagmaSolver = std::make_shared>(name, domain, logLevel); gpuMagmaSolver->setDirectLinearSolverImplementation( @@ -138,7 +138,7 @@ class MnaSolverFactory { #endif #ifdef WITH_MNASOLVERPLUGIN case DirectLinearSolverImpl::Plugin: - log->info("creating Plugin solver implementation"); + SPDLOG_LOGGER_INFO(log, "creating Plugin solver implementation"); return std::make_shared>(pluginName, name, domain, logLevel); #endif diff --git a/dpsim/src/MNASolverPlugin.cpp b/dpsim/src/MNASolverPlugin.cpp index f25135b0a2..13ce9005b2 100644 --- a/dpsim/src/MNASolverPlugin.cpp +++ b/dpsim/src/MNASolverPlugin.cpp @@ -35,7 +35,7 @@ template MnaSolverPlugin::~MnaSolverPlugin() { extern "C" void pluginLogger(const char *str) { CPS::Logger::Log log = CPS::Logger::get("Plugin", CPS::Logger::Level::debug, CPS::Logger::Level::debug); - log->info(str); + SPDLOG_LOGGER_INFO(log, str); } template diff --git a/dpsim/src/RealTimeDataLogger.cpp b/dpsim/src/RealTimeDataLogger.cpp index 648b40a36b..e9865573d5 100644 --- a/dpsim/src/RealTimeDataLogger.cpp +++ b/dpsim/src/RealTimeDataLogger.cpp @@ -31,9 +31,10 @@ void RealTimeDataLogger::start() { static_cast(mRowNumber) * (mAttributes.size() + 1) * sizeof(Real); auto log = CPS::Logger::get("RealTimeDataLogger", CPS::Logger::Level::off, CPS::Logger::Level::info); - log->info("Preallocating memory for real-time data logger: {} rows for {} " - "attributes ({} MB)", - mRowNumber, mAttributes.size(), mb_size / (1024 * 1024)); + SPDLOG_LOGGER_INFO( + log, "Preallocating memory for real-time data logger: {} rows for {} " + "attributes ({} MB)", + mRowNumber, mAttributes.size(), mb_size / (1024 * 1024)); // We are doing real time so preallocate everything mAttributeData.resize(mRowNumber); for (auto &it : mAttributeData) { @@ -45,8 +46,9 @@ void RealTimeDataLogger::start() { void RealTimeDataLogger::stop() { auto log = CPS::Logger::get("RealTimeDataLogger", CPS::Logger::Level::off, CPS::Logger::Level::info); - log->info("Stopping real-time data logger. Writing memory to file {}", - mFilename.string()); + SPDLOG_LOGGER_INFO( + log, "Stopping real-time data logger. Writing memory to file {}", + mFilename.string()); const auto parent = mFilename.parent_path(); if (!parent.empty()) { @@ -76,8 +78,8 @@ void RealTimeDataLogger::stop() { mLogFile << '\n'; } mLogFile.close(); - log->info("Finished writing real-time data log to file {}", - mFilename.string()); + SPDLOG_LOGGER_INFO(log, "Finished writing real-time data log to file {}", + mFilename.string()); } void RealTimeDataLogger::log(Real time, Int timeStepCount) { diff --git a/dpsim/src/Simulation.cpp b/dpsim/src/Simulation.cpp index f27d7e2922..55646c97c9 100644 --- a/dpsim/src/Simulation.cpp +++ b/dpsim/src/Simulation.cpp @@ -397,12 +397,12 @@ void Simulation::logStepTimes(String logName) { return; } Logger::setLogPattern(stepTimeLog, "%v"); - stepTimeLog->info("step_time"); + SPDLOG_LOGGER_INFO(stepTimeLog, "step_time"); Real stepTimeSum = 0; for (auto meas : mStepTimes) { stepTimeSum += meas; - stepTimeLog->info("{:.9f}", meas); + SPDLOG_LOGGER_INFO(stepTimeLog, "{:.9f}", meas); } SPDLOG_LOGGER_INFO(mLog, "Average step time: {:.9f}", stepTimeSum / mStepTimes.size()); @@ -411,7 +411,7 @@ void Simulation::logStepTimes(String logName) { void Simulation::checkForOverruns(String logName) { auto stepTimeLog = Logger::get(logName, Logger::Level::info); Logger::setLogPattern(stepTimeLog, "%v"); - stepTimeLog->info("overruns"); + SPDLOG_LOGGER_INFO(stepTimeLog, "overruns"); int overruns = 0; for (auto meas : mStepTimes) { From 52cd86be6821b29e981ba43fce06e9a3d66368e0 Mon Sep 17 00:00:00 2001 From: shikhin Date: Mon, 20 Oct 2025 20:20:40 +0530 Subject: [PATCH 114/168] Fixing format of the changes Signed-off-by: shikhin --- .../src/EMT/EMT_Ph3_ControlledCurrentSource.cpp | 6 ++---- dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp | 11 +++++------ dpsim-villas/examples/cxx/Fpga9BusHil.cpp | 6 ++---- .../examples/cxx/FpgaCosim3PhInfiniteBus.cpp | 9 ++++----- dpsim-villas/examples/cxx/FpgaCosimulation.cpp | 10 ++++------ dpsim-villas/examples/cxx/FpgaExample.cpp | 6 ++---- dpsim-villas/src/InterfaceWorkerVillas.cpp | 12 ++++++++---- dpsim/include/dpsim/MNASolverFactory.h | 3 ++- dpsim/src/RealTimeDataLogger.cpp | 3 ++- 9 files changed, 31 insertions(+), 35 deletions(-) diff --git a/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp b/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp index b0f335f61b..ddfb4a9251 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_ControlledCurrentSource.cpp @@ -28,10 +28,8 @@ SimPowerComp::Ptr EMT::Ph3::ControlledCurrentSource::clone(String name) { void EMT::Ph3::ControlledCurrentSource::setParameters(Matrix currentRef) { **mCurrentRef = currentRef; - SPDLOG_LOGGER_INFO( - mSLog, "\nCurrent reference phasor [I]: {:s}", - Logger::matrixCompToString(currentRef) - ); + SPDLOG_LOGGER_INFO(mSLog, "\nCurrent reference phasor [I]: {:s}", + Logger::matrixCompToString(currentRef)); mParametersSet = true; } diff --git a/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp b/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp index 647873a815..a3dfbdb5b9 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp @@ -39,12 +39,11 @@ void EMT::Ph3::CurrentSource::setParameters(MatrixComp currentRef, **mCurrentRef = currentRef; mSrcFreq->setReference(mSrcSig->mFreq); - SPDLOG_LOGGER_INFO( - mSLog, "\nCurrent reference phasor [I]: {:s}" - "\nFrequency [Hz]: {:s}", - Logger::matrixCompToString(currentRef), - Logger::realToString(srcFreq) - ); + SPDLOG_LOGGER_INFO(mSLog, + "\nCurrent reference phasor [I]: {:s}" + "\nFrequency [Hz]: {:s}", + Logger::matrixCompToString(currentRef), + Logger::realToString(srcFreq)); mParametersSet = true; } diff --git a/dpsim-villas/examples/cxx/Fpga9BusHil.cpp b/dpsim-villas/examples/cxx/Fpga9BusHil.cpp index c81879112c..868104f6dd 100644 --- a/dpsim-villas/examples/cxx/Fpga9BusHil.cpp +++ b/dpsim-villas/examples/cxx/Fpga9BusHil.cpp @@ -85,10 +85,8 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - SPDLOG_LOGGER_DEBUG( - DPsim::Logger::get("FpgaExample"), - "Config for Node:\n{}", - config); + SPDLOG_LOGGER_DEBUG(DPsim::Logger::get("FpgaExample"), "Config for Node:\n{}", + config); return config; } diff --git a/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp b/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp index 05adbb7cf2..0f39f9c669 100644 --- a/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp +++ b/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp @@ -133,10 +133,8 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - SPDLOG_LOGGER_DEBUG( - DPsim::Logger::get("FpgaCosim3PhInfiniteBus"), - "Config for Node:\n{}", - config); + SPDLOG_LOGGER_DEBUG(DPsim::Logger::get("FpgaCosim3PhInfiniteBus"), + "Config for Node:\n{}", config); return config; } @@ -252,7 +250,8 @@ int main(int argc, char *argv[]) { } sim.run(); - SPDLOG_LOGGER_INFO(CPS::Logger::get("FpgaCosim3PhInfiniteBus"), "Simulation finished."); + SPDLOG_LOGGER_INFO(CPS::Logger::get("FpgaCosim3PhInfiniteBus"), + "Simulation finished."); sim.logStepTimes("FpgaCosim3PhInfiniteBus"); // std::ofstream of("task_dependencies.svg"); diff --git a/dpsim-villas/examples/cxx/FpgaCosimulation.cpp b/dpsim-villas/examples/cxx/FpgaCosimulation.cpp index 723f98926d..6f134fa25f 100644 --- a/dpsim-villas/examples/cxx/FpgaCosimulation.cpp +++ b/dpsim-villas/examples/cxx/FpgaCosimulation.cpp @@ -129,11 +129,8 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - SPDLOG_LOGGER_DEBUG( - DPsim::Logger::get("FpgaExample"), - "Config for Node:\n{}", - config - ); + SPDLOG_LOGGER_DEBUG(DPsim::Logger::get("FpgaExample"), "Config for Node:\n{}", + config); return config; } @@ -235,7 +232,8 @@ int main(int argc, char *argv[]) { } sim.run(); - SPDLOG_LOGGER_INFO(CPS::Logger::get("FpgaCosimulation"), "Simulation finished."); + SPDLOG_LOGGER_INFO(CPS::Logger::get("FpgaCosimulation"), + "Simulation finished."); sim.logStepTimes("FpgaCosimulation"); // std::ofstream of("task_dependencies.svg"); diff --git a/dpsim-villas/examples/cxx/FpgaExample.cpp b/dpsim-villas/examples/cxx/FpgaExample.cpp index b6f027f5a4..ec19b9f8dc 100644 --- a/dpsim-villas/examples/cxx/FpgaExample.cpp +++ b/dpsim-villas/examples/cxx/FpgaExample.cpp @@ -92,10 +92,8 @@ const std::string buildFpgaConfig(CommandLineArgs &args) { {} }})STRING", cardConfig, signalOutConfig, signalInConfig); - SPDLOG_LOGGER_DEBUG( - DPsim::Logger::get("FpgaExample"), - "Config for Node:\n{}", - config); + SPDLOG_LOGGER_DEBUG(DPsim::Logger::get("FpgaExample"), "Config for Node:\n{}", + config); return config; } diff --git a/dpsim-villas/src/InterfaceWorkerVillas.cpp b/dpsim-villas/src/InterfaceWorkerVillas.cpp index 26c144adb5..3faefa82b3 100644 --- a/dpsim-villas/src/InterfaceWorkerVillas.cpp +++ b/dpsim-villas/src/InterfaceWorkerVillas.cpp @@ -520,7 +520,8 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, mImports.emplace_back( [idx, log](Sample *smp) -> AttributeBase::Ptr { if (idx >= smp->length) { - SPDLOG_LOGGER_ERROR(log, "incomplete data received from InterfaceVillas"); + SPDLOG_LOGGER_ERROR( + log, "incomplete data received from InterfaceVillas"); return nullptr; } return AttributePointer( @@ -533,7 +534,8 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, mImports.emplace_back( [idx, log](Sample *smp) -> AttributeBase::Ptr { if (idx >= smp->length) { - SPDLOG_LOGGER_ERROR(log, "incomplete data received from InterfaceVillas"); + SPDLOG_LOGGER_ERROR( + log, "incomplete data received from InterfaceVillas"); return nullptr; } return AttributePointer( @@ -546,7 +548,8 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, mImports.emplace_back( [idx, log](Sample *smp) -> AttributeBase::Ptr { if (idx >= smp->length) { - SPDLOG_LOGGER_ERROR(log, "incomplete data received from InterfaceVillas"); + SPDLOG_LOGGER_ERROR( + log, "incomplete data received from InterfaceVillas"); return nullptr; } return AttributePointer( @@ -559,7 +562,8 @@ void InterfaceWorkerVillas::configureImport(UInt attributeId, mImports.emplace_back( [idx, log](Sample *smp) -> AttributeBase::Ptr { if (idx >= smp->length) { - SPDLOG_LOGGER_ERROR(log, "incomplete data received from InterfaceVillas"); + SPDLOG_LOGGER_ERROR( + log, "incomplete data received from InterfaceVillas"); return nullptr; } return AttributePointer( diff --git a/dpsim/include/dpsim/MNASolverFactory.h b/dpsim/include/dpsim/MNASolverFactory.h index 8377b85ebb..1dc9416e3f 100644 --- a/dpsim/include/dpsim/MNASolverFactory.h +++ b/dpsim/include/dpsim/MNASolverFactory.h @@ -117,7 +117,8 @@ class MnaSolverFactory { } #ifdef WITH_CUDA_SPARSE case DirectLinearSolverImpl::CUDASparse: { - SPDLOG_LOGGER_INFO(log, "creating GpuSparseAdapter solver implementation"); + SPDLOG_LOGGER_INFO(log, + "creating GpuSparseAdapter solver implementation"); std::shared_ptr> gpuSparseSolver = std::make_shared>(name, domain, logLevel); gpuSparseSolver->setDirectLinearSolverImplementation( diff --git a/dpsim/src/RealTimeDataLogger.cpp b/dpsim/src/RealTimeDataLogger.cpp index e9865573d5..97c5f818c9 100644 --- a/dpsim/src/RealTimeDataLogger.cpp +++ b/dpsim/src/RealTimeDataLogger.cpp @@ -32,7 +32,8 @@ void RealTimeDataLogger::start() { auto log = CPS::Logger::get("RealTimeDataLogger", CPS::Logger::Level::off, CPS::Logger::Level::info); SPDLOG_LOGGER_INFO( - log, "Preallocating memory for real-time data logger: {} rows for {} " + log, + "Preallocating memory for real-time data logger: {} rows for {} " "attributes ({} MB)", mRowNumber, mAttributes.size(), mb_size / (1024 * 1024)); // We are doing real time so preallocate everything From 407e37d9bee0f0be2e340b1e3854ab3ba6d7a526 Mon Sep 17 00:00:00 2001 From: cwirtz Date: Wed, 15 Oct 2025 21:13:34 +0200 Subject: [PATCH 115/168] - issue with std::max in simulation.cpp: windows.h seems to be included somewhere and standard C++ behaviour of std::max is broken Fix for std::max issue: define NOMINMAX on Windows Now solved in CMakeLists.txt: Define NOMINMAX on Windows to restore correct std::max behavior Signed-off-by: cwirtz Signed-off-by: Leonardo Carreras --- CMakeLists.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2d817bd6ac..e32e653b1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,11 @@ if(WIN32) cmake_policy(SET CMP0074 NEW) endif() +# Define NOMINMAX to prevent Windows macros from breaking std::max +if(WIN32) + add_compile_definitions(NOMINMAX) +endif() + # Allow shadowing of CMake targets # As we include dependencies via add_subdirectory() # we import their targets into the DPsim CMake tree From eefa4374815787d35adeb439ee4e0996b7f0b55a Mon Sep 17 00:00:00 2001 From: cwirtz Date: Wed, 29 Oct 2025 15:25:51 +0100 Subject: [PATCH 116/168] changed from two spaces indentation to tab Signed-off-by: cwirtz Signed-off-by: Leonardo Carreras --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e32e653b1e..8d4020a4bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -63,7 +63,7 @@ endif() # Define NOMINMAX to prevent Windows macros from breaking std::max if(WIN32) - add_compile_definitions(NOMINMAX) + add_compile_definitions(NOMINMAX) endif() # Allow shadowing of CMake targets From 86f17a64f51887265cc368fda58a929d89be52c9 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 11 Nov 2025 15:41:19 +0100 Subject: [PATCH 117/168] Bump version of black & black jupyter to 25.11.0 Signed-off-by: Leonardo Carreras --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 29266f40f6..2163547fc3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -38,7 +38,7 @@ repos: # Using this mirror lets us use mypyc-compiled black, which is about 2x faster - repo: https://github.com/psf/black-pre-commit-mirror - rev: "23.3.0" + rev: "25.11.0" hooks: - id: black - id: black-jupyter From 098c996c057a778ede5371546c9d598e123181ca Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 11 Nov 2025 15:45:32 +0100 Subject: [PATCH 118/168] Apply changes in the format due to newer version Signed-off-by: Leonardo Carreras --- examples/Notebooks/Components/Trafo.ipynb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/examples/Notebooks/Components/Trafo.ipynb b/examples/Notebooks/Components/Trafo.ipynb index 68fb87e486..5fa3908da4 100644 --- a/examples/Notebooks/Components/Trafo.ipynb +++ b/examples/Notebooks/Components/Trafo.ipynb @@ -56,9 +56,7 @@ "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", "snubber_resistance_hv_side = np.abs(voltage_hv_side) ** 2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = (\n", - " ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", - ")\n", + "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", "snubber_capacitance_mv_side_to_hv_side = 1 / (\n", " omega * ratio**2 * np.abs(voltage_mv_side) ** 2 / q_snub\n", ")\n", @@ -222,9 +220,7 @@ "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", "snubber_resistance_hv_side = np.abs(voltage_hv_side) ** 2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = (\n", - " ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", - ")\n", + "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", "snubber_capacitance_mv_side_to_hv_side = 1 / (\n", " omega * ratio**2 * np.abs(voltage_mv_side) ** 2 / q_snub\n", ")\n", @@ -388,9 +384,7 @@ "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", "snubber_resistance_hv_side = np.abs(voltage_hv_side) ** 2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = (\n", - " ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", - ")\n", + "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side) ** 2 / p_snub\n", "snubber_capacitance_mv_side_to_hv_side = 1 / (\n", " omega * ratio**2 * np.abs(voltage_mv_side) ** 2 / q_snub\n", ")\n", From 02633f25cada852386e72171d792b8d9d9bd3dbf Mon Sep 17 00:00:00 2001 From: shikhin Date: Thu, 6 Nov 2025 00:23:20 +0530 Subject: [PATCH 119/168] Unified names for switch open/close state Attribute::Ptr in Base Phase 1 and 3 switch classes Signed-off-by: shikhin --- .../include/dpsim-models/Base/Base_Ph3_Switch.h | 10 +++++----- dpsim-models/src/EMT/EMT_Ph3_Switch.cpp | 13 ++++++------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Base/Base_Ph3_Switch.h b/dpsim-models/include/dpsim-models/Base/Base_Ph3_Switch.h index 02b7f2f49b..d74fd2bb7c 100644 --- a/dpsim-models/include/dpsim-models/Base/Base_Ph3_Switch.h +++ b/dpsim-models/include/dpsim-models/Base/Base_Ph3_Switch.h @@ -21,22 +21,22 @@ class Switch { /// Resistance if switch is closed [ohm] const CPS::Attribute::Ptr mClosedResistance; /// Defines if Switch is open or closed - const CPS::Attribute::Ptr mSwitchClosed; + const CPS::Attribute::Ptr mIsClosed; explicit Switch(CPS::AttributeList::Ptr attributeList) : mOpenResistance(attributeList->create("R_open")), mClosedResistance(attributeList->create("R_closed")), - mSwitchClosed(attributeList->create("is_closed")){}; + mIsClosed(attributeList->create("is_closed")){}; /// void setParameters(Matrix openResistance, Matrix closedResistance, Bool closed = false) { **mOpenResistance = openResistance; **mClosedResistance = closedResistance; - **mSwitchClosed = closed; + **mIsClosed = closed; } - void closeSwitch() { **mSwitchClosed = true; } - void openSwitch() { **mSwitchClosed = false; } + void closeSwitch() { **mIsClosed = true; } + void openSwitch() { **mIsClosed = false; } }; } // namespace Ph3 } // namespace Base diff --git a/dpsim-models/src/EMT/EMT_Ph3_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph3_Switch.cpp index 8eeb521d27..2a832badc7 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Switch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Switch.cpp @@ -23,14 +23,13 @@ EMT::Ph3::Switch::Switch(String uid, String name, Logger::Level logLevel) SimPowerComp::Ptr EMT::Ph3::Switch::clone(String name) { auto copy = Switch::make(name, mLogLevel); - copy->setParameters(**mOpenResistance, **mClosedResistance, **mSwitchClosed); + copy->setParameters(**mOpenResistance, **mClosedResistance, **mIsClosed); return copy; } void EMT::Ph3::Switch::initializeFromNodesAndTerminals(Real frequency) { - Matrix impedance = - (**mSwitchClosed) ? **mClosedResistance : **mOpenResistance; + Matrix impedance = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; MatrixComp vInitABC = MatrixComp::Zero(3, 1); vInitABC(0, 0) = initialSingleVoltage(1) - initialSingleVoltage(0); vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B; @@ -57,11 +56,11 @@ void EMT::Ph3::Switch::mnaCompInitialize(Real omega, Real timeStep, **mRightVector = Matrix::Zero(0, 0); } -Bool EMT::Ph3::Switch::mnaIsClosed() { return **mSwitchClosed; } +Bool EMT::Ph3::Switch::mnaIsClosed() { return **mIsClosed; } void EMT::Ph3::Switch::mnaCompApplySystemMatrixStamp( SparseMatrixRow &systemMatrix) { - MatrixFixedSize<3, 3> conductance = (**mSwitchClosed) + MatrixFixedSize<3, 3> conductance = (**mIsClosed) ? (**mClosedResistance).inverse() : (**mOpenResistance).inverse(); @@ -130,8 +129,8 @@ void EMT::Ph3::Switch::mnaCompUpdateVoltage(const Matrix &leftVector) { void EMT::Ph3::Switch::mnaCompUpdateCurrent(const Matrix &leftVector) { Matrix conductance = Matrix::Zero(3, 3); - (**mSwitchClosed) ? Math::invertMatrix(**mClosedResistance, conductance) - : Math::invertMatrix(**mOpenResistance, conductance); + (**mIsClosed) ? Math::invertMatrix(**mClosedResistance, conductance) + : Math::invertMatrix(**mOpenResistance, conductance); **mIntfCurrent = conductance * **mIntfVoltage; } From 3daf3c6ae9ac0018f913fc11cce32ed5bd648265 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sun, 16 Nov 2025 11:35:14 +0100 Subject: [PATCH 120/168] Implement new component DecouplingLineEMT_Ph3 and test circuit. Signed-off-by: pipeacosta --- .../include/dpsim-models/Components.h | 1 + .../Signal/DecouplingLineEMT_Ph3.h | 96 +++++++++++ dpsim-models/src/CMakeLists.txt | 1 + .../src/Signal/DecouplingLineEMT_Ph3.cpp | 150 +++++++++++++++++ dpsim/examples/cxx/CMakeLists.txt | 1 + .../cxx/Circuits/EMT_DecouplingLine_Ph3.cpp | 153 ++++++++++++++++++ 6 files changed, 402 insertions(+) create mode 100644 dpsim-models/include/dpsim-models/Signal/DecouplingLineEMT_Ph3.h create mode 100644 dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp create mode 100644 dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index 8b73d3ca32..bd47323e02 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -128,6 +128,7 @@ #include #include #include +#include #include #include #include diff --git a/dpsim-models/include/dpsim-models/Signal/DecouplingLineEMT_Ph3.h b/dpsim-models/include/dpsim-models/Signal/DecouplingLineEMT_Ph3.h new file mode 100644 index 0000000000..84d8986701 --- /dev/null +++ b/dpsim-models/include/dpsim-models/Signal/DecouplingLineEMT_Ph3.h @@ -0,0 +1,96 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * 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 https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#pragma once + +#include "dpsim-models/Definitions.h" +#include "dpsim-models/EMT/EMT_Ph3_ControlledCurrentSource.h" +#include + +#include +#include +#include + +namespace CPS { +namespace Signal { +class DecouplingLineEMT_Ph3 : public SimSignalComp, + public SharedFactory { +protected: + Real mDelay; + Matrix mResistance = Matrix::Zero(3, 3); + Matrix mInductance = Matrix::Zero(3, 3); + Matrix mCapacitance = Matrix::Zero(3, 3); + Matrix mSurgeImpedance; + + std::shared_ptr mNode1, mNode2; + std::shared_ptr mRes1, mRes2; + std::shared_ptr mSrc1, mSrc2; + Attribute::Ptr mSrcCur1, mSrcCur2; + + // Ringbuffers for the values of previous timesteps + // TODO make these matrix attributes + Matrix mVolt1, mVolt2, mCur1, mCur2; + UInt mBufIdx = 0; + UInt mBufSize; + Real mAlpha; + + Matrix interpolate(Matrix &data); + +public: + typedef std::shared_ptr Ptr; + + const Attribute::Ptr mSrcCur1Ref; + const Attribute::Ptr mSrcCur2Ref; + + ///FIXME: workaround for dependency analysis as long as the states aren't attributes + const Attribute::Ptr mStates; + + DecouplingLineEMT_Ph3(String name, Logger::Level logLevel = Logger::Level::info); + + void setParameters(SimNode::Ptr node1, SimNode::Ptr node2, + Matrix resistance, Matrix inductance, Matrix capacitance); + void initialize(Real omega, Real timeStep); + void step(Real time, Int timeStepCount); + void postStep(); + Task::List getTasks(); + IdentifiedObject::List getLineComponents(); + + class PreStep : public Task { + public: + PreStep(DecouplingLineEMT_Ph3 &line) + : Task(**line.mName + ".MnaPreStep"), mLine(line) { + mPrevStepDependencies.push_back(mLine.mStates); + mModifiedAttributes.push_back(mLine.mSrc1->mCurrentRef); + mModifiedAttributes.push_back(mLine.mSrc2->mCurrentRef); + } + + void execute(Real time, Int timeStepCount); + + private: + DecouplingLineEMT_Ph3 &mLine; + }; + + class PostStep : public Task { + public: + PostStep(DecouplingLineEMT_Ph3 &line) + : Task(**line.mName + ".PostStep"), mLine(line) { + mAttributeDependencies.push_back(mLine.mRes1->mIntfVoltage); + mAttributeDependencies.push_back(mLine.mRes1->mIntfCurrent); + mAttributeDependencies.push_back(mLine.mRes2->mIntfVoltage); + mAttributeDependencies.push_back(mLine.mRes2->mIntfCurrent); + mModifiedAttributes.push_back(mLine.mStates); + } + + void execute(Real time, Int timeStepCount); + + private: + DecouplingLineEMT_Ph3 &mLine; + }; +}; +} // namespace Signal +} // namespace CPS diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index db23ea808d..6507269e40 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -142,6 +142,7 @@ list(APPEND MODELS_SOURCES Signal/DecouplingLine.cpp Signal/DecouplingLineEMT.cpp + Signal/DecouplingLineEMT_Ph3.cpp Signal/Exciter.cpp Signal/FIRFilter.cpp Signal/TurbineGovernor.cpp diff --git a/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp b/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp new file mode 100644 index 0000000000..53a616c6fa --- /dev/null +++ b/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp @@ -0,0 +1,150 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * 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 https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#include "dpsim-models/Definitions.h" +#include "dpsim-models/EMT/EMT_Ph3_Resistor.h" +#include "dpsim-models/MathUtils.h" +#include +#include + +using namespace CPS; +using namespace CPS::EMT::Ph3; +using namespace CPS::Signal; + +DecouplingLineEMT_Ph3::DecouplingLineEMT_Ph3(String name, Logger::Level logLevel) + : SimSignalComp(name, name, logLevel), + mStates(mAttributes->create("states")), + mSrcCur1Ref(mAttributes->create("i_src1", Matrix::Zero(3, 1))), + mSrcCur2Ref(mAttributes->create("i_src2", Matrix::Zero(3, 1))) { + + mRes1 = EMT::Ph3::Resistor::make(name + "_r1", logLevel); + mRes2 = EMT::Ph3::Resistor::make(name + "_r2", logLevel); + mSrc1 = ControlledCurrentSource::make(name + "_i1", logLevel); + mSrc2 = ControlledCurrentSource::make(name + "_i2", logLevel); +} + +void DecouplingLineEMT_Ph3::setParameters(SimNode::Ptr node1, + SimNode::Ptr node2, Matrix resistance, + Matrix inductance, Matrix capacitance) { + + mResistance = resistance; + mInductance = inductance; + mCapacitance = capacitance; + mNode1 = node1; + mNode2 = node2; + + mSurgeImpedance = (inductance * capacitance.inverse()).array().sqrt(); + mDelay = (inductance.array() * capacitance.array()).sqrt().maxCoeff(); + SPDLOG_LOGGER_INFO(mSLog, "surge impedance: {}", mSurgeImpedance); + SPDLOG_LOGGER_INFO(mSLog, "delay: {}", mDelay); + + mRes1->setParameters(Math::singlePhaseParameterToThreePhase(mSurgeImpedance(0,0) + mResistance(0,0) / 4)); + mRes1->connect({SimNode::GND, node1}); + mRes2->setParameters(Math::singlePhaseParameterToThreePhase(mSurgeImpedance(0,0) + mResistance(0,0) / 4)); + /*Notice that, as opposed to the DecouplingLine Ph1, this resistor is connected from GND to node2, + since currently the Ph3 resistor has the opposite sign convention for voltage and current, compared to the Ph1 countepart.*/ + mRes2->connect({SimNode::GND, node2}); + mSrc1->setParameters(Matrix::Zero(3,1)); + mSrc1->connect({node1, SimNode::GND}); + mSrc2->setParameters(Matrix::Zero(3,1)); + mSrc2->connect({node2, SimNode::GND}); + + mSrcCur1 = mSrc1->mCurrentRef; + mSrcCur2 = mSrc2->mCurrentRef; +} + +void DecouplingLineEMT_Ph3::initialize(Real omega, Real timeStep) { + if (mDelay < timeStep) + throw SystemError("Timestep too large for decoupling"); + + mBufSize = static_cast(ceil(mDelay / timeStep)); + mAlpha = 1 - (mBufSize - mDelay / timeStep); + SPDLOG_LOGGER_INFO(mSLog, "bufsize {} alpha {}", mBufSize, mAlpha); + + // Initialization based on static PI-line model + MatrixComp volt1 = -mNode1->initialVoltage(); + MatrixComp volt2 = -mNode2->initialVoltage(); + + MatrixComp initAdmittance = (mResistance + Complex(0, omega) * mInductance).inverse() + + Complex(0, omega) * mCapacitance / 2; + MatrixComp cur1 = initAdmittance * volt1 - + (mResistance + Complex(0, omega) * mInductance).inverse() * volt2; + MatrixComp cur2 = initAdmittance * volt2 - + (mResistance + Complex(0, omega) * mInductance).inverse() * volt1; + + SPDLOG_LOGGER_INFO(mSLog, "initial voltages: v_k {} v_m {}", volt1, volt2); + SPDLOG_LOGGER_INFO(mSLog, "initial currents: i_km {} i_mk {}", cur1, cur2); + + // Resize ring buffers and initialize + mVolt1 = volt1.real().transpose().replicate(mBufSize, 1); + mVolt2 = volt2.real().transpose().replicate(mBufSize, 1); + mCur1 = cur1.real().transpose().replicate(mBufSize, 1); + mCur2 = cur2.real().transpose().replicate(mBufSize, 1); +} + +Matrix DecouplingLineEMT_Ph3::interpolate(Matrix &data) { + // linear interpolation of the nearest values + Matrix c1 = data.row(mBufIdx); + Matrix c2 = mBufIdx == mBufSize - 1 ? data.row(0) : data.row(mBufIdx + 1); + return (mAlpha * c1 + (1 - mAlpha) * c2).transpose(); +} + +void DecouplingLineEMT_Ph3::step(Real time, Int timeStepCount) { + Matrix volt1 = interpolate(mVolt1); + Matrix volt2 = interpolate(mVolt2); + Matrix cur1 = interpolate(mCur1); + Matrix cur2 = interpolate(mCur2); + Matrix denom = (mSurgeImpedance + (mResistance / 4)) * (mSurgeImpedance + (mResistance / 4)); + + if (timeStepCount == 0) { + // initialization + **mSrcCur1Ref = cur1 - (mSurgeImpedance + mResistance / 4).inverse() * volt1; + **mSrcCur2Ref = cur2 - (mSurgeImpedance + mResistance / 4).inverse() * volt2; + } else { + // Update currents + **mSrcCur1Ref = -mSurgeImpedance * denom.inverse() * + (volt2 + (mSurgeImpedance - mResistance / 4) * cur2) - + mResistance / 4 * denom.inverse() * + (volt1 + (mSurgeImpedance - mResistance / 4) * cur1); + **mSrcCur2Ref = -mSurgeImpedance * denom.inverse() * + (volt1 + (mSurgeImpedance - mResistance / 4) * cur1) - + mResistance / 4 * denom.inverse() * + (volt2 + (mSurgeImpedance - mResistance / 4) * cur2); + } + mSrcCur1->set(**mSrcCur1Ref); + mSrcCur2->set(**mSrcCur2Ref); +} + +void DecouplingLineEMT_Ph3::PreStep::execute(Real time, Int timeStepCount) { + mLine.step(time, timeStepCount); +} + +void DecouplingLineEMT_Ph3::postStep() { + // Update ringbuffers with new values + mVolt1.row(mBufIdx) = -mRes1->intfVoltage().transpose(); + mVolt2.row(mBufIdx) = -mRes2->intfVoltage().transpose(); + mCur1.row(mBufIdx) = -mRes1->intfCurrent().transpose() + mSrcCur1->get().real().transpose(); + mCur2.row(mBufIdx) = -mRes2->intfCurrent().transpose() + mSrcCur2->get().real().transpose(); + + mBufIdx++; + if (mBufIdx == mBufSize) + mBufIdx = 0; +} + +void DecouplingLineEMT_Ph3::PostStep::execute(Real time, Int timeStepCount) { + mLine.postStep(); +} + +Task::List DecouplingLineEMT_Ph3::getTasks() { + return Task::List( + {std::make_shared(*this), std::make_shared(*this)}); +} + +IdentifiedObject::List DecouplingLineEMT_Ph3::getLineComponents() { + return IdentifiedObject::List({mRes1, mRes2, mSrc1, mSrc2}); +} diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index 8fc377730e..b9075bc7e1 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -33,6 +33,7 @@ set(CIRCUIT_SOURCES #Circuits/EMT_ResVS_RL_Switch.cpp Circuits/EMT_VSI.cpp Circuits/EMT_PiLine.cpp + Circuits/EMT_DecouplingLine_Ph3.cpp Circuits/EMT_Ph3_R3C1L1CS1_RC_vs_SSN.cpp Circuits/EMT_Ph3_RLC1VS1_RC_vs_SSN.cpp diff --git a/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp b/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp new file mode 100644 index 0000000000..287365d7a2 --- /dev/null +++ b/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp @@ -0,0 +1,153 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * 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 https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#include "dpsim-models/Definitions.h" +#include "dpsim/Definitions.h" +#include + +using namespace DPsim; +using namespace CPS::EMT; +using namespace CPS::EMT::Ph3; +using namespace CPS::Signal; + +void simElements() { + Real timeStep = 0.00005; + Real finalTime = 1; + String simName = "EMT_DecouplingLine_Ph3_Elements"; + Logger::setLogDir("logs/" + simName); + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::ABC); + auto n2 = SimNode::make("n2", PhaseType::ABC); + auto vn1 = SimNode::make("vn1", PhaseType::ABC); + + // Components + auto vs = VoltageSource::make("v_1", Logger::Level::debug); + vs->setParameters( + CPS::Math::singlePhaseVariableToThreePhase(CPS::Math::polar(100000, 0)), + 50); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + Real conductance = 1e-6; + + auto res = Resistor::make("R_line", Logger::Level::debug); + res->setParameters(CPS::Math::singlePhaseParameterToThreePhase(resistance)); + auto ind = Inductor::make("L_line", Logger::Level::debug); + ind->setParameters(CPS::Math::singlePhaseParameterToThreePhase(inductance)); + auto cap1 = Capacitor::make("Cp_1", Logger::Level::debug); + cap1->setParameters( + CPS::Math::singlePhaseParameterToThreePhase(capacitance / 2.)); + auto cap2 = Capacitor::make("Cp_2", Logger::Level::debug); + cap2->setParameters( + CPS::Math::singlePhaseParameterToThreePhase(capacitance / 2.)); + auto con1 = Resistor::make("Gp_1", Logger::Level::debug); + con1->setParameters( + CPS::Math::singlePhaseParameterToThreePhase(2. / conductance)); + auto con2 = Resistor::make("Gp_2", Logger::Level::debug); + con2->setParameters( + CPS::Math::singlePhaseParameterToThreePhase(2. / conductance)); + + auto load = Resistor::make("R_load", Logger::Level::debug); + load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); + + // Topology + vs->connect({SimNode::GND, n1}); + res->connect({n1, vn1}); + ind->connect({vn1, n2}); + cap1->connect({n1, SimNode::GND}); + cap2->connect({n2, SimNode::GND}); + con1->connect({n1, SimNode::GND}); + con2->connect({n2, SimNode::GND}); + load->connect({n2, SimNode::GND}); + + auto sys = SystemTopology( + 50, SystemNodeList{n1, n2, vn1}, + SystemComponentList{vs, res, ind, cap1, cap2, con1, con2, load}); + //SystemComponentList{vs, res, ind, cap1, cap2, load}); + //SystemComponentList{vs, res, ind, load}); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->attribute("v")); + logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", ind->attribute("i_intf")); + + Simulation sim(simName, Logger::Level::debug); + sim.setSystem(sys); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + +void simDecouplingLine_Ph3() { + Real timeStep = 0.00005; + Real finalTime = 0.1; + String simName = "EMT_DecouplingLine_Ph3_Component"; + Logger::setLogDir("logs/" + simName); + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::ABC); + auto n2 = SimNode::make("n2", PhaseType::ABC); + + // Components + auto vs = VoltageSource::make("v_1", Logger::Level::debug); + Real VsRefRMS = 100000 * PEAK1PH_TO_RMS3PH; + MatrixComp VsRefPh3 = CPS::Math::singlePhaseVariableToThreePhase(Complex(VsRefRMS, 0)); + vs->setParameters(VsRefPh3, 50); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + + auto dline = DecouplingLineEMT_Ph3::make("dline", Logger::Level::debug); + dline->setParameters(n1, n2, + CPS::Math::singlePhaseParameterToThreePhase(resistance), + CPS::Math::singlePhaseParameterToThreePhase(inductance), + CPS::Math::singlePhaseParameterToThreePhase(capacitance)); + + auto load = Resistor::make("R_load", Logger::Level::debug); + load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); + + // Topology + vs->connect({SimNode::GND, n1}); + load->connect({n2, SimNode::GND}); + + auto sys = SystemTopology(50, SystemNodeList{n1, n2}, + SystemComponentList{vs, dline, load}); + sys.addComponents(dline->getLineComponents()); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("1_i1", vs->attribute("i_intf")); + logger->logAttribute("2_i_src1", dline->attribute("i_src1")); + logger->logAttribute("3_i_src2", dline->attribute("i_src2")); + logger->logAttribute("4_i2", load->attribute("i_intf")); + logger->logAttribute("5_v1", n1->attribute("v")); + logger->logAttribute("6_v2", n2->attribute("v")); + + Simulation sim(simName, Logger::Level::debug); + sim.setSystem(sys); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + +int main(int argc, char *argv[]) { +// simElements(); + simDecouplingLine_Ph3(); +} From f1caece8618f483d5ad149edf2284b8dca9324a6 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Thu, 20 Nov 2025 08:01:21 +0000 Subject: [PATCH 121/168] Add test for decoupling line Ph3 to Line.ipynb example. Signed-off-by: pipeacosta --- dpsim/src/pybind/SignalComponents.cpp | 12 ++ examples/Notebooks/Components/Line.ipynb | 193 ++++++++++++++++++++++- 2 files changed, 201 insertions(+), 4 deletions(-) diff --git a/dpsim/src/pybind/SignalComponents.cpp b/dpsim/src/pybind/SignalComponents.cpp index 01821c9dc6..f66b7035e0 100644 --- a/dpsim/src/pybind/SignalComponents.cpp +++ b/dpsim/src/pybind/SignalComponents.cpp @@ -48,6 +48,18 @@ void addSignalComponents(py::module_ mSignal) { .def("get_line_components", &CPS::Signal::DecouplingLineEMT::getLineComponents); + py::class_, + CPS::SimSignalComp>(mSignal, "DecouplingLineEMT_Ph3", + py::multiple_inheritance()) + .def(py::init()) + .def(py::init()) + .def("set_parameters", &CPS::Signal::DecouplingLineEMT_Ph3::setParameters, + "node_1"_a, "node_2"_a, "resistance"_a, "inductance"_a, + "capacitance"_a) + .def("get_line_components", + &CPS::Signal::DecouplingLineEMT_Ph3::getLineComponents); + py::class_, CPS::SimSignalComp>(mSignal, "Exciter", py::multiple_inheritance()) .def(py::init()) diff --git a/examples/Notebooks/Components/Line.ipynb b/examples/Notebooks/Components/Line.ipynb index 2f2152c1d7..dcbc17fbdc 100644 --- a/examples/Notebooks/Components/Line.ipynb +++ b/examples/Notebooks/Components/Line.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -437,7 +437,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": {}, "outputs": [], "source": [ @@ -1212,6 +1212,60 @@ "sim.run()" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "time_step = 0.00005\n", + "final_time = 0.1\n", + "sim_name = 'EMT_Decoupling_Wave_Ph3'\n", + "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "\n", + "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", + "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "\n", + "resistance = dpsimpy.Math.single_phase_parameter_to_three_phase(5)\n", + "inductance = dpsimpy.Math.single_phase_parameter_to_three_phase(0.16)\n", + "capacitance = dpsimpy.Math.single_phase_parameter_to_three_phase(1e-6)\n", + "\n", + "vs = dpsimpy.emt.ph3.VoltageSource('Vsrc_emt')\n", + "vs_ref_rms = 100000 * dpsimpy.PEAK1PH_TO_RMS3PH\n", + "vs_ref_ph3 = dpsimpy.Math.single_phase_variable_to_three_phase(complex(vs_ref_rms, 0))\n", + "vs.set_parameters(vs_ref_ph3, 50)\n", + "\n", + "dline = dpsimpy.signal.DecouplingLineEMT_Ph3('DecLine_emt_ph3', dpsimpy.LogLevel.debug)\n", + "dline.set_parameters(n1, n2, resistance, inductance, capacitance)\n", + "\n", + "load = dpsimpy.emt.ph3.Resistor('R_load')\n", + "load.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(10000))\n", + "\n", + "vs.connect([gnd, n1])\n", + "load.connect([n2, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [n1, n2], [vs, dline, load])\n", + "sys.add(dline.get_line_components())\n", + "\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute('v1', 'v', n1)\n", + "logger.log_attribute('v2', 'v', n2)\n", + "logger.log_attribute('i1', 'i_intf', vs)\n", + "logger.log_attribute('i2', 'i_intf', load)\n", + "logger.log_attribute('i_src1', 'i_src1', dline)\n", + "logger.log_attribute('i_src2', 'i_src2', dline)\n", + "\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.add_logger(logger)\n", + "\n", + "sim.run()" + ] + }, { "cell_type": "code", "execution_count": null, @@ -1337,6 +1391,57 @@ "plt.show()" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "work_dir = 'logs/EMT_Decoupling_Wave_Ph3/'\n", + "log_name = 'EMT_Decoupling_Wave_Ph3'\n", + "print(work_dir + log_name + '.csv')\n", + "emt_decoupling_wave_ph3 = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.plot(emt_decoupling_wave_ph3['v1_0'].time, emt_decoupling_wave_ph3['v1_0'].values)\n", + "plt.plot(emt_decoupling_wave_ph3['v2_0'].time, emt_decoupling_wave_ph3['v2_0'].values)\n", + "#plt.xlim([0,0.02])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.plot(emt_decoupling_wave_ph3['i_src1_0'].time, emt_decoupling_wave_ph3['i_src1_0'].values)\n", + "plt.plot(emt_decoupling_wave_ph3['i_src2_0'].time, emt_decoupling_wave_ph3['i_src2_0'].values)\n", + "#plt.xlim([0,0.02])\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.plot(emt_decoupling_wave_ph3['i1_0'].time, emt_decoupling_wave_ph3['i1_0'].values)\n", + "plt.plot(emt_decoupling_wave_ph3['i2_0'].time, emt_decoupling_wave_ph3['i2_0'].values)\n", + "#plt.xlim([0,0.02])\n", + "plt.show()" + ] + }, { "cell_type": "code", "execution_count": null, @@ -1409,7 +1514,7 @@ " decoupling_wave_emt[\"v2_shift\"].values,\n", " linestyle=\":\",\n", " color=\"#d62728ff\",\n", - " label=\"v1_dp\",\n", + " label=\"v2_dp\",\n", ")\n", "plt.legend()\n", "plt.xlabel(\"time (s)\")\n", @@ -1418,6 +1523,86 @@ "# plt.ylim([-20,20])\n", "plt.savefig(\"tlm_dp_emt_voltage.pdf\")" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.plot(\n", + " emt_decoupling_wave['v1'].time,\n", + " emt_decoupling_wave['v1'].values,\n", + " color = '#939393ff',\n", + " label = 'v1_emt'\n", + ")\n", + "plt.plot(\n", + " emt_decoupling_wave['v2'].time,\n", + " emt_decoupling_wave['v2'].values,\n", + " color = '#939393ff',\n", + " label = 'v2_emt'\n", + ")\n", + "plt.plot(\n", + " emt_decoupling_wave_ph3['v1_0'].time,\n", + " emt_decoupling_wave_ph3['v1_0'].values,\n", + " linestyle=':',\n", + " color = '#0055ffff',\n", + " label = 'v1_emt_ph3'\n", + ")\n", + "plt.plot(\n", + " emt_decoupling_wave_ph3['v2_0'].time,\n", + " -emt_decoupling_wave_ph3['v2_0'].values,\n", + " linestyle=':',\n", + " color = '#d62728ff',\n", + " label = 'v2_emt_ph3'\n", + ")\n", + "plt.legend()\n", + "plt.xlabel('time (s)')\n", + "plt.ylabel('voltage (V)')\n", + "#plt.xlim([0.02,0.1])\n", + "#plt.ylim([-20,20])\n", + "plt.savefig('tlm_emt_emt3ph_voltage.pdf')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.plot(\n", + " emt_decoupling_wave['i_src1'].time,\n", + " emt_decoupling_wave['i_src1'].values,\n", + " color = '#939393ff',\n", + " label = 'i_src1_emt'\n", + ")\n", + "plt.plot(\n", + " emt_decoupling_wave['i_src2'].time,\n", + " emt_decoupling_wave['i_src2'].values,\n", + " color = '#939393ff',\n", + " label = 'i_src2_emt'\n", + ")\n", + "plt.plot(\n", + " emt_decoupling_wave_ph3['i_src1_0'].time,\n", + " emt_decoupling_wave_ph3['i_src1_0'].values,\n", + " linestyle=':', color = '#0055ffff',\n", + " label = 'i_src1_emt_ph3'\n", + ")\n", + "plt.plot(\n", + " emt_decoupling_wave_ph3['i_src2_0'].time,\n", + " emt_decoupling_wave_ph3['i_src2_0'].values,\n", + " linestyle=':', color = '#d62728ff',\n", + " label = 'i_src2_emt_ph3'\n", + ")\n", + "plt.legend()\n", + "plt.xlabel('time (s)')\n", + "plt.ylabel('current (A)')\n", + "#plt.xlim([0.02,0.1])\n", + "#plt.ylim([-20,20])\n", + "plt.savefig('tlm_emt_emt3ph_current.pdf')" + ] } ], "metadata": { @@ -1436,7 +1621,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.10" + "version": "3.13.9" } }, "nbformat": 4, From 4ab9b3aff49bb917eb461b7c9b2e01c20102931b Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Thu, 20 Nov 2025 11:27:41 +0000 Subject: [PATCH 122/168] Improve nine bus decoupling example with 3ph decoupling line. Signed-off-by: pipeacosta --- .../Signal/DecouplingLineEMT_Ph3.h | 5 +- .../src/Signal/DecouplingLineEMT_Ph3.cpp | 50 +++--- .../cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp | 21 ++- .../cxx/Circuits/EMT_DecouplingLine_Ph3.cpp | 13 +- examples/Notebooks/Components/Line.ipynb | 146 +++++++++--------- 5 files changed, 127 insertions(+), 108 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Signal/DecouplingLineEMT_Ph3.h b/dpsim-models/include/dpsim-models/Signal/DecouplingLineEMT_Ph3.h index 84d8986701..563f991c98 100644 --- a/dpsim-models/include/dpsim-models/Signal/DecouplingLineEMT_Ph3.h +++ b/dpsim-models/include/dpsim-models/Signal/DecouplingLineEMT_Ph3.h @@ -19,7 +19,7 @@ namespace CPS { namespace Signal { class DecouplingLineEMT_Ph3 : public SimSignalComp, - public SharedFactory { + public SharedFactory { protected: Real mDelay; Matrix mResistance = Matrix::Zero(3, 3); @@ -50,7 +50,8 @@ class DecouplingLineEMT_Ph3 : public SimSignalComp, ///FIXME: workaround for dependency analysis as long as the states aren't attributes const Attribute::Ptr mStates; - DecouplingLineEMT_Ph3(String name, Logger::Level logLevel = Logger::Level::info); + DecouplingLineEMT_Ph3(String name, + Logger::Level logLevel = Logger::Level::info); void setParameters(SimNode::Ptr node1, SimNode::Ptr node2, Matrix resistance, Matrix inductance, Matrix capacitance); diff --git a/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp b/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp index 53a616c6fa..a052f00400 100644 --- a/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp +++ b/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp @@ -16,7 +16,8 @@ using namespace CPS; using namespace CPS::EMT::Ph3; using namespace CPS::Signal; -DecouplingLineEMT_Ph3::DecouplingLineEMT_Ph3(String name, Logger::Level logLevel) +DecouplingLineEMT_Ph3::DecouplingLineEMT_Ph3(String name, + Logger::Level logLevel) : SimSignalComp(name, name, logLevel), mStates(mAttributes->create("states")), mSrcCur1Ref(mAttributes->create("i_src1", Matrix::Zero(3, 1))), @@ -29,8 +30,9 @@ DecouplingLineEMT_Ph3::DecouplingLineEMT_Ph3(String name, Logger::Level logLevel } void DecouplingLineEMT_Ph3::setParameters(SimNode::Ptr node1, - SimNode::Ptr node2, Matrix resistance, - Matrix inductance, Matrix capacitance) { + SimNode::Ptr node2, + Matrix resistance, Matrix inductance, + Matrix capacitance) { mResistance = resistance; mInductance = inductance; @@ -43,15 +45,17 @@ void DecouplingLineEMT_Ph3::setParameters(SimNode::Ptr node1, SPDLOG_LOGGER_INFO(mSLog, "surge impedance: {}", mSurgeImpedance); SPDLOG_LOGGER_INFO(mSLog, "delay: {}", mDelay); - mRes1->setParameters(Math::singlePhaseParameterToThreePhase(mSurgeImpedance(0,0) + mResistance(0,0) / 4)); + mRes1->setParameters(Math::singlePhaseParameterToThreePhase( + mSurgeImpedance(0, 0) + mResistance(0, 0) / 4)); mRes1->connect({SimNode::GND, node1}); - mRes2->setParameters(Math::singlePhaseParameterToThreePhase(mSurgeImpedance(0,0) + mResistance(0,0) / 4)); + mRes2->setParameters(Math::singlePhaseParameterToThreePhase( + mSurgeImpedance(0, 0) + mResistance(0, 0) / 4)); /*Notice that, as opposed to the DecouplingLine Ph1, this resistor is connected from GND to node2, since currently the Ph3 resistor has the opposite sign convention for voltage and current, compared to the Ph1 countepart.*/ mRes2->connect({SimNode::GND, node2}); - mSrc1->setParameters(Matrix::Zero(3,1)); + mSrc1->setParameters(Matrix::Zero(3, 1)); mSrc1->connect({node1, SimNode::GND}); - mSrc2->setParameters(Matrix::Zero(3,1)); + mSrc2->setParameters(Matrix::Zero(3, 1)); mSrc2->connect({node2, SimNode::GND}); mSrcCur1 = mSrc1->mCurrentRef; @@ -70,12 +74,15 @@ void DecouplingLineEMT_Ph3::initialize(Real omega, Real timeStep) { MatrixComp volt1 = -mNode1->initialVoltage(); MatrixComp volt2 = -mNode2->initialVoltage(); - MatrixComp initAdmittance = (mResistance + Complex(0, omega) * mInductance).inverse() + - Complex(0, omega) * mCapacitance / 2; - MatrixComp cur1 = initAdmittance * volt1 - - (mResistance + Complex(0, omega) * mInductance).inverse() * volt2; - MatrixComp cur2 = initAdmittance * volt2 - - (mResistance + Complex(0, omega) * mInductance).inverse() * volt1; + MatrixComp initAdmittance = + (mResistance + Complex(0, omega) * mInductance).inverse() + + Complex(0, omega) * mCapacitance / 2; + MatrixComp cur1 = + initAdmittance * volt1 - + (mResistance + Complex(0, omega) * mInductance).inverse() * volt2; + MatrixComp cur2 = + initAdmittance * volt2 - + (mResistance + Complex(0, omega) * mInductance).inverse() * volt1; SPDLOG_LOGGER_INFO(mSLog, "initial voltages: v_k {} v_m {}", volt1, volt2); SPDLOG_LOGGER_INFO(mSLog, "initial currents: i_km {} i_mk {}", cur1, cur2); @@ -99,12 +106,15 @@ void DecouplingLineEMT_Ph3::step(Real time, Int timeStepCount) { Matrix volt2 = interpolate(mVolt2); Matrix cur1 = interpolate(mCur1); Matrix cur2 = interpolate(mCur2); - Matrix denom = (mSurgeImpedance + (mResistance / 4)) * (mSurgeImpedance + (mResistance / 4)); + Matrix denom = (mSurgeImpedance + (mResistance / 4)) * + (mSurgeImpedance + (mResistance / 4)); if (timeStepCount == 0) { // initialization - **mSrcCur1Ref = cur1 - (mSurgeImpedance + mResistance / 4).inverse() * volt1; - **mSrcCur2Ref = cur2 - (mSurgeImpedance + mResistance / 4).inverse() * volt2; + **mSrcCur1Ref = + cur1 - (mSurgeImpedance + mResistance / 4).inverse() * volt1; + **mSrcCur2Ref = + cur2 - (mSurgeImpedance + mResistance / 4).inverse() * volt2; } else { // Update currents **mSrcCur1Ref = -mSurgeImpedance * denom.inverse() * @@ -125,11 +135,13 @@ void DecouplingLineEMT_Ph3::PreStep::execute(Real time, Int timeStepCount) { } void DecouplingLineEMT_Ph3::postStep() { - // Update ringbuffers with new values + // Update ringbuffers with new values mVolt1.row(mBufIdx) = -mRes1->intfVoltage().transpose(); mVolt2.row(mBufIdx) = -mRes2->intfVoltage().transpose(); - mCur1.row(mBufIdx) = -mRes1->intfCurrent().transpose() + mSrcCur1->get().real().transpose(); - mCur2.row(mBufIdx) = -mRes2->intfCurrent().transpose() + mSrcCur2->get().real().transpose(); + mCur1.row(mBufIdx) = + -mRes1->intfCurrent().transpose() + mSrcCur1->get().real().transpose(); + mCur2.row(mBufIdx) = + -mRes2->intfCurrent().transpose() + mSrcCur2->get().real().transpose(); mBufIdx++; if (mBufIdx == mBufSize) diff --git a/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp b/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp index 6d8cbcbe55..3bf2c41b47 100644 --- a/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp +++ b/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp @@ -6,6 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. *********************************************************************************/ +#include "dpsim-models/Signal/DecouplingLineEMT_Ph3.h" #include #include #include @@ -27,16 +28,11 @@ String decoupleLine(SystemTopology &sys, const String &lineName, String dline_name = "dline_" + node1 + "_" + node2; - auto line = Signal::DecouplingLineEMT::make("dline_" + node1 + "_" + node2, - Logger::Level::debug); - - Real Rline_scalar = Rline(0, 0); - Real Lline_scalar = Lline(0, 0); - Real Cline_scalar = Cline(0, 0); + auto line = Signal::DecouplingLineEMT_Ph3::make( + "dline_" + node1 + "_" + node2, Logger::Level::debug); line->setParameters(sys.node(node1), - sys.node(node2), Rline_scalar, Lline_scalar, - Cline_scalar); + sys.node(node2), Rline, Lline, Cline); sys.addComponent(line); sys.addComponents(line->getLineComponents()); @@ -47,9 +43,12 @@ void doSim(String &name, SystemTopology &sys, Int threads) { // Logging auto logger = DataLogger::make(name); - // logger->logAttribute("BUS5.v", sys.node("BUS5")->attribute("v")); - // logger->logAttribute("BUS6.v", sys.node("BUS6")->attribute("v")); - // logger->logAttribute("BUS8.v", sys.node("BUS8")->attribute("v")); + logger->logAttribute("BUS5.v", + sys.node("BUS5")->attribute("v")); + logger->logAttribute("BUS6.v", + sys.node("BUS6")->attribute("v")); + logger->logAttribute("BUS8.v", + sys.node("BUS8")->attribute("v")); for (Int bus = 1; bus <= 9; bus++) { String attrName = "v" + std::to_string(bus); String nodeName = "BUS" + std::to_string(bus); diff --git a/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp b/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp index 287365d7a2..54aa571c08 100644 --- a/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp +++ b/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp @@ -103,7 +103,8 @@ void simDecouplingLine_Ph3() { // Components auto vs = VoltageSource::make("v_1", Logger::Level::debug); Real VsRefRMS = 100000 * PEAK1PH_TO_RMS3PH; - MatrixComp VsRefPh3 = CPS::Math::singlePhaseVariableToThreePhase(Complex(VsRefRMS, 0)); + MatrixComp VsRefPh3 = + CPS::Math::singlePhaseVariableToThreePhase(Complex(VsRefRMS, 0)); vs->setParameters(VsRefPh3, 50); // Parametrization of components @@ -112,10 +113,10 @@ void simDecouplingLine_Ph3() { Real capacitance = 1.0e-6; auto dline = DecouplingLineEMT_Ph3::make("dline", Logger::Level::debug); - dline->setParameters(n1, n2, - CPS::Math::singlePhaseParameterToThreePhase(resistance), - CPS::Math::singlePhaseParameterToThreePhase(inductance), - CPS::Math::singlePhaseParameterToThreePhase(capacitance)); + dline->setParameters( + n1, n2, CPS::Math::singlePhaseParameterToThreePhase(resistance), + CPS::Math::singlePhaseParameterToThreePhase(inductance), + CPS::Math::singlePhaseParameterToThreePhase(capacitance)); auto load = Resistor::make("R_load", Logger::Level::debug); load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); @@ -148,6 +149,6 @@ void simDecouplingLine_Ph3() { } int main(int argc, char *argv[]) { -// simElements(); + // simElements(); simDecouplingLine_Ph3(); } diff --git a/examples/Notebooks/Components/Line.ipynb b/examples/Notebooks/Components/Line.ipynb index dcbc17fbdc..f0127f2f0b 100644 --- a/examples/Notebooks/Components/Line.ipynb +++ b/examples/Notebooks/Components/Line.ipynb @@ -1220,26 +1220,26 @@ "source": [ "time_step = 0.00005\n", "final_time = 0.1\n", - "sim_name = 'EMT_Decoupling_Wave_Ph3'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "sim_name = \"EMT_Decoupling_Wave_Ph3\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", - "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", - "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.ABC)\n", + "n2 = dpsimpy.emt.SimNode(\"n2\", dpsimpy.PhaseType.ABC)\n", "gnd = dpsimpy.emt.SimNode.gnd\n", "\n", "resistance = dpsimpy.Math.single_phase_parameter_to_three_phase(5)\n", "inductance = dpsimpy.Math.single_phase_parameter_to_three_phase(0.16)\n", "capacitance = dpsimpy.Math.single_phase_parameter_to_three_phase(1e-6)\n", "\n", - "vs = dpsimpy.emt.ph3.VoltageSource('Vsrc_emt')\n", + "vs = dpsimpy.emt.ph3.VoltageSource(\"Vsrc_emt\")\n", "vs_ref_rms = 100000 * dpsimpy.PEAK1PH_TO_RMS3PH\n", "vs_ref_ph3 = dpsimpy.Math.single_phase_variable_to_three_phase(complex(vs_ref_rms, 0))\n", "vs.set_parameters(vs_ref_ph3, 50)\n", "\n", - "dline = dpsimpy.signal.DecouplingLineEMT_Ph3('DecLine_emt_ph3', dpsimpy.LogLevel.debug)\n", + "dline = dpsimpy.signal.DecouplingLineEMT_Ph3(\"DecLine_emt_ph3\", dpsimpy.LogLevel.debug)\n", "dline.set_parameters(n1, n2, resistance, inductance, capacitance)\n", "\n", - "load = dpsimpy.emt.ph3.Resistor('R_load')\n", + "load = dpsimpy.emt.ph3.Resistor(\"R_load\")\n", "load.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(10000))\n", "\n", "vs.connect([gnd, n1])\n", @@ -1249,12 +1249,12 @@ "sys.add(dline.get_line_components())\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v1', 'v', n1)\n", - "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('i1', 'i_intf', vs)\n", - "logger.log_attribute('i2', 'i_intf', load)\n", - "logger.log_attribute('i_src1', 'i_src1', dline)\n", - "logger.log_attribute('i_src2', 'i_src2', dline)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"v2\", \"v\", n2)\n", + "logger.log_attribute(\"i1\", \"i_intf\", vs)\n", + "logger.log_attribute(\"i2\", \"i_intf\", load)\n", + "logger.log_attribute(\"i_src1\", \"i_src1\", dline)\n", + "logger.log_attribute(\"i_src2\", \"i_src2\", dline)\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", "sim.set_system(sys)\n", @@ -1397,10 +1397,10 @@ "metadata": {}, "outputs": [], "source": [ - "work_dir = 'logs/EMT_Decoupling_Wave_Ph3/'\n", - "log_name = 'EMT_Decoupling_Wave_Ph3'\n", - "print(work_dir + log_name + '.csv')\n", - "emt_decoupling_wave_ph3 = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + "work_dir = \"logs/EMT_Decoupling_Wave_Ph3/\"\n", + "log_name = \"EMT_Decoupling_Wave_Ph3\"\n", + "print(work_dir + log_name + \".csv\")\n", + "emt_decoupling_wave_ph3 = rt.read_timeseries_dpsim(work_dir + log_name + \".csv\")" ] }, { @@ -1410,9 +1410,9 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(emt_decoupling_wave_ph3['v1_0'].time, emt_decoupling_wave_ph3['v1_0'].values)\n", - "plt.plot(emt_decoupling_wave_ph3['v2_0'].time, emt_decoupling_wave_ph3['v2_0'].values)\n", - "#plt.xlim([0,0.02])\n", + "plt.plot(emt_decoupling_wave_ph3[\"v1_0\"].time, emt_decoupling_wave_ph3[\"v1_0\"].values)\n", + "plt.plot(emt_decoupling_wave_ph3[\"v2_0\"].time, emt_decoupling_wave_ph3[\"v2_0\"].values)\n", + "# plt.xlim([0,0.02])\n", "plt.show()" ] }, @@ -1423,9 +1423,13 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(emt_decoupling_wave_ph3['i_src1_0'].time, emt_decoupling_wave_ph3['i_src1_0'].values)\n", - "plt.plot(emt_decoupling_wave_ph3['i_src2_0'].time, emt_decoupling_wave_ph3['i_src2_0'].values)\n", - "#plt.xlim([0,0.02])\n", + "plt.plot(\n", + " emt_decoupling_wave_ph3[\"i_src1_0\"].time, emt_decoupling_wave_ph3[\"i_src1_0\"].values\n", + ")\n", + "plt.plot(\n", + " emt_decoupling_wave_ph3[\"i_src2_0\"].time, emt_decoupling_wave_ph3[\"i_src2_0\"].values\n", + ")\n", + "# plt.xlim([0,0.02])\n", "plt.show()" ] }, @@ -1436,9 +1440,9 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(emt_decoupling_wave_ph3['i1_0'].time, emt_decoupling_wave_ph3['i1_0'].values)\n", - "plt.plot(emt_decoupling_wave_ph3['i2_0'].time, emt_decoupling_wave_ph3['i2_0'].values)\n", - "#plt.xlim([0,0.02])\n", + "plt.plot(emt_decoupling_wave_ph3[\"i1_0\"].time, emt_decoupling_wave_ph3[\"i1_0\"].values)\n", + "plt.plot(emt_decoupling_wave_ph3[\"i2_0\"].time, emt_decoupling_wave_ph3[\"i2_0\"].values)\n", + "# plt.xlim([0,0.02])\n", "plt.show()" ] }, @@ -1532,37 +1536,37 @@ "source": [ "plt.figure()\n", "plt.plot(\n", - " emt_decoupling_wave['v1'].time,\n", - " emt_decoupling_wave['v1'].values,\n", - " color = '#939393ff',\n", - " label = 'v1_emt'\n", + " emt_decoupling_wave[\"v1\"].time,\n", + " emt_decoupling_wave[\"v1\"].values,\n", + " color=\"#939393ff\",\n", + " label=\"v1_emt\",\n", ")\n", "plt.plot(\n", - " emt_decoupling_wave['v2'].time,\n", - " emt_decoupling_wave['v2'].values,\n", - " color = '#939393ff',\n", - " label = 'v2_emt'\n", + " emt_decoupling_wave[\"v2\"].time,\n", + " emt_decoupling_wave[\"v2\"].values,\n", + " color=\"#939393ff\",\n", + " label=\"v2_emt\",\n", ")\n", "plt.plot(\n", - " emt_decoupling_wave_ph3['v1_0'].time,\n", - " emt_decoupling_wave_ph3['v1_0'].values,\n", - " linestyle=':',\n", - " color = '#0055ffff',\n", - " label = 'v1_emt_ph3'\n", + " emt_decoupling_wave_ph3[\"v1_0\"].time,\n", + " emt_decoupling_wave_ph3[\"v1_0\"].values,\n", + " linestyle=\":\",\n", + " color=\"#0055ffff\",\n", + " label=\"v1_emt_ph3\",\n", ")\n", "plt.plot(\n", - " emt_decoupling_wave_ph3['v2_0'].time,\n", - " -emt_decoupling_wave_ph3['v2_0'].values,\n", - " linestyle=':',\n", - " color = '#d62728ff',\n", - " label = 'v2_emt_ph3'\n", + " emt_decoupling_wave_ph3[\"v2_0\"].time,\n", + " emt_decoupling_wave_ph3[\"v2_0\"].values,\n", + " linestyle=\":\",\n", + " color=\"#d62728ff\",\n", + " label=\"v2_emt_ph3\",\n", ")\n", "plt.legend()\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('voltage (V)')\n", - "#plt.xlim([0.02,0.1])\n", - "#plt.ylim([-20,20])\n", - "plt.savefig('tlm_emt_emt3ph_voltage.pdf')" + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"voltage (V)\")\n", + "# plt.xlim([0.02,0.1])\n", + "# plt.ylim([-20,20])\n", + "plt.savefig(\"tlm_emt_emt3ph_voltage.pdf\")" ] }, { @@ -1573,35 +1577,37 @@ "source": [ "plt.figure()\n", "plt.plot(\n", - " emt_decoupling_wave['i_src1'].time,\n", - " emt_decoupling_wave['i_src1'].values,\n", - " color = '#939393ff',\n", - " label = 'i_src1_emt'\n", + " emt_decoupling_wave[\"i_src1\"].time,\n", + " emt_decoupling_wave[\"i_src1\"].values,\n", + " color=\"#939393ff\",\n", + " label=\"i_src1_emt\",\n", ")\n", "plt.plot(\n", - " emt_decoupling_wave['i_src2'].time,\n", - " emt_decoupling_wave['i_src2'].values,\n", - " color = '#939393ff',\n", - " label = 'i_src2_emt'\n", + " emt_decoupling_wave[\"i_src2\"].time,\n", + " emt_decoupling_wave[\"i_src2\"].values,\n", + " color=\"#939393ff\",\n", + " label=\"i_src2_emt\",\n", ")\n", "plt.plot(\n", - " emt_decoupling_wave_ph3['i_src1_0'].time,\n", - " emt_decoupling_wave_ph3['i_src1_0'].values,\n", - " linestyle=':', color = '#0055ffff',\n", - " label = 'i_src1_emt_ph3'\n", + " emt_decoupling_wave_ph3[\"i_src1_0\"].time,\n", + " emt_decoupling_wave_ph3[\"i_src1_0\"].values,\n", + " linestyle=\":\",\n", + " color=\"#0055ffff\",\n", + " label=\"i_src1_emt_ph3\",\n", ")\n", "plt.plot(\n", - " emt_decoupling_wave_ph3['i_src2_0'].time,\n", - " emt_decoupling_wave_ph3['i_src2_0'].values,\n", - " linestyle=':', color = '#d62728ff',\n", - " label = 'i_src2_emt_ph3'\n", + " emt_decoupling_wave_ph3[\"i_src2_0\"].time,\n", + " emt_decoupling_wave_ph3[\"i_src2_0\"].values,\n", + " linestyle=\":\",\n", + " color=\"#d62728ff\",\n", + " label=\"i_src2_emt_ph3\",\n", ")\n", "plt.legend()\n", - "plt.xlabel('time (s)')\n", - "plt.ylabel('current (A)')\n", - "#plt.xlim([0.02,0.1])\n", - "#plt.ylim([-20,20])\n", - "plt.savefig('tlm_emt_emt3ph_current.pdf')" + "plt.xlabel(\"time (s)\")\n", + "plt.ylabel(\"current (A)\")\n", + "# plt.xlim([0.02,0.1])\n", + "# plt.ylim([-20,20])\n", + "plt.savefig(\"tlm_emt_emt3ph_current.pdf\")" ] } ], From 7ff3cae1c86d3a8ecbf098947ad0e7d800493903 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Thu, 20 Nov 2025 15:03:22 +0000 Subject: [PATCH 123/168] Clean code and remove redundant includes. Signed-off-by: pipeacosta --- dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp | 2 -- dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp | 1 - dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp | 5 +---- examples/Notebooks/Components/Line.ipynb | 6 +++--- 4 files changed, 4 insertions(+), 10 deletions(-) diff --git a/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp b/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp index a052f00400..662ed8b734 100644 --- a/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp +++ b/dpsim-models/src/Signal/DecouplingLineEMT_Ph3.cpp @@ -6,8 +6,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. *********************************************************************************/ -#include "dpsim-models/Definitions.h" -#include "dpsim-models/EMT/EMT_Ph3_Resistor.h" #include "dpsim-models/MathUtils.h" #include #include diff --git a/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp b/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp index 3bf2c41b47..9827d378c6 100644 --- a/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp +++ b/dpsim/examples/cxx/CIM/EMT_WSCC_9bus_split_decoupled.cpp @@ -6,7 +6,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. *********************************************************************************/ -#include "dpsim-models/Signal/DecouplingLineEMT_Ph3.h" #include #include #include diff --git a/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp b/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp index 54aa571c08..dbf43bb272 100644 --- a/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp +++ b/dpsim/examples/cxx/Circuits/EMT_DecouplingLine_Ph3.cpp @@ -6,7 +6,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. *********************************************************************************/ -#include "dpsim-models/Definitions.h" #include "dpsim/Definitions.h" #include @@ -71,8 +70,6 @@ void simElements() { auto sys = SystemTopology( 50, SystemNodeList{n1, n2, vn1}, SystemComponentList{vs, res, ind, cap1, cap2, con1, con2, load}); - //SystemComponentList{vs, res, ind, cap1, cap2, load}); - //SystemComponentList{vs, res, ind, load}); // Logging auto logger = DataLogger::make(simName); @@ -149,6 +146,6 @@ void simDecouplingLine_Ph3() { } int main(int argc, char *argv[]) { - // simElements(); + simElements(); simDecouplingLine_Ph3(); } diff --git a/examples/Notebooks/Components/Line.ipynb b/examples/Notebooks/Components/Line.ipynb index f0127f2f0b..3804d3c788 100644 --- a/examples/Notebooks/Components/Line.ipynb +++ b/examples/Notebooks/Components/Line.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -437,7 +437,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1613,7 +1613,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, From 02d1fac3073bc8dfcae418e5d965972f22cd2582 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Fri, 29 Aug 2025 19:04:28 +0200 Subject: [PATCH 124/168] Reorganize structure of module Now the module has his own Config.h to expose options. This will allow in the future to have more control on the compilation of the modules and examples. A file that lists the intefaces is now the main include point of the module. The loading of the module dpsim-villas is done now before dpsim, to make it available as done with dpsim-models. Signed-off-by: Leonardo Carreras --- CMakeLists.txt | 7 ++--- dpsim-villas/CMakeLists.txt | 24 +++++++++++++-- dpsim-villas/include/dpsim-villas/Config.h.in | 29 +++++++++++++++++++ .../include/dpsim-villas/Interfaces.h | 9 ++++++ 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 dpsim-villas/include/dpsim-villas/Config.h.in create mode 100644 dpsim-villas/include/dpsim-villas/Interfaces.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8d4020a4bf..e61eab6944 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -280,16 +280,15 @@ if(WITH_PYBIND) endif() add_subdirectory(dpsim-models) +if(WITH_VILLAS) + add_subdirectory(dpsim-villas) +endif() add_subdirectory(dpsim) if(DPSIM_BUILD_DOC) add_subdirectory(docs) endif() -if(WITH_VILLAS) - add_subdirectory(dpsim-villas) -endif() - if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16") message(VERBOSE "Compiler Release Flags: " ${CMAKE_CXX_FLAGS_RELEASE}) message(VERBOSE "Compiler Debug Flags: " ${CMAKE_CXX_FLAGS_DEBUG}) diff --git a/dpsim-villas/CMakeLists.txt b/dpsim-villas/CMakeLists.txt index 29e4a5bea7..eae8c6ddaa 100644 --- a/dpsim-villas/CMakeLists.txt +++ b/dpsim-villas/CMakeLists.txt @@ -1,3 +1,13 @@ +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/include/dpsim-villas/Config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/include/dpsim-villas/Config.h +) + +set(DPSIM_VILLAS_INCLUDE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include +) + if(WITH_PYBIND) pybind11_add_module(dpsimpyvillas src/pybind-dpsim-villas.cpp) set_target_properties(dpsimpyvillas @@ -17,17 +27,27 @@ endif() add_subdirectory(src) +target_include_directories(dpsim-villas PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include +) + if(DPSIM_BUILD_EXAMPLES) add_subdirectory(examples) endif() file(GLOB_RECURSE HEADER_FILES include/*.h) +set(GENERATED_HEADER ${CMAKE_CURRENT_BINARY_DIR}/include/dpsim-villas/Config.h) target_sources(dpsim-villas PUBLIC FILE_SET public_headers TYPE HEADERS - BASE_DIRS include - FILES "${HEADER_FILES}" + BASE_DIRS + ${CMAKE_CURRENT_SOURCE_DIR}/include + ${CMAKE_CURRENT_BINARY_DIR}/include + FILES + ${HEADER_FILES} + ${GENERATED_HEADER} ) install(TARGETS dpsim-villas diff --git a/dpsim-villas/include/dpsim-villas/Config.h.in b/dpsim-villas/include/dpsim-villas/Config.h.in new file mode 100644 index 0000000000..92d073266e --- /dev/null +++ b/dpsim-villas/include/dpsim-villas/Config.h.in @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#ifndef DPSIM_VILLAS_CONFIG_H +#define DPSIM_VILLAS_CONFIG_H + +#define DPSIM_VILLAS_VERSION "@PROJECT_VERSION@" + +// Features +#cmakedefine WITH_RT +#cmakedefine WITH_VILLAS +#cmakedefine WITH_CIM +#cmakedefine WITH_PYBIND +#cmakedefine WITH_SUNDIALS +#cmakedefine WITH_OPENMP +#cmakedefine WITH_CUDA +#cmakedefine WITH_CUDA_SPARSE +#cmakedefine WITH_MAGMA +#cmakedefine WITH_KLU +#cmakedefine WITH_MNASOLVERPLUGIN +#cmakedefine WITH_JSON +#cmakedefine CGMES_BUILD + +#cmakedefine HAVE_GETOPT +#cmakedefine HAVE_TIMERFD + +#endif diff --git a/dpsim-villas/include/dpsim-villas/Interfaces.h b/dpsim-villas/include/dpsim-villas/Interfaces.h new file mode 100644 index 0000000000..4668785406 --- /dev/null +++ b/dpsim-villas/include/dpsim-villas/Interfaces.h @@ -0,0 +1,9 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include + +#include +#include From 1cc846b8d7fc0ef73042be605f2b1c6bb1625f03 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Fri, 29 Aug 2025 19:12:37 +0200 Subject: [PATCH 125/168] Add missing component EMT 3Ph ControlledCurrentSource to component list Signed-off-by: Leonardo Carreras --- dpsim-models/include/dpsim-models/Components.h | 1 + 1 file changed, 1 insertion(+) diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index bd47323e02..42653ce13f 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -92,6 +92,7 @@ #include #include #include +#include #include #include #include From 292d5342993d6fe553e67cf514f76c6fdcd4d040 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Fri, 29 Aug 2025 19:14:09 +0200 Subject: [PATCH 126/168] fix examples: clean imports and use the method for 3ph parameter creation Signed-off-by: Leonardo Carreras --- dpsim-villas/examples/cxx/Fpga9BusHil.cpp | 29 +++++++------------ .../examples/cxx/FpgaCosim3PhInfiniteBus.cpp | 25 ++++------------ .../examples/cxx/FpgaCosimulation.cpp | 19 ++++-------- 3 files changed, 22 insertions(+), 51 deletions(-) diff --git a/dpsim-villas/examples/cxx/Fpga9BusHil.cpp b/dpsim-villas/examples/cxx/Fpga9BusHil.cpp index 868104f6dd..93a1229b41 100644 --- a/dpsim-villas/examples/cxx/Fpga9BusHil.cpp +++ b/dpsim-villas/examples/cxx/Fpga9BusHil.cpp @@ -7,20 +7,11 @@ #include #include -#include "../examples/cxx/Examples.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#include + +#include "../examples/cxx/Examples.h" using namespace DPsim; using namespace CPS::EMT; @@ -136,16 +127,16 @@ hilTopology(CommandLineArgs &args, std::shared_ptr intf, sys.initWithPowerflow(systemPF, CPS::Domain::EMT); sys.component("LOAD5")->setParameters( - Matrix({{125e6, 0, 0}, {0, 125e6, 0}, {0, 0, 125e6}}), - Matrix({{90e6, 0, 0}, {0, 90e6, 0}, {0, 0, 90e6}}), 230e3, true); + CPS::Math::singlePhaseParameterToThreePhase(125e6), + CPS::Math::singlePhaseParameterToThreePhase(90e6), 230e3, true); sys.component("LOAD8")->setParameters( - Matrix({{100e6, 0, 0}, {0, 100e6, 0}, {0, 0, 100e6}}), - Matrix({{30e6, 0, 0}, {0, 30e6, 0}, {0, 0, 30e6}}), 230e3, true); + CPS::Math::singlePhaseParameterToThreePhase(100e6), + CPS::Math::singlePhaseParameterToThreePhase(30e6), 230e3, true); sys.component("LOAD6")->setParameters( - Matrix({{90e6, 0, 0}, {0, 90e6, 0}, {0, 0, 90e6}}), - Matrix({{30e6, 0, 0}, {0, 30e6, 0}, {0, 0, 30e6}}), 230e3, true); + CPS::Math::singlePhaseParameterToThreePhase(90e6), + CPS::Math::singlePhaseParameterToThreePhase(30e6), 230e3, true); auto gen1 = sys.component("GEN1"); gen1->addGovernor(govKundur.Ta_t, govKundur.Tb, govKundur.Tc, govKundur.Fa, diff --git a/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp b/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp index 0f39f9c669..aa0a865a02 100644 --- a/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp +++ b/dpsim-villas/examples/cxx/FpgaCosim3PhInfiniteBus.cpp @@ -6,24 +6,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#include using namespace DPsim; using namespace CPS::EMT; @@ -153,16 +141,15 @@ SystemTopology buildTopology(CommandLineArgs &args, 50); auto r = Ph3::Resistor::make("R"); - r->setParameters(Matrix{{10.4275, 0, 0}, {0, 10.4275, 0}, {0, 0, 10.4275}}); + r->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10.4275)); auto l = Ph3::Inductor::make("L"); - l->setParameters( - Matrix{{0.325101, 0, 0}, {0, 0.325101, 0}, {0, 0, 0.325101}}); + l->setParameters(CPS::Math::singlePhaseParameterToThreePhase(0.325101)); auto r2 = Ph3::Resistor::make("R2"); - r2->setParameters(Matrix{{5.29e6, 0, 0}, {0, 5.29e6, 0}, {0, 0, 5.29e6}}); + r2->setParameters(CPS::Math::singlePhaseParameterToThreePhase(5.29e6)); auto cs = Ph3::ControlledCurrentSource::make("cs"); - cs->setParameters(Matrix{{0.0}, {0.0}, {0.0}}); + cs->setParameters(CPS::Math::singlePhaseParameterToThreePhase(0.0)); // Topology vs->connect({SimNode::GND, bus1}); diff --git a/dpsim-villas/examples/cxx/FpgaCosimulation.cpp b/dpsim-villas/examples/cxx/FpgaCosimulation.cpp index 6f134fa25f..1819d3e6b6 100644 --- a/dpsim-villas/examples/cxx/FpgaCosimulation.cpp +++ b/dpsim-villas/examples/cxx/FpgaCosimulation.cpp @@ -6,20 +6,13 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include #include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#include using namespace DPsim; using namespace CPS::EMT; @@ -142,13 +135,13 @@ SystemTopology buildTopology(CommandLineArgs &args, // Components auto vs = Ph3::ControlledVoltageSource::make("vs"); - auto voltageRef = Matrix({{230e3}, {230e3}, {230e3}}); + auto voltageRef = CPS::Math::singlePhaseParameterToThreePhase(230e3); vs->setParameters(voltageRef); auto load = Ph3::RXLoad::make("load"); - auto active = Matrix({{125e6, 0, 0}, {0, 125e6, 0}, {0, 0, 125e6}}); + auto active = CPS::Math::singlePhaseParameterToThreePhase(125e6); // auto reactive = Matrix::Zero(3, 3); - auto reactive = Matrix({{50e6, 0, 0}, {0, 50e6, 0}, {0, 0, 50e6}}); + auto reactive = CPS::Math::singlePhaseParameterToThreePhase(50e6); load->setParameters(active, reactive, 230e3, true); // Topology From 39fa8e1cea5e0260525deeda860fd29e86c64418 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 1 Sep 2025 22:21:03 +0200 Subject: [PATCH 127/168] Add suggestions Signed-off-by: Leonardo Carreras --- dpsim-villas/CMakeLists.txt | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/dpsim-villas/CMakeLists.txt b/dpsim-villas/CMakeLists.txt index eae8c6ddaa..08a8a0181b 100644 --- a/dpsim-villas/CMakeLists.txt +++ b/dpsim-villas/CMakeLists.txt @@ -28,8 +28,7 @@ endif() add_subdirectory(src) target_include_directories(dpsim-villas PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_BINARY_DIR}/include + ${DPSIM_VILLAS_INCLUDE_DIRS} ) if(DPSIM_BUILD_EXAMPLES) @@ -43,8 +42,7 @@ target_sources(dpsim-villas PUBLIC FILE_SET public_headers TYPE HEADERS BASE_DIRS - ${CMAKE_CURRENT_SOURCE_DIR}/include - ${CMAKE_CURRENT_BINARY_DIR}/include + ${DPSIM_VILLAS_INCLUDE_DIRS} FILES ${HEADER_FILES} ${GENERATED_HEADER} From 5a443883f08e86ca082d779b9f2db5edb274d17d Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 25 Sep 2025 21:00:36 +0200 Subject: [PATCH 128/168] Add a way to search for all parts of villas library Signed-off-by: Leonardo Carreras --- cmake/FindVILLASnode.cmake | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/cmake/FindVILLASnode.cmake b/cmake/FindVILLASnode.cmake index 0feeca4eaa..ce54fe9748 100644 --- a/cmake/FindVILLASnode.cmake +++ b/cmake/FindVILLASnode.cmake @@ -6,10 +6,36 @@ find_library(VILLASNODE_LIBRARY NAMES villas ) +find_library(VILLASCOMMON_LIBRARY + NAMES villas-common +) + +find_library(VILLASFPGA_LIBRARY + NAMES villas-fpga +) + set(VILLASNODE_LIBRARIES ${VILLASNODE_LIBRARY}) set(VILLASNODE_INCLUDE_DIRS ${VILLASNODE_INCLUDE_DIR}) +set(VILLASCOMMON_LIBRARIES ${VILLASCOMMON_LIBRARY}) +set(VILLASFPGA_LIBRARIES ${VILLASFPGA_LIBRARY}) include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(VILLASnode DEFAULT_MSG VILLASNODE_LIBRARY VILLASNODE_INCLUDE_DIR) +find_package_handle_standard_args( + VILLASnode + DEFAULT_MSG + VILLASNODE_LIBRARY + VILLASNODE_INCLUDE_DIR + VILLASCOMMON_LIBRARY +) + +message(STATUS "VILLAS include: ${VILLASNODE_INCLUDE_DIR}") +message(STATUS "VILLASnode library: ${VILLASNODE_LIBRARY}") +message(STATUS "VILLAScommon library: ${VILLASCOMMON_LIBRARY}") +message(STATUS "VILLASfpga library: ${VILLASFPGA_LIBRARY}") -mark_as_advanced(VILLASNODE_INCLUDE_DIR VILLASNODE_LIBRARY) +mark_as_advanced( + VILLASNODE_INCLUDE_DIR + VILLASNODE_LIBRARY + VILLASCOMMON_LIBRARY + VILLASFPGA_LIBRARY +) From fe8d4b5377646b3009f90fdaf9db233b29285ebd Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 25 Sep 2025 21:02:13 +0200 Subject: [PATCH 129/168] Move deprecated files using shared memory and fix changes Signed-off-by: Leonardo Carreras --- .../ShmemControllableFiltSource.cpp | 31 ++++++-- .../ShmemControllableSource.cpp | 26 +++++-- .../ShmemDistributedDirect.cpp | 48 +++++++++--- .../ShmemDistributedReference.cpp | 0 .../ShmemDistributedVillas.cpp | 34 ++++++-- .../cxx/{ => deprecated}/ShmemExample.cpp | 30 +++++--- .../Shmem_CIGRE_MV_PowerFlowTest.cpp | 28 +++++-- ...em_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp | 29 +++++-- .../cxx/{ => deprecated}/Shmem_WSCC-9bus.cpp | 26 +++++-- .../{ => deprecated}/Shmem_WSCC-9bus_Ctrl.cpp | 39 +++++++--- .../Shmem_WSCC-9bus_CtrlDist.cpp | 77 ++++++++++++++----- 11 files changed, 282 insertions(+), 86 deletions(-) rename dpsim-villas/examples/cxx/{ => deprecated}/ShmemControllableFiltSource.cpp (73%) rename dpsim-villas/examples/cxx/{ => deprecated}/ShmemControllableSource.cpp (61%) rename dpsim-villas/examples/cxx/{ => deprecated}/ShmemDistributedDirect.cpp (81%) rename dpsim-villas/examples/cxx/{ => deprecated}/ShmemDistributedReference.cpp (100%) rename dpsim-villas/examples/cxx/{ => deprecated}/ShmemDistributedVillas.cpp (77%) rename dpsim-villas/examples/cxx/{ => deprecated}/ShmemExample.cpp (80%) rename dpsim-villas/examples/cxx/{ => deprecated}/Shmem_CIGRE_MV_PowerFlowTest.cpp (77%) rename dpsim-villas/examples/cxx/{ => deprecated}/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp (86%) rename dpsim-villas/examples/cxx/{ => deprecated}/Shmem_WSCC-9bus.cpp (66%) rename dpsim-villas/examples/cxx/{ => deprecated}/Shmem_WSCC-9bus_Ctrl.cpp (76%) rename dpsim-villas/examples/cxx/{ => deprecated}/Shmem_WSCC-9bus_CtrlDist.cpp (65%) diff --git a/dpsim-villas/examples/cxx/ShmemControllableFiltSource.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemControllableFiltSource.cpp similarity index 73% rename from dpsim-villas/examples/cxx/ShmemControllableFiltSource.cpp rename to dpsim-villas/examples/cxx/deprecated/ShmemControllableFiltSource.cpp index dac1cd023d..dad1adffdb 100644 --- a/dpsim-villas/examples/cxx/ShmemControllableFiltSource.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemControllableFiltSource.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include +#include using namespace DPsim; using namespace CPS::Signal; @@ -13,7 +13,19 @@ int main(int argc, char *argv[]) { Real finalTime = 10; String simName = "ShmemControllableSource"; - InterfaceShmem intf("/dpsim01", "/dpsim10"); + const std::string shmemConfig = R"STRING( + { + "type": "shmem", + "in": { + "name": "dpsim01" + }, + "out": { + "name": "dpsim10" + }, + "queuelen": 1024 + })STRING"; + + auto intf = std::make_shared(shmemConfig); // Controllers and filter std::vector coefficients = { @@ -49,20 +61,29 @@ int main(int argc, char *argv[]) { load->mActivePower->setReference(filtP->mOutput); load->mReactivePower->setReference(filtQ->mOutput); - filtP->setInput(intf.importReal(0)); - filtQ->setInput(intf.importReal(1)); + auto filtPInput = CPS::AttributeDynamic::make(0.0); + intf->importAttribute(filtPInput, 0, true); + filtP->setInput(filtPInput); + + auto filtQInput = CPS::AttributeDynamic::make(0.0); + intf->importAttribute(filtQInput, 1, true); + filtQ->setInput(filtQInput); auto sys = SystemTopology(50, SystemNodeList{n1}, SystemComponentList{ecs, r1, load, filtP, filtQ}); +#ifdef WITH_RT RealTimeSimulation sim(simName, CPS::Logger::Level::info); +#else + Simulation sim(simName, CPS::Logger::Level::info); +#endif sim.setSystem(sys); sim.setTimeStep(timeStep); sim.setFinalTime(finalTime); sim.setDomain(Domain::DP); sim.setSolverType(Solver::Type::MNA); - sim.addInterface(std::shared_ptr(&intf)); + sim.addInterface(intf); sim.run(); return 0; diff --git a/dpsim-villas/examples/cxx/ShmemControllableSource.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemControllableSource.cpp similarity index 61% rename from dpsim-villas/examples/cxx/ShmemControllableSource.cpp rename to dpsim-villas/examples/cxx/deprecated/ShmemControllableSource.cpp index a0ed24a867..a78c6f196f 100644 --- a/dpsim-villas/examples/cxx/ShmemControllableSource.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemControllableSource.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include +#include using namespace DPsim; using namespace CPS::DP; @@ -12,7 +12,19 @@ int main(int argc, char *argv[]) { Real finalTime = 10; String simName = "ShmemControllableSource"; - InterfaceShmem intf("/dpsim01", "/dpsim10"); + const std::string shmemConfig = R"STRING( + { + "type": "shmem", + "in": { + "name": "dpsim01" + }, + "out": { + "name": "dpsim10" + }, + "queuelen": 1024 + })STRING"; + + auto intf = std::make_shared(shmemConfig); // Nodes auto n1 = SimNode::make("n1"); @@ -26,20 +38,24 @@ int main(int argc, char *argv[]) { ecs->connect({SimNode::GND, n1}); r1->connect({SimNode::GND, n1}); - intf.importAttribute(ecs->mCurrentRef, 0); - intf.exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0); + intf->importAttribute(ecs->mCurrentRef, 0, true); + intf->exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0, true); auto sys = SystemTopology(50, SystemNodeList{n1}, SystemComponentList{ecs, r1}); +#ifdef WITH_RT RealTimeSimulation sim(simName, CPS::Logger::Level::info); +#else + Simulation sim(simName, CPS::Logger::Level::info); +#endif sim.setSystem(sys); sim.setTimeStep(timeStep); sim.setFinalTime(finalTime); sim.setDomain(Domain::DP); sim.setSolverType(Solver::Type::MNA); - sim.addInterface(std::shared_ptr(&intf)); + sim.addInterface(intf); sim.run(); return 0; diff --git a/dpsim-villas/examples/cxx/ShmemDistributedDirect.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedDirect.cpp similarity index 81% rename from dpsim-villas/examples/cxx/ShmemDistributedDirect.cpp rename to dpsim-villas/examples/cxx/deprecated/ShmemDistributedDirect.cpp index e2708bfea7..cba29ff941 100644 --- a/dpsim-villas/examples/cxx/ShmemDistributedDirect.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedDirect.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include +#include using namespace DPsim; using namespace CPS::DP; @@ -77,11 +77,25 @@ int main(int argc, char *argv[]) { sim.addLogger(logger); // Map attributes to interface entries - InterfaceShmem intf(in, out); - intf.importAttribute(evs->mVoltageRef, 0); + const auto shmemConfig = fmt::format( + R"STRING( + {{ + "type": "shmem", + "in": {{ + "name": "{}" + }}, + "out": {{ + "name": "{}" + }}, + "queuelen": 1024 + }})STRING", + in, out); + + auto intf = std::make_shared(shmemConfig); + intf->importAttribute(evs->mVoltageRef, 0, true); auto evsAttrMinus = evs->mIntfCurrent->deriveCoeff(0, 0); - intf.exportAttribute(evsAttrMinus, 0); - sim.addInterface(std::shared_ptr(&intf)); + intf->exportAttribute(evsAttrMinus, 0, true); + sim.addInterface(intf); MatrixComp initialEvsCurrent = MatrixComp::Zero(1, 1); initialEvsCurrent(0, 0) = Complex(5, 0); @@ -122,14 +136,28 @@ int main(int argc, char *argv[]) { sim.addLogger(logger); // Map attributes to interface entries - InterfaceShmem intf(in, out); - intf.importAttribute(ecs->mCurrentRef, 0); + const auto shmemConfig = fmt::format( + R"STRING( + {{ + "type": "shmem", + "in": {{ + "name": "{}" + }}, + "out": {{ + "name": "{}" + }}, + "queuelen": 1024 + }})STRING", + in, out); + + auto intf = std::make_shared(shmemConfig); + intf->importAttribute(ecs->mCurrentRef, 0, true); //intf.exportComplex(ecs->mIntfVoltage->coeff(0, 0), 0); - intf.exportAttribute( + intf->exportAttribute( ecs->mIntfVoltage->deriveCoeff(0, 0)->deriveScaled( Complex(-1., 0)), - 0); - sim.addInterface(std::shared_ptr(&intf)); + 0, true); + sim.addInterface(intf); sim.run(); } diff --git a/dpsim-villas/examples/cxx/ShmemDistributedReference.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedReference.cpp similarity index 100% rename from dpsim-villas/examples/cxx/ShmemDistributedReference.cpp rename to dpsim-villas/examples/cxx/deprecated/ShmemDistributedReference.cpp diff --git a/dpsim-villas/examples/cxx/ShmemDistributedVillas.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp similarity index 77% rename from dpsim-villas/examples/cxx/ShmemDistributedVillas.cpp rename to dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp index 3051c51bed..da266b9e57 100644 --- a/dpsim-villas/examples/cxx/ShmemDistributedVillas.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include +#include using namespace DPsim; using namespace CPS::DP; @@ -27,7 +27,21 @@ int main(int argc, char *argv[]) { out = "/villas1-out"; } - InterfaceShmem intf(in, out, nullptr); + const auto shmemConfig = fmt::format( + R"STRING( + {{ + "type": "shmem", + "in": {{ + "name": "{}" + }}, + "out": {{ + "name": "{}" + }}, + "queuelen": 1024 + }})STRING", + in, out); + + auto intf = std::make_shared(shmemConfig); if (String(argv[1]) == "0") { // Nodes @@ -56,8 +70,9 @@ int main(int argc, char *argv[]) { comps = SystemComponentList{evs, vs, l1, r1}; nodes = SystemNodeList{SimNode::GND, n1, n2, n3}; - intf.importAttribute(evs->mVoltageRef, 0); - intf.exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0); + intf->importAttribute(evs->mVoltageRef, 0, true); + intf->exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0, + true); } else if (String(argv[1]) == "1") { // Nodes @@ -85,8 +100,9 @@ int main(int argc, char *argv[]) { comps = SystemComponentList{ecs, sw, r2A, r2B}; nodes = SystemNodeList{SimNode::GND, n4, n5}; - intf.importAttribute(ecs->mCurrentRef, 0); - intf.exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0); + intf->importAttribute(ecs->mCurrentRef, 0, true); + intf->exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0, + true); } else { std::cerr << "invalid test number" << std::endl; std::exit(1); @@ -97,11 +113,15 @@ int main(int argc, char *argv[]) { auto sys = SystemTopology(50, nodes, comps); +#ifdef WITH_RT RealTimeSimulation sim(simName + argv[1]); +#else + Simulation sim(simName + argv[1]); +#endif sim.setSystem(sys); sim.setTimeStep(timeStep); sim.setFinalTime(20); - sim.addInterface(std::shared_ptr(&intf)); + sim.addInterface(intf); if (String(argv[1]) == "1") { auto evt = SwitchEvent::make( diff --git a/dpsim-villas/examples/cxx/ShmemExample.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemExample.cpp similarity index 80% rename from dpsim-villas/examples/cxx/ShmemExample.cpp rename to dpsim-villas/examples/cxx/deprecated/ShmemExample.cpp index 7f8f942155..029292508e 100644 --- a/dpsim-villas/examples/cxx/ShmemExample.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemExample.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include using namespace DPsim; using namespace CPS::DP; @@ -44,24 +44,32 @@ int main(int argc, char *argv[]) { auto sys = SystemTopology(50, SystemNodeList{SimNode::GND, n1, n2, n3, n4}, SystemComponentList{evs, rs, rl, ll, rL}); -#ifdef REALTIME +#ifdef WITH_RT RealTimeSimulation sim(simName); - sim.setSystem(sys); - sim.setTimeStep(timeStep); - sim.setFinalTime(1.0); - InterfaceShmem intf("/villas1-in", "/villas1-out", nullptr, false); #else Simulation sim(simName); +#endif sim.setSystem(sys); sim.setTimeStep(timeStep); sim.setFinalTime(1.0); - InterfaceShmem intf("/villas1-in", "/villas1-out"); -#endif + + std::string shmemConfig = R"STRING( + { + "type": "shmem", + "in": { + "name": "villas1-in" + }, + "out": { + "name": "villas1-out" + } + })STRING"; + + auto intf = std::make_shared(shmemConfig); // Interface - intf.importAttribute(evs->mVoltageRef, 0); - intf.exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0); - sim.addInterface(std::shared_ptr(&intf)); + intf->importAttribute(evs->mVoltageRef, 0, true); + intf->exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0, true); + sim.addInterface(intf); // Logger auto logger = DataLogger::make(simName); diff --git a/dpsim-villas/examples/cxx/Shmem_CIGRE_MV_PowerFlowTest.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp similarity index 77% rename from dpsim-villas/examples/cxx/Shmem_CIGRE_MV_PowerFlowTest.cpp rename to dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp index db15186e05..dd9eaa11e5 100644 --- a/dpsim-villas/examples/cxx/Shmem_CIGRE_MV_PowerFlowTest.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp @@ -1,8 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include -#include +#include using namespace std; using namespace DPsim; @@ -31,13 +30,30 @@ int main(int argc, char **argv) { CPS::Logger::Level::off); SystemTopology sys = reader.loadCIM(system_freq, filenames, CPS::Domain::SP); +#ifdef WITH_RT RealTimeSimulation sim(simName, args.logLevel); +#else + Simulation sim(simName, args.logLevel); +#endif sim.setSystem(sys); sim.setTimeStep(args.timeStep); sim.setFinalTime(args.duration); sim.setDomain(args.solver.domain); sim.setSolverType(args.solver.type); - InterfaceShmem intf("/dpsim1-villas", "/villas-dpsim1"); + + const std::string shmemConfig = R"STRING( + { + "type": "shmem", + "in": { + "name": "dpsim1-villas" + }, + "out": { + "name": "villas-dpsim1" + }, + "queuelen": 1024 + })STRING"; + + auto intf = std::make_shared(shmemConfig); // Register exportable node voltages UInt o = 0; @@ -57,13 +73,13 @@ int main(int argc, char **argv) { std::cout << "Signal " << (i * 2) + 1 << ": Phas " << n->name() << std::endl; - intf.exportReal(v->deriveMag(), (i * 2) + 0); + intf->exportAttribute(v->deriveMag(), (i * 2) + 0, true); o++; - intf.exportReal(v->derivePhase(), (i * 2) + 1); + intf->exportAttribute(v->derivePhase(), (i * 2) + 1, true); o++; } - sim.addInterface(std::shared_ptr(&intf)); + sim.addInterface(intf); sim.run(std::chrono::seconds(5)); diff --git a/dpsim-villas/examples/cxx/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp similarity index 86% rename from dpsim-villas/examples/cxx/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp rename to dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp index 4aab9918d7..eb5b9ea6d3 100644 --- a/dpsim-villas/examples/cxx/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp @@ -1,9 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 #include -#include -#include -#include +#include #include #include @@ -58,13 +56,30 @@ int main(int argc, char **argv) { csvreader.assignLoadProfile(sys, 0, args.timeStep, args.duration, CSVReader::Mode::MANUAL); +#ifdef WITH_RT RealTimeSimulation sim(simName, args.logLevel); +#else + Simulation sim(simName, args.logLevel); +#endif sim.setSystem(sys); sim.setTimeStep(args.timeStep); sim.setFinalTime(args.duration); sim.setDomain(args.solver.domain); sim.setSolverType(args.solver.type); - InterfaceShmem intf("/dpsim1-villas", "/villas-dpsim1"); + + const std::string shmemConfig = R"STRING( + { + "type": "shmem", + "in": { + "name": "dpsim1-villas" + }, + "out": { + "name": "villas-dpsim1" + }, + "queuelen": 1024 + })STRING"; + + auto intf = std::make_shared(shmemConfig); ofstream villas_conf; villas_conf.open("villas_sent_data.conf"); @@ -88,9 +103,9 @@ int main(int argc, char **argv) { std::cout << "Signal " << (i * 2) + 1 << ": Phas " << n->name() << std::endl; - intf.exportReal(v->deriveMag(), (i * 2) + 0); + intf->exportAttribute(v->deriveMag(), (i * 2) + 0, true); o++; - intf.exportReal(v->derivePhase(), (i * 2) + 1); + intf->exportAttribute(v->derivePhase(), (i * 2) + 1, true); o++; list_varnames[(i * 2) + 0] = n->name() + ".V.mag"; @@ -102,7 +117,7 @@ int main(int argc, char **argv) { } villas_conf.close(); - sim.addInterface(std::shared_ptr(&intf)); + sim.addInterface(intf); sim.run(std::chrono::seconds(5)); diff --git a/dpsim-villas/examples/cxx/Shmem_WSCC-9bus.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus.cpp similarity index 66% rename from dpsim-villas/examples/cxx/Shmem_WSCC-9bus.cpp rename to dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus.cpp index bd53e098b9..82a61e9889 100644 --- a/dpsim-villas/examples/cxx/Shmem_WSCC-9bus.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include using namespace DPsim; using namespace CPS::DP; @@ -22,7 +22,11 @@ int main(int argc, char *argv[]) { CIMReader reader(simName, CPS::Logger::Level::info, CPS::Logger::Level::info); SystemTopology sys = reader.loadCIM(60, filenames); +#ifdef WITH_RT RealTimeSimulation sim(simName, CPS::Logger::Level::debug); +#else + Simulation sim(simName, CPS::Logger::Level::debug); +#endif sim.setSystem(sys); sim.setTimeStep(0.001); sim.setFinalTime(120); @@ -30,20 +34,32 @@ int main(int argc, char *argv[]) { sim.setSolverType(Solver::Type::MNA); sim.doInitFromNodesAndTerminals(true); - InterfaceShmem intf("/dpsim-villas", "/villas-dpsim"); + const std::string shmemConfig = R"STRING( + { + "type": "shmem", + "in": { + "name": "dpsim-villas" + }, + "out": { + "name": "villas-dpsim" + }, + "queuelen": 1024 + })STRING"; + + auto intf = std::make_shared(shmemConfig); // Register exportable node voltages UInt o = 0; for (auto n : sys.mNodes) { auto v = n->attributeTyped("v"); - intf.exportReal(v->deriveMag(), o + 0); - intf.exportReal(v->derivePhase(), o + 1); + intf->exportAttribute(v->deriveMag(), o + 0, true); + intf->exportAttribute(v->derivePhase(), o + 1, true); o += 2; } - sim.addInterface(std::shared_ptr(&intf)); + sim.addInterface(intf); sim.run(); return 0; diff --git a/dpsim-villas/examples/cxx/Shmem_WSCC-9bus_Ctrl.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_Ctrl.cpp similarity index 76% rename from dpsim-villas/examples/cxx/Shmem_WSCC-9bus_Ctrl.cpp rename to dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_Ctrl.cpp index 51fa3a2eb5..478e1ace1c 100644 --- a/dpsim-villas/examples/cxx/Shmem_WSCC-9bus_Ctrl.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_Ctrl.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include using namespace DPsim; using namespace CPS::DP::Ph1; @@ -59,7 +59,11 @@ int main(int argc, char *argv[]) { load->mActivePower->setReference(filtP->mOutput); sys.mComponents.push_back(filtP); +#ifdef WITH_RT RealTimeSimulation sim(simName, CPS::Logger::Level::off); +#else + Simulation sim(simName, CPS::Logger::Level::off); +#endif sim.setSystem(sys); sim.setTimeStep(args.timeStep); sim.setFinalTime(args.duration); @@ -67,7 +71,19 @@ int main(int argc, char *argv[]) { sim.setSolverType(Solver::Type::MNA); sim.doInitFromNodesAndTerminals(true); - InterfaceShmem intf("/dpsim1-villas", "/villas-dpsim1", nullptr, false); + const std::string shmemConfig = R"STRING( + { + "type": "shmem", + "in": { + "name": "dpsim1-villas" + }, + "out": { + "name": "villas-dpsim1" + }, + "queuelen": 1024 + })STRING"; + + auto intf = std::make_shared(shmemConfig); auto logger = DataLogger::make(simName); @@ -91,9 +107,9 @@ int main(int argc, char *argv[]) { std::cout << "Signal " << (i * 2) + 1 << ": Phas " << n->name() << std::endl; - intf.exportReal(v->deriveMag(), (i * 2) + 0); + intf->exportAttribute(v->deriveMag(), (i * 2) + 0, true); o++; - intf.exportReal(v->derivePhase(), (i * 2) + 1); + intf->exportAttribute(v->derivePhase(), (i * 2) + 1, true); o++; logger->logAttribute(fmt::format("mag_{}", i), v->deriveMag()); @@ -103,13 +119,18 @@ int main(int argc, char *argv[]) { logger->logAttribute("v3", sys.node("BUS3")->mVoltage); // TODO gain by 20e8 - filtP->setInput(intf.importReal(0)); - filtP_profile->setInput(intf.importReal(1)); + auto filtPInput = CPS::AttributeDynamic::make(0.0); + intf->importAttribute(filtPInput, 0, true); + filtP->setInput(filtPInput); + + auto filtPProfileInput = CPS::AttributeDynamic::make(0.0); + intf->importAttribute(filtPProfileInput, 1, true); + filtP_profile->setInput(filtPProfileInput); - intf.exportReal(load->attributeTyped("P"), o++); - intf.exportReal(load_profile->attributeTyped("P"), o++); + intf->exportAttribute(load->attributeTyped("P"), o++, true); + intf->exportAttribute(load_profile->attributeTyped("P"), o++, true); - sim.addInterface(std::shared_ptr(&intf)); + sim.addInterface(intf); sim.addLogger(logger); sim.run(args.startTime); diff --git a/dpsim-villas/examples/cxx/Shmem_WSCC-9bus_CtrlDist.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_CtrlDist.cpp similarity index 65% rename from dpsim-villas/examples/cxx/Shmem_WSCC-9bus_CtrlDist.cpp rename to dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_CtrlDist.cpp index 114c99a03a..9abcba61e2 100644 --- a/dpsim-villas/examples/cxx/Shmem_WSCC-9bus_CtrlDist.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_CtrlDist.cpp @@ -4,8 +4,7 @@ #include #include -#include -#include +#include using namespace DPsim; using namespace CPS; @@ -16,6 +15,22 @@ int main(int argc, char *argv[]) { CommandLineArgs args(argc, argv, "Shmem_WSCC-9bus_CtrlDist", 0.001, 20, 60); + auto makeShmemConfig = [](const String &inName, const String &outName) { + return fmt::format( + R"STRING( + {{ + "type": "shmem", + "in": {{ + "name": "{}" + }}, + "out": {{ + "name": "{}" + }}, + "queuelen": 1024 + }})STRING", + inName, outName); + }; + if (args.scenario == 0) { // Find CIM files std::list filenames; @@ -44,7 +59,11 @@ int main(int argc, char *argv[]) { ecs->connect({sys.node("BUS4"), DP::SimNode::GND}); sys.mComponents.push_back(ecs); +#ifdef WITH_RT RealTimeSimulation sim(args.name + "_1", CPS::Logger::Level::debug); +#else + Simulation sim(args.name + "_1", CPS::Logger::Level::debug); +#endif sim.setSystem(sys); sim.setTimeStep(args.timeStep); sim.setFinalTime(args.duration); @@ -52,10 +71,12 @@ int main(int argc, char *argv[]) { sim.setSolverType(Solver::Type::MNA); sim.doInitFromNodesAndTerminals(true); - InterfaceShmem intf1("/dpsim01", "/dpsim10", nullptr, false); - InterfaceShmem intf2("/dpsim1-villas", "/villas-dpsim1", nullptr, false); - sim.addInterface(std::shared_ptr(&intf1)); - sim.addInterface(std::shared_ptr(&intf2)); + auto intf1 = std::make_shared( + makeShmemConfig("dpsim01", "dpsim10")); + auto intf2 = std::make_shared( + makeShmemConfig("dpsim1-villas", "villas-dpsim1")); + sim.addInterface(intf1); + sim.addInterface(intf2); // Controllers and filter std::vector coefficients_profile = std::vector(2000, 1. / 2000); @@ -66,11 +87,14 @@ int main(int argc, char *argv[]) { sys.mComponents.push_back(filtP_profile); // Register interface current source and voltage drop - intf1.importAttribute(ecs->mCurrentRef, 0); - intf1.exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0); + intf1->importAttribute(ecs->mCurrentRef, 0, true); + intf1->exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0, + true); // TODO: gain by 20e8 - filtP_profile->setInput(intf2.importReal(0)); + auto filtPProfileInput = CPS::AttributeDynamic::make(0.0); + intf2->importAttribute(filtPProfileInput, 0, true); + filtP_profile->setInput(filtPProfileInput); // Register exportable node voltages for (auto n : sys.mNodes) { @@ -90,8 +114,8 @@ int main(int argc, char *argv[]) { std::cout << "Signal " << (i * 2) + 1 << ": Phas " << n->name() << std::endl; - intf2.exportReal(v->deriveMag(), (i * 2) + 0); - intf2.exportReal(v->derivePhase(), (i * 2) + 1); + intf2->exportAttribute(v->deriveMag(), (i * 2) + 0, true); + intf2->exportAttribute(v->derivePhase(), (i * 2) + 1, true); } sim.run(args.startTime); @@ -120,28 +144,39 @@ int main(int argc, char *argv[]) { auto sys = SystemTopology(args.sysFreq, SystemNodeList{n1}, SystemComponentList{evs, load, filtP}); +#ifdef WITH_RT RealTimeSimulation sim(args.name + "_2"); +#else + Simulation sim(args.name + "_2"); +#endif sim.setSystem(sys); sim.setTimeStep(args.timeStep); sim.setFinalTime(args.duration); - InterfaceShmem intf1("/dpsim10", "/dpsim01", nullptr, false); - sim.addInterface(std::shared_ptr(&intf1)); + auto intf1 = std::make_shared( + makeShmemConfig("dpsim10", "dpsim01")); + sim.addInterface(intf1); - InterfaceShmem intf2("/dpsim2-villas", "/villas-dpsim2", nullptr, false); - sim.addInterface(std::shared_ptr(&intf2)); + auto intf2 = std::make_shared( + makeShmemConfig("dpsim2-villas", "villas-dpsim2")); + sim.addInterface(intf2); // Register voltage source reference and current flowing through source // multiply with -1 to consider passive sign convention - intf1.importAttribute(evs->mVoltageRef, 0); + intf1->importAttribute(evs->mVoltageRef, 0, true); // TODO: invalid sign - intf1.exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0); + intf1->exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0, + true); // Register controllable load - filtP->setInput(intf2.importReal(0)); - intf2.exportReal(load->mActivePower, 0); - intf2.exportComplex(load->mIntfVoltage->deriveCoeff(0, 0), 1); - intf2.exportComplex(load->mIntfCurrent->deriveCoeff(0, 0), 2); + auto filtPInput = CPS::AttributeDynamic::make(0.0); + intf2->importAttribute(filtPInput, 0, true); + filtP->setInput(filtPInput); + intf2->exportAttribute(load->mActivePower, 0, true); + intf2->exportAttribute(load->mIntfVoltage->deriveCoeff(0, 0), 1, + true); + intf2->exportAttribute(load->mIntfCurrent->deriveCoeff(0, 0), 2, + true); sim.run(args.startTime); } From 7a01776a065825087c59a80408435b0cd4c5be97 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 25 Sep 2025 21:02:49 +0200 Subject: [PATCH 130/168] Fix imports and coding of current examples Signed-off-by: Leonardo Carreras --- dpsim-villas/examples/cxx/FileExample.cpp | 2 +- dpsim-villas/examples/cxx/FpgaExample.cpp | 73 +++++++++---------- dpsim-villas/examples/cxx/MqttExample.cpp | 2 +- .../examples/cxx/SharedMemExample.cpp | 2 +- 4 files changed, 37 insertions(+), 42 deletions(-) diff --git a/dpsim-villas/examples/cxx/FileExample.cpp b/dpsim-villas/examples/cxx/FileExample.cpp index ec9956917e..58227c912e 100644 --- a/dpsim-villas/examples/cxx/FileExample.cpp +++ b/dpsim-villas/examples/cxx/FileExample.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include using namespace DPsim; using namespace CPS::DP; diff --git a/dpsim-villas/examples/cxx/FpgaExample.cpp b/dpsim-villas/examples/cxx/FpgaExample.cpp index ec19b9f8dc..c8a3cfed5b 100644 --- a/dpsim-villas/examples/cxx/FpgaExample.cpp +++ b/dpsim-villas/examples/cxx/FpgaExample.cpp @@ -7,23 +7,13 @@ #include #include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include + +#include using namespace DPsim; -using namespace CPS::DP; -using namespace CPS::DP::Ph1; const std::string buildFpgaConfig(CommandLineArgs &args) { std::filesystem::path fpgaIpPath = @@ -101,17 +91,17 @@ SystemTopology loopbackTopology(CommandLineArgs &args, std::shared_ptr intf, std::shared_ptr logger) { // Nodes - auto n1 = SimNode::make("n1"); + auto n1 = CPS::DP::SimNode::make("n1"); // Components - auto vs = VoltageSource::make("v_s"); + auto vs = CPS::DP::Ph1::VoltageSource::make("v_s"); vs->setParameters(10.); - auto rl = Resistor::make("r_l"); + auto rl = CPS::DP::Ph1::Resistor::make("r_l"); rl->setParameters(1); // Topology - vs->connect({n1, SimNode::GND}); - rl->connect({n1, SimNode::GND}); + vs->connect({n1, CPS::DP::SimNode::GND}); + rl->connect({n1, CPS::DP::SimNode::GND}); // Interface auto seqnumAttribute = CPS::AttributeStatic::make(0); @@ -125,7 +115,7 @@ SystemTopology loopbackTopology(CommandLineArgs &args, logger->logAttribute("rl_i", rl->mIntfCurrent); } - return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, n1}, + return SystemTopology(args.sysFreq, SystemNodeList{CPS::DP::SimNode::GND, n1}, SystemComponentList{vs, rl}); } @@ -133,22 +123,22 @@ SystemTopology hilTopology(CommandLineArgs &args, std::shared_ptr intf, std::shared_ptr logger) { // Nodes - auto n1 = SimNode::make("n1"); - auto n2 = SimNode::make("n2"); + auto n1 = CPS::DP::SimNode::make("n1"); + auto n2 = CPS::DP::SimNode::make("n2"); // Components - auto vs = VoltageSource::make("v_s"); + auto vs = CPS::DP::Ph1::VoltageSource::make("v_s"); vs->setParameters(Complex(1, 0), 50); - auto rs = Resistor::make("r_s"); + auto rs = CPS::DP::Ph1::Resistor::make("r_s"); rs->setParameters(1); - auto cs = CurrentSource::make("i_l"); + auto cs = CPS::DP::Ph1::CurrentSource::make("i_l"); cs->setParameters(Complex(0, 0)); // Topology - vs->connect({n1, SimNode::GND}); + vs->connect({n1, CPS::DP::SimNode::GND}); cs->connect({n1, n2}); - rs->connect({n2, SimNode::GND}); + rs->connect({n2, CPS::DP::SimNode::GND}); // Interface auto seqnumAttribute = CPS::AttributeStatic::make(0); @@ -163,7 +153,8 @@ SystemTopology hilTopology(CommandLineArgs &args, logger->logAttribute("cs_i", cs->mIntfCurrent); } - return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, n1, n2}, + return SystemTopology(args.sysFreq, + SystemNodeList{CPS::DP::SimNode::GND, n1, n2}, SystemComponentList{vs, rs, cs}); } @@ -171,21 +162,21 @@ SystemTopology profileTopology(CommandLineArgs &args, std::shared_ptr intf, std::shared_ptr logger) { // Nodes - auto n1 = SimNode::make("n1"); - auto n2 = SimNode::make("n2"); + auto n1 = CPS::DP::SimNode::make("n1"); + auto n2 = CPS::DP::SimNode::make("n2"); // Components - auto vs = ProfileVoltageSource::make("v_s", "data.bin"); - auto rs = Resistor::make("r_s"); + auto vs = CPS::DP::Ph1::ProfileVoltageSource::make("v_s", "data.bin"); + auto rs = CPS::DP::Ph1::Resistor::make("r_s"); rs->setParameters(1); - auto cs = CurrentSource::make("i_l"); + auto cs = CPS::DP::Ph1::CurrentSource::make("i_l"); cs->setParameters(Complex(0, 0)); // Topology - vs->connect({n1, SimNode::GND}); + vs->connect({n1, CPS::DP::SimNode::GND}); cs->connect({n1, n2}); - rs->connect({n2, SimNode::GND}); + rs->connect({n2, CPS::DP::SimNode::GND}); // Interface auto seqnumAttribute = CPS::AttributeStatic::make(0); @@ -200,7 +191,8 @@ SystemTopology profileTopology(CommandLineArgs &args, logger->logAttribute("cs_i", cs->mIntfCurrent); } - return SystemTopology(args.sysFreq, SystemNodeList{SimNode::GND, n1, n2}, + return SystemTopology(args.sysFreq, + SystemNodeList{CPS::DP::SimNode::GND, n1, n2}, SystemComponentList{vs, rs, cs}); } @@ -232,16 +224,19 @@ std::shared_ptr getEvent(CommandLineArgs &args, SystemTopology &sys) { throw std::runtime_error( "frequencyDrop event only supported for topology \"hil\"."); } - auto vs = std::dynamic_pointer_cast(sys.mComponents[0]); - return AttributeEvent::make(3, vs->mSrcFreq, 45.); + auto vs = std::dynamic_pointer_cast( + sys.mComponents[0]); + return AttributeEvent::make(3, vs->mSrcFreq, 45.); } if (event == "voltageDrop") { if (topology != "hil") { throw std::runtime_error( "voltageDrop event only supported for topology \"hil\"."); } - auto vs = std::dynamic_pointer_cast(sys.mComponents[0]); - return AttributeEvent::make(3, vs->mVoltageRef->deriveReal(), 0.7); + auto vs = std::dynamic_pointer_cast( + sys.mComponents[0]); + return AttributeEvent::make(3, vs->mVoltageRef->deriveReal(), + 0.7); } } return nullptr; diff --git a/dpsim-villas/examples/cxx/MqttExample.cpp b/dpsim-villas/examples/cxx/MqttExample.cpp index 5cb152100a..92e7801bbd 100644 --- a/dpsim-villas/examples/cxx/MqttExample.cpp +++ b/dpsim-villas/examples/cxx/MqttExample.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include using namespace DPsim; using namespace CPS::DP; diff --git a/dpsim-villas/examples/cxx/SharedMemExample.cpp b/dpsim-villas/examples/cxx/SharedMemExample.cpp index 5fda8761a7..1d492b5d5b 100644 --- a/dpsim-villas/examples/cxx/SharedMemExample.cpp +++ b/dpsim-villas/examples/cxx/SharedMemExample.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include using namespace DPsim; using namespace CPS::DP; From ee2a1a776deaf2f7a9523852560a225e9dec30cb Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 25 Sep 2025 21:03:09 +0200 Subject: [PATCH 131/168] Fix and adapt cmakelists Signed-off-by: Leonardo Carreras --- dpsim-villas/examples/cxx/CMakeLists.txt | 82 +++++++++++++++++------- dpsim-villas/src/CMakeLists.txt | 21 +++++- 2 files changed, 79 insertions(+), 24 deletions(-) diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index e499857119..e2cea68356 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -6,33 +6,74 @@ if(NOT WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") endif() -list(APPEND LIBRARIES ${VILLASNODE_LIBRARIES}) -list(APPEND LIBRARIES "jansson") -list(APPEND LIBRARIES "uuid") -list(APPEND LIBRARIES "villas-common") -list(APPEND LIBRARIES "villas-fpga") -list(APPEND LIBRARIES "xil") +if(NOT VILLASNODE_LIBRARIES) + message(FATAL_ERROR "villas-node is required when building DPsim VILLAS examples.") +endif() + +if(NOT VILLASCOMMON_LIBRARIES) + message(FATAL_ERROR "villas-common is required when building DPsim VILLAS examples.") +endif() + +list(APPEND LIBRARIES + ${VILLASNODE_LIBRARIES} + ${VILLASCOMMON_LIBRARIES} + "jansson" + "uuid" +) + +if(VILLASFPGA_LIBRARIES) + list(APPEND LIBRARIES ${VILLASFPGA_LIBRARIES}) + list(APPEND LIBRARIES "xil") +endif() list(APPEND INCLUDE_DIRS ${VILLASNODE_INCLUDE_DIRS}) + set(DPSIM_VILLAS_EXAMPLE_SOURCES FileExample.cpp MqttExample.cpp - FpgaExample.cpp - FpgaCosim3PhInfiniteBus.cpp - FpgaCosimulation.cpp SharedMemExample.cpp - # ShmemExample.cpp - # ShmemDistributedReference.cpp - # ShmemDistributedDirect.cpp - # ShmemDistributedVillas.cpp - # ShmemControllableSource.cpp - # ShmemControllableFiltSource.cpp - # Shmem_CIGRE_MV_PowerFlowTest.cpp - # Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp ) +set(DPSIM_VILLAS_DEPRECATED_BASE + deprecated/ShmemExample.cpp + deprecated/ShmemDistributedReference.cpp + deprecated/ShmemDistributedDirect.cpp + deprecated/ShmemDistributedVillas.cpp + deprecated/ShmemControllableSource.cpp + deprecated/ShmemControllableFiltSource.cpp +) + +set(DPSIM_VILLAS_DEPRECATED_CIM + deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp + deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp + deprecated/Shmem_WSCC-9bus.cpp + deprecated/Shmem_WSCC-9bus_Ctrl.cpp + deprecated/Shmem_WSCC-9bus_CtrlDist.cpp +) + +list(APPEND DPSIM_VILLAS_EXAMPLE_SOURCES ${DPSIM_VILLAS_DEPRECATED_BASE}) + +if(WITH_CIM) + list(APPEND DPSIM_VILLAS_EXAMPLE_SOURCES ${DPSIM_VILLAS_DEPRECATED_CIM}) +else() + message(STATUS "Skipping deprecated CIM-based shmem examples because WITH_CIM is disabled") +endif() + +if(VILLASFPGA_LIBRARIES) + list(APPEND DPSIM_VILLAS_EXAMPLE_SOURCES + FpgaExample.cpp + FpgaCosim3PhInfiniteBus.cpp + FpgaCosimulation.cpp + ) + + if(WITH_CIM) + list(APPEND DPSIM_VILLAS_EXAMPLE_SOURCES Fpga9BusHil.cpp) + endif() +elseif(WITH_CIM) + message(STATUS "Skipping FPGA-related CIM example because villas-fpga was not found.") +endif() + if(WITH_CIM) - list(APPEND DPSIM_VILLAS_EXAMPLE_SOURCES Fpga9BusHil.cpp) list(APPEND INCLUDE_DIRS ${CIMPP_INCLUDE_DIRS}) endif() @@ -45,8 +86,3 @@ foreach(SOURCE ${DPSIM_VILLAS_EXAMPLE_SOURCES} ${CIM_DPSIM_VILLAS_SOURCES}) target_include_directories(${TARGET} PRIVATE ${INCLUDE_DIRS}) target_compile_options(${TARGET} PUBLIC ${DPSIM_CXX_FLAGS}) endforeach() - -# add_executable(ShmemRealtimeExample ShmemExample.cpp) -# target_link_libraries(ShmemRealtimeExample ${LIBRARIES}) -# target_include_directories(ShmemRealtimeExample PRIVATE ${INCLUDE_DIRS}) -# target_compile_definitions(ShmemRealtimeExample PUBLIC REALTIME) diff --git a/dpsim-villas/src/CMakeLists.txt b/dpsim-villas/src/CMakeLists.txt index 654414c0b7..ea5c2523ec 100644 --- a/dpsim-villas/src/CMakeLists.txt +++ b/dpsim-villas/src/CMakeLists.txt @@ -5,6 +5,25 @@ set(DPSIM_VILLAS_SOURCES ) add_library(dpsim-villas ${DPSIM_VILLAS_SOURCES}) -target_link_libraries(dpsim-villas PUBLIC dpsim ${VILLASNODE_LIBRARIES} pthread) + +if(NOT VILLASNODE_LIBRARIES) + message(FATAL_ERROR "villas-node is required when building DPsim with VILLAS support.") +endif() + +if(NOT VILLASCOMMON_LIBRARIES) + message(FATAL_ERROR "villas-common is required when building DPsim with VILLAS support.") +endif() + +set(DPSIM_VILLAS_LIBRARIES + dpsim + ${VILLASNODE_LIBRARIES} + ${VILLASCOMMON_LIBRARIES} + pthread +) +if(VILLASFPGA_LIBRARIES) + list(APPEND DPSIM_VILLAS_LIBRARIES ${VILLASFPGA_LIBRARIES}) +endif() + +target_link_libraries(dpsim-villas PUBLIC ${DPSIM_VILLAS_LIBRARIES}) target_include_directories(dpsim-villas PUBLIC ../include ${VILLASNODE_INCLUDE_DIRS}) target_compile_options(dpsim-villas PUBLIC ${DPSIM_CXX_FLAGS}) From 2a293631f26e0130b1f7fad12fbcb18c064ba7ed Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 25 Sep 2025 21:03:40 +0200 Subject: [PATCH 132/168] Adapt files used in or with examples Signed-off-by: Leonardo Carreras --- configs/shmem_cosim/shmem_test.conf | 4 ++-- configs/start_ShmemExample.sh | 2 +- dpsim-models/include/dpsim-models/Components.h | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/configs/shmem_cosim/shmem_test.conf b/configs/shmem_cosim/shmem_test.conf index 6e0f623b37..cf9546b090 100644 --- a/configs/shmem_cosim/shmem_test.conf +++ b/configs/shmem_cosim/shmem_test.conf @@ -9,7 +9,7 @@ "dpsim": { "path": "./", "scenario": { - "directory": "build/dpsim/examples/cxx/", + "directory": "build/dpsim-villas/examples/cxx/", "name": "ShmemDistributedVillas", "args": "1" }, @@ -26,6 +26,6 @@ "remote_sim":{ "path": "dpsim/", - "exec_command": "docker exec -w /dpsim shmem_tests ./build/dpsim/examples/cxx/ShmemDistributedVillas 0" + "exec_command": "docker exec -w /dpsim shmem_tests ./build/dpsim-villas/examples/cxx/ShmemDistributedVillas 0" } } diff --git a/configs/start_ShmemExample.sh b/configs/start_ShmemExample.sh index cb5eab653f..26c60cda34 100755 --- a/configs/start_ShmemExample.sh +++ b/configs/start_ShmemExample.sh @@ -24,7 +24,7 @@ nodes = { ) } - exec = [ "build/dpsim/examples/cxx/ShmemExample" ] + exec = [ "build/dpsim-villas/examples/cxx/ShmemExample" ] } input = { diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index 42653ce13f..a32e3d5f07 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -51,6 +51,9 @@ #include #include #include +#ifdef WITH_VILLAS +#include +#endif #include #include #include From af6bb8ec73b38170b5e15f60227395655cc9b54c Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 25 Sep 2025 22:07:52 +0200 Subject: [PATCH 133/168] Adapt files used in or with examples Signed-off-by: Leonardo Carreras --- dpsim/include/DPsim.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dpsim/include/DPsim.h b/dpsim/include/DPsim.h index 599cd8b844..7cdf47bb0c 100644 --- a/dpsim/include/DPsim.h +++ b/dpsim/include/DPsim.h @@ -22,6 +22,8 @@ #include #endif +#include + #ifdef WITH_OPENMP #include #endif @@ -37,4 +39,5 @@ using PhaseType = CPS::PhaseType; #ifdef WITH_CIM using CIMReader = CPS::CIM::Reader; #endif +using CSVReader = CPS::CSVReader; } // namespace DPsim From 0b86a889252a80c6913427b3387fbd18ce4b60d7 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 25 Sep 2025 22:08:51 +0200 Subject: [PATCH 134/168] Fixes in examples for realtime and CIM usage Signed-off-by: Leonardo Carreras --- .../deprecated/ShmemControllableFiltSource.cpp | 4 ++++ .../cxx/deprecated/ShmemControllableSource.cpp | 4 ++++ .../cxx/deprecated/ShmemDistributedVillas.cpp | 4 ++++ .../examples/cxx/deprecated/ShmemExample.cpp | 4 ++++ .../deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp | 11 +++++++---- ...hmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp | 17 ++++++++++------- .../examples/cxx/deprecated/Shmem_WSCC-9bus.cpp | 7 ++++++- .../cxx/deprecated/Shmem_WSCC-9bus_Ctrl.cpp | 6 +++++- .../cxx/deprecated/Shmem_WSCC-9bus_CtrlDist.cpp | 16 ++++++++++++---- 9 files changed, 56 insertions(+), 17 deletions(-) diff --git a/dpsim-villas/examples/cxx/deprecated/ShmemControllableFiltSource.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemControllableFiltSource.cpp index dad1adffdb..9935283c5e 100644 --- a/dpsim-villas/examples/cxx/deprecated/ShmemControllableFiltSource.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemControllableFiltSource.cpp @@ -84,7 +84,11 @@ int main(int argc, char *argv[]) { sim.setSolverType(Solver::Type::MNA); sim.addInterface(intf); +#ifdef WITH_RT + sim.run(10); +#else sim.run(); +#endif return 0; } diff --git a/dpsim-villas/examples/cxx/deprecated/ShmemControllableSource.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemControllableSource.cpp index a78c6f196f..5add06c0c2 100644 --- a/dpsim-villas/examples/cxx/deprecated/ShmemControllableSource.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemControllableSource.cpp @@ -56,7 +56,11 @@ int main(int argc, char *argv[]) { sim.setSolverType(Solver::Type::MNA); sim.addInterface(intf); +#ifdef WITH_RT + sim.run(10); +#else sim.run(); +#endif return 0; } diff --git a/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp index da266b9e57..a0914327fe 100644 --- a/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp @@ -130,7 +130,11 @@ int main(int argc, char *argv[]) { sim.addEvent(evt); } +#ifdef WITH_RT + sim.run(10); +#else sim.run(); +#endif return 0; } diff --git a/dpsim-villas/examples/cxx/deprecated/ShmemExample.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemExample.cpp index 029292508e..39a32c8c74 100644 --- a/dpsim-villas/examples/cxx/deprecated/ShmemExample.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemExample.cpp @@ -81,7 +81,11 @@ int main(int argc, char *argv[]) { logger->logAttribute("i_evs", evs->mIntfCurrent, 1, 1); sim.addLogger(logger); +#ifdef WITH_RT + sim.run(10); +#else sim.run(); +#endif //std::ofstream of("task_dependencies.svg"); //sim.dependencyGraph().render(of); diff --git a/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp index dd9eaa11e5..b3ac1d0f33 100644 --- a/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp @@ -6,7 +6,6 @@ using namespace std; using namespace DPsim; using namespace CPS; -using namespace CPS::CIM; /* * This example runs the powerflow for the CIGRE MV benchmark system (neglecting the tap changers of the transformers) @@ -26,8 +25,8 @@ int main(int argc, char **argv) { String simName = "Shmem_CIGRE_MV_PowerFlowTest"; CPS::Real system_freq = 50; - CIM::Reader reader(simName, CPS::Logger::Level::debug, - CPS::Logger::Level::off); + CPS::CIM::Reader reader(simName, CPS::Logger::Level::debug, + CPS::Logger::Level::off); SystemTopology sys = reader.loadCIM(system_freq, filenames, CPS::Domain::SP); #ifdef WITH_RT @@ -81,7 +80,11 @@ int main(int argc, char **argv) { sim.addInterface(intf); - sim.run(std::chrono::seconds(5)); +#ifdef WITH_RT + sim.run(10); +#else + sim.run(); +#endif return 0; } diff --git a/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp index eb5b9ea6d3..684a51a3cc 100644 --- a/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp @@ -8,7 +8,6 @@ using namespace std; using namespace DPsim; using namespace CPS; -using namespace CPS::CIM; /* * This example runs the powerflow for the CIGRE MV benchmark system (neglecting the tap changers of the transformers) @@ -47,14 +46,14 @@ int main(int argc, char **argv) { String simName = "Shmem_CIGRE-MV-NoTap"; CPS::Real system_freq = 50; - CIM::Reader reader(simName, CPS::Logger::Level::debug, - CPS::Logger::Level::off); + CPS::CIM::Reader reader(simName, CPS::Logger::Level::debug, + CPS::Logger::Level::off); SystemTopology sys = reader.loadCIM(system_freq, filenames, CPS::Domain::SP); - CSVReader csvreader(simName, loadProfilePath, assignList, - CPS::Logger::Level::info); + CPS::CSVReader csvreader(simName, loadProfilePath, assignList, + CPS::Logger::Level::info); csvreader.assignLoadProfile(sys, 0, args.timeStep, args.duration, - CSVReader::Mode::MANUAL); + CPS::CSVReader::Mode::MANUAL); #ifdef WITH_RT RealTimeSimulation sim(simName, args.logLevel); @@ -119,7 +118,11 @@ int main(int argc, char **argv) { sim.addInterface(intf); - sim.run(std::chrono::seconds(5)); +#ifdef WITH_RT + sim.run(10); +#else + sim.run(); +#endif return 0; } diff --git a/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus.cpp index 82a61e9889..fdbc0a8fd1 100644 --- a/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus.cpp @@ -19,7 +19,8 @@ int main(int argc, char *argv[]) { String simName = "Shmem_WSCC-9bus"; - CIMReader reader(simName, CPS::Logger::Level::info, CPS::Logger::Level::info); + CPS::CIM::Reader reader(simName, CPS::Logger::Level::info, + CPS::Logger::Level::info); SystemTopology sys = reader.loadCIM(60, filenames); #ifdef WITH_RT @@ -60,7 +61,11 @@ int main(int argc, char *argv[]) { } sim.addInterface(intf); +#ifdef WITH_RT + sim.run(10); +#else sim.run(); +#endif return 0; } diff --git a/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_Ctrl.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_Ctrl.cpp index 478e1ace1c..ecf6ac2026 100644 --- a/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_Ctrl.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_Ctrl.cpp @@ -132,7 +132,11 @@ int main(int argc, char *argv[]) { sim.addInterface(intf); sim.addLogger(logger); - sim.run(args.startTime); +#ifdef WITH_RT + sim.run(10); +#else + sim.run(); +#endif return 0; } diff --git a/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_CtrlDist.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_CtrlDist.cpp index 9abcba61e2..809a66c157 100644 --- a/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_CtrlDist.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_WSCC-9bus_CtrlDist.cpp @@ -43,8 +43,8 @@ int main(int argc, char *argv[]) { filenames = args.positionalPaths(); } - CIM::Reader reader(args.name, CPS::Logger::Level::info, - CPS::Logger::Level::info); + CPS::CIM::Reader reader(args.name, CPS::Logger::Level::info, + CPS::Logger::Level::info); SystemTopology sys = reader.loadCIM(args.sysFreq, filenames); // Extend system with controllable load (Profile) @@ -118,7 +118,11 @@ int main(int argc, char *argv[]) { intf2->exportAttribute(v->derivePhase(), (i * 2) + 1, true); } - sim.run(args.startTime); +#ifdef WITH_RT + sim.run(10); +#else + sim.run(); +#endif } if (args.scenario == 1) { @@ -178,7 +182,11 @@ int main(int argc, char *argv[]) { intf2->exportAttribute(load->mIntfCurrent->deriveCoeff(0, 0), 2, true); - sim.run(args.startTime); +#ifdef WITH_RT + sim.run(10); +#else + sim.run(); +#endif } return 0; From e47d3bb8f87a5cd3a3c1c38fe923529d352b3189 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Wed, 15 Oct 2025 11:08:48 +0200 Subject: [PATCH 135/168] Fix ambiguous use of VoltageNorton->SetParameters Signed-off-by: Leonardo Carreras --- dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp index a0914327fe..651d3b309b 100644 --- a/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp +++ b/dpsim-villas/examples/cxx/deprecated/ShmemDistributedVillas.cpp @@ -63,7 +63,7 @@ int main(int argc, char *argv[]) { // Parameters evs->setParameters(Complex(0, 0)); - vs->setParameters(Complex(10000, 0), 1); + vs->setParameters(Complex(10000, 0), -1, 1e9); l1->setParameters(0.1); r1->setParameters(1); From 8e7c44747390e8d598e65035a66dbaf87b5dfd09 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Wed, 15 Oct 2025 11:35:29 +0200 Subject: [PATCH 136/168] Fix clang reported errors Signed-off-by: Leonardo Carreras --- .../examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp | 2 +- .../deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp index b3ac1d0f33..9dd26974d8 100644 --- a/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest.cpp @@ -55,7 +55,7 @@ int main(int argc, char **argv) { auto intf = std::make_shared(shmemConfig); // Register exportable node voltages - UInt o = 0; + [[maybe_unused]] UInt o = 0; for (auto n : sys.mNodes) { UInt i; if (sscanf(n->name().c_str(), "N%u", &i) != 1) { diff --git a/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp index 684a51a3cc..7f4e0a4198 100644 --- a/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp +++ b/dpsim-villas/examples/cxx/deprecated/Shmem_CIGRE_MV_PowerFlowTest_LoadProfiles.cpp @@ -4,6 +4,7 @@ #include #include #include +#include using namespace std; using namespace DPsim; @@ -84,8 +85,8 @@ int main(int argc, char **argv) { villas_conf.open("villas_sent_data.conf"); // Register exportable node voltages - string list_varnames[sys.mNodes.size() * 2]; - UInt o = 0; + std::vector list_varnames(sys.mNodes.size() * 2); + [[maybe_unused]] UInt o = 0; for (auto n : sys.mNodes) { UInt i; if (sscanf(n->name().c_str(), "N%u", &i) != 1) { From 9193696c112e14e7e52a4d19769bbf3749db1162 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 25 Nov 2025 02:57:32 +0100 Subject: [PATCH 137/168] Changelog including older versions Signed-off-by: Leonardo Carreras --- CHANGELOG.md | 441 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 441 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000..040e3d2ea4 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,441 @@ +# Changelog + +All notable changes to this project will be documented in this file. +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/). + +## [Unreleased] + +### Added + +- Adapt DPsim to deploy it in Mybinder (#323), moving Dockerfile to new .binder folder and adding job for building the binder Dockerfile. +- Add Code Coverage Report (#395), adding codecove badge and updating yaml file for code coverage. +- Add CODEOWNERS (#290) +- Add pre-commit (#352) +- Add pre-commit /2 (#361) +- Add pre-commit /3 (#363) +- Add pre-commit /4 (#377) +- Add pre-commit /5 (#382) +- Add pre-commit /6 (#383) +- Add pre-commit /7 (#385), harmonizing comments and indentation. +- Add pre-commit /8 (#386), harmonizing capitalization of Markdown filenames. +- feat(cmake): Add install target (#381) +- New queueless VILLAS interface / improve real-time performance (#316), creating DCGenerator in VoltageSource only if special setParameters is used and not always when the frequency is 0 (avoiding regressions), and adding DP_PH1_ProfileVoltageSource used for the villas / fpga interface. +- Reuse conductance stamp code (#306), adding functions in MNAStampUtils for stamping value as a scalar matrix. +- Supress a warning treated as an error in MSVC (#280) +- update contact details (#254), updating contact details. +- Add support for CMake `find_package` and rename "KLU" dependency to name of actual library "SuiteSparse" (#380) +- Addition of EMT::Ph1::Switch component (#312), adding test notebook for VS_SW_RL1 circuit in EMT, DP and SP and fixing initialization. +- Linear SSN (#175), making EMT::Ph3 CurrentSource and SSN Full_Serial_RLC usable in pybind with implementation and declaration adjustments for EMT Ph3 CurrentSource. +- Implement decoupling line emt ph3 (#422), improving nine bus decoupling example with 3ph decoupling line and adding test for decoupling line Ph3 to Line.ipynb example. +- VILLASfpga cosimulation development (#325), adding n-eiling as codeowner of /dpsim-villas and fixing MNASolver to start loggers for vectors. +- Villas Interface: Improve FpgaExample (#299), allowing different topologies to be tested and updating VILLAS_VERSION in Dockerfile. + +### Changed + +- Change python to python3 to run the building for pypi (#272) +- Disable code coverage in linux-fedora-examples on workflow (#412) +- editorconfig: set C++ indentation size to two (#295), setting it twice. +- Move pytest.ini to pyproject.toml (#348) +- Reduce attributes number (#388), declaring nominal/base voltages as Real instead of Attribute. +- Replace CentOS badge with RockyLinux badge (#282) +- villas: Use Python dictionaries for defining VILLASconfig files (#343) +- Change default linear solver to KLU (#250), fixing logging statements by using macros and removing explicit choice of SparseLU from cxx examples. +- Update WSCC_9bus_mult examples and implement splitting examples in DP and EMT (#322), removing SP_Ph1_CurrentSource component and fixing path to CIM files in decoupling line diakoptics example. +- Upgrade Fedora dockerfiles to v42 (#387), fixing KLU Adapter varying entry index check and adding libre to Dockerfile to fix one of the real-time errors using villas. + +### Fixed + +- 5th Order Synchronous Generator (#230), fixing some minor details and adding SG5Order to CIM Reader in DP and EMT domain. +- Adding correct logger usage (#411) +- Allow builds without nlohmann/json library (#362) +- dpsim-villas: fix hardcoded paths (#327) +- Enable compilation in gcc 14 and clang 18 (code fixes) (#294) +- feat(cmake): Allow disable LTO builds (#341), adding WITH_MARCH_NATIVE option to enable native host arch builds. +- Fix consistency of calculations at first time step (#210), using Ph3 RMS quantities for initialSingleVoltage in EMT domain and adding macro DOUBLE_EPSILON. +- Fix docu issues (#310), substituting duplicate ODESolver with DAESolver in dpsim_classes_simulation.svg. +- Fix docu pipeline (#333) +- Fix initialization rxload (#241), fixing current initialization of EMT RXLoad. +- Fix module dpsimvillas (#401), fixing ambiguous use of VoltageNorton->SetParameters and fixing examples for realtime and CIM usage. +- Fix power flow initialisation of synchronous generators (#238), fixing pybind double definition of components_at_node and enforcing domain argument for initWithPowerflow. +- Fix rocky workflow due to changes in the profiling triggering (#305) +- Fix some capitalization (#351) +- Fix sonar scanner errors due to Java deprecated version (#265) +- Fix submodule initialization for CIMpp in Dockerfiles (#331), fixing it twice. +- Fix the profiling workflow (#399) +- Fix VILLASnode in Dockerfiles (#292), updating VILLASnode version in Dockerfile.manylinux and in other Dockerfiles. +- Fix workflow: option for parallel in make and error in publish to PyPI (#303) +- fix(cmake): Show feature summary even if not Git info is available (#379) +- fix: MNASolverPlugins examples (#346), fixing include paths of MNASolverPlugin examples and wrapping extern c in preprocessor condition. +- Fixes to the doxygen documentation INPUT line (#264) +- Fixing inconsistent switch attribute names in Base::Ph1::Switch and Base::Ph3::Switch (#418) +- Fixup whitespaces (#350) +- Hotfix: missing simulation stop (#247), adding missing stop function in the Simulation using pybind. +- pybind: Errors when compiling with clang (#334), fixing rocky container and updating villas version, fixing fedora container error in mosquito install and updating villas version. +- Reuse code for MNA matrix stamp operations (#297), logging stamping in MNAStampUtils and reusing admittance stamping logic for SP R,L,C components. +- Reuse stamp code for EMT synchron. generators (#315), adding matrix stamp functions with optimized logic in MNAStampUtils and fixing stamping of full matrix. +- Revision of power flow solver (#284), fixing PFSolver and minimizing file changes. +- Trigger actions for PRs and pin the version of libcimpp (#329), pinning libcimpp version in containers and cmake and triggering relevant workflows on pull_request event. +- Update actions in workflow and improve parallelisation and cache handling (#298), changing the profiling execution to manually triggered and enabling parallelisation with reorganized cache. + +### Removed + +- Remove commented out code (#390) +- Remove further RWTH gitlab dependencies (#261) +- Remove Python versions 3.6 and 3.7 for PyPi upload (#229) + +### Maintenance + +- Add new action using the build wrapper from sonar directly (#296) +- Bump braces from 3.0.2 to 3.0.3 in /docs/hugo (#304) +- Bump postcss from 8.4.20 to 8.4.31 in /docs/hugo (#281) +- Bump version of black & black jupyter to 25.11.0 (#421) +- Bump yaml from 2.1.3 to 2.2.2 in /docs/hugo (#215) +- chore (deps): update to CIMpp rpm/deb install + bump VILLAS (#404), updating cmake fetch and finding of libcimpp and fixing dependent files and CIMReader. +- chore(cmake): Remove deprecated options (#342) +- chore(deps): Bump pypa/gh-action-pypi-publish from 1.12.4 to 1.13.0 in /.github/workflows (#405) +- chore: update docs on real-time and VILLASnode interfaces (#335) +- Disable test actions for PRs (#237) +- feat(ci): Use trusted / OIDC publishing to PyPi.org (#375), only attempting upload to PyPi for pushes to master or tags. +- fix clang compilation and FPGA integration (#293), fixing clang compiler errors and adding clang compilation to CI. +- Fix CMake typos and style (#376) +- Fix GitHub actions workflow for publishing to PyPi (#355), building with newer CMake versions and simplifying triggers for workflows. +- Fix realtime datalogger (#400), adding example notebook for tests and pybind bindings. +- fix std::max behaviour in simulation.cpp for windows build using CMake (#408), fixing issue where windows.h breaks standard C++ behaviour of std::max. +- Fix the villas examples workflow (#319), adding supplementary cache and testing cache deletion. +- Fix Windows and Rocky/Clang builds (#360), fixing Windows builds with newer CMake versions. +- fix(ci): Attempt to fix PyPi package publish (#353) +- fix(ci): Fix tag of pypa/gh-action-pypi-publish action (#354), fixing the tag twice. +- fix(cmake): Fix code-style (#356) +- fix(deps): Add support for newer Spdlog versions (#340), adding missing #pragma once. +- fix(docs): Fix typo and wrong diff (#337) +- fix(examples): Only build Fpga9BusHil example if build with CIMpp (#338), applying it twice. +- fix(style): Remove duplicated typedef (#339) +- fix: Cleanup code-style of setup.py (#336) +- Nix packaging (#357), adding GitHub CI workflow for building DPsim with Nix and Nix packaging. +- python: Harmonize comment style (#349) +- Remove outdated and broken GitLab CI pipeline (#347) +- Update villas version (#245), updating python command to python3 in test-villas-examples actions and removing libwebsockets installation from source. +- Use clang-format to format the whole codebase (#278), fixing missing includes and moving development scripts from configs/ to scripts./ + +## [v1.1.1] - 2023-07-13 + +### Added + +- Add latest publications to website (#161) +- Introduce a common subclass for composite components (#177), adding comments for empty method implementations and renaming systemMatrixStamp methods for sparse matrices. + +### Changed + +- Unify subcomponent handling and call MNA methods through the parent (#141) + +### Fixed + +- Configurable linear solver (#199), addressing further pull request comments and processing default configuration options. +- Fix EMT_Ph1_Inductor initialization (#134), using Modelica results for validation and adding current validation in example VS_RL1. +- fix hugo website deployment (#158) +- Fix missing 'this' in logger macros (#217) +- Fix network frequency modulations and vsi snubber comps (#218), fixing some logging issues and trafo instantiation in dp and sp vsi for proper snubber comps. +- Fix various issues related to attributes (#140), addressing SonarCloud code smells and moving method implementations into source files. +- Introduce common base class MNASimPowerComp (#178), fixing merge errors and addressing SonarCloud issues. +- Profiling based optimisation (#194), addressing pull request comments and applying switched component stamps. +- Resolve FIXME comments (#142), addressing SonarCloud issues and renaming mMechPower attribute. + +### Maintenance + +- Build and push RockyLinux image (#148) +- Cleanup of CMake and Docker files (#168), adding missing libcimpp dependency for cimviz and comment explaining CMAKE_POLICY_DEFAULT_CMP0077. +- Deploy docs to FEIN website (#160), fixing repo url and subdir. +- fix and update documentation (#165), updating Contribution Guidelines and Roadmap. +- Fix implementation of exciter, new turbine governor model and refactor VBR models (#120), applying minor fixes and replacing validation notebook of reduced order SG models. +- Move documentation to main repo (#154), adding hugo website files and moving content from dpsim-docs repo. +- Reduced-order syngen models (#213), removing unused variable in MNASolverDirect and unused methods/variables of MNASyncGenInterface. +- Refactoring of direct linear solvers in MNA solver (#171), addressing further pull request comments and adding fetching of minimized suitesparse. +- Update and expand documentation (#159), adding documentation on MNASimPowerComp and subcomponent handling. + +## [v1.1.0] - 2022-12-09 + +### Added + +- Add a basic VS Code devcontainer configuration +- add cppcheck for use in github actions, updating Dockerfile and install shell scripts and adding docker-compose for dpsim-mqtt examples. +- Add cps files to dpsim repo +- add deployment to gitlab pages +- add missing file headers, updating copyright year to 2021. +- Add new working mqtt example +- add notebook checking powerflow of ieee lv, adding notebook checking powerflow for cigre mv. +- add pillow dependencies to centos dockerfile +- add powerflow cim example +- add villas import example, using PQ attributes in SP load. +- add vsi model and examples +- allow vd, pv and pq comp at the same bus, setting bus type to vd, updating submodule grid-data and updating syngen model in sp1ph. +- avoid deadlock, adding log prefix and console logger for simulation and shmem interface. +- docker: add entry page to docker image, copying examples into image and starting Jupyter Lab by default. +- made all power components set parametersSet flag, adding setParameters flag and function with new constructor. +- python: add missing Compontents (closes #118) +- require only cmake 3.11 and make policies requiring a newer version optional +- shmem: update Python examples, allowing exporting of attributes with name & unit. +- sphinx: add sections in reference +- update cps, only declaring node templates in cpp for win and adding description type to setup.py. +- update steady state init and add logging + +### Changed + +- cmake dependent opt causes problem with cim +- cmake: use cmake_dependent_option() to avoid caching issues +- Create vnodes in pcomps instead of MNA solver and differentiate between 1ph and 3ph for the simNode assignment. +- flush spdlog after sim initialization, switching case for python log level and adding function to get current voltage. +- force gcc 11 in manylinux image +- initialize frequencies in SystemTopology +- Merge branch 'development' into 'master' +- Merge branch 'master' into multisampling, updating notebooks and gitignore. +- Merge branch 'patch-1' into 'master' +- Merge pull request #60 from JTS22/python-spdlog +- MNASolver: Increase maximum switch number to theoretical limit +- move libcps to models +- notebooks: clear results +- run autodoc on python submodules +- run page deploy on dedicated branch +- silence experimental fs visual studio warning +- started working on developer documentation +- Trigger PyPi-Workflow for tags (#151) +- update 9bus parallel notebook +- update cps, updating shmem distributed direct nb and shmem direct examples. +- update CPS +- update file headers and replace gpl with mpl in most files +- update inverter nbs +- update shmem example of cigre mv +- update submodules path, updating dpsim results path in notebooks. + +### Fixed + +- add sst model and fix powerflow +- append .git to all module urls, fixing path to cim grid data and updating README. +- examples: fix notebook bin path, considering load "P" attribute in PF during simulation. +- fix brief class descriptions of reduced-order vbr models, fixing sp shift and adding grid voltage evaluations in validation notebooks, fixing cmd options after rebase. +- fix cim path for shmem example of cigre mv +- fix cmake policy warning +- fix dp ph3 voltagesource stamp +- Fix dpsim-villas version tag, using new villas version. +- fix GPLv3 logo (closes #125) +- fix load profile generation for different time steps in cigre shmem example, fixing cim files path and extending CLI options. +- fix minimal dockerfile +- fix powerflow with load profiles and use csvreader instead of loadprofilereader +- fix rxload initialization +- fix sourcevec writing and update villas-dataprocessing +- fixing mechanical torque as attribute after rebasing, adding logging of indices of varying matrix entries for reduced order VBR models in DP and EMT and adding smib reduced order load step examples. +- Merge branch 'debug-msp-example', updating cps and adding notebook with CS RL1 circuit. +- merge master, updating cps and using cmake_dependent_option() to avoid caching issues. +- MNASolverFactory.h: Only use Plugin Solver if activated, adding *.so to .gitignore and making MNASolverPlugin optional and deactivated on windows. +- python: fix invalid return value for Node::setInitialVoltage() +- spdlog macros, fix simNode assignment of vnodes, set links to master branch +- switch shared library off to fix dpsim_python, updating editorconfig and adding numpy cmake option again. +- update cps, ignoring attributes if index is larger than length and updating 9bus ctrl shmem example. +- update cps, fixing error in WSCC 9bus notebook and fixing feature notebooks. +- update readme, fixing shm python example and adding removed FindSphinx cmake file. +- update tlm comparison notebook, adding correct phase shift to transmission line and adding emt decoupling wave line model. +- use correct attribute dependency, making the phase changeable through mVoltageRef and using member variables for attribute access. +- use image for devcontainer, setting manual trigger for container workflow and fixing devcontainer.json. +- use initialization list for mZigZag, adding comments on voltage source behaviour and removing constructor for removing the SignalGenerator. + +### Removed + +- harmonize namespace aliases of std::filesystem, removing useless printing of working directory in examples. +- rename Terminal, renaming TopologicalComponent and Node class. + +### Maintenance + +- add comments, adding another export to Simulation::sync and increasing timeout to allow dpsim to catch all mqtt messages. +- add link to build notebooks +- disable cim and render if deps not available, removing obsolete cim reader includes and working around github permission issue. +- disable macos build +- enable tests for pull requests, updating sonar settings and adding sonar cache and multithreading. +- examples: reduce sim time because of CI duration, fixing find pybind python in cmake. +- fix .gitlab-ci.yml to include correct path to rocky Dockerfile, fixing docker labels and removing duplicate needs statement. +- fix build badge +- fix doc gh-pages deployment +- fix emt ode syngen model, using systemtopolgy initFromPowerflow in examples and setting initFromNodes for MNA solver. +- fix file paths in notebook, updating notebook to use the new attribute system and exposing the entire attribute system to python. +- fix gitlab ci using old docker syntax (#147) +- Fix PyPi-Upload CI workflow (#149), finding Python3 instead of Python and updating container workflow actions. +- fix set pattern in scheduler, setting log pattern in scheduler and merging master. +- fix submodule build: throwing only warning when git version unavailable +- include Magma in Dockerfile, cleaning up gitlab-ci.yml, fixing GPUMagma inverse permutation bug and adding Magma based MNASolver. +- keep governor and exciter params separate from machine params, adding governor and exciter test examples for 9th order syngens and fixing exciter of dcim syngen. +- merge 1ph-refactoring, updating cps and fixing cpp 9 bus nb. +- Merge branch 'test-villas' into 'master', updating repo link in build docs and shmem example nb. +- Merge pull request #39 from stv0g/ci-minimal-build +- Merge pull request #46 from stv0g/ci-minimal-build +- minor tweaks to gitlab-ci +- move imports into cpp files, removing binary dir include for dpsimpy and clarifying Cpp version change. +- output dpsimpyvillas into top-level build directory, exporting complex attributes instead of matrices and moving old examples into villas-deprecated folder. +- pybind: remove superfluous includes, removing unused VILLAS_VERSION variable from docker and allowing building examples without CIM support. +- re-enable notebook test, re-enabling example and adding missing test examples. +- reactivate continue_on_error parameter, adapting cigre mqtt example to run in pipeline and adding test for dpsim-mqtt-cigre example. +- refactor to store cli options as string +- remove cmake copy image, updating grid-data and examples with new grid data path. +- remove debug info from workflow, removing redundant jobs from gitlab and cleaning up dockerfiles. +- remove obsolete gitlab CI jobs, generating sphinx docs for new python interface. +- Revert :Fix compilation without libcimpp and minor tweaks to CMake code-style +- skip tests for old notebooks, adapting quickstart guide to dpsimpy and triggering actions on push to any branch. +- update ci, restructuring sphinx doxygen docs and removing notebook related sphinx cmake. +- update cps, merging master and restructuring notebooks. +- update docs url +- update global scope of SynGenTrStab examples, adding Events category to examples and splitting examples in two categories: components & grids. +- update install script and new dockerfile, updating docker dev and using libxml instead of libexpat in cimpp. +- update shmem examples, using new cpp export methods in python interface and adding jupyter requirements file to docker fs. +- updated installation instructions, showing cmake invocation during setup.py and allowing setting CMake options via envvar. +- use correct minimum cmake version (3.13 instead of 3.12) because Policy CMP0076 requires 3.13, using different cache key for build with and without cuda and making CI build with CUDA support with CUDA dependencies in Dockerfile.dev. +- Use read-the-docs sphinx theme +- use updated dpsim-villas and villas-node versions, removing pipeline build caches and updating fedora and pybind versions. + +## [v1.0.0] - 2019-04-15 + +### Fixed + +- Continued to fix odeint example problem, adding example program for odeint based on DP_SynGen_dq_ThreePhFault of Arkode and first implementation of odeint solver class. +- Fixed initial value setting of odeint solver + +### Maintenance + +- adaptations for DQ SynGen class split, merging branch 'development' into parallel and updating cps submodule. +- fixes for clang, adding parallel multimachine benchmark and fixing memleak in ODESolver. +- ifdef for sim_ode, updating .gitmodules and cps. +- include nbs in docs +- Merge branch 'dae-solver-test' into 'development', adding documentation on real-time execution of DPsim (closes #108) and merging development into dae-solver-test. +- Merge branch 'gen-arkode' into 'development', updating Simulation.cpp and DataLogger.cpp. +- merge powerflow, applying minor logging fix in cigre mv powerflow test and writing config of data sent via villas. +- update cps, merging branch 'development' into powerflow-integration and updating dockerfile.dev. + +## [v0.1.6] - 2018-11-04 + +## [v0.1.5] - 2018-11-03 + +### Added + +- add missing _dpsim module to binary Python packages +- cmake: only integrate interface code if the platform supports it, adding more parameters to DPsim::RealTimeSimulation::run() and moving timer creation into {create,destroy}Timer(). +- docker: enable jupyter widgets +- python: add missing invocation of loggers to python simulation loop, adding proper reference counting for logged Components/Nodes. +- python: add missing progressbar package as dependency, pausing and resuming simulation asynchronously and adding more async events. +- update CPS submodule, providing synchronization settings per interface and making start script executable. +- updated cmake files for cimpp, including cimpp submodule in make files and adding libcimpp as submodule. +- updating cps, updating freq and load step example and removing NZ publication example. +- updating emt example, merging branch 'development' into msv-pra and updating examples. + +### Changed + +- flush data logs on simulation end, updating notebooks and raising error when dpsim.Simulation.run() is used with an already running event loop. +- Install expat dependency and execute setup +- Merge branch 'redesign_cimreader' into 'development' +- merge updated circuit examples, updating examples. +- python: do not fail load _dpsim.Interface (closes #93), reverting "comment out interface python class". +- python: separate EventChannel in header/source +- updated copyright year in C++ example + +### Fixed + +- Adapted DAEsolver to new node/component structure and removed IDA dependency of Simulation file, making Residual function static and integrating DAE into Solver structure. +- docker: add Dockerfile for building a ready-to-run version of DPsim, fixing RPM dependencies and building RPM packages. +- docker: use fedora 29, fixing compilation without VILLASnode in python. +- fix DPsim logo in README.md +- fixing namespaces in simulation.cpp, updating CPS submodule for fixing linking errors and moving Python bindings for components to CPS. +- last buf fixes before merging, improving usage infos for command line args and adding missing header file. +- Merge branch 'development', changing shmem ids and increasing simulation time in wscc. +- python: fix logging of node voltages (closes #97) +- update CPS submodule, fixing attribute names in examples and python tests. + +### Maintenance + +- fix windows build +- fixing CIM test yml, xfail for larger CIM example and removing TopologicalIsland from examples. +- Fixing parallel support of node indices and CIM, removing deprecated line load test and fixing network description without node objects. +- fixing segfault in mna solver when getting nodes, adding new examples and updating cps. +- Merge branch 'development', merging generator examples and updating cps. +- merge changes into development, updating .gitlab-ci.yml and deactivating windows build until we have a runner again. +- merging changes in mna solver, using new DataLogger and making MNASolver not rely on CIM::Reader. +- merging changes into development, merging branch 'refactor-move-cps' into 'development' and not crashing if there are no CIM tests. +- merging new commits from development and node-terminal update, updating CPowerSystems submodule and refactoring Add{Excitor,Goveronor} -> add{Excitor,Goveronor}. +- python: add some documentation to factory functions, fixing unit tests and changing NULL -> nullptr. +- shmem: libvillas-ext has been obsoleted by libvillas, simplifying dpsim.Simulation.run() and fixing error messages in CPS::Python::Component:getattro(). +- tests: renamed python script in order to be selected by pytest, updating Python version of ShmemDistributedDirect test and refactoring examples for new lambda interface. +- Update Build.rst +- updating libcps, merging attribute test and merging redesign-simulation into development. + +## [v0.1.3] - 2018-02-21 + +### Changed + +- Update CMakeLists.txt + +### Fixed + +- fixed mistakes after merging, using SynGenSimulation for VBR simulation and integrating new DP VBR model with nodal analysis. +- Merge branch 'fix-transformer' into development merge, fixing CIM reader and example and applying minor changes in logging. + +### Maintenance + +- examples: disable another failing CIM test, disabling broken IEEE-9-bus CIM test and refactoring mSeq -> mSequence. +- refactor: DPsim::Components::Base -> DPsim::Component (closes #44), renaming "EMT_VoltageSourceNorton.{h, cpp}" to "EMT_VoltageSource_Norton.{h,cpp}" (see #43). +- version bump, fixing url and image links in readme. + +## [v0.1.1] - 2018-01-12 + +### Added + +- added missing license and copyright headers (closes #23) +- TurbineGovernor: Added init function to initialize governor variables +- Update DP_ResVS_RXLine1.cpp, merging branch 'development' into 'shared-factory' and applying smaller cleanups. + +### Changed + +- do not use shared_ptrs for simulation Loggers + +### Maintenance + +- examples: fix hardcoded path (this is still ugly), installing libraries to correct location on Fedora and adding setup.py for installing / packaging with setuptools. +- fixed test builds +- Merge branch 'python-log' into 'development', fixing Python CI test and python ctor of Simulation class. +- refactor: rename namespace "DPsim::Component" -> "DPsim::Components", removing default constructor from components and naming base class files "Base_*.h". +- simulation: remove obsolete Generator test classes, simplifying expression and fixing real time simulation support in python. +- Update .gitlab-ci.yml +- Update FaultSimulation.cpp, updating Simulation.cpp and merging branch 'development' into 'refactor-component-element-naming'. +- updated logdataline, fixing capitalization of filenames and excluding certain parts from Doxygen as they break Breathe. + +## [v0.1.0] - 2017-12-26 + +### Added + +- changed newNode to node3, adding comments to header files of capacitor, ideal voltage source, inductor, inductor2 and voltSourceRes and adding documentation for ideal and real voltage source. +- created new components classes +- loglevel filter, updating study scripts and adding svg figures. +- Merge branch 'dev-vsa' into 'master', adding figures for synchronous machine and synchronous generator figure. +- Merge branch 'dev-vsa' into 'master', changing capacitor and inductor in simulation models and updating figure of inductor model. +- merge dev-mmi into master, documenting EMT DP comparison and first version of comparison between EMT and DP. +- moved Simulink models to other repo, adding folder DPsimReferenceExamples and deleting folder SimulinkExamples. +- Update LICENSE, adding license. +- VBR DP, merging branch 'development' and adding logo. + +### Changed + +- DP VBR working +- Merge branch 'development', merging master into dev-mmi merge and updating matlab scripts. +- Merge branch 'master' of git.rwth-aachen.de:PowerSystemSimulation/DPsim merge +- Update README.md +- VBR euler, adding matlab script to compare plecs with c++ results for synchronous generator and only compiling shmem/RT parts on Linux. +- VBR model - simulation of steady state + +### Fixed + +- added GPLv3 headers to source files (closes #9), moving Source/Examples to Examples/ and treating unused variables as errors in Clang. +- Created Ideal Voltage Source EMT and fixed "virtual node", simplifying models with operational and fundamental parameters. +- fix compiler warnings (closes #15), creating simplified model of synchronous machine and making all generator models use SynchGenBase. +- implemented exciter and turbine to VBR DP model, fixing mistake in fault clearing function and adding Turbine Governor model. + +### Maintenance + +- Added omega_base to the equations of trapezoidal rule and implemented trapezoidal rule with current as state variable, implementing trapezoidal rule with flux as state for EMT and correcting mistake in equation of ifd. +- adjust CMakeLists.txt, merging branch 'development' and merging branch 'cim-xml' into development. +- Created voltage behind reactance model - in construction, adding trapezoidal rule to DP synchronous generator and merging branch 'rt-exceptions' into development. +- deleted vs project files, cmake works now in vs, adding vs folder to gitignore and deleting vs installation md file, updating build.rst. +- Merge branch 'dev-vsa' into 'master', updating LinearResistor.cpp and BaseComponent.h. +- pass matrices via reference to silence compiler errors, adding Dockerfile and GitLab CI configuration and searching in standard location for Eigen. From 665ac608a0ace5463bf2bcf9534a4a505d1f42f9 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Tue, 25 Nov 2025 15:28:06 +0100 Subject: [PATCH 138/168] Remove section maintenance, reassign the tasks to the sections in keepchangelog Signed-off-by: Leonardo Carreras --- CHANGELOG.md | 157 ++++++++++++++++++++++++--------------------------- 1 file changed, 74 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 040e3d2ea4..2102ab515e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Implement decoupling line emt ph3 (#422), improving nine bus decoupling example with 3ph decoupling line and adding test for decoupling line Ph3 to Line.ipynb example. - VILLASfpga cosimulation development (#325), adding n-eiling as codeowner of /dpsim-villas and fixing MNASolver to start loggers for vectors. - Villas Interface: Improve FpgaExample (#299), allowing different topologies to be tested and updating VILLAS_VERSION in Dockerfile. +- Nix packaging (#357), adding GitHub CI workflow for building DPsim with Nix and Nix packaging. +- chore: update docs on real-time and VILLASnode interfaces (#335) ### Changed @@ -42,12 +44,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Change default linear solver to KLU (#250), fixing logging statements by using macros and removing explicit choice of SparseLU from cxx examples. - Update WSCC_9bus_mult examples and implement splitting examples in DP and EMT (#322), removing SP_Ph1_CurrentSource component and fixing path to CIM files in decoupling line diakoptics example. - Upgrade Fedora dockerfiles to v42 (#387), fixing KLU Adapter varying entry index check and adding libre to Dockerfile to fix one of the real-time errors using villas. +- Add new action using the build wrapper from sonar directly (#296) +- Allow builds without nlohmann/json library (#362) +- feat(ci): Use trusted / OIDC publishing to PyPi.org (#375), only attempting upload to PyPi for pushes to master or tags. + +### Removed + +- Remove commented out code (#390) +- Remove further RWTH gitlab dependencies (#261) +- Remove Python versions 3.6 and 3.7 for PyPi upload (#229) +- Disable test actions for PRs (#237) +- chore(cmake): Remove deprecated options (#342) +- Remove outdated and broken GitLab CI pipeline (#347) ### Fixed - 5th Order Synchronous Generator (#230), fixing some minor details and adding SG5Order to CIM Reader in DP and EMT domain. - Adding correct logger usage (#411) -- Allow builds without nlohmann/json library (#362) - dpsim-villas: fix hardcoded paths (#327) - Enable compilation in gcc 14 and clang 18 (code fixes) (#294) - feat(cmake): Allow disable LTO builds (#341), adding WITH_MARCH_NATIVE option to enable native host arch builds. @@ -76,26 +89,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Revision of power flow solver (#284), fixing PFSolver and minimizing file changes. - Trigger actions for PRs and pin the version of libcimpp (#329), pinning libcimpp version in containers and cmake and triggering relevant workflows on pull_request event. - Update actions in workflow and improve parallelisation and cache handling (#298), changing the profiling execution to manually triggered and enabling parallelisation with reorganized cache. - -### Removed - -- Remove commented out code (#390) -- Remove further RWTH gitlab dependencies (#261) -- Remove Python versions 3.6 and 3.7 for PyPi upload (#229) - -### Maintenance - -- Add new action using the build wrapper from sonar directly (#296) - Bump braces from 3.0.2 to 3.0.3 in /docs/hugo (#304) - Bump postcss from 8.4.20 to 8.4.31 in /docs/hugo (#281) - Bump version of black & black jupyter to 25.11.0 (#421) - Bump yaml from 2.1.3 to 2.2.2 in /docs/hugo (#215) -- chore (deps): update to CIMpp rpm/deb install + bump VILLAS (#404), updating cmake fetch and finding of libcimpp and fixing dependent files and CIMReader. -- chore(cmake): Remove deprecated options (#342) -- chore(deps): Bump pypa/gh-action-pypi-publish from 1.12.4 to 1.13.0 in /.github/workflows (#405) -- chore: update docs on real-time and VILLASnode interfaces (#335) -- Disable test actions for PRs (#237) -- feat(ci): Use trusted / OIDC publishing to PyPi.org (#375), only attempting upload to PyPi for pushes to master or tags. - fix clang compilation and FPGA integration (#293), fixing clang compiler errors and adding clang compilation to CI. - Fix CMake typos and style (#376) - Fix GitHub actions workflow for publishing to PyPi (#355), building with newer CMake versions and simplifying triggers for workflows. @@ -110,12 +107,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - fix(docs): Fix typo and wrong diff (#337) - fix(examples): Only build Fpga9BusHil example if build with CIMpp (#338), applying it twice. - fix(style): Remove duplicated typedef (#339) -- fix: Cleanup code-style of setup.py (#336) -- Nix packaging (#357), adding GitHub CI workflow for building DPsim with Nix and Nix packaging. - python: Harmonize comment style (#349) -- Remove outdated and broken GitLab CI pipeline (#347) +- chore(deps): Bump pypa/gh-action-pypi-publish from 1.12.4 to 1.13.0 in /.github/workflows (#405) - Update villas version (#245), updating python command to python3 in test-villas-examples actions and removing libwebsockets installation from source. - Use clang-format to format the whole codebase (#278), fixing missing includes and moving development scripts from configs/ to scripts./ +- chore (deps): update to CIMpp rpm/deb install + bump VILLAS (#404), updating cmake fetch and finding of libcimpp and fixing dependent files and CIMReader. +- fix: Cleanup code-style of setup.py (#336) ## [v1.1.1] - 2023-07-13 @@ -123,10 +120,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Add latest publications to website (#161) - Introduce a common subclass for composite components (#177), adding comments for empty method implementations and renaming systemMatrixStamp methods for sparse matrices. +- Build and push RockyLinux image (#148) +- Update and expand documentation (#159), adding documentation on MNASimPowerComp and subcomponent handling. +- Introduce common base class MNASimPowerComp (#178), fixing merge errors and addressing SonarCloud issues. ### Changed - Unify subcomponent handling and call MNA methods through the parent (#141) +- Move documentation to main repo (#154), adding hugo website files and moving content from dpsim-docs repo. +- Refactoring of direct linear solvers in MNA solver (#171), addressing further pull request comments and adding fetching of minimized suitesparse. ### Fixed @@ -136,21 +138,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Fix missing 'this' in logger macros (#217) - Fix network frequency modulations and vsi snubber comps (#218), fixing some logging issues and trafo instantiation in dp and sp vsi for proper snubber comps. - Fix various issues related to attributes (#140), addressing SonarCloud code smells and moving method implementations into source files. -- Introduce common base class MNASimPowerComp (#178), fixing merge errors and addressing SonarCloud issues. - Profiling based optimisation (#194), addressing pull request comments and applying switched component stamps. - Resolve FIXME comments (#142), addressing SonarCloud issues and renaming mMechPower attribute. - -### Maintenance - -- Build and push RockyLinux image (#148) - Cleanup of CMake and Docker files (#168), adding missing libcimpp dependency for cimviz and comment explaining CMAKE_POLICY_DEFAULT_CMP0077. - Deploy docs to FEIN website (#160), fixing repo url and subdir. - fix and update documentation (#165), updating Contribution Guidelines and Roadmap. - Fix implementation of exciter, new turbine governor model and refactor VBR models (#120), applying minor fixes and replacing validation notebook of reduced order SG models. -- Move documentation to main repo (#154), adding hugo website files and moving content from dpsim-docs repo. - Reduced-order syngen models (#213), removing unused variable in MNASolverDirect and unused methods/variables of MNASyncGenInterface. -- Refactoring of direct linear solvers in MNA solver (#171), addressing further pull request comments and adding fetching of minimized suitesparse. -- Update and expand documentation (#159), adding documentation on MNASimPowerComp and subcomponent handling. ## [v1.1.0] - 2022-12-09 @@ -200,11 +194,30 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Trigger PyPi-Workflow for tags (#151) - update 9bus parallel notebook - update cps, updating shmem distributed direct nb and shmem direct examples. -- update CPS - update file headers and replace gpl with mpl in most files -- update inverter nbs +- update inverter notebooks - update shmem example of cigre mv - update submodules path, updating dpsim results path in notebooks. +- rename Terminal, renaming TopologicalComponent and Node class. +- disable cim and render if deps not available, removing obsolete cim reader includes and working around github permission issue. +- update ci, restructuring sphinx doxygen docs and removing notebook related sphinx cmake. +- update cps, merging master and restructuring notebooks. +- update docs url +- update global scope of SynGenTrStab examples, adding Events category to examples and splitting examples in two categories: components & grids. +- update install script and new dockerfile, updating docker dev and using libxml instead of libexpat in cimpp. +- update shmem examples, using new cpp export methods in python interface and adding jupyter requirements file to docker fs. +- updated installation instructions, showing cmake invocation during setup.py and allowing setting CMake options via envvar. +- use correct minimum cmake version (3.13 instead of 3.12) because Policy CMP0076 requires 3.13, using different cache key for build with and without cuda and making CI build with CUDA support with CUDA dependencies in Dockerfile.dev. +- use updated dpsim-villas and villas-node versions, removing pipeline build caches and updating fedora and pybind versions. + +### Deprecated + +- moving old examples into villas-deprecated folder. + +### Removed + +- disable macos build +- harmonize namespace aliases of std::filesystem, removing useless printing of working directory in examples. ### Fixed @@ -236,18 +249,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - use correct attribute dependency, making the phase changeable through mVoltageRef and using member variables for attribute access. - use image for devcontainer, setting manual trigger for container workflow and fixing devcontainer.json. - use initialization list for mZigZag, adding comments on voltage source behaviour and removing constructor for removing the SignalGenerator. - -### Removed - -- harmonize namespace aliases of std::filesystem, removing useless printing of working directory in examples. -- rename Terminal, renaming TopologicalComponent and Node class. - -### Maintenance - - add comments, adding another export to Simulation::sync and increasing timeout to allow dpsim to catch all mqtt messages. - add link to build notebooks -- disable cim and render if deps not available, removing obsolete cim reader includes and working around github permission issue. -- disable macos build - enable tests for pull requests, updating sonar settings and adding sonar cache and multithreading. - examples: reduce sim time because of CI duration, fixing find pybind python in cmake. - fix .gitlab-ci.yml to include correct path to rocky Dockerfile, fixing docker labels and removing duplicate needs statement. @@ -267,7 +270,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Merge pull request #46 from stv0g/ci-minimal-build - minor tweaks to gitlab-ci - move imports into cpp files, removing binary dir include for dpsimpy and clarifying Cpp version change. -- output dpsimpyvillas into top-level build directory, exporting complex attributes instead of matrices and moving old examples into villas-deprecated folder. +- output dpsimpyvillas into top-level build directory, exporting complex attributes instead of matrices - pybind: remove superfluous includes, removing unused VILLAS_VERSION variable from docker and allowing building examples without CIM support. - re-enable notebook test, re-enabling example and adding missing test examples. - reactivate continue_on_error parameter, adapting cigre mqtt example to run in pipeline and adding test for dpsim-mqtt-cigre example. @@ -277,32 +280,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - remove obsolete gitlab CI jobs, generating sphinx docs for new python interface. - Revert :Fix compilation without libcimpp and minor tweaks to CMake code-style - skip tests for old notebooks, adapting quickstart guide to dpsimpy and triggering actions on push to any branch. -- update ci, restructuring sphinx doxygen docs and removing notebook related sphinx cmake. -- update cps, merging master and restructuring notebooks. -- update docs url -- update global scope of SynGenTrStab examples, adding Events category to examples and splitting examples in two categories: components & grids. -- update install script and new dockerfile, updating docker dev and using libxml instead of libexpat in cimpp. -- update shmem examples, using new cpp export methods in python interface and adding jupyter requirements file to docker fs. -- updated installation instructions, showing cmake invocation during setup.py and allowing setting CMake options via envvar. -- use correct minimum cmake version (3.13 instead of 3.12) because Policy CMP0076 requires 3.13, using different cache key for build with and without cuda and making CI build with CUDA support with CUDA dependencies in Dockerfile.dev. - Use read-the-docs sphinx theme -- use updated dpsim-villas and villas-node versions, removing pipeline build caches and updating fedora and pybind versions. ## [v1.0.0] - 2019-04-15 +### Changed + +- Merge branch 'dae-solver-test' into 'development', adding documentation on real-time execution of DPsim (closes #108) and merging development into dae-solver-test. +- Merge branch 'gen-arkode' into 'development', updating Simulation.cpp and DataLogger.cpp. + ### Fixed - Continued to fix odeint example problem, adding example program for odeint based on DP_SynGen_dq_ThreePhFault of Arkode and first implementation of odeint solver class. - Fixed initial value setting of odeint solver - -### Maintenance - - adaptations for DQ SynGen class split, merging branch 'development' into parallel and updating cps submodule. - fixes for clang, adding parallel multimachine benchmark and fixing memleak in ODESolver. - ifdef for sim_ode, updating .gitmodules and cps. - include nbs in docs -- Merge branch 'dae-solver-test' into 'development', adding documentation on real-time execution of DPsim (closes #108) and merging development into dae-solver-test. -- Merge branch 'gen-arkode' into 'development', updating Simulation.cpp and DataLogger.cpp. - merge powerflow, applying minor logging fix in cigre mv powerflow test and writing config of data sent via villas. - update cps, merging branch 'development' into powerflow-integration and updating dockerfile.dev. @@ -331,6 +325,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - python: do not fail load _dpsim.Interface (closes #93), reverting "comment out interface python class". - python: separate EventChannel in header/source - updated copyright year in C++ example +- merge changes into development, updating .gitlab-ci.yml and deactivating windows build until we have a runner again. +- merging changes in mna solver, using new DataLogger and making MNASolver not rely on CIM::Reader. +- merging changes into development, merging branch 'refactor-move-cps' into 'development' and not crashing if there are no CIM tests. +- merging new commits from development and node-terminal update, updating CPowerSystems submodule and refactoring Add{Excitor,Goveronor} -> add{Excitor,Goveronor}. +- Update Build.rst +- updating libcps, merging attribute test and merging redesign-simulation into development. +- shmem: libvillas-ext has been obsoleted by libvillas, simplifying dpsim.Simulation.run() and fixing error messages in CPS::Python::Component:getattro(). ### Fixed @@ -343,39 +344,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Merge branch 'development', changing shmem ids and increasing simulation time in wscc. - python: fix logging of node voltages (closes #97) - update CPS submodule, fixing attribute names in examples and python tests. - -### Maintenance - - fix windows build - fixing CIM test yml, xfail for larger CIM example and removing TopologicalIsland from examples. - Fixing parallel support of node indices and CIM, removing deprecated line load test and fixing network description without node objects. - fixing segfault in mna solver when getting nodes, adding new examples and updating cps. - Merge branch 'development', merging generator examples and updating cps. -- merge changes into development, updating .gitlab-ci.yml and deactivating windows build until we have a runner again. -- merging changes in mna solver, using new DataLogger and making MNASolver not rely on CIM::Reader. -- merging changes into development, merging branch 'refactor-move-cps' into 'development' and not crashing if there are no CIM tests. -- merging new commits from development and node-terminal update, updating CPowerSystems submodule and refactoring Add{Excitor,Goveronor} -> add{Excitor,Goveronor}. - python: add some documentation to factory functions, fixing unit tests and changing NULL -> nullptr. -- shmem: libvillas-ext has been obsoleted by libvillas, simplifying dpsim.Simulation.run() and fixing error messages in CPS::Python::Component:getattro(). - tests: renamed python script in order to be selected by pytest, updating Python version of ShmemDistributedDirect test and refactoring examples for new lambda interface. -- Update Build.rst -- updating libcps, merging attribute test and merging redesign-simulation into development. ## [v0.1.3] - 2018-02-21 ### Changed - Update CMakeLists.txt +- refactor: DPsim::Components::Base -> DPsim::Component (closes #44), renaming "EMT_VoltageSourceNorton.{h, cpp}" to "EMT_VoltageSource_Norton.{h,cpp}" (see #43). ### Fixed - fixed mistakes after merging, using SynGenSimulation for VBR simulation and integrating new DP VBR model with nodal analysis. - Merge branch 'fix-transformer' into development merge, fixing CIM reader and example and applying minor changes in logging. - -### Maintenance - - examples: disable another failing CIM test, disabling broken IEEE-9-bus CIM test and refactoring mSeq -> mSequence. -- refactor: DPsim::Components::Base -> DPsim::Component (closes #44), renaming "EMT_VoltageSourceNorton.{h, cpp}" to "EMT_VoltageSource_Norton.{h,cpp}" (see #43). - version bump, fixing url and image links in readme. ## [v0.1.1] - 2018-01-12 @@ -389,17 +377,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) ### Changed - do not use shared_ptrs for simulation Loggers +- Update .gitlab-ci.yml +- Update FaultSimulation.cpp, updating Simulation.cpp and merging branch 'development' into 'refactor-component-element-naming'. +- updated logdataline, fixing capitalization of filenames and excluding certain parts from Doxygen as they break Breathe. -### Maintenance +### Removed + +- refactor: rename namespace "DPsim::Component" -> "DPsim::Components", removing default constructor from components and naming base class files "Base_*.h". +- simulation: remove obsolete Generator test classes, simplifying expression and fixing real time simulation support in python. + +### Fixed - examples: fix hardcoded path (this is still ugly), installing libraries to correct location on Fedora and adding setup.py for installing / packaging with setuptools. - fixed test builds - Merge branch 'python-log' into 'development', fixing Python CI test and python ctor of Simulation class. -- refactor: rename namespace "DPsim::Component" -> "DPsim::Components", removing default constructor from components and naming base class files "Base_*.h". -- simulation: remove obsolete Generator test classes, simplifying expression and fixing real time simulation support in python. -- Update .gitlab-ci.yml -- Update FaultSimulation.cpp, updating Simulation.cpp and merging branch 'development' into 'refactor-component-element-naming'. -- updated logdataline, fixing capitalization of filenames and excluding certain parts from Doxygen as they break Breathe. ## [v0.1.0] - 2017-12-26 @@ -414,6 +405,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - moved Simulink models to other repo, adding folder DPsimReferenceExamples and deleting folder SimulinkExamples. - Update LICENSE, adding license. - VBR DP, merging branch 'development' and adding logo. +- Added omega_base to the equations of trapezoidal rule and implemented trapezoidal rule with current as state variable, implementing trapezoidal rule with flux as state for EMT and correcting mistake in equation of ifd. +- Created voltage behind reactance model - in construction, adding trapezoidal rule to DP synchronous generator and merging branch 'rt-exceptions' into development. ### Changed @@ -423,6 +416,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Update README.md - VBR euler, adding matlab script to compare plecs with c++ results for synchronous generator and only compiling shmem/RT parts on Linux. - VBR model - simulation of steady state +- adjust CMakeLists.txt, merging branch 'development' and merging branch 'cim-xml' into development. +- Merge branch 'dev-vsa' into 'master', updating LinearResistor.cpp and BaseComponent.h. + +### Removed + +- deleted vs project files, cmake works now in vs, adding vs folder to gitignore and deleting vs installation md file, updating build.rst. ### Fixed @@ -430,12 +429,4 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Created Ideal Voltage Source EMT and fixed "virtual node", simplifying models with operational and fundamental parameters. - fix compiler warnings (closes #15), creating simplified model of synchronous machine and making all generator models use SynchGenBase. - implemented exciter and turbine to VBR DP model, fixing mistake in fault clearing function and adding Turbine Governor model. - -### Maintenance - -- Added omega_base to the equations of trapezoidal rule and implemented trapezoidal rule with current as state variable, implementing trapezoidal rule with flux as state for EMT and correcting mistake in equation of ifd. -- adjust CMakeLists.txt, merging branch 'development' and merging branch 'cim-xml' into development. -- Created voltage behind reactance model - in construction, adding trapezoidal rule to DP synchronous generator and merging branch 'rt-exceptions' into development. -- deleted vs project files, cmake works now in vs, adding vs folder to gitignore and deleting vs installation md file, updating build.rst. -- Merge branch 'dev-vsa' into 'master', updating LinearResistor.cpp and BaseComponent.h. - pass matrices via reference to silence compiler errors, adding Dockerfile and GitLab CI configuration and searching in standard location for Eigen. From 093c23da20aab10103406cc967f5c36abac2d13b Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 27 Nov 2025 15:14:49 +0100 Subject: [PATCH 139/168] Fix compilation issue when using dpsimpy on binder and a container that has villas Signed-off-by: Leonardo Carreras --- .binder/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.binder/Dockerfile b/.binder/Dockerfile index f3e6f600d4..e9003e2173 100644 --- a/.binder/Dockerfile +++ b/.binder/Dockerfile @@ -19,6 +19,8 @@ RUN adduser \ COPY . ${HOME}/dpsim ENV PATH="${HOME}/.local/bin:${PATH}" +# FIXME: Temporary disable VILLAS to keep old behavior using WITH_VILLAS +ENV CMAKE_OPTS="-DWITH_VILLAS=OFF" RUN python3 -m pip install notebook jupyterlab jupyterhub USER root RUN chown -R ${NB_UID} ${HOME} From 9d8007980506dce7ed41f4bcaa53c2f599225c45 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Thu, 4 Dec 2025 15:15:15 +0100 Subject: [PATCH 140/168] Fix workflow issue with sonar, bump to version v6 Signed-off-by: Leonardo Carreras --- .github/workflows/sonar_cloud.yaml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/sonar_cloud.yaml b/.github/workflows/sonar_cloud.yaml index 3976490cb4..97be653c1b 100644 --- a/.github/workflows/sonar_cloud.yaml +++ b/.github/workflows/sonar_cloud.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest container: sogno/dpsim:dev outputs: - skip: ${{ steps.check-token.outputs.skip }} # Output to indicate if the job was skipped + skip: ${{ steps.check_token.outputs.skip }} # Output to indicate if the job was skipped env: BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory steps: @@ -45,7 +45,7 @@ jobs: - name: Install sonar-scanner and build-wrapper if: steps.check_token.outputs.skip != 'true' - uses: sonarsource/sonarcloud-github-c-cpp@v2 + uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v6 - name: Create Build Folder if: steps.check_token.outputs.skip != 'true' @@ -81,8 +81,10 @@ jobs: - name: Run sonar-scanner if: steps.check_token.outputs.skip != 'true' + uses: SonarSource/sonarqube-scan-action@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} - run: | - sonar-scanner --define sonar.cfamily.compile-commands=${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json + with: + args: > + --define sonar.cfamily.compile-commands=${{ env.BUILD_WRAPPER_OUT_DIR }}/compile_commands.json From 9f882f056d85b3d6eff7a8726d2cb1f7eff0ced2 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Sun, 7 Dec 2025 23:54:28 +0100 Subject: [PATCH 141/168] Make dpsim to be linked to villas Signed-off-by: Leonardo Carreras --- dpsim/src/CMakeLists.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dpsim/src/CMakeLists.txt b/dpsim/src/CMakeLists.txt index e24e2b668d..fe1227f5f7 100644 --- a/dpsim/src/CMakeLists.txt +++ b/dpsim/src/CMakeLists.txt @@ -92,6 +92,17 @@ if(WITH_OPENMP) list(APPEND DPSIM_LIBRARIES ${OpenMP_CXX_FLAGS}) endif() +if(WITH_VILLAS) + list(APPEND DPSIM_LIBRARIES + ${VILLASNODE_LIBRARIES} + ${VILLASCOMMON_LIBRARIES} + pthread + ) + if(VILLASFPGA_LIBRARIES) + list(APPEND DPSIM_LIBRARIES ${VILLASFPGA_LIBRARIES}) + endif() +endif() + add_library(dpsim ${DPSIM_SOURCES}) target_link_libraries(dpsim PUBLIC ${DPSIM_LIBRARIES}) target_include_directories(dpsim PUBLIC ${DPSIM_INCLUDE_DIRS}) From ab40e7b51f6bf7a16b2a7faf14ec468e49adbcb6 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 00:39:38 +0100 Subject: [PATCH 142/168] Add contributors file Signed-off-by: Leonardo Carreras --- CONTRIBUTORS.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 CONTRIBUTORS.md diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md new file mode 100644 index 0000000000..5198bc84d6 --- /dev/null +++ b/CONTRIBUTORS.md @@ -0,0 +1,41 @@ +# Contributors + +We would like to thank all contributors who have helped develop and improve DPsim over the years, whether through code, research, testing, or feedback. + +This list is based on deduplicated commit authors and highlights main contributors. +For a complete, automatically updated list use the command `git shortlog -sne`. + +## Main contributors + +- Markus Mirz +- Steffen Vogel +- Jonas Schroeder +- Jan Dinkelbach +- Georg Reinke +- Viviane Sapucaia +- Niklas Eiling +- Lennart Schumacher +- Junjie Zhang +- Martin Moraga +- Ghassen Nakti + +## Other contributors (alphabetical) + +- Anas Bahr +- Andrés Acosta +- Bettina Schäfer +- Christoph Wirtz +- Daniel Döhring +- Felix Wege +- Florian Oppermann +- Georgii Tishenin +- Henri Lubjuhn +- Leonardo Carreras +- Marvin Tollnitsch +- Petra Raussi +- Philipp Fensch +- Philipp Jungkamp +- Richard Marston +- Ruben Sander +- Shikhin Dah +- Stefan Lankes From fc26c6d35e5adc108c6690c7dd316352da075b3e Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 00:40:22 +0100 Subject: [PATCH 143/168] Fix readme, add contributors info, change contacts Signed-off-by: Leonardo Carreras --- README.md | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 87cad62e63..75ebc11ef3 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,13 @@ # DPsim [![Build & Test RockyLinux](https://github.com/sogno-platform/dpsim/actions/workflows/build_test_linux_rocky.yaml/badge.svg)](https://github.com/sogno-platform/dpsim/actions/workflows/build_test_linux_rocky.yaml) - [![Build & Test Fedora](https://github.com/sogno-platform/dpsim/actions/workflows/build_test_linux_fedora.yaml/badge.svg)](https://github.com/sogno-platform/dpsim/actions/workflows/build_test_linux_fedora.yaml) - [![Build & Test Fedora Minimal](https://github.com/sogno-platform/dpsim/actions/workflows/build_test_linux_fedora_minimal.yaml/badge.svg)](https://github.com/sogno-platform/dpsim/actions/workflows/build_test_linux_fedora_minimal.yaml) - [![Build & Test Windows](https://github.com/sogno-platform/dpsim/actions/workflows/build_test_windows.yaml/badge.svg)](https://github.com/sogno-platform/dpsim/actions/workflows/build_test_windows.yaml) [![License: MPL 2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0) - [![codecov](https://codecov.io/gh/sogno-platform/dpsim/graph/badge.svg?token=FLUOQ8U7MH)](https://codecov.io/gh/sogno-platform/dpsim) +[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/4887/badge)](https://www.bestpractices.dev/projects/4887) DPsim is a solver library for dynamic power system simulation. @@ -28,6 +25,11 @@ Click the badge below to explore the interactive Jupyter notebooks in your brows [![Binder](https://2i2c.mybinder.org/badge_logo.svg)](https://2i2c.mybinder.org/v2/gh/sogno-platform/dpsim/HEAD?urlpath=%2Fdoc%2Ftree%2Fexamples%2FIndex.ipynb) +Or install it using the command +´´´ +pip install dpsim +´´´ + ## Documentation The [documentation](https://dpsim.fein-aachen.org/) has build / installation instructions, links to examples and explains the concepts implemented in DPsim as well as its architecture. @@ -36,12 +38,18 @@ The [documentation](https://dpsim.fein-aachen.org/) has build / installation ins The project is released under the terms of the [MPL 2.0](https://mozilla.org/MPL/2.0/). +For email inquiries regarding other licensing options, please contact the Institute for Automation of Complex Power Systems (ACS), which coordinates DPsim development: [post_acs@eonerc.rwth-aachen.de](mailto:post_acs@eonerc.rwth-aachen.de). + ## Contact -[LF Energy Slack](https://slack.lfenergy.org/) - Chat with other users and developers and get help in the **#sogno** or **#sogno-dpsim** channel. +[GitHub Discussions](https://github.com/sogno-platform/dpsim/discussions) - Ask questions, share ideas, and get community support. + +## Contribute + +If you want to get more involved with DPsim, we welcome contributions of all kinds, including code, documentation, examples, models, bug reports, feature requests, and reviews. + +Please open a Pull Request or issue on [GitHub](https://github.com/sogno-platform/dpsim), or start a discussion there to propose ideas and get feedback from the community. -You can also send a direct message to: +## Contributors -- Markus Mirz -- Jan Dinkelbach -- Steffen Vogel +See [CONTRIBUTORS.md](CONTRIBUTORS.md) for a list of contributors. From 6e83eebe39da6144d28b827f8c586b949d0f189d Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 00:41:20 +0100 Subject: [PATCH 144/168] Update docu and contacts in packaging files Signed-off-by: Leonardo Carreras --- cmake/DPsimPackaging.cmake | 2 +- docs/hugo/content/en/docs/_index.md | 16 ++++++++++------ setup.cfg | 2 +- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cmake/DPsimPackaging.cmake b/cmake/DPsimPackaging.cmake index b202bcc6bb..1d2d6e3594 100644 --- a/cmake/DPsimPackaging.cmake +++ b/cmake/DPsimPackaging.cmake @@ -1,6 +1,6 @@ set(CPACK_PACKAGE_NAME ${PROJECT_NAME}) set(CPACK_PACKAGE_VENDOR ${PROJECT_AUTHOR}) -set(CPACK_PACKAGE_CONTACT "Steffen Vogel ") set(CPACK_PACKAGE_VERSION ${DPSIM_SHORT_VERSION}) set(CPACK_PACKAGE_VERSION_MAJOR ${DPSIM_MAJOR_VERSION}) set(CPACK_PACKAGE_VERSION_MINOR ${DPSIM_MINOR_VERSION}) diff --git a/docs/hugo/content/en/docs/_index.md b/docs/hugo/content/en/docs/_index.md index 0dd1b6ec5c..b017d65cf4 100644 --- a/docs/hugo/content/en/docs/_index.md +++ b/docs/hugo/content/en/docs/_index.md @@ -21,17 +21,21 @@ DPsim is a solver library for dynamic power system simulation. Using or want to use DPsim? Find out more here: +[GitHub Discussions](https://github.com/sogno-platform/dpsim/discussions) - Ask questions, share ideas, and get community support. + [LF Energy Slack](https://slack.lfenergy.org/) - Chat with other users and developers and get help in the **#sogno** or **#sogno-dpsim** channel. -You can also send a direct message to: +For email inquiries, please contact the Institute for Automation of Complex Power Systems (ACS), which coordinates DPsim development: [post_acs@eonerc.rwth-aachen.de](mailto:post_acs@eonerc.rwth-aachen.de). + +# How to contribute + +If you want to get more involved with DPsim, we welcome contributions of all kinds, including code, documentation, examples, models, bug reports, feature requests, and reviews. -- Markus Mirz -- Jan Dinkelbach -- Steffen Vogel +Please open a Pull Request or issue on [GitHub](https://github.com/sogno-platform/dpsim), or start a discussion there to propose ideas and get feedback from the community. -# Contribute +## Contributors -If you want to get more involved by contributing to DPsim, please send us a Pull Request on [GitHub](https://github.com/sogno-platform/dpsim). +See [CONTRIBUTORS.md](CONTRIBUTORS.md) for a list of contributors. # Publications diff --git a/setup.cfg b/setup.cfg index d2c07643a4..0e98957787 100644 --- a/setup.cfg +++ b/setup.cfg @@ -2,7 +2,7 @@ name = dpsim version = 1.1.1 author = The DPsim Authors -author_email = mmirz@eonerc.rwth-aachen.de +author_email = post_acs@eonerc.rwth-aachen.de description = dynamic real-time power system simulator long_description = file: README.md long_description_content_type = text/markdown From af14d5e4b64346a6f16752520dc224e6ea62018c Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Sun, 7 Dec 2025 23:49:01 +0100 Subject: [PATCH 145/168] Make fedora-release wait for dpsim-dev container Signed-off-by: Leonardo Carreras --- .github/workflows/container.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/container.yaml b/.github/workflows/container.yaml index c5a0799c84..5e3343b983 100644 --- a/.github/workflows/container.yaml +++ b/.github/workflows/container.yaml @@ -25,6 +25,7 @@ jobs: tags: sogno/dpsim:dev-rocky create-docker-fedora-release: + needs: create-docker-fedora-dev runs-on: ubuntu-latest steps: - name: Checkout From b8a34c788df67b9112f3c9a54acc862afbd5adfa Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 00:03:43 +0100 Subject: [PATCH 146/168] Create symlink in manylinux to install path of opendss c lib Signed-off-by: Leonardo Carreras --- packaging/Docker/Dockerfile.manylinux | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packaging/Docker/Dockerfile.manylinux b/packaging/Docker/Dockerfile.manylinux index 2ae98fc7e3..b01fdbed52 100644 --- a/packaging/Docker/Dockerfile.manylinux +++ b/packaging/Docker/Dockerfile.manylinux @@ -121,3 +121,9 @@ RUN cd /tmp && \ -DCMAKE_POLICY_VERSION_MINIMUM=3.5 && \ make ${MAKE_OPTS} install && \ rm -rf /tmp/villas-node + + # Fix OpenDSSC library path + RUN if [ -f /usr/local/openDSSC/bin/libOpenDSSC.so ]; then \ + mkdir -p /usr/lib64; \ + ln -sf /usr/local/openDSSC/bin/libOpenDSSC.so /usr/lib64/libOpenDSSC.so; \ + fi From f426fd464a8ca307062b8e0fada8b29e79c490e3 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 00:10:16 +0100 Subject: [PATCH 147/168] Add dpsimpyvillas and use correct python install deps Signed-off-by: Leonardo Carreras --- setup.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index f3fb9afd18..4046eec991 100644 --- a/setup.py +++ b/setup.py @@ -51,9 +51,15 @@ def build_extension(self, ext): ["cmake", sourcedir] + cmake_args, cwd=self.build_temp, env=env ) - print(" ".join(["cmake", "--build", ".", "--target", "dpsimpy"] + build_args)) + print( + " ".join( + ["cmake", "--build", ".", "--target", "dpsimpy", "dpsimpyvillas"] + + build_args + ) + ) subprocess.check_call( - ["cmake", "--build", ".", "--target", "dpsimpy"] + build_args, + ["cmake", "--build", ".", "--target", "dpsimpy", "dpsimpyvillas"] + + build_args, cwd=self.build_temp, ) @@ -61,10 +67,15 @@ def build_extension(self, ext): setup( packages=find_packages("python/src"), package_dir={"dpsim": "python/src/dpsim"}, - python_requires=">=3.8", + python_requires=">=3.9", + install_requires=[ + "numpy>=2.0.0", + "pandas>=2.0.0", + "scipy>=1.10.0", + ], setup_requires=["pytest-runner", "wheel"], tests_require=["pytest", "pyyaml", "nbformat", "nbconvert"], - ext_modules=[CMakeExtension("dpsimpy")], + ext_modules=[CMakeExtension("dpsimpy"), CMakeExtension("dpsimpyvillas")], cmdclass={"build_ext": CMakeBuild}, zip_safe=False, ) From 494051066f9e97d1348ca9e3430c362fb2b8925e Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 00:16:23 +0100 Subject: [PATCH 148/168] Reactivates villas in mybinder python packaging Signed-off-by: Leonardo Carreras --- .binder/Dockerfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.binder/Dockerfile b/.binder/Dockerfile index e9003e2173..840042b32f 100644 --- a/.binder/Dockerfile +++ b/.binder/Dockerfile @@ -19,8 +19,7 @@ RUN adduser \ COPY . ${HOME}/dpsim ENV PATH="${HOME}/.local/bin:${PATH}" -# FIXME: Temporary disable VILLAS to keep old behavior using WITH_VILLAS -ENV CMAKE_OPTS="-DWITH_VILLAS=OFF" + RUN python3 -m pip install notebook jupyterlab jupyterhub USER root RUN chown -R ${NB_UID} ${HOME} From dbb70faeec78f6bc88f1e981c903e7403e12ae3f Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 00:22:41 +0100 Subject: [PATCH 149/168] Uses dpsim manylinux container and skips rc versions in PyPI Signed-off-by: Leonardo Carreras --- .github/workflows/publish_to_pypi.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index a4e4462288..2172bb0a9f 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -46,6 +46,7 @@ jobs: uses: pypa/cibuildwheel@v2.23.2 env: CIBW_BUILD: "${{ matrix.python }}-${{ matrix.platform }}" + CIBW_MANYLINUX_X86_64_IMAGE: sogno/dpsim:manylinux with: output-dir: dist @@ -80,5 +81,5 @@ jobs: skip-existing: true - name: Publish distribution to PyPI - if: startsWith(github.ref, 'refs/tags') + if: startsWith(github.ref, 'refs/tags') && !contains(github.ref, '-rc') uses: pypa/gh-action-pypi-publish@v1.13.0 From 44df880236a42512dd83cae67c61a2aa9a51df46 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 20:06:16 +0100 Subject: [PATCH 150/168] Adapt sonar to avoid deprecated checks for secrets, allow PRs scan Signed-off-by: Leonardo Carreras --- .github/workflows/sonar_cloud.yaml | 38 +++++------------------------- 1 file changed, 6 insertions(+), 32 deletions(-) diff --git a/.github/workflows/sonar_cloud.yaml b/.github/workflows/sonar_cloud.yaml index 97be653c1b..f845e31404 100644 --- a/.github/workflows/sonar_cloud.yaml +++ b/.github/workflows/sonar_cloud.yaml @@ -1,65 +1,44 @@ name: Sonar Cloud Analysis + on: push: branches: - master - pull_request: + pull_request_target: jobs: sonarcloud: name: Prepare and run Sonar Scan runs-on: ubuntu-latest container: sogno/dpsim:dev - outputs: - skip: ${{ steps.check_token.outputs.skip }} # Output to indicate if the job was skipped env: BUILD_WRAPPER_OUT_DIR: build_wrapper_output_directory - steps: - - name: Check for SONAR_TOKEN - id: check_token - run: | - if [ -z "${{ secrets.SONAR_TOKEN }}" ]; then - echo "SONAR_TOKEN is not set. Skipping the job." - echo "::set-output name=skip::true" - else - echo "::set-output name=skip::false" - fi - - - name: Skip Job if Token is Missing - if: steps.check_token.outputs.skip == 'true' - run: | - echo "Skipping the SonarCloud analysis due to missing SONAR_TOKEN." - exit 0 + steps: - name: Fetch repository - if: steps.check_token.outputs.skip != 'true' uses: actions/checkout@v4 with: fetch-depth: 0 + ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.sha || github.sha }} - name: Setup Node 20 - if: steps.check_token.outputs.skip != 'true' uses: actions/setup-node@v4 with: node-version: 20 - name: Install sonar-scanner and build-wrapper - if: steps.check_token.outputs.skip != 'true' uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v6 - name: Create Build Folder - if: steps.check_token.outputs.skip != 'true' run: mkdir build - name: Setup build directory cache - if: steps.check_token.outputs.skip != 'true' uses: actions/cache@v4 with: path: ${{ github.workspace }}/build key: wrapper-dir-cache-${{ github.ref }} - name: Setup sonar cache - if: steps.check_token.outputs.skip != 'true' uses: actions/cache@v4 with: path: | @@ -68,19 +47,14 @@ jobs: key: sonar-cache-${{ github.ref }} - name: Configure CMake - if: steps.check_token.outputs.skip != 'true' shell: bash working-directory: ${{ github.workspace }}/build - run: | - cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 $GITHUB_WORKSPACE + run: cmake -DCIM_VERSION=CGMES_2.4.15_16FEB2016 "$GITHUB_WORKSPACE" - name: Run build-wrapper - if: steps.check_token.outputs.skip != 'true' - run: | - build-wrapper-linux-x86-64 --out-dir ${{ env.BUILD_WRAPPER_OUT_DIR }} cmake --build build/ -j $(nproc) + run: build-wrapper-linux-x86-64 --out-dir "${{ env.BUILD_WRAPPER_OUT_DIR }}" cmake --build build/ -j "$(nproc)" - name: Run sonar-scanner - if: steps.check_token.outputs.skip != 'true' uses: SonarSource/sonarqube-scan-action@v6 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 816d58c5001ad2b259321fe59cdbc48984bf2a11 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 18:59:51 +0100 Subject: [PATCH 151/168] Security fix for villas workflow Signed-off-by: Leonardo Carreras --- .../workflows/build_test_linux_fedora.yaml | 25 ++---- .github/workflows/run_villas_example.yaml | 86 ++++++++++++++----- 2 files changed, 71 insertions(+), 40 deletions(-) diff --git a/.github/workflows/build_test_linux_fedora.yaml b/.github/workflows/build_test_linux_fedora.yaml index 9e0d9aa16b..516c848448 100644 --- a/.github/workflows/build_test_linux_fedora.yaml +++ b/.github/workflows/build_test_linux_fedora.yaml @@ -313,11 +313,8 @@ jobs: uses: ./.github/workflows/run_villas_example.yaml with: compose_file_path: examples/villas/docker-compose-tests - container_commands: | - docker exec dpsim-compose-dpsim-1 /bin/bash -c "pip install paho-mqtt" - docker exec dpsim-compose-mqtt-1 mosquitto_sub -t "/dpsim-mqtt" -u wildcard -v& - docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt-producer.py"& - docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt.py" + example_name: dpsim-mqtt + continue_on_error: true test-villas-examples-2: name: Run dpsim-mqtt-import-export VILLASnode example @@ -325,9 +322,8 @@ jobs: uses: ./.github/workflows/run_villas_example.yaml with: compose_file_path: examples/villas/docker-compose-tests - container_commands: | - docker exec dpsim-compose-mqtt-1 mosquitto_sub -t "#" -u wildcard -v& - docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt-import-export.py" + example_name: dpsim-mqtt-import-export + continue_on_error: true test-villas-examples-3: name: Run dpsim-mqtt-import-export-MIMO VILLASnode example @@ -335,10 +331,8 @@ jobs: uses: ./.github/workflows/run_villas_example.yaml with: compose_file_path: examples/villas/docker-compose-tests + example_name: dpsim-mqtt-import-export-mimo continue_on_error: true - container_commands: | - docker exec dpsim-compose-mqtt-1 mosquitto_sub -t "#" -u wildcard -v& - docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt-import-export-MIMO.py" test-villas-examples-4: name: Run dpsim-file VILLASnode example @@ -346,10 +340,8 @@ jobs: uses: ./.github/workflows/run_villas_example.yaml with: compose_file_path: examples/villas/docker-compose-tests + example_name: dpsim-file continue_on_error: true - container_commands: | - docker exec dpsim-compose-dpsim-1 /bin/bash -c "sleep 3 && tail -f /dpsim/logs/output.csv"& - docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-file.py" test-villas-examples-5: name: Run mqtt-cigre-mv-pf-profiles VILLASnode example @@ -357,6 +349,5 @@ jobs: uses: ./.github/workflows/run_villas_example.yaml with: compose_file_path: examples/villas/docker-compose-tests - container_commands: | - docker exec dpsim-compose-mqtt-1 mosquitto_sub -t "#" -u wildcard -v& - docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py" + example_name: mqtt-cigre-mv-pf-profiles + continue_on_error: true diff --git a/.github/workflows/run_villas_example.yaml b/.github/workflows/run_villas_example.yaml index 3a7891e0e0..363797262b 100644 --- a/.github/workflows/run_villas_example.yaml +++ b/.github/workflows/run_villas_example.yaml @@ -7,8 +7,8 @@ on: description: 'Path to the multi-container compose file' required: true type: string - container_commands: - description: 'docker exec commands for running tests in the containers' + example_name: + description: 'Which VILLAS example to run' required: true type: string continue_on_error: @@ -22,24 +22,64 @@ jobs: name: Run a VILLASnode example across multiple containers runs-on: ubuntu-latest steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Restore build archive - uses: actions/download-artifact@v4 - with: - name: build-cache-examples-cpp-${{ github.sha }} - path: ${{ github.workspace }}/build - - - name: Start containers - run: cd ${{ inputs.compose_file_path }} && docker compose -p dpsim-compose up -d - - - name: Run container commands - timeout-minutes: 5 - continue-on-error: ${{ inputs.continue_on_error }} - shell: bash - run: ${{ inputs.container_commands }} - - - name: Stop containers - if: ${{ always() }} - run: cd ${{ inputs.compose_file_path }} && docker compose -p dpsim-compose down + - name: Checkout + uses: actions/checkout@v4 + + - name: Restore build archive + uses: actions/download-artifact@v4 + with: + name: build-cache-examples-cpp-${{ github.sha }} + path: ${{ github.workspace }}/build + + - name: Start containers + working-directory: ${{ inputs.compose_file_path }} + run: docker compose -p dpsim-compose up -d + + - name: Run VILLAS example container commands + timeout-minutes: 5 + continue-on-error: ${{ inputs.continue_on_error }} + shell: bash + env: + EXAMPLE_NAME: ${{ inputs.example_name }} + working-directory: ${{ github.workspace }} + run: | + set -e + + case "$EXAMPLE_NAME" in + dpsim-mqtt) + docker exec dpsim-compose-dpsim-1 /bin/bash -c "pip install paho-mqtt" + docker exec dpsim-compose-mqtt-1 mosquitto_sub -t "/dpsim-mqtt" -u wildcard -v & + docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt-producer.py" & + docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt.py" + ;; + + dpsim-mqtt-import-export) + docker exec dpsim-compose-mqtt-1 mosquitto_sub -t "#" -u wildcard -v & + docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt-import-export.py" + ;; + + dpsim-mqtt-import-export-mimo) + docker exec dpsim-compose-mqtt-1 mosquitto_sub -t "#" -u wildcard -v & + docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt-import-export-MIMO.py" + ;; + + dpsim-file) + docker exec dpsim-compose-dpsim-1 /bin/bash -c "sleep 3 && tail -f /dpsim/logs/output.csv" & + docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-file.py" + ;; + + mqtt-cigre-mv-pf-profiles) + docker exec dpsim-compose-mqtt-1 mosquitto_sub -t "#" -u wildcard -v & + docker exec dpsim-compose-dpsim-1 /bin/bash -c "cd /dpsim && python3 /dpsim/examples/villas/dpsim-mqtt-cigre-mv-pf-profiles.py" + ;; + + *) + echo "Unknown EXAMPLE_NAME: $EXAMPLE_NAME" >&2 + exit 1 + ;; + esac + + - name: Stop containers + if: ${{ always() }} + working-directory: ${{ inputs.compose_file_path }} + run: docker compose -p dpsim-compose down From c3b040744cd4ef17217c3d7305ae5421900ffb48 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 19:13:37 +0100 Subject: [PATCH 152/168] Security fix for profiling workflow Signed-off-by: Leonardo Carreras --- .../workflows/run_and_profile_example.yaml | 53 ++++++++++--------- 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/.github/workflows/run_and_profile_example.yaml b/.github/workflows/run_and_profile_example.yaml index 7e92830322..c24d8ab54f 100644 --- a/.github/workflows/run_and_profile_example.yaml +++ b/.github/workflows/run_and_profile_example.yaml @@ -12,37 +12,42 @@ on: required: true type: string - jobs: profiling-examples: name: Run example with profiling runs-on: ubuntu-latest container: sogno/dpsim:dev-rocky steps: - - name: Restore Cache - uses: actions/cache@v4 - with: - path: ${{ github.workspace }}/build - key: build-cache-rocky-profiling-${{ github.sha }} + - name: Restore Cache + uses: actions/cache@v4 + with: + path: ${{ github.workspace }}/build + key: build-cache-rocky-profiling-${{ github.sha }} - - name: Run Binary - run: ${{ inputs.path }} 2>&1 | tee output.log + - name: Run Binary + env: + BINARY_PATH: ${{ inputs.path }} + run: | + "$BINARY_PATH" 2>&1 | tee output.log - - name: Extract metrics - shell: bash - working-directory: ${{ github.workspace }} - run: | - cat output.log | - sed -n -E -e 's/^.*Average step time. ([0-9]+\.[0-9]+)$/step-time \1/p' | - tee -a metrics.txt + - name: Extract metrics + shell: bash + working-directory: ${{ github.workspace }} + run: | + cat output.log | + sed -n -E -e 's/^.*Average step time. ([0-9]+\.[0-9]+)$/step-time \1/p' | + tee -a metrics.txt - - name: Run Profiler - run: gprof ${{ inputs.path }} | gprof2dot -s | dot -Tpng -o profiling.png || true + - name: Run Profiler + env: + BINARY_PATH: ${{ inputs.path }} + run: | + gprof "$BINARY_PATH" | gprof2dot -s | dot -Tpng -o profiling.png || true - - name: Archive profiler output - uses: actions/upload-artifact@v4 - with: - name: profiler-output-${{ inputs.name }} - path: | - metrics.txt - profiling.png + - name: Archive profiler output + uses: actions/upload-artifact@v4 + with: + name: profiler-output-${{ inputs.name }} + path: | + metrics.txt + profiling.png From 761760b07f8f9b6d4473d60fe3050c82c4887ba3 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Wed, 10 Dec 2025 11:06:50 +0100 Subject: [PATCH 153/168] Updates to the documentation: install and contribution Signed-off-by: Leonardo Carreras --- README.md | 17 ++++--- .../content/en/docs/Development/guidelines.md | 45 +++++++++++++++++-- .../content/en/docs/Getting started/build.md | 2 +- .../en/docs/Getting started/install.md | 14 ++++-- docs/hugo/content/en/docs/_index.md | 4 +- 5 files changed, 66 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 75ebc11ef3..111dc1debb 100644 --- a/README.md +++ b/README.md @@ -19,16 +19,21 @@ DPsim is a solver library for dynamic power system simulation. - It can load models in the IEC61970 CIM / CGMES XML format. - It can be interfaced to a variety of protocols and interfaces via [VILLASnode](https://fein-aachen.org/projects/villas-node/). -## Getting started using Binder +## Getting started + +### Using Binder Click the badge below to explore the interactive Jupyter notebooks in your browser: [![Binder](https://2i2c.mybinder.org/badge_logo.svg)](https://2i2c.mybinder.org/v2/gh/sogno-platform/dpsim/HEAD?urlpath=%2Fdoc%2Ftree%2Fexamples%2FIndex.ipynb) -Or install it using the command -´´´ +### Using Python on Linux + +Install DPsim on Linux using the command + +```shell pip install dpsim -´´´ +``` ## Documentation @@ -50,6 +55,8 @@ If you want to get more involved with DPsim, we welcome contributions of all kin Please open a Pull Request or issue on [GitHub](https://github.com/sogno-platform/dpsim), or start a discussion there to propose ideas and get feedback from the community. +Have you developed something new and want to contribute it? Check the [documentation](https://dpsim.fein-aachen.org/) for details on the preferred way to organize your code contributions. + ## Contributors -See [CONTRIBUTORS.md](CONTRIBUTORS.md) for a list of contributors. +See [CONTRIBUTORS.md](https://github.com/sogno-platform/dpsim/blob/master/CONTRIBUTORS.md) for a list of contributors. diff --git a/docs/hugo/content/en/docs/Development/guidelines.md b/docs/hugo/content/en/docs/Development/guidelines.md index df85d3a0e6..5cd74875a6 100644 --- a/docs/hugo/content/en/docs/Development/guidelines.md +++ b/docs/hugo/content/en/docs/Development/guidelines.md @@ -22,19 +22,56 @@ Current quantities are expressed either as `RMS` or as `PEAK` values: Debug or trace should be the default log level for information that might be nice to have but not necessary for every simulation case. -Calls to the logger that might occur during simulation must use spdlog macros, like SPDLOG_LOGGER_INFO. +Calls to the logger that might occur during simulation must use spdlog macros, like `SPDLOG_LOGGER_INFO`. -# Creating New Releases +# Pull Requests -Although DPsim currently does not have any conventions on versioning, the periodic creation of +There are no strict formal requirements besides the following: + +1. **Developer Certificate of Origin (DCO)** + + We require a Developer Certificate of Origin. See more [here](https://github.com/lf-energy/tac/blob/main/process/contribution_guidelines.md#contribution-sign-off). + +1. **Code Formatting with `pre-commit`** + + We enforce code formatting automatically using `pre-commit`. Please run `pre-commit install` the first time you clone the repository to run `pre-commit` before each commit automatically. If you forgot to do this, you will need to use the command `pre-commit run --all-files` one time to format your changes. + +1. **Development in Forks Only** + + We accept contributions made in forks only. The main repository is not intended for contributor-specific branches. + +1. **SPDX Headers** + + Use SPDX headers to indicate copyright and licensing information, especially when introducing new files to the codebase. For example: + + ```cpp + /* Author: John Smith + * SPDX-FileCopyrightText: 2025 Example.com + * SPDX-License-Identifier: MPL-2.0 + */ + ``` + +# Creating New Releases (info for maintainers) + +DPsim currently uses to [Semantic Versioning](https://semver.org/). The periodic creation of new versions can help to mark significant changes and to analyze new portions of code using tools like SonarCloud. A new version of DPsim has to be indicated as follows: -- Create a new tag with an increased version number - Update setup.cfg - Update CMakeLists.txt - Update sonar-project.properties +- Update CHANGELOG.md and include all the unreleaed changes in the list +- Create a new tag with an increased version number (can be done during the Release in GitHub) + +## Python Packages Due to the creation of a new tag, a new PyPi package will be deployed automatically. + +Only Linux packages are currently available, other platforms will be supported in the future. + +## Container Images + To release an updated Docker image, the container workflow needs to be triggered manually. + +If a Pull Request changes a container image, this is not updated automatically in the container image register. diff --git a/docs/hugo/content/en/docs/Getting started/build.md b/docs/hugo/content/en/docs/Getting started/build.md index 1276740afd..afeb91bc2a 100644 --- a/docs/hugo/content/en/docs/Getting started/build.md +++ b/docs/hugo/content/en/docs/Getting started/build.md @@ -22,7 +22,7 @@ In the repository, there is a Docker file with all required dependencies ```shell cd dpsim -docker build -t sogno/dpsim:dev -f Packaging/Docker/Dockerfile.dev . +docker build -t sogno/dpsim:dev -f packaging/Docker/Dockerfile.dev . ``` Alternatively, the image can be pulled from DockerHub like so diff --git a/docs/hugo/content/en/docs/Getting started/install.md b/docs/hugo/content/en/docs/Getting started/install.md index f4a1e9a1c9..3c3c094166 100644 --- a/docs/hugo/content/en/docs/Getting started/install.md +++ b/docs/hugo/content/en/docs/Getting started/install.md @@ -21,9 +21,13 @@ docker run -p 8888:8888 sogno/dpsim And access the session by opening the following link: -# Python +# Python in Linux -**Currently, the pypi packages are not maintained. Until we have updated the packages, please use the docker installation.** +DPsim can be installed in Linux as a Python module: + +```shell +pip install dpsim +``` ## Prerequisites @@ -33,7 +37,7 @@ To get started, install the latest installer for Python 3.x from the [downloads Then, run the Anaconda Prompt and create a new conda environment: ```shell -conda create -n dpsim python=3.6 +conda create -n dpsim python=3.13 ``` After creating the environment you need to make sure that it is activated. @@ -47,12 +51,14 @@ activate dpsim ## Pip Package Installation -Then, DPsim can be installed as a Python module: +Then, DPsim can be installed as a Python module in Linux: ```shell pip install dpsim ``` +Some examples also need additional packages to process the data or show graphics. Please have a look at the import section of them in case you run into any errors. + # From Source To build and install DPsim from the source files, please refer to the build section. diff --git a/docs/hugo/content/en/docs/_index.md b/docs/hugo/content/en/docs/_index.md index b017d65cf4..c171901706 100644 --- a/docs/hugo/content/en/docs/_index.md +++ b/docs/hugo/content/en/docs/_index.md @@ -21,7 +21,7 @@ DPsim is a solver library for dynamic power system simulation. Using or want to use DPsim? Find out more here: -[GitHub Discussions](https://github.com/sogno-platform/dpsim/discussions) - Ask questions, share ideas, and get community support. +[GitHub Discussions](https://github.com/sogno-platform/dpsim/discussions) - Ask questions, share ideas, and get community support. This is our main point of contact. [LF Energy Slack](https://slack.lfenergy.org/) - Chat with other users and developers and get help in the **#sogno** or **#sogno-dpsim** channel. @@ -35,7 +35,7 @@ Please open a Pull Request or issue on [GitHub](https://github.com/sogno-platfor ## Contributors -See [CONTRIBUTORS.md](CONTRIBUTORS.md) for a list of contributors. +See [CONTRIBUTORS.md](https://github.com/sogno-platform/dpsim/blob/master/CONTRIBUTORS.md) for a list of contributors. # Publications From b6538b7857f7f74d956db7806c7f8a2dc2e9d8c9 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Wed, 10 Dec 2025 12:22:14 +0100 Subject: [PATCH 154/168] Last updates for release 1.2.0 in changelog Signed-off-by: Leonardo Carreras --- CHANGELOG.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2102ab515e..64c2704fa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,17 +7,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) ### Added +- Added this CHANGELOG.md file to track changes in the project. - Adapt DPsim to deploy it in Mybinder (#323), moving Dockerfile to new .binder folder and adding job for building the binder Dockerfile. - Add Code Coverage Report (#395), adding codecove badge and updating yaml file for code coverage. - Add CODEOWNERS (#290) -- Add pre-commit (#352) -- Add pre-commit /2 (#361) -- Add pre-commit /3 (#363) -- Add pre-commit /4 (#377) -- Add pre-commit /5 (#382) -- Add pre-commit /6 (#383) -- Add pre-commit /7 (#385), harmonizing comments and indentation. -- Add pre-commit /8 (#386), harmonizing capitalization of Markdown filenames. +- Add pre-commit (#352, #361, #363, #377, #382, #383, #385, #386) to harmonize code - feat(cmake): Add install target (#381) - New queueless VILLAS interface / improve real-time performance (#316), creating DCGenerator in VoltageSource only if special setParameters is used and not always when the frequency is 0 (avoiding regressions), and adding DP_PH1_ProfileVoltageSource used for the villas / fpga interface. - Reuse conductance stamp code (#306), adding functions in MNAStampUtils for stamping value as a scalar matrix. @@ -31,6 +25,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Villas Interface: Improve FpgaExample (#299), allowing different topologies to be tested and updating VILLAS_VERSION in Dockerfile. - Nix packaging (#357), adding GitHub CI workflow for building DPsim with Nix and Nix packaging. - chore: update docs on real-time and VILLASnode interfaces (#335) +- Add dpsimpyvillas module to the CMake targets and include it in the Python wheel, using the correct Python install dependencies (#449) ### Changed @@ -47,6 +42,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Add new action using the build wrapper from sonar directly (#296) - Allow builds without nlohmann/json library (#362) - feat(ci): Use trusted / OIDC publishing to PyPi.org (#375), only attempting upload to PyPi for pushes to master or tags. +- Fixes to documentation and README, adding extra details about installation methods, contribution guidelines and how to try DPsim (#457). +- Update documentation and packaging metadata contact information, add CONTRIBUTORS file and GitHub Discussions link, and improve contributor/community guidance (#429, #413). +- Extend the changelog to include entries for older release versions and previously unreleased changes (#430). +- Use the DPsim manylinux container for building the Python package and skip RC versions when publishing to PyPI.org, while still publishing RC versions to TestPyPI (#451). ### Removed @@ -113,6 +112,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) - Use clang-format to format the whole codebase (#278), fixing missing includes and moving development scripts from configs/ to scripts./ - chore (deps): update to CIMpp rpm/deb install + bump VILLAS (#404), updating cmake fetch and finding of libcimpp and fixing dependent files and CIMReader. - fix: Cleanup code-style of setup.py (#336) +- Reactivate VILLAS support in the MyBinder Python packaging workflow and fix related compilation issues when using dpsimpy with VILLAS-enabled containers (#450, #434, resolves #445). +- Create a symlink in the manylinux image to the install path of the OpenDSS C library to fix Python packaging and runtime loading issues (#448). +- Link DPsim to VILLAS libraries via CMake to fix missing linkage in VILLAS-enabled builds and examples (#447). +- Make the Fedora release workflow wait for the dpsim-dev container build to avoid race conditions in the release pipeline (#446). +- Security fix for the profiling workflow, avoiding passing commands as inputs to scripts in the profiling job (#455). +- Security fix for the VILLAS workflow, preventing commands from being passed as raw inputs into the shell (#454). +- Adapt the Sonar workflow to avoid deprecated secret checks so that scans still run for pull requests from forks (#456). +- Fix the Sonar workflow by bumping the action to the supported v6 version and adjusting configuration (#439). ## [v1.1.1] - 2023-07-13 From a3feda2926ef32cd3e9517562796232d55b889d1 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Mon, 8 Dec 2025 00:48:52 +0100 Subject: [PATCH 155/168] Update versions for publishing Signed-off-by: Leonardo Carreras --- CHANGELOG.md | 2 +- CMakeLists.txt | 2 +- setup.cfg | 2 +- sonar-project.properties | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64c2704fa5..0ab36d2b90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/). -## [Unreleased] +## [v1.2.0] - 2025-12-15 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index e61eab6944..09811df03e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Please keep 3.14 as minimum requirement for building on OPAL-RT targets cmake_minimum_required(VERSION 3.14...3.23) project(DPsim - VERSION 1.1.1 + VERSION 1.2.0 DESCRIPTION "C++ Power System Simulation Library" LANGUAGES CXX HOMEPAGE_URL "https://dpsim.fein-aachen.org/") diff --git a/setup.cfg b/setup.cfg index 0e98957787..b9a9409a1e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = dpsim -version = 1.1.1 +version = 1.2.0 author = The DPsim Authors author_email = post_acs@eonerc.rwth-aachen.de description = dynamic real-time power system simulator diff --git a/sonar-project.properties b/sonar-project.properties index 3a918355ea..7d163596b0 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -7,14 +7,14 @@ sonar.cfamily.analysisCache.path=sonar-cache sonar.cfamily.analysisCache.mode=fs # Sonar Python Version -sonar.python.version=3.8, 3.9, 3.10 +sonar.python.version=3.9, 3.10, 3.11, 3.12, 3.13, 3.14 # Patterns excluded from duplication detection sonar.cpd.exclusions=dpsim/examples/**/*,examples/**/* # This is the name and version displayed in the SonarCloud UI. sonar.projectName=DPsim -sonar.projectVersion=1.1.1 +sonar.projectVersion=1.2.0 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. #sonar.sources=. From 97b103e6430f551793195e823d0d900f4d883cec Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Wed, 10 Dec 2025 13:08:05 +0100 Subject: [PATCH 156/168] Update publishing date Signed-off-by: Leonardo Carreras --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ab36d2b90..72ee0bb2c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/). -## [v1.2.0] - 2025-12-15 +## [v1.2.0] - 2025-12-10 ### Added From 5b321c8ea077d0f4ed84239e2fb40930f7ccf826 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Wed, 10 Dec 2025 15:04:47 +0100 Subject: [PATCH 157/168] Fix python publishing workflow Signed-off-by: Leonardo Carreras --- .github/workflows/publish_to_pypi.yaml | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish_to_pypi.yaml b/.github/workflows/publish_to_pypi.yaml index 2172bb0a9f..9503a201b2 100644 --- a/.github/workflows/publish_to_pypi.yaml +++ b/.github/workflows/publish_to_pypi.yaml @@ -56,8 +56,8 @@ jobs: name: dist-wheels-${{ matrix.python }}-${{ matrix.platform }} path: dist/ - publish: - name: Publish wheels and source distribution to PyPI + publish-testpypi: + name: Publish wheels and source distribution to Test PyPI runs-on: ubuntu-24.04 if: github.event_name == 'push' permissions: @@ -80,6 +80,23 @@ jobs: repository-url: https://test.pypi.org/legacy/ skip-existing: true + publish-pypi: + name: Publish wheels and source distribution to PyPI + runs-on: ubuntu-24.04 + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags') && !contains(github.ref, '-rc') + permissions: + id-token: write + needs: + - build-wheels + - build-sdist + + steps: + - name: Download wheels from build jobs + uses: actions/download-artifact@v4 + with: + pattern: dist-* + merge-multiple: true + path: dist/ + - name: Publish distribution to PyPI - if: startsWith(github.ref, 'refs/tags') && !contains(github.ref, '-rc') uses: pypa/gh-action-pypi-publish@v1.13.0 From 40d7e19de12588c7eef5c428cbfccac075544807 Mon Sep 17 00:00:00 2001 From: Leonardo Carreras Date: Wed, 10 Dec 2025 15:04:57 +0100 Subject: [PATCH 158/168] Update versions for publishing and changelog Signed-off-by: Leonardo Carreras --- CHANGELOG.md | 8 ++++++++ CMakeLists.txt | 2 +- setup.cfg | 2 +- sonar-project.properties | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72ee0bb2c4..ff4a265e0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/). +## [v1.2.1] - 2025-12-10 + +Note: this version only includes a fix to the publishing workflow. See v1.2.0 for relevant changes since the last v1.1.1 + +### Fixed + +- TestPyPI and PyPI were part of the same job, solved a mixup/reuse of attestations (#459) + ## [v1.2.0] - 2025-12-10 ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index 09811df03e..e5022257a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ # Please keep 3.14 as minimum requirement for building on OPAL-RT targets cmake_minimum_required(VERSION 3.14...3.23) project(DPsim - VERSION 1.2.0 + VERSION 1.2.1 DESCRIPTION "C++ Power System Simulation Library" LANGUAGES CXX HOMEPAGE_URL "https://dpsim.fein-aachen.org/") diff --git a/setup.cfg b/setup.cfg index b9a9409a1e..e6ca8df9d6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = dpsim -version = 1.2.0 +version = 1.2.1 author = The DPsim Authors author_email = post_acs@eonerc.rwth-aachen.de description = dynamic real-time power system simulator diff --git a/sonar-project.properties b/sonar-project.properties index 7d163596b0..a06b6c77c2 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -14,7 +14,7 @@ sonar.cpd.exclusions=dpsim/examples/**/*,examples/**/* # This is the name and version displayed in the SonarCloud UI. sonar.projectName=DPsim -sonar.projectVersion=1.2.0 +sonar.projectVersion=1.2.1 # Path is relative to the sonar-project.properties file. Replace "\" by "/" on Windows. #sonar.sources=. From 92c215301f109b95269653df1eae335c8d9d3a87 Mon Sep 17 00:00:00 2001 From: Marvin Tollnitsch Date: Fri, 12 Dec 2025 06:39:19 +0100 Subject: [PATCH 159/168] Added trapezoidal discretization for state space matrices A, B + added declaration for "static void calculateStateSpaceTrapezoidalMatrices(...)" which transforms state space matrices A and B and omits C and D to "MathUtils.h" + added corresponding definition of "static void calculateStateSpaceTrapezoidalMatrices(...)" to "MathUtils.cpp" Signed-off-by: Marvin Tollnitsch --- dpsim-models/include/dpsim-models/MathUtils.h | 4 ++++ dpsim-models/src/MathUtils.cpp | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/dpsim-models/include/dpsim-models/MathUtils.h b/dpsim-models/include/dpsim-models/MathUtils.h index 6841df8ebc..0f091827db 100644 --- a/dpsim-models/include/dpsim-models/MathUtils.h +++ b/dpsim-models/include/dpsim-models/MathUtils.h @@ -119,6 +119,10 @@ class Math { const Matrix &C, const Real &dt, Matrix &Ad, Matrix &Bd, Matrix &Cd); + static void calculateStateSpaceTrapezoidalMatrices(const Matrix &A, + const Matrix &B, + const Real &dt, Matrix &Ad, + Matrix &Bd); /// Apply the trapezoidal based state space matrices Ad, Bd, Cd to get the states at the current time step static Matrix applyStateSpaceTrapezoidalMatrices(const Matrix &Ad, const Matrix &Bd, diff --git a/dpsim-models/src/MathUtils.cpp b/dpsim-models/src/MathUtils.cpp index 4439464f3d..57972930b6 100644 --- a/dpsim-models/src/MathUtils.cpp +++ b/dpsim-models/src/MathUtils.cpp @@ -338,6 +338,21 @@ void Math::calculateStateSpaceTrapezoidalMatrices(const Matrix &A, Cd = F2inv * dt * C; } +void Math::calculateStateSpaceTrapezoidalMatrices(const Matrix &A, + const Matrix &B, + const Real &dt, Matrix &Ad, + Matrix &Bd) { + Matrix::Index n = A.rows(); + Matrix I = Matrix::Identity(n, n); + + Matrix F1 = I + (dt / 2.) * A; + Matrix F2 = I - (dt / 2.) * A; + Matrix F2inv = F2.inverse(); + + Ad = F2inv * F1; + Bd = F2inv * (dt / 2.) * B; +} + Matrix Math::applyStateSpaceTrapezoidalMatrices(const Matrix &Ad, const Matrix &Bd, const Matrix &Cd, From 1231409bb45b782a9d5f62935938c9caaf51aa2c Mon Sep 17 00:00:00 2001 From: Marvin Tollnitsch Date: Fri, 12 Dec 2025 07:09:06 +0100 Subject: [PATCH 160/168] Added SSN models: Ph1 serial RLC, & generalized two terminal SSN + added "EMT::Ph1::SSN::Full_Serial_RLC" class with "EMT_Ph1_SSN_Full_Serial_RLC.h" and "EMT_Ph1_SSN_Full_Serial_RLC.cpp" + added "EMT::Ph1::SSNTypeI2T" class with "EMT_Ph1_SSNTypeI2T.h" and "EMT_Ph1_SSNTypeI2T.cpp" for a generalized model of an arbitrary two terminal I-type SSN component + added "EMT::Ph1::SSNTypeV2T" class with "EMT_Ph1_SSNTypeV2T.h" and "EMT_Ph1_SSNTypeV2T.cpp" for a generalized model of an arbitrary two terminal V-type SSN component + added above headers ("EMT_Ph1_SSN_Full_Serial_RLC.h", "EMT_Ph1_SSNTypeI2T.h", "EMT_Ph1_SSNTypeV2T.h") to "Components.h" to include them into the project + added above cpp files ("EMT_Ph1_SSN_Full_Serial_RLC.cpp", "EMT_Ph1_SSNTypeI2T.cpp", "EMT_Ph1_SSNTypeV2T.cpp") to the "CMakeLists.txt" for component models Signed-off-by: Marvin Tollnitsch --- .../include/dpsim-models/Components.h | 3 + .../dpsim-models/EMT/EMT_Ph1_SSNTypeI2T.h | 93 +++++++ .../dpsim-models/EMT/EMT_Ph1_SSNTypeV2T.h | 94 +++++++ .../EMT/EMT_Ph1_SSN_Full_Serial_RLC.h | 100 +++++++ dpsim-models/src/CMakeLists.txt | 3 + dpsim-models/src/EMT/EMT_Ph1_SSNTypeI2T.cpp | 254 ++++++++++++++++++ dpsim-models/src/EMT/EMT_Ph1_SSNTypeV2T.cpp | 241 +++++++++++++++++ .../src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp | 222 +++++++++++++++ 8 files changed, 1010 insertions(+) create mode 100644 dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSNTypeI2T.h create mode 100644 dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSNTypeV2T.h create mode 100644 dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSN_Full_Serial_RLC.h create mode 100644 dpsim-models/src/EMT/EMT_Ph1_SSNTypeI2T.cpp create mode 100644 dpsim-models/src/EMT/EMT_Ph1_SSNTypeV2T.cpp create mode 100644 dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index a32e3d5f07..fabe07f6be 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -87,6 +87,9 @@ #include #include #include +#include +#include +#include #include #include #include diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSNTypeI2T.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSNTypeI2T.h new file mode 100644 index 0000000000..3494ab6aa7 --- /dev/null +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSNTypeI2T.h @@ -0,0 +1,93 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include +#include + +namespace CPS { +namespace EMT { +namespace Ph1 { +/// \brief SSNTypeI2T +/// Model for a one phase, two terminal I-type SSN component which can be represented using +/// a state space equation system +/// x' = A * x + B * u +/// y = C * x + D * u +/// with x: state vector, y: output vector, u: input vector, +/// where u represents external current (mIntfCurrent), +/// y represents external voltage (mIntfVoltage), +/// x represents any component states. +class SSNTypeI2T : public MNASimPowerComp, + public SharedFactory { +private: + void ssnUpdateState(); + void setSSNMatricesToZero(); + +protected: + Matrix mX; + Matrix mU; + Matrix mUOld; + Matrix mW; + Matrix mYHist; + +public: + const CPS::Attribute::Ptr mA; + const CPS::Attribute::Ptr mB; + const CPS::Attribute::Ptr mC; + const CPS::Attribute::Ptr mD; + + const CPS::Attribute::Ptr mdA; + const CPS::Attribute::Ptr mdB; + const CPS::Attribute::Ptr mdC; + + /// Defines UID, name, component parameters and logging level + SSNTypeI2T(String uid, String name, + Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + SSNTypeI2T(String name, Logger::Level logLevel = Logger::Level::off) + : SSNTypeI2T(name, name, logLevel) {} + + SimPowerComp::Ptr clone(String name) override; + + void manualInit(Matrix initialState, Matrix initialInput, + Matrix initialOldInput, Real initCurrent, Real initVoltage); + // #### General #### + void setParameters(const Matrix A, const Matrix B, const Matrix C, + const Matrix D); + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + // #### MNA section #### + /// Initializes internal variables of the component + void mnaCompInitialize(Real omega, Real timeStep, + Attribute::Ptr leftVector) override; + /// Stamps system matrix + void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override; + /// Stamps right side (source) vector + void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override; + /// Update interface voltage from MNA system result + void mnaCompUpdateVoltage(const Matrix &leftVector) override; + /// Update interface current from MNA system result + void mnaCompUpdateCurrent(const Matrix &leftVector) override; + + void mnaCompPreStep(Real time, Int timeStepCount) override; + void mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; + + /// Add MNA pre step dependencies + void mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) override; + + /// Add MNA post step dependencies + void + mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; +}; +} // namespace Ph1 +} // namespace EMT +} // namespace CPS diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSNTypeV2T.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSNTypeV2T.h new file mode 100644 index 0000000000..078bd8c54e --- /dev/null +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSNTypeV2T.h @@ -0,0 +1,94 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include +#include + +namespace CPS { +namespace EMT { +namespace Ph1 { +/// \brief SSNTypeV2T +/// Model for a one phase, two terminal V-type SSN component which can be represented using +/// a state space equation system +/// x' = A * x + B * u +/// y = C * x + D * u +/// with x: state vector, y: output vector, u: input vector, +/// where u represents external voltage (mIntfVoltage), +/// y represents external current (mIntfCurrent), +/// x represents any component states. +class SSNTypeV2T : public MNASimPowerComp, + public SharedFactory { +private: + void ssnUpdateState(); + void setSSNMatricesToZero(); + +protected: + Matrix mX; + Matrix mU; + Matrix mUOld; + Matrix mW; + Matrix mYHist; + +public: + const CPS::Attribute::Ptr mA; + const CPS::Attribute::Ptr mB; + const CPS::Attribute::Ptr mC; + const CPS::Attribute::Ptr mD; + + const CPS::Attribute::Ptr mdA; + const CPS::Attribute::Ptr mdB; + const CPS::Attribute::Ptr mdC; + + /// Defines UID, name, component parameters and logging level + SSNTypeV2T(String uid, String name, + Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + SSNTypeV2T(String name, Logger::Level logLevel = Logger::Level::off) + : SSNTypeV2T(name, name, logLevel) {} + + SimPowerComp::Ptr clone(String name) override; + + void manualInit(Matrix initialState, Matrix initialInput, + Matrix initialOldInput, Real initCurrent, Real initVoltage); + + // #### General #### + void setParameters(const Matrix A, const Matrix B, const Matrix C, + const Matrix D); + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + // #### MNA section #### + /// Initializes internal variables of the component + void mnaCompInitialize(Real omega, Real timeStep, + Attribute::Ptr leftVector) override; + /// Stamps system matrix + void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override; + /// Stamps right side (source) vector + void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override; + /// Update interface voltage from MNA system result + void mnaCompUpdateVoltage(const Matrix &leftVector) override; + /// Update interface current from MNA system result + void mnaCompUpdateCurrent(const Matrix &leftVector) override; + + void mnaCompPreStep(Real time, Int timeStepCount) override; + void mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; + + /// Add MNA pre step dependencies + void mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) override; + + /// Add MNA post step dependencies + void + mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; +}; +} // namespace Ph1 +} // namespace EMT +} // namespace CPS diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSN_Full_Serial_RLC.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSN_Full_Serial_RLC.h new file mode 100644 index 0000000000..9a83abcef8 --- /dev/null +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_SSN_Full_Serial_RLC.h @@ -0,0 +1,100 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#pragma once + +#include +#include +#include +#include +#include + +namespace CPS { +namespace EMT { +namespace Ph1 { +namespace SSN { +/// \brief Full_Serial_RLC +/// +/// This element represents an one port circuit consisting of a resistor, +/// an inductor and a capacitor connected in series. The terminals are at +/// the beginning and the end of the component chain. +/// The states are the capacitor voltage and the inductor current, the output +/// is the latter of those states (inductor current). The input is the voltage +/// across the whole circuit. States and past inputs are updated after each +/// time step and are used to calculate the current (input) voltage, +/// represented as MNA node voltages. +/// SSN theory and variable naming based on +/// C. Dufour, J. Mahseredjian and J. Belanger, +/// "A combined state-space nodal method for the simulation of power system +/// transients," 2011 IEEE Power and Energy Society General Meeting, Detroit, +/// MI, USA, 2011, pp. 1-1, doi: 10.1109/PES.2011.6038887. keywords: +/// {Mathematical model;Analytical models;Equations;Power system transients; +/// Couplings;Switching circuits} + +class Full_Serial_RLC final : public MNASimPowerComp, + public SharedFactory, + public Base::Ph1::Resistor, + public Base::Ph1::Inductor, + public Base::Ph1::Capacitor { +public: + /// Defines UID, name, component parameters and logging level + Full_Serial_RLC(String uid, String name, + Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + Full_Serial_RLC(String name, Logger::Level logLevel = Logger::Level::off) + : Full_Serial_RLC(name, name, logLevel) {} + + SimPowerComp::Ptr clone(String name) override; + void setParameters(Real resistance, Real inductance, Real capacitance); + + // #### General #### + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + // #### MNA section #### + /// Initializes internal variables of the component + void mnaCompInitialize(Real omega, Real timeStep, + Attribute::Ptr leftVector) override; + /// Stamps system matrix + void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override; + /// Stamps right side (source) vector + void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override; + /// Update interface voltage from MNA system result + void mnaCompUpdateVoltage(const Matrix &leftVector) override; + /// Update interface current from MNA system result + void mnaCompUpdateCurrent(const Matrix &leftVector) override; + /// MNA pre step operations + void mnaCompPreStep(Real time, Int timeStepCount) override; + /// MNA post step operations + void mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; + /// Add MNA pre step dependencies + void mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) override; + /// Add MNA post step dependencies + void + mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; + +private: + Matrix mState = Matrix::Zero(2, 1); + Real mYHistory = 0; + + Real mDufourUNT = 0; + + Matrix mDufourAKHat = Matrix::Zero(2, 2); + Matrix mDufourBKHat = Matrix::Zero(2, 1); + Matrix mDufourBKNHat = Matrix::Zero(2, 1); + Real mDufourWKN = 0; + Matrix mDufourCKN = Matrix::Zero(1, 2); + + void ssnUpdateState(); +}; +} // namespace SSN +} // namespace Ph1 +} // namespace EMT +} // namespace CPS diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index 6507269e40..74dc60f479 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -70,6 +70,9 @@ list(APPEND MODELS_SOURCES EMT/EMT_Ph1_VoltageSourceRamp.cpp EMT/EMT_Ph1_VoltageSourceNorton.cpp EMT/EMT_Ph1_Switch.cpp + EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp + EMT/EMT_Ph1_SSNTypeI2T.cpp + EMT/EMT_Ph1_SSNTypeV2T.cpp EMT/EMT_Ph3_CurrentSource.cpp EMT/EMT_Ph3_VoltageSource.cpp diff --git a/dpsim-models/src/EMT/EMT_Ph1_SSNTypeI2T.cpp b/dpsim-models/src/EMT/EMT_Ph1_SSNTypeI2T.cpp new file mode 100644 index 0000000000..ffa8276ed0 --- /dev/null +++ b/dpsim-models/src/EMT/EMT_Ph1_SSNTypeI2T.cpp @@ -0,0 +1,254 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#include + +using namespace CPS; + +EMT::Ph1::SSNTypeI2T::SSNTypeI2T(String uid, String name, + Logger::Level logLevel) + : MNASimPowerComp(uid, name, true, true, logLevel), + mA(mAttributes->create("A")), + mB(mAttributes->create("B")), + mC(mAttributes->create("C")), + mD(mAttributes->create("D")), + mdA(mAttributes->create("dA")), + mdB(mAttributes->create("dB")), + mdC(mAttributes->create("dC")) { + setTerminalNumber(2); + setVirtualNodeNumber(1); + **mIntfVoltage = Matrix::Zero(1, 1); + **mIntfCurrent = Matrix::Zero(1, 1); + mParametersSet = false; +} + +void EMT::Ph1::SSNTypeI2T::setParameters(const Matrix A, const Matrix B, + const Matrix C, const Matrix D) { + try { + if (A.cols() != A.rows()) + throw std::invalid_argument( + "A needs to be quadratic; Set all matrices to scalar zero."); + **mA = A; + mX = Matrix::Zero((**mA).rows(), 1); + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + setSSNMatricesToZero(); + return; + } + try { + if (B.rows() != (**mA).cols()) + throw std::invalid_argument( + "Invalid dimensions; rows of B do not match columns and rows of A! " + "Set all matrices to scalar zero."); + if (B.cols() != 1) + throw std::invalid_argument( + "Invalid dimensions; two terminal V-type SSN component only has on " + "external voltage, so column number of B must be one! Set all " + "matrices to scalar zero."); + **mB = B; + mU = Matrix::Zero((**mB).cols(), 1); + mUOld = Matrix::Zero((**mB).cols(), 1); + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + setSSNMatricesToZero(); + return; + } + try { + if (C.rows() != 1) + throw std::invalid_argument( + "Invalid dimensions; a two terminal V type SSN component only has " + "one output current! C must have exactly one row! Set all matrices " + "to scalar zero."); + if (C.cols() != (**mA).rows()) + throw std::invalid_argument( + "Invalid dimensions; columns of C do not match rows of A! Set all " + "matrices to scalar zero."); + **mC = C; + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + setSSNMatricesToZero(); + return; + } + try { + if (D.rows() != 1) + throw std::invalid_argument( + "Invalid dimensions; a two terminal V type SSN component only has " + "one output current! D must have exactly one row! Set all matrices " + "to scalar zero."); + if (D.cols() != (**mB).cols()) + throw std::invalid_argument( + "Invalid dimensions; columns of D do not match columns of B and rows " + "of input vector u, which need to be one! Set all matrices to scalar " + "zero."); + **mD = D; + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + setSSNMatricesToZero(); + return; + } + mParametersSet = true; +} + +SimPowerComp::Ptr EMT::Ph1::SSNTypeI2T::clone(String name) { + auto copy = SSNTypeI2T::make(name, mLogLevel); + copy->setParameters(**mA, **mB, **mC, **mD); + return copy; +} + +void EMT::Ph1::SSNTypeI2T::initializeFromNodesAndTerminals(Real frequency) { + + (**mIntfCurrent)(0, 0) = 0; + (**mIntfVoltage)(0, 0) = 0; + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:f}" + "\nCurrent: {:f}" + "\nTerminal 0 voltage: {:f}" + "\nTerminal 1 voltage: {:f}" + "\n--- Initialization from powerflow finished ---", + (**mIntfVoltage)(0, 0), (**mIntfCurrent)(0, 0), + (RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)).real(), + (RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)).real()); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompInitialize( + Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); + + Math::calculateStateSpaceTrapezoidalMatrices(**mA, **mB, timeStep, **mdA, + **mdB); + mW = Matrix::Zero(1, 1); + mW = (**mC) * (**mdB) + (**mD); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompApplySystemMatrixStamp( + SparseMatrixRow &systemMatrix) { + + //IntfCurrent from terminal 1 (out of node 1, positive) into terminal 2 (negative) + if (terminalNotGrounded(0)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), + mVirtualNodes[0]->matrixNodeIndex(), -1); + Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), + matrixNodeIndex(0), -1); + } + if (terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), + mVirtualNodes[0]->matrixNodeIndex(), 1); + Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), + matrixNodeIndex(1), 1); + } + //negative entry to close mesh equation (V1-V0) - mW*IntfCurrent = y_hist + Math::addToMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), + mVirtualNodes[0]->matrixNodeIndex(), -mW(0, 0)); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompApplyRightSideVectorStamp( + Matrix &rightVector) { + // Update internal state + mYHist = (**mC) * ((**mdA) * mX + (**mdB) * mU); + Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(), + mYHist(0, 0)); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) { + + modifiedAttributes.push_back(mRightVector); + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompPreStep(Real time, Int timeStepCount) { + mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompAddPostStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); + ssnUpdateState(); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompUpdateVoltage(const Matrix &leftVector) { + // v1 - v0 + (**mIntfVoltage)(0, 0) = 0; + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0, 0) = + Math::realFromVectorElement(leftVector, matrixNodeIndex(1)); + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0, 0) = + (**mIntfVoltage)(0, 0) - + Math::realFromVectorElement(leftVector, matrixNodeIndex(0)); +} + +void EMT::Ph1::SSNTypeI2T::mnaCompUpdateCurrent(const Matrix &leftVector) { + mUOld = mU; + (**mIntfCurrent)(0, 0) = Math::realFromVectorElement( + leftVector, mVirtualNodes[0]->matrixNodeIndex()); + mU = **mIntfCurrent; +} + +void CPS::EMT::Ph1::SSNTypeI2T::setSSNMatricesToZero() { + **mA = Matrix::Zero(1, 1); + **mB = Matrix::Zero(1, 1); + **mC = Matrix::Zero(1, 1); + **mD = Matrix::Zero(1, 1); + + **mdA = Matrix::Zero(1, 1); + **mdB = Matrix::Zero(1, 1); + **mdC = Matrix::Zero(1, 1); + + mX = Matrix::Zero(1, 1); + mU = Matrix::Zero(1, 1); + mUOld = Matrix::Zero(1, 1); +} + +void EMT::Ph1::SSNTypeI2T::ssnUpdateState() { + mX = (**mdA) * mX + (**mdB) * (mU + mUOld); +} + +void EMT::Ph1::SSNTypeI2T::manualInit(Matrix initialState, Matrix initialInput, + Matrix initialOldInput, Real initCurrent, + Real initVoltage) { + try { + if (mParametersSet == false) + throw std::invalid_argument( + "Set parameters first! Setting x, u, u_old to zero."); + if (initialState.cols() != 1) + throw std::invalid_argument("State matrix is a vector; column number " + "must be one. Setting x, u, u_old to zero."); + if (initialState.rows() != (**mA).cols()) + throw std::invalid_argument( + "State row number does not match row and column number of A. Setting " + "x, u, u_old to zero."); + if (initialInput.cols() != 1 || initialOldInput.cols() != 1) + throw std::invalid_argument("Input matrices are vectors; column number " + "must be one. Setting x, u, u_old to zero."); + if (initialInput.rows() != (**mB).cols() || + initialOldInput.rows() != (**mB).cols()) + throw std::invalid_argument("Input vector rows have to match columns of " + "Matrix B; Setting x, u, u_old to zero."); + mX = initialState; + mU = initialInput; + mUOld = initialOldInput; + (**mIntfCurrent)(0, 0) = initCurrent; + (**mIntfVoltage)(0, 0) = initVoltage; + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + (**mIntfCurrent)(0, 0) = 0; + (**mIntfVoltage)(0, 0) = 0; + } +} diff --git a/dpsim-models/src/EMT/EMT_Ph1_SSNTypeV2T.cpp b/dpsim-models/src/EMT/EMT_Ph1_SSNTypeV2T.cpp new file mode 100644 index 0000000000..4b2b50bbed --- /dev/null +++ b/dpsim-models/src/EMT/EMT_Ph1_SSNTypeV2T.cpp @@ -0,0 +1,241 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#include + +using namespace CPS; + +EMT::Ph1::SSNTypeV2T::SSNTypeV2T(String uid, String name, + Logger::Level logLevel) + : MNASimPowerComp(uid, name, true, true, logLevel), + mA(mAttributes->create("A")), + mB(mAttributes->create("B")), + mC(mAttributes->create("C")), + mD(mAttributes->create("D")), + mdA(mAttributes->create("dA")), + mdB(mAttributes->create("dB")), + mdC(mAttributes->create("dC")) { + setTerminalNumber(2); + **mIntfVoltage = Matrix::Zero(1, 1); + **mIntfCurrent = Matrix::Zero(1, 1); + mParametersSet = false; +} + +void EMT::Ph1::SSNTypeV2T::setParameters(const Matrix A, const Matrix B, + const Matrix C, const Matrix D) { + try { + if (A.cols() != A.rows()) + throw std::invalid_argument( + "A needs to be quadratic; Set all matrices to scalar zero."); + **mA = A; + mX = Matrix::Zero((**mA).rows(), 1); + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + setSSNMatricesToZero(); + return; + } + try { + if (B.rows() != (**mA).cols()) + throw std::invalid_argument( + "Invalid dimensions; rows of B do not match columns and rows of A! " + "Set all matrices to scalar zero."); + if (B.cols() != 1) + throw std::invalid_argument( + "Invalid dimensions; two terminal V-type SSN component only has on " + "external voltage, so column number of B must be one! Set all " + "matrices to scalar zero."); + **mB = B; + mU = Matrix::Zero((**mB).cols(), 1); + mUOld = Matrix::Zero((**mB).cols(), 1); + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + setSSNMatricesToZero(); + return; + } + try { + if (C.rows() != 1) + throw std::invalid_argument( + "Invalid dimensions; a two terminal V type SSN component only has " + "one output current! C must have exactly one row! Set all matrices " + "to scalar zero."); + if (C.cols() != (**mA).rows()) + throw std::invalid_argument( + "Invalid dimensions; columns of C do not match rows of A! Set all " + "matrices to scalar zero."); + **mC = C; + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + setSSNMatricesToZero(); + return; + } + try { + if (D.rows() != 1) + throw std::invalid_argument( + "Invalid dimensions; a two terminal V type SSN component only has " + "one output current! D must have exactly one row! Set all matrices " + "to scalar zero."); + if (D.cols() != (**mB).cols()) + throw std::invalid_argument( + "Invalid dimensions; columns of D do not match columns of B and rows " + "of input vector u, which need to be one! Set all matrices to scalar " + "zero."); + **mD = D; + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + setSSNMatricesToZero(); + return; + } + mParametersSet = true; +} + +SimPowerComp::Ptr EMT::Ph1::SSNTypeV2T::clone(String name) { + auto copy = SSNTypeV2T::make(name, mLogLevel); + copy->setParameters(**mA, **mB, **mC, **mD); + return copy; +} + +void EMT::Ph1::SSNTypeV2T::initializeFromNodesAndTerminals(Real frequency) { + + (**mIntfCurrent)(0, 0) = 0; + (**mIntfVoltage)(0, 0) = 0; + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:f}" + "\nCurrent: {:f}" + "\nTerminal 0 voltage: {:f}" + "\nTerminal 1 voltage: {:f}" + "\n--- Initialization from powerflow finished ---", + (**mIntfVoltage)(0, 0), (**mIntfCurrent)(0, 0), + (RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)).real(), + (RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)).real()); +} + +void EMT::Ph1::SSNTypeV2T::mnaCompInitialize( + Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); + + Math::calculateStateSpaceTrapezoidalMatrices(**mA, **mB, timeStep, **mdA, + **mdB); + mW = Matrix::Zero(1, 1); + mW = (**mC) * (**mdB) + (**mD); +} + +void EMT::Ph1::SSNTypeV2T::mnaCompApplySystemMatrixStamp( + SparseMatrixRow &systemMatrix) { + + MNAStampUtils::stampConductance(mW(0, 0), systemMatrix, matrixNodeIndex(0), + matrixNodeIndex(1), terminalNotGrounded(0), + terminalNotGrounded(1), mSLog); +} + +void EMT::Ph1::SSNTypeV2T::mnaCompApplyRightSideVectorStamp( + Matrix &rightVector) { + // Update internal state + mYHist = (**mC) * ((**mdA) * mX + (**mdB) * mU); + if (terminalNotGrounded(0)) + Math::setVectorElement(rightVector, matrixNodeIndex(0), mYHist(0, 0)); + if (terminalNotGrounded(1)) + Math::setVectorElement(rightVector, matrixNodeIndex(1), -mYHist(0, 0)); +} + +void EMT::Ph1::SSNTypeV2T::mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) { + + modifiedAttributes.push_back(mRightVector); + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); +} + +void EMT::Ph1::SSNTypeV2T::mnaCompPreStep(Real time, Int timeStepCount) { + mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void EMT::Ph1::SSNTypeV2T::mnaCompAddPostStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void EMT::Ph1::SSNTypeV2T::mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); + ssnUpdateState(); +} + +void EMT::Ph1::SSNTypeV2T::mnaCompUpdateVoltage(const Matrix &leftVector) { + // v1 - v0 + mUOld = mU; + (**mIntfVoltage)(0, 0) = 0; + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0, 0) = + Math::realFromVectorElement(leftVector, matrixNodeIndex(1)); + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0, 0) = + (**mIntfVoltage)(0, 0) - + Math::realFromVectorElement(leftVector, matrixNodeIndex(0)); + mU = **mIntfVoltage; +} + +void EMT::Ph1::SSNTypeV2T::mnaCompUpdateCurrent(const Matrix &leftVector) { + **mIntfCurrent = mW * (**mIntfVoltage) + mYHist; +} + +void CPS::EMT::Ph1::SSNTypeV2T::setSSNMatricesToZero() { + **mA = Matrix::Zero(1, 1); + **mB = Matrix::Zero(1, 1); + **mC = Matrix::Zero(1, 1); + **mD = Matrix::Zero(1, 1); + + **mdA = Matrix::Zero(1, 1); + **mdB = Matrix::Zero(1, 1); + **mdC = Matrix::Zero(1, 1); + + mX = Matrix::Zero(1, 1); + mU = Matrix::Zero(1, 1); + mUOld = Matrix::Zero(1, 1); +} + +void EMT::Ph1::SSNTypeV2T::ssnUpdateState() { + mX = (**mdA) * mX + (**mdB) * (mU + mUOld); +} + +void EMT::Ph1::SSNTypeV2T::manualInit(Matrix initialState, Matrix initialInput, + Matrix initialOldInput, Real initCurrent, + Real initVoltage) { + try { + if (mParametersSet == false) + throw std::invalid_argument( + "Set parameters first! Setting x, u, u_old to zero."); + if (initialState.cols() != 1) + throw std::invalid_argument("State matrix is a vector; column number " + "must be one. Setting x, u, u_old to zero."); + if (initialState.rows() != (**mA).cols()) + throw std::invalid_argument( + "State row number does not match row and column number of A. Setting " + "x, u, u_old to zero."); + if (initialInput.cols() != 1 || initialOldInput.cols() != 1) + throw std::invalid_argument("Input matrices are vectors; column number " + "must be one. Setting x, u, u_old to zero."); + if (initialInput.rows() != (**mB).cols() || + initialOldInput.rows() != (**mB).cols()) + throw std::invalid_argument("Input vector rows have to match columns of " + "Matrix B; Setting x, u, u_old to zero."); + mX = initialState; + mU = initialInput; + mUOld = initialOldInput; + (**mIntfCurrent)(0, 0) = initCurrent; + (**mIntfVoltage)(0, 0) = initVoltage; + } catch (std::exception &e) { + SPDLOG_LOGGER_ERROR(mSLog, "Component {} : {}\n", **mName, e.what()); + (**mIntfCurrent)(0, 0) = 0; + (**mIntfVoltage)(0, 0) = 0; + } +} diff --git a/dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp b/dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp new file mode 100644 index 0000000000..6051a27972 --- /dev/null +++ b/dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp @@ -0,0 +1,222 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#include + +using namespace CPS; + +EMT::Ph1::SSN::Full_Serial_RLC::Full_Serial_RLC(String uid, String name, + Logger::Level logLevel) + : MNASimPowerComp(uid, name, true, true, logLevel), + Base::Ph1::Resistor(mAttributes), Base::Ph1::Inductor(mAttributes), + Base::Ph1::Capacitor(mAttributes) { + + mPhaseType = PhaseType::Single; + + **mIntfVoltage = Matrix::Zero(1, 1); + **mIntfCurrent = Matrix::Zero(1, 1); + setTerminalNumber(2); +} + +SimPowerComp::Ptr EMT::Ph1::SSN::Full_Serial_RLC::clone(String name) { + auto copy = Full_Serial_RLC::make(name, mLogLevel); + copy->setParameters(**mResistance, **mInductance, **mCapacitance); + return copy; +} + +void EMT::Ph1::SSN::Full_Serial_RLC::initializeFromNodesAndTerminals( + Real frequency) { + + Real omega = 2 * PI * frequency; + + Complex impedance = + Complex((**mResistance), + omega * (**mInductance) - 1. / (omega * (**mCapacitance))); + + Complex vInit = RMS3PH_TO_PEAK1PH * initialSingleVoltage(1) - + RMS3PH_TO_PEAK1PH * initialSingleVoltage(0); + (**mIntfVoltage)(0, 0) = vInit.real(); + (**mIntfCurrent)(0, 0) = (vInit / impedance).real(); + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:f}" + "\nCurrent: {:f}" + "\nTerminal 0 voltage: {:f}" + "\nTerminal 1 voltage: {:f}" + "\n--- Initialization from powerflow finished ---", + (**mIntfVoltage)(0, 0), (**mIntfCurrent)(0, 0), + (RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)).real(), + (RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)).real()); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompInitialize( + Real omega, Real timeStep, Attribute::Ptr leftVector) { + + updateMatrixNodeIndices(); + + mState = Matrix::Zero(2, 1); + mYHistory = 0; + + //Fill mDufourAKHat + //State Equation one: top left entry + mDufourAKHat(0, 0) = + 1. - ((2. * (timeStep * timeStep)) / + (4. * (**mInductance) * (**mCapacitance) + + 2. * timeStep * (**mCapacitance) * (**mResistance) + + timeStep * timeStep)); + //State Equation one: top right entry + mDufourAKHat(0, 1) = + (timeStep / (2. * (**mCapacitance))) * + (1. + ((4. * (**mInductance) * (**mCapacitance) - + 2. * timeStep * (**mResistance) * (**mCapacitance) - + (timeStep * timeStep)) / + (4. * (**mInductance) * (**mCapacitance) + + 2. * timeStep * (**mResistance) * (**mCapacitance) + + (timeStep * timeStep)))); + //State Equation two: bottom left entry + mDufourAKHat(1, 0) = -((4. * (**mCapacitance) * timeStep) / + (4. * (**mInductance) * (**mCapacitance) + + 2. * timeStep * (**mCapacitance) * (**mResistance) + + (timeStep * timeStep))); + //State Equation two: bottom right entry + mDufourAKHat(1, 1) = (4. * (**mInductance) * (**mCapacitance) - + 2. * timeStep * (**mResistance) * (**mCapacitance) - + (timeStep * timeStep)) / + (4. * (**mInductance) * (**mCapacitance) + + 2. * timeStep * (**mResistance) * (**mCapacitance) + + (timeStep * timeStep)); + + ///Fill mDufourBKHat + //State Equation one: top entry + mDufourBKHat(0, 0) = (timeStep * timeStep) / + (4. * (**mInductance) * (**mCapacitance) + + 2. * timeStep * (**mCapacitance) * (**mResistance) + + (timeStep * timeStep)); + + //State Equation two: bottom entry + mDufourBKHat(1, 0) = (timeStep * 2. * (**mCapacitance)) / + (4. * (**mInductance) * (**mCapacitance) + + 2. * timeStep * (**mCapacitance) * (**mResistance) + + (timeStep * timeStep)); + + mDufourBKNHat = mDufourBKHat; + + mDufourCKN(0, 1) = 1.; + + mDufourWKN = (mDufourCKN * mDufourBKHat)(0, 0); + + mState(1, 0) = (**mIntfCurrent)(0, 0); + ssnUpdateState(); + mState(1, 0) = (**mIntfCurrent)(0, 0); + + **mRightVector = Matrix::Zero(leftVector->get().rows(), 1); + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- MNA initialization ---" + "\nInitial voltage {:s}" + "\nInitial current {:s}" + "\n--- MNA initialization finished ---", + Logger::matrixToString(**mIntfVoltage), + Logger::matrixToString(**mIntfCurrent)); + mSLog->flush(); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompApplySystemMatrixStamp( + SparseMatrixRow &systemMatrix) { + MNAStampUtils::stampConductance(mDufourWKN, systemMatrix, matrixNodeIndex(0), + matrixNodeIndex(1), terminalNotGrounded(0), + terminalNotGrounded(1), mSLog); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompApplyRightSideVectorStamp( + Matrix &rightVector) { + // Update history term + mYHistory = (mDufourCKN * + (mDufourAKHat * mState + mDufourBKHat * **mIntfVoltage))(0, 0); + + if (terminalNotGrounded(0)) { + Math::setVectorElement(rightVector, matrixNodeIndex(0, 0), mYHistory); + } + if (terminalNotGrounded(1)) { + Math::setVectorElement(rightVector, matrixNodeIndex(1, 0), -mYHistory); + } + SPDLOG_LOGGER_DEBUG( + mSLog, "\nHistory current term (mnaCompApplyRightSideVectorStamp): {:s}", + Logger::matrixToString(mYHistory)); + mSLog->flush(); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) { + // actually depends on L,C, but then we'd have to modify the system matrix anyway + prevStepDependencies.push_back(mIntfVoltage); + prevStepDependencies.push_back(mIntfCurrent); + modifiedAttributes.push_back(mRightVector); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompPreStep(Real time, + Int timeStepCount) { + mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompAddPostStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompPostStep( + Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); + ssnUpdateState(); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompUpdateVoltage( + const Matrix &leftVector) { + // v1 - v0 + mDufourUNT = (**mIntfVoltage)(0, 0); + **mIntfVoltage = Matrix::Zero(1, 1); + if (terminalNotGrounded(1)) { + (**mIntfVoltage)(0, 0) = + Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); + } + if (terminalNotGrounded(0)) { + (**mIntfVoltage)(0, 0) = + (**mIntfVoltage)(0, 0) - + Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); + } + SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate Voltage: {:s}", + Logger::matrixToString(**mIntfVoltage)); + mSLog->flush(); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompUpdateCurrent( + const Matrix &leftVector) { + (**mIntfCurrent)(0, 0) = mYHistory + (mDufourWKN * **mIntfVoltage)(0, 0); + + SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate Current: {:s}", + Logger::matrixToString(**mIntfCurrent)); + mSLog->flush(); +} + +void EMT::Ph1::SSN::Full_Serial_RLC::setParameters(Real resistance, + Real inductance, + Real capacitance) { + **mInductance = inductance; + **mCapacitance = capacitance; + **mResistance = resistance; + mParametersSet = true; +} + +void EMT::Ph1::SSN::Full_Serial_RLC::ssnUpdateState() { + mState = mDufourAKHat * mState + mDufourBKHat * mDufourUNT + + mDufourBKNHat * **mIntfVoltage; +} From 951e880ae8646ad08bf4a2b6bf3a6aaa4fd320e1 Mon Sep 17 00:00:00 2001 From: Marvin Tollnitsch Date: Fri, 12 Dec 2025 07:10:26 +0100 Subject: [PATCH 161/168] Made Ph1::SSN::RLC & general. two terminal SSN models usable in pybind Signed-off-by: Marvin Tollnitsch --- dpsim/src/pybind/EMTComponents.cpp | 83 +++++++++++++++++++++++++++--- 1 file changed, 77 insertions(+), 6 deletions(-) diff --git a/dpsim/src/pybind/EMTComponents.cpp b/dpsim/src/pybind/EMTComponents.cpp index 9d0a2d4ac5..2afc272f7d 100644 --- a/dpsim/src/pybind/EMTComponents.cpp +++ b/dpsim/src/pybind/EMTComponents.cpp @@ -119,6 +119,77 @@ void addEMTPh1Components(py::module_ mEMTPh1) { .def("open", &CPS::EMT::Ph1::Switch::open) .def("close", &CPS::EMT::Ph1::Switch::close) .def("connect", &CPS::EMT::Ph1::Switch::connect); + + py::class_, + CPS::SimPowerComp>(mEMTPh1, "Full_Serial_RLC", + py::multiple_inheritance()) + .def(py::init()) + .def(py::init()) + .def("set_parameters", + &CPS::EMT::Ph1::SSN::Full_Serial_RLC::setParameters, "R"_a, "L"_a, + "C"_a) + .def("connect", &CPS::EMT::Ph1::SSN::Full_Serial_RLC::connect) + .def_property("R", createAttributeGetter("R"), + createAttributeSetter("R")) + .def_property("L", createAttributeGetter("L"), + createAttributeSetter("L")) + .def_property("C", createAttributeGetter("C"), + createAttributeSetter("C")); + + py::class_, + CPS::SimPowerComp>(mEMTPh1, "SSNTypeI2T", + py::multiple_inheritance()) + .def(py::init()) + .def(py::init()) + .def("set_parameters", &CPS::EMT::Ph1::SSNTypeI2T::setParameters, "A"_a, + "B"_a, "C"_a, "D"_a) + .def("manual_init", &CPS::EMT::Ph1::SSNTypeI2T::manualInit, + "initialState"_a, "initialInput"_a, "initialOldInput"_a, + "initCurr"_a, "initVol"_a) + .def("connect", &CPS::EMT::Ph1::SSNTypeI2T::connect) + .def_property("mA", createAttributeGetter("mA"), + createAttributeSetter("mA")) + .def_property("mB", createAttributeGetter("mB"), + createAttributeSetter("mB")) + .def_property("mC", createAttributeGetter("mC"), + createAttributeSetter("mC")) + .def_property("mD", createAttributeGetter("mD"), + createAttributeSetter("mD")) + .def_property("mdA", createAttributeGetter("mdA"), + createAttributeSetter("mdA")) + .def_property("mdB", createAttributeGetter("mdB"), + createAttributeSetter("mdB")) + .def_property("mdC", createAttributeGetter("mdC"), + createAttributeSetter("mdC")); + + py::class_, + CPS::SimPowerComp>(mEMTPh1, "SSNTypeV2T", + py::multiple_inheritance()) + .def(py::init()) + .def(py::init()) + .def("set_parameters", &CPS::EMT::Ph1::SSNTypeV2T::setParameters, "A"_a, + "B"_a, "C"_a, "D"_a) + .def("manual_init", &CPS::EMT::Ph1::SSNTypeV2T::manualInit, + "initialState"_a, "initialInput"_a, "initialOldInput"_a, + "initCurr"_a, "initVol"_a) + .def("connect", &CPS::EMT::Ph1::SSNTypeV2T::connect) + .def_property("mA", createAttributeGetter("mA"), + createAttributeSetter("mA")) + .def_property("mB", createAttributeGetter("mB"), + createAttributeSetter("mB")) + .def_property("mC", createAttributeGetter("mC"), + createAttributeSetter("mC")) + .def_property("mD", createAttributeGetter("mD"), + createAttributeSetter("mD")) + .def_property("mdA", createAttributeGetter("mdA"), + createAttributeSetter("mdA")) + .def_property("mdB", createAttributeGetter("mdB"), + createAttributeSetter("mdB")) + .def_property("mdC", createAttributeGetter("mdC"), + createAttributeSetter("mdC")); } void addEMTPh3Components(py::module_ mEMTPh3) { @@ -487,10 +558,10 @@ void addEMTPh3Components(py::module_ mEMTPh3) { &CPS::EMT::Ph3::SSN::Full_Serial_RLC::setParameters, "R"_a, "L"_a, "C"_a) .def("connect", &CPS::EMT::Ph3::SSN::Full_Serial_RLC::connect) - .def_property("R", createAttributeGetter("R"), - createAttributeSetter("R")) - .def_property("L", createAttributeGetter("L"), - createAttributeSetter("L")) - .def_property("C", createAttributeGetter("C"), - createAttributeSetter("C")); + .def_property("R", createAttributeGetter("R"), + createAttributeSetter("R")) + .def_property("L", createAttributeGetter("L"), + createAttributeSetter("L")) + .def_property("C", createAttributeGetter("C"), + createAttributeSetter("C")); } From 2899c09d84010defcbf0dddb9dc608365c8cda93 Mon Sep 17 00:00:00 2001 From: Marvin Tollnitsch Date: Fri, 12 Dec 2025 07:12:24 +0100 Subject: [PATCH 162/168] Added example circuits for new generalized two terminal SSN models + added "EMT_Ph1_General2TerminalSSN.cpp" and corresponding notebook "EMT_Ph1_generalizedSSN.ipynb" + added "EMT_Ph1_General2TerminalSSN.cpp" to "examples/cxx/CMakeLists.txt" as a circuit source + added "EMT_generalizedSSN_RLC_dpsimpy.ipynb" to test generalized SSN RLC implementation in a circuit via pybind Signed-off-by: Marvin Tollnitsch --- dpsim/examples/cxx/CMakeLists.txt | 2 + .../Circuits/EMT_Ph1_General2TerminalSSN.cpp | 373 ++++++++++++++++ .../Circuits/EMT_Ph1_generalizedSSN.ipynb | 374 +++++++++++++++++ .../EMT_generalizedSSN_RLC_dpsimpy.ipynb | 397 ++++++++++++++++++ 4 files changed, 1146 insertions(+) create mode 100644 dpsim/examples/cxx/Circuits/EMT_Ph1_General2TerminalSSN.cpp create mode 100644 examples/Notebooks/Circuits/EMT_Ph1_generalizedSSN.ipynb create mode 100644 examples/Notebooks/Circuits/EMT_generalizedSSN_RLC_dpsimpy.ipynb diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index b9075bc7e1..3965d6b3ae 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -36,6 +36,7 @@ set(CIRCUIT_SOURCES Circuits/EMT_DecouplingLine_Ph3.cpp Circuits/EMT_Ph3_R3C1L1CS1_RC_vs_SSN.cpp Circuits/EMT_Ph3_RLC1VS1_RC_vs_SSN.cpp + Circuits/EMT_Ph1_General2TerminalSSN.cpp # EMT examples with PF initialization Circuits/EMT_Slack_PiLine_PQLoad_with_PF_Init.cpp @@ -141,6 +142,7 @@ list(APPEND TEST_SOURCES Circuits/DP_SMIB_ReducedOrderSGIterative_LoadStep.cpp Circuits/EMT_Ph3_R3C1L1CS1_RC_vs_SSN.cpp Circuits/EMT_Ph3_RLC1VS1_RC_vs_SSN.cpp + Circuits/EMT_Ph1_General2TerminalSSN.cpp ) if(WITH_SUNDIALS) diff --git a/dpsim/examples/cxx/Circuits/EMT_Ph1_General2TerminalSSN.cpp b/dpsim/examples/cxx/Circuits/EMT_Ph1_General2TerminalSSN.cpp new file mode 100644 index 0000000000..893ba4bb3a --- /dev/null +++ b/dpsim/examples/cxx/Circuits/EMT_Ph1_General2TerminalSSN.cpp @@ -0,0 +1,373 @@ +// SPDX-FileCopyrightText: 2025 Institute for Automation of Complex Power Systems, EONERC, RWTH Aachen University +// SPDX-License-Identifier: MPL-2.0 + +#include + +using namespace DPsim; +using namespace CPS::EMT; + +void EMT_Ph1_C1R1Vs_RC() { + // Define simulation scenario + Real timeStep = 0.0001; + Real finalTime = 0.1; + String simName = "EMT_Ph1_General2TerminalSSN_C1R1Vs_RC"; + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::Single); + auto n2 = SimNode::make("n2", PhaseType::Single); + + // Components + + auto c = Ph1::Capacitor::make("c_rc"); + c->setParameters(0.01); + + auto r = Ph1::Resistor::make("r_rc"); + r->setParameters(10.0); + + auto vs = Ph1::VoltageSource::make("vs_rc"); + vs->setParameters((CPS::Math::polar(1.0, CPS::Math::degToRad(-90.0))), 50.0); + + // Topology + vs->connect(SimNode::List{SimNode::GND, n1}); + + c->connect(SimNode::List{n1, n2}); + r->connect(SimNode::List{n2, SimNode::GND}); + + // Define system topology + auto sys = + SystemTopology(50, SystemNodeList{n1, n2}, SystemComponentList{vs, c, r}); + + // Logging + Logger::setLogDir("logs/" + simName); + auto logger = DataLogger::make(simName); + logger->logAttribute("v_c_rc", c->attribute("v_intf")); + logger->logAttribute("i_c_rc", c->attribute("i_intf")); + + Simulation sim(simName, Logger::Level::info); + sim.setSystem(sys); + sim.addLogger(logger); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.run(); +} + +void EMT_Ph1_C1R1Vs_generalizedSSN() { + // Define simulation scenario + Real timeStep = 0.0001; + Real finalTime = 0.1; + String simName = "EMT_Ph1_General2TerminalSSN_C1R1Vs_generalizedSSN"; + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::Single); + auto n2 = SimNode::make("n2", PhaseType::Single); + + // Components + + auto c = Ph1::SSNTypeI2T::make("c_genSSN"); + //du_c/dt = i_c/c , y = u_c --> u = i_c, x = u_c, A = 0, B = 1/c, C = 1, D = 0 + double c_param = 0.01; + Matrix A = Matrix::Zero(1, 1); + Matrix B = Matrix::Zero(1, 1); + B(0, 0) = (1 / c_param); + Matrix C = Matrix::Zero(1, 1); + C(0, 0) = 1; + Matrix D = Matrix::Zero(1, 1); + c->setParameters(A, B, C, D); + + auto r = Ph1::Resistor::make("r_genSSN"); + r->setParameters(10.0); + + auto vs = Ph1::VoltageSource::make("vs_genSSN"); + vs->setParameters((CPS::Math::polar(1.0, CPS::Math::degToRad(-90.0))), 50.0); + + // Topology + vs->connect(SimNode::List{SimNode::GND, n1}); + + c->connect(SimNode::List{n1, n2}); + r->connect(SimNode::List{n2, SimNode::GND}); + + // Define system topology + auto sys = + SystemTopology(50, SystemNodeList{n1, n2}, SystemComponentList{vs, c, r}); + + // Logging + Logger::setLogDir("logs/" + simName); + auto logger = DataLogger::make(simName); + logger->logAttribute("v_c_genSSN", c->attribute("v_intf")); + logger->logAttribute("i_c_genSSN", c->attribute("i_intf")); + + Simulation sim(simName, Logger::Level::info); + sim.setSystem(sys); + sim.addLogger(logger); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.run(); +} + +void EMT_Ph1_L1R1Vs_RC() { + // Define simulation scenario + Real timeStep = 0.0001; + Real finalTime = 0.1; + String simName = "EMT_Ph1_General2TerminalSSN_L1R1Vs_RC"; + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::Single); + auto n2 = SimNode::make("n2", PhaseType::Single); + + // Components + + auto l = Ph1::Inductor::make("l_rc"); + l->setParameters(0.01); + + auto r = Ph1::Resistor::make("r_rc"); + r->setParameters(10.0); + + auto vs = Ph1::VoltageSource::make("vs_rc"); + vs->setParameters((CPS::Math::polar(1.0, CPS::Math::degToRad(-90.0))), 50.0); + + // Topology + vs->connect(SimNode::List{SimNode::GND, n1}); + + l->connect(SimNode::List{n1, n2}); + r->connect(SimNode::List{n2, SimNode::GND}); + + // Define system topology + auto sys = + SystemTopology(50, SystemNodeList{n1, n2}, SystemComponentList{vs, l, r}); + + // Logging + Logger::setLogDir("logs/" + simName); + auto logger = DataLogger::make(simName); + logger->logAttribute("v_l_rc", l->attribute("v_intf")); + logger->logAttribute("i_l_rc", l->attribute("i_intf")); + + Simulation sim(simName, Logger::Level::info); + sim.setSystem(sys); + sim.addLogger(logger); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.run(); +} + +void EMT_Ph1_L1R1Vs_generalizedSSN() { + // Define simulation scenario + Real timeStep = 0.0001; + Real finalTime = 0.1; + String simName = "EMT_Ph1_General2TerminalSSN_L1R1Vs_generalizedSSN"; + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::Single); + auto n2 = SimNode::make("n2", PhaseType::Single); + + // Components + + auto l = Ph1::SSNTypeV2T::make("l_genSSN"); + //di_L/dt = v_L/L , y = i_L --> u = v_L, x = i_L, A = 0, B = 1/L, C = 1, D = 0 + double l_param = 0.01; + Matrix A = Matrix::Zero(1, 1); + Matrix B = Matrix::Zero(1, 1); + B(0, 0) = (1 / l_param); + Matrix C = Matrix::Zero(1, 1); + C(0, 0) = 1; + Matrix D = Matrix::Zero(1, 1); + l->setParameters(A, B, C, D); + + auto r = Ph1::Resistor::make("R1"); + r->setParameters(10.0); + + auto vs = Ph1::VoltageSource::make("vs"); + vs->setParameters((CPS::Math::polar(1.0, CPS::Math::degToRad(-90.0))), 50.0); + + // Topology + vs->connect(SimNode::List{SimNode::GND, n1}); + + l->connect(SimNode::List{n1, n2}); + r->connect(SimNode::List{n2, SimNode::GND}); + + // Define system topology + auto sys = + SystemTopology(50, SystemNodeList{n1, n2}, SystemComponentList{vs, l, r}); + + // Logging + Logger::setLogDir("logs/" + simName); + auto logger = DataLogger::make(simName); + logger->logAttribute("v_l_genSSN", l->attribute("v_intf")); + logger->logAttribute("i_l_genSSN", l->attribute("i_intf")); + + Simulation sim(simName, Logger::Level::info); + sim.setSystem(sys); + sim.addLogger(logger); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.run(); +} + +void EMT_Ph1_RLCVs_RC() { + // Define simulation scenario + Real timeStep = 0.0001; + Real finalTime = 0.1; + String simName = "EMT_Ph1_General2TerminalSSN_RLCVs_RC"; + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::Single); + auto n2 = SimNode::make("n2", PhaseType::Single); + auto n3 = SimNode::make("n3", PhaseType::Single); + + // Components + + auto r = Ph1::Resistor::make("r_rc"); + r->setParameters(10.0); + + auto l = Ph1::Inductor::make("l_rc"); + l->setParameters(0.01); + + auto c = Ph1::Capacitor::make("c_rc"); + c->setParameters(0.002); + + auto vs = Ph1::VoltageSource::make("vs_rc"); + vs->setParameters((CPS::Math::polar(1.0, CPS::Math::degToRad(-90.0))), 50.0); + + // Topology + vs->connect(SimNode::List{SimNode::GND, n1}); + + r->connect(SimNode::List{n1, n2}); + l->connect(SimNode::List{n2, n3}); + c->connect(SimNode::List{n3, SimNode::GND}); + + // Define system topology + auto sys = SystemTopology(50, SystemNodeList{n1, n2, n3}, + SystemComponentList{vs, r, l, c}); + + // Logging + Logger::setLogDir("logs/" + simName); + auto logger = DataLogger::make(simName); + logger->logAttribute("v_l_rlc_rc", l->attribute("v_intf")); + logger->logAttribute("i_l_rlc_rc", l->attribute("i_intf")); + + Simulation sim(simName, Logger::Level::info); + sim.setSystem(sys); + sim.addLogger(logger); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.run(); +} + +void EMT_Ph1_RLCVs_explicitSSN() { + // Define simulation scenario + Real timeStep = 0.0001; + Real finalTime = 0.1; + String simName = "EMT_Ph1_General2TerminalSSN_RLCVs_explicitSSN"; + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::Single); + + // Components + + auto rlc = Ph1::SSN::Full_Serial_RLC::make("rlc"); + double r_param = 10.0; + double l_param = 0.01; + double c_param = 0.002; + + rlc->setParameters(r_param, l_param, c_param); + + auto vs = Ph1::VoltageSource::make("vs"); + vs->setParameters((CPS::Math::polar(1.0, CPS::Math::degToRad(-90.0))), 50.0); + + // Topology + vs->connect(SimNode::List{SimNode::GND, n1}); + + rlc->connect(SimNode::List{n1, SimNode::GND}); + + // Define system topology + auto sys = + SystemTopology(50, SystemNodeList{n1}, SystemComponentList{vs, rlc}); + + // Logging + Logger::setLogDir("logs/" + simName); + auto logger = DataLogger::make(simName); + logger->logAttribute("v_rlc_explSSN", rlc->attribute("v_intf")); + logger->logAttribute("i_rlc_explSSN", rlc->attribute("i_intf")); + + Simulation sim(simName, Logger::Level::info); + sim.setSystem(sys); + sim.addLogger(logger); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.run(); +} + +void EMT_Ph1_RLCVs_generalizedSSN() { + // Define simulation scenario + Real timeStep = 0.0001; + Real finalTime = 0.1; + String simName = "EMT_Ph1_General2TerminalSSN_RLCVs_generalizedSSN"; + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::Single); + + // Components + + auto rlc = Ph1::SSNTypeV2T::make("rlc_genSSN"); + + double r = 10.0; + double l = 0.01; + double c = 0.002; + + Matrix A = Matrix::Zero(2, 2); + A(0, 0) = 0; + A(0, 1) = 1. / c; + A(1, 0) = -1. / l; + A(1, 1) = -r / l; + Matrix B = Matrix::Zero(2, 1); + B(0, 0) = 0; + B(1, 0) = 1. / l; + Matrix C = Matrix::Zero(1, 2); + C(0, 0) = 0; + C(0, 1) = 1; + Matrix D = Matrix::Zero(1, 1); + rlc->setParameters(A, B, C, D); + + auto vs = Ph1::VoltageSource::make("vs"); + vs->setParameters((CPS::Math::polar(1.0, CPS::Math::degToRad(-90.0))), 50.0); + + // Topology + vs->connect(SimNode::List{SimNode::GND, n1}); + + rlc->connect(SimNode::List{n1, SimNode::GND}); + + // Define system topology + auto sys = + SystemTopology(50, SystemNodeList{n1}, SystemComponentList{vs, rlc}); + + // Logging + Logger::setLogDir("logs/" + simName); + auto logger = DataLogger::make(simName); + logger->logAttribute("v_rlc_genSSN", rlc->attribute("v_intf")); + logger->logAttribute("i_rlc_genSSN", rlc->attribute("i_intf")); + + Simulation sim(simName, Logger::Level::info); + sim.setSystem(sys); + sim.addLogger(logger); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.run(); +} + +int main(int argc, char *argv[]) { + EMT_Ph1_C1R1Vs_RC(); + EMT_Ph1_C1R1Vs_generalizedSSN(); + + EMT_Ph1_L1R1Vs_RC(); + EMT_Ph1_L1R1Vs_generalizedSSN(); + + EMT_Ph1_RLCVs_RC(); + EMT_Ph1_RLCVs_explicitSSN(); + EMT_Ph1_RLCVs_generalizedSSN(); +} diff --git a/examples/Notebooks/Circuits/EMT_Ph1_generalizedSSN.ipynb b/examples/Notebooks/Circuits/EMT_Ph1_generalizedSSN.ipynb new file mode 100644 index 0000000000..4b5e9b7440 --- /dev/null +++ b/examples/Notebooks/Circuits/EMT_Ph1_generalizedSSN.ipynb @@ -0,0 +1,374 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Comparing RC and generalized two terminal SSN linear circuit simulations in EMT Ph1 domain\n", + "### Comparing EMT domain simulations of Ph1 linear circuits built from Resistive Companion (RC) component models against the same linear circuits build from generalized two terminal SSN (State Space Nodal) component models." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run C++ examples: R1C1Vs, R1L1Vs and RLCVs circuits" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import subprocess\n", + "\n", + "# %matplotlib widget\n", + "\n", + "name = \"EMT_Ph1_General2TerminalSSN\"\n", + "\n", + "dpsim_path = (\n", + " subprocess.Popen([\"git\", \"rev-parse\", \"--show-toplevel\"], stdout=subprocess.PIPE)\n", + " .communicate()[0]\n", + " .rstrip()\n", + " .decode(\"utf-8\")\n", + ")\n", + "\n", + "path_exec = dpsim_path + \"/build/dpsim/examples/cxx/\"\n", + "sim = subprocess.Popen(\n", + " [path_exec + name], stdout=subprocess.PIPE, stderr=subprocess.STDOUT\n", + ")\n", + "print(sim.communicate()[0].decode())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load Results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from villas.dataprocessing.readtools import *\n", + "from villas.dataprocessing.timeseries import *\n", + "from villas.dataprocessing.timeseries import TimeSeries as ts\n", + "import matplotlib.pyplot as plt\n", + "import re\n", + "import numpy as np\n", + "import math\n", + "\n", + "work_dir = os.getcwd() + \"/logs/\"\n", + "path_logfile_C1R1Vs_RC = work_dir + name + \"_C1R1Vs_RC/\" + name + \"_C1R1Vs_RC\" + \".csv\"\n", + "ts_EMT_Ph1_C1R1Vs_RC = read_timeseries_dpsim(path_logfile_C1R1Vs_RC)\n", + "path_logfile_C1R1Vs_generalizedSSN = (\n", + " work_dir\n", + " + name\n", + " + \"_C1R1Vs_generalizedSSN/\"\n", + " + name\n", + " + \"_C1R1Vs_generalizedSSN\"\n", + " + \".csv\"\n", + ")\n", + "ts_EMT_Ph1_C1R1Vs_generalizedSSN = read_timeseries_dpsim(\n", + " path_logfile_C1R1Vs_generalizedSSN\n", + ")\n", + "\n", + "path_logfile_L1R1Vs_RC = work_dir + name + \"_L1R1Vs_RC/\" + name + \"_L1R1Vs_RC\" + \".csv\"\n", + "ts_EMT_Ph1_L1R1Vs_RC = read_timeseries_dpsim(path_logfile_L1R1Vs_RC)\n", + "path_logfile_L1R1Vs_generalizedSSN = (\n", + " work_dir\n", + " + name\n", + " + \"_L1R1Vs_generalizedSSN/\"\n", + " + name\n", + " + \"_L1R1Vs_generalizedSSN\"\n", + " + \".csv\"\n", + ")\n", + "ts_EMT_Ph1_L1R1Vs_generalizedSSN = read_timeseries_dpsim(\n", + " path_logfile_L1R1Vs_generalizedSSN\n", + ")\n", + "\n", + "path_logfile_RLCVs_RC = work_dir + name + \"_RLCVs_RC/\" + name + \"_RLCVs_RC\" + \".csv\"\n", + "ts_EMT_Ph1_RLCVs_RC = read_timeseries_dpsim(path_logfile_RLCVs_RC)\n", + "path_logfile_RLCVs_explicitSSN = (\n", + " work_dir + name + \"_RLCVs_explicitSSN/\" + name + \"_RLCVs_explicitSSN\" + \".csv\"\n", + ")\n", + "ts_EMT_Ph1_RLCVs_explicitSSN = read_timeseries_dpsim(path_logfile_RLCVs_explicitSSN)\n", + "path_logfile_RLCVs_generalizedSSN = (\n", + " work_dir + name + \"_RLCVs_generalizedSSN/\" + name + \"_RLCVs_generalizedSSN\" + \".csv\"\n", + ")\n", + "ts_EMT_Ph1_RLCVs_generalizedSSN = read_timeseries_dpsim(\n", + " path_logfile_RLCVs_generalizedSSN\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plot C1R1Vs circuit results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.close(\"all\")\n", + "fig1 = plt.figure()\n", + "\n", + "plt.plot(\n", + " ts_EMT_Ph1_C1R1Vs_RC[\"v_c_rc\"].time,\n", + " ts_EMT_Ph1_C1R1Vs_RC[\"v_c_rc\"].values,\n", + " \"b-\",\n", + " label=\"v_c_rc\",\n", + ")\n", + "plt.plot(\n", + " ts_EMT_Ph1_C1R1Vs_generalizedSSN[\"v_c_genSSN\"].time,\n", + " ts_EMT_Ph1_C1R1Vs_generalizedSSN[\"v_c_genSSN\"].values,\n", + " \"bx\",\n", + " markevery=5,\n", + " label=\"v_c_genSSN\",\n", + ")\n", + "\n", + "plt.legend(loc=4)\n", + "\n", + "plt.title(\"RC vs generalized SSN simulation: Capacitor voltage\")\n", + "plt.xlabel(\"t [s]\")\n", + "plt.ylabel(\"Capacitor Voltage [V]\")\n", + "\n", + "\n", + "fig2 = plt.figure()\n", + "\n", + "plt.plot(\n", + " ts_EMT_Ph1_C1R1Vs_RC[\"i_c_rc\"].time,\n", + " ts_EMT_Ph1_C1R1Vs_RC[\"i_c_rc\"].values,\n", + " \"r-\",\n", + " label=\"i_c_rc\",\n", + ")\n", + "plt.plot(\n", + " ts_EMT_Ph1_C1R1Vs_generalizedSSN[\"i_c_genSSN\"].time,\n", + " ts_EMT_Ph1_C1R1Vs_generalizedSSN[\"i_c_genSSN\"].values,\n", + " \"rx\",\n", + " markevery=5,\n", + " label=\"i_c_genSSN\",\n", + ")\n", + "\n", + "plt.legend(loc=4)\n", + "\n", + "plt.title(\"RC vs generalized SSN simulation: Capacitor current\")\n", + "plt.xlabel(\"t [s]\")\n", + "plt.ylabel(\"Capacitor Current [A]\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plot L1R1Vs circuit results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig3 = plt.figure()\n", + "\n", + "plt.plot(\n", + " ts_EMT_Ph1_L1R1Vs_RC[\"v_l_rc\"].time,\n", + " ts_EMT_Ph1_L1R1Vs_RC[\"v_l_rc\"].values,\n", + " \"b-\",\n", + " label=\"v_l_rc\",\n", + ")\n", + "plt.plot(\n", + " ts_EMT_Ph1_L1R1Vs_generalizedSSN[\"v_l_genSSN\"].time,\n", + " ts_EMT_Ph1_L1R1Vs_generalizedSSN[\"v_l_genSSN\"].values,\n", + " \"bx\",\n", + " markevery=5,\n", + " label=\"v_l_genSSN\",\n", + ")\n", + "\n", + "plt.legend(loc=4)\n", + "\n", + "plt.title(\"RC vs generalized SSN simulation: Inductor voltage\")\n", + "plt.xlabel(\"t [s]\")\n", + "plt.ylabel(\"Inductor Voltage [V]\")\n", + "\n", + "\n", + "fig4 = plt.figure()\n", + "\n", + "plt.plot(\n", + " ts_EMT_Ph1_L1R1Vs_RC[\"i_l_rc\"].time,\n", + " ts_EMT_Ph1_L1R1Vs_RC[\"i_l_rc\"].values,\n", + " \"r-\",\n", + " label=\"i_l_rc\",\n", + ")\n", + "plt.plot(\n", + " ts_EMT_Ph1_L1R1Vs_generalizedSSN[\"i_l_genSSN\"].time,\n", + " ts_EMT_Ph1_L1R1Vs_generalizedSSN[\"i_l_genSSN\"].values,\n", + " \"rx\",\n", + " markevery=5,\n", + " label=\"i_l_genSSN\",\n", + ")\n", + "\n", + "plt.legend(loc=4)\n", + "\n", + "plt.title(\"RC vs generalized SSN simulation: Inductor current\")\n", + "plt.xlabel(\"t [s]\")\n", + "plt.ylabel(\"Inductor Current [A]\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plot RLCVs circuit results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "fig5 = plt.figure()\n", + "\n", + "plt.plot(\n", + " ts_EMT_Ph1_RLCVs_RC[\"i_l_rlc_rc\"].time,\n", + " ts_EMT_Ph1_RLCVs_RC[\"i_l_rlc_rc\"].values,\n", + " \"r-\",\n", + " label=\"i_rlc_rc\",\n", + ")\n", + "plt.plot(\n", + " ts_EMT_Ph1_RLCVs_explicitSSN[\"i_rlc_explSSN\"].time,\n", + " ts_EMT_Ph1_RLCVs_explicitSSN[\"i_rlc_explSSN\"].values,\n", + " \"rx\",\n", + " markevery=8,\n", + " label=\"i_rlc_explSSN\",\n", + ")\n", + "plt.plot(\n", + " ts_EMT_Ph1_RLCVs_generalizedSSN[\"i_rlc_genSSN\"].time,\n", + " ts_EMT_Ph1_RLCVs_generalizedSSN[\"i_rlc_genSSN\"].values,\n", + " \"bx\",\n", + " markevery=(4, 8),\n", + " label=\"i_rlc_genSSN\",\n", + ")\n", + "\n", + "plt.legend(loc=4)\n", + "\n", + "plt.title(\"RC vs explicit SSN vs generalized SSN: RLC current\")\n", + "plt.xlabel(\"t [s]\")\n", + "plt.ylabel(\"RLC branch current [A]\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Assert" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "epsilon = 1e-12\n", + "\n", + "# Capacitor circuit\n", + "assert (\n", + " np.max(\n", + " ts_EMT_Ph1_C1R1Vs_RC[\"v_c_rc\"].values\n", + " - ts_EMT_Ph1_C1R1Vs_generalizedSSN[\"v_c_genSSN\"].values\n", + " )\n", + " < epsilon\n", + ")\n", + "assert (\n", + " np.max(\n", + " ts_EMT_Ph1_C1R1Vs_RC[\"i_c_rc\"].values\n", + " - ts_EMT_Ph1_C1R1Vs_generalizedSSN[\"i_c_genSSN\"].values\n", + " )\n", + " < epsilon\n", + ")\n", + "\n", + "# Inductor circuit\n", + "assert (\n", + " np.max(\n", + " ts_EMT_Ph1_L1R1Vs_RC[\"v_l_rc\"].values\n", + " - ts_EMT_Ph1_L1R1Vs_generalizedSSN[\"v_l_genSSN\"].values\n", + " )\n", + " < epsilon\n", + ")\n", + "assert (\n", + " np.max(\n", + " ts_EMT_Ph1_L1R1Vs_RC[\"i_l_rc\"].values\n", + " - ts_EMT_Ph1_L1R1Vs_generalizedSSN[\"i_l_genSSN\"].values\n", + " )\n", + " < epsilon\n", + ")\n", + "\n", + "# RLC circuit\n", + "assert (\n", + " np.max(\n", + " ts_EMT_Ph1_RLCVs_RC[\"i_l_rlc_rc\"].values\n", + " - ts_EMT_Ph1_RLCVs_explicitSSN[\"i_rlc_explSSN\"].values\n", + " )\n", + " < epsilon\n", + ")\n", + "assert (\n", + " np.max(\n", + " ts_EMT_Ph1_RLCVs_RC[\"i_l_rlc_rc\"].values\n", + " - ts_EMT_Ph1_RLCVs_generalizedSSN[\"i_rlc_genSSN\"].values\n", + " )\n", + " < epsilon\n", + ")\n", + "assert (\n", + " np.max(\n", + " ts_EMT_Ph1_RLCVs_explicitSSN[\"i_rlc_explSSN\"].values\n", + " - ts_EMT_Ph1_RLCVs_generalizedSSN[\"i_rlc_genSSN\"].values\n", + " )\n", + " < epsilon\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.13" + }, + "tests": { + "skip": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/Notebooks/Circuits/EMT_generalizedSSN_RLC_dpsimpy.ipynb b/examples/Notebooks/Circuits/EMT_generalizedSSN_RLC_dpsimpy.ipynb new file mode 100644 index 0000000000..b21ff9356f --- /dev/null +++ b/examples/Notebooks/Circuits/EMT_generalizedSSN_RLC_dpsimpy.ipynb @@ -0,0 +1,397 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from villas.dataprocessing.readtools import *\n", + "from villas.dataprocessing.timeseries import *\n", + "from villas.dataprocessing.timeseries import TimeSeries as ts\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import dpsimpy\n", + "import re\n", + "\n", + "# %matplotlib widget" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## RLC circuit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "time_step = 0.00005\n", + "final_time = 1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sim_name = \"EMT_RLC_py_RC\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "n2 = dpsimpy.emt.SimNode(\"n2\", dpsimpy.PhaseType.Single)\n", + "n3 = dpsimpy.emt.SimNode(\"n3\", dpsimpy.PhaseType.Single)\n", + "\n", + "# Components\n", + "vs = dpsimpy.emt.ph1.VoltageSource(\"vs\")\n", + "vs.set_parameters(complex(10, 0), 50)\n", + "\n", + "r = 10.0\n", + "res = dpsimpy.emt.ph1.Resistor(\"r\", dpsimpy.LogLevel.debug)\n", + "res.set_parameters(r)\n", + "l = 0.01\n", + "ind = dpsimpy.emt.ph1.Inductor(\"l\", dpsimpy.LogLevel.debug)\n", + "ind.set_parameters(l)\n", + "c = 0.002\n", + "cap = dpsimpy.emt.ph1.Capacitor(\"c\", dpsimpy.LogLevel.debug)\n", + "cap.set_parameters(c)\n", + "\n", + "# Topology\n", + "vs.connect([gnd, n1])\n", + "res.connect([n1, n2])\n", + "ind.connect([n2, n3])\n", + "cap.connect([n3, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [n1, n2, n3], [vs, res, ind, cap])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_RC\", \"i_intf\", res)\n", + "\n", + "# Simulation\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sim_name = \"EMT_RLC_py_explSSN\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "\n", + "# Components\n", + "vs = dpsimpy.emt.ph1.VoltageSource(\"vs\")\n", + "vs.set_parameters(complex(10, 0), 50)\n", + "\n", + "rlc = dpsimpy.emt.ph1.SSNTypeV2T(\"rlc\", dpsimpy.LogLevel.debug)\n", + "r = 10.0\n", + "l = 0.01\n", + "c = 0.002\n", + "A = [[0, 1.0 / c], [-1.0 / l, -r / l]]\n", + "B = [[0.0], [1.0 / l]]\n", + "C = [[0.0, 1.0]]\n", + "D = [[0.0]]\n", + "rlc.set_parameters(A, B, C, D)\n", + "\n", + "# Topology\n", + "vs.connect([gnd, n1])\n", + "rlc.connect([n1, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [n1], [vs, rlc])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_explSSN\", \"i_intf\", rlc)\n", + "\n", + "# Simulation\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sim_name = \"EMT_RLC_py_genSSN\"\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode(\"n1\", dpsimpy.PhaseType.Single)\n", + "\n", + "# Components\n", + "vs = dpsimpy.emt.ph1.VoltageSource(\"vs\")\n", + "vs.set_parameters(complex(10, 0), 50)\n", + "\n", + "rlc = dpsimpy.emt.ph1.Full_Serial_RLC(\"rlc\", dpsimpy.LogLevel.debug)\n", + "r = 10.0\n", + "l = 0.01\n", + "c = 0.002\n", + "rlc.set_parameters(r, l, c)\n", + "\n", + "# Topology\n", + "vs.connect([gnd, n1])\n", + "rlc.connect([n1, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [n1], [vs, rlc])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute(\"v1\", \"v\", n1)\n", + "logger.log_attribute(\"i_genSSN\", \"i_intf\", rlc)\n", + "\n", + "# Simulation\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "model_name = \"EMT_RLC_py\"\n", + "\n", + "path_RC = \"logs/\" + model_name + \"_RC\" + \"/\"\n", + "dpsim_result_file_RC = path_RC + model_name + \"_RC\" + \".csv\"\n", + "ts_dpsim_RC = read_timeseries_csv(dpsim_result_file_RC)\n", + "\n", + "path_explSSN = \"logs/\" + model_name + \"_explSSN\" + \"/\"\n", + "dpsim_result_file_explSSN = path_explSSN + model_name + \"_explSSN\" + \".csv\"\n", + "ts_dpsim_explSSN = read_timeseries_csv(dpsim_result_file_explSSN)\n", + "\n", + "path_genSSN = \"logs/\" + model_name + \"_genSSN\" + \"/\"\n", + "dpsim_result_file_genSSN = path_genSSN + model_name + \"_genSSN\" + \".csv\"\n", + "ts_dpsim_genSSN = read_timeseries_csv(dpsim_result_file_genSSN)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot voltages" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "\n", + "# RC\n", + "var_names = [\"v1\"]\n", + "for var_name in var_names:\n", + " plt.plot(\n", + " ts_dpsim_RC[var_name].time,\n", + " ts_dpsim_RC[var_name].values,\n", + " label=var_name + \"_RC\",\n", + " )\n", + "\n", + "# explicit SSN\n", + "var_names = [\"v1\"]\n", + "for var_name in var_names:\n", + " plt.plot(\n", + " ts_dpsim_explSSN[var_name].time,\n", + " ts_dpsim_explSSN[var_name].values,\n", + " label=var_name + \"_explSSN\",\n", + " linestyle=\"-.\",\n", + " markevery=(6, 9),\n", + " )\n", + "\n", + "# generalized SSN\n", + "var_names = [\"v1\"]\n", + "for var_name in var_names:\n", + " plt.plot(\n", + " ts_dpsim_genSSN[var_name].time,\n", + " ts_dpsim_genSSN[var_name].values,\n", + " label=var_name + \"_genSSN\",\n", + " linestyle=\":\",\n", + " markevery=(3, 9),\n", + " )\n", + "\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot currents" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "\n", + "# RC\n", + "var_names = [\"i_RC\"]\n", + "for var_name in var_names:\n", + " plt.plot(\n", + " ts_dpsim_RC[var_name].time,\n", + " ts_dpsim_RC[var_name].values,\n", + " label=var_name,\n", + " )\n", + "\n", + "# explicit SSN\n", + "var_names = [\"i_explSSN\"]\n", + "for var_name in var_names:\n", + " plt.plot(\n", + " ts_dpsim_explSSN[var_name].time,\n", + " ts_dpsim_explSSN[var_name].values,\n", + " label=var_name,\n", + " linestyle=\"-.\",\n", + " markevery=(6, 9),\n", + " )\n", + "\n", + "# generalized SSN\n", + "var_names = [\"i_genSSN\"]\n", + "for var_name in var_names:\n", + " plt.plot(\n", + " ts_dpsim_genSSN[var_name].time,\n", + " ts_dpsim_genSSN[var_name].values,\n", + " label=var_name,\n", + " linestyle=\":\",\n", + " markevery=(3, 9),\n", + " )\n", + "\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Assertion RC vs. explicit SSN vs. generalized SSN" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "epsilon = 1e-12\n", + "\n", + "max_abs_err_RC_explSSN = (\n", + " np.absolute(ts_dpsim_RC[\"i_RC\"].values - ts_dpsim_explSSN[\"i_explSSN\"].values)\n", + ").max()\n", + "max_abs_err_RC_genSSN = (\n", + " np.absolute(ts_dpsim_RC[\"i_RC\"].values - ts_dpsim_genSSN[\"i_genSSN\"].values)\n", + ").max()\n", + "max_abs_err_explSSN_genSSN = (\n", + " np.absolute(\n", + " ts_dpsim_explSSN[\"i_explSSN\"].values - ts_dpsim_genSSN[\"i_genSSN\"].values\n", + " )\n", + ").max()\n", + "\n", + "max_rel_err_RC_explSSN = (\n", + " max_abs_err_RC_explSSN / (np.absolute(ts_dpsim_RC[\"i_RC\"].values)).max()\n", + ")\n", + "max_rel_err_RC_genSSN = (\n", + " max_abs_err_RC_genSSN / (np.absolute(ts_dpsim_RC[\"i_RC\"].values)).max()\n", + ")\n", + "max_rel_err_explSSN_genSSN = (\n", + " max_abs_err_explSSN_genSSN\n", + " / (np.absolute(ts_dpsim_explSSN[\"i_explSSN\"].values)).max()\n", + ")\n", + "\n", + "print(\n", + " \"Maximum absolute Error for RC vs. expicit SSN: \",\n", + " max_abs_err_RC_explSSN,\n", + " \" giving a maximum relative error of: \",\n", + " max_rel_err_RC_explSSN,\n", + ")\n", + "print(\n", + " \"Maximum absolute Error for RC vs. generalized SSN: \",\n", + " max_abs_err_RC_genSSN,\n", + " \" giving a maximum relative error of: \",\n", + " max_rel_err_RC_genSSN,\n", + ")\n", + "print(\n", + " \"Maximum absolute Error for explicit SSN vs. generalized SSN: \",\n", + " max_abs_err_explSSN_genSSN,\n", + " \" giving a maximum relative error of: \",\n", + " max_rel_err_explSSN_genSSN,\n", + ")\n", + "\n", + "assert max_abs_err_RC_explSSN < epsilon\n", + "assert max_abs_err_RC_genSSN < epsilon\n", + "assert max_abs_err_explSSN_genSSN < epsilon\n", + "\n", + "assert max_rel_err_RC_explSSN < epsilon\n", + "assert max_rel_err_RC_genSSN < epsilon\n", + "assert max_rel_err_explSSN_genSSN < epsilon" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.13" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} From ff0965cd68975e802b1c376103ea46e094ae0538 Mon Sep 17 00:00:00 2001 From: Georgii Tishenin Date: Fri, 12 Dec 2025 14:02:46 +0100 Subject: [PATCH 163/168] Remove unnecessary use of mSLog->flush() Signed-off-by: Georgii Tishenin --- dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp b/dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp index 6051a27972..f46a9ad267 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp @@ -144,7 +144,6 @@ void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompApplyRightSideVectorStamp( SPDLOG_LOGGER_DEBUG( mSLog, "\nHistory current term (mnaCompApplyRightSideVectorStamp): {:s}", Logger::matrixToString(mYHistory)); - mSLog->flush(); } void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompAddPreStepDependencies( @@ -195,7 +194,6 @@ void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompUpdateVoltage( } SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate Voltage: {:s}", Logger::matrixToString(**mIntfVoltage)); - mSLog->flush(); } void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompUpdateCurrent( @@ -204,7 +202,6 @@ void EMT::Ph1::SSN::Full_Serial_RLC::mnaCompUpdateCurrent( SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate Current: {:s}", Logger::matrixToString(**mIntfCurrent)); - mSLog->flush(); } void EMT::Ph1::SSN::Full_Serial_RLC::setParameters(Real resistance, From 3ff63fd657379053d58b83d00b9a29741c6dc5b4 Mon Sep 17 00:00:00 2001 From: cwirtz Date: Tue, 4 Nov 2025 16:07:56 +0100 Subject: [PATCH 164/168] - Base Switch components changed to mnaVarCompInterface - all switches have hasComponentChanged functionality - in matrix recomputation case in mna solver, switch components are only restamped once with VarCompInterface Signed-off-by: cwirtz --- .../include/dpsim-models/Base/Base_Ph1_Switch.h | 3 +++ .../include/dpsim-models/Base/Base_Ph3_Switch.h | 6 ++++++ .../include/dpsim-models/DP/DP_Ph1_RXLoadSwitch.h | 4 ++++ .../include/dpsim-models/DP/DP_Ph1_Switch.h | 9 ++++++--- .../include/dpsim-models/DP/DP_Ph1_varResSwitch.h | 2 +- .../include/dpsim-models/DP/DP_Ph3_SeriesSwitch.h | 10 ++++++++-- .../include/dpsim-models/EMT/EMT_Ph1_Switch.h | 6 ++++-- .../include/dpsim-models/EMT/EMT_Ph3_SeriesSwitch.h | 8 +++++++- .../include/dpsim-models/EMT/EMT_Ph3_Switch.h | 7 +++++-- .../include/dpsim-models/SP/SP_Ph1_Switch.h | 6 +++++- .../include/dpsim-models/SP/SP_Ph1_varResSwitch.h | 2 +- dpsim-models/src/DP/DP_Ph1_RXLoadSwitch.cpp | 4 ++++ dpsim-models/src/DP/DP_Ph1_Switch.cpp | 10 ++++++++++ dpsim-models/src/DP/DP_Ph1_varResSwitch.cpp | 11 ++++------- dpsim-models/src/DP/DP_Ph3_SeriesSwitch.cpp | 13 +++++++++++++ dpsim-models/src/EMT/EMT_Ph1_Switch.cpp | 10 ++++++++++ dpsim-models/src/EMT/EMT_Ph3_SeriesSwitch.cpp | 10 ++++++++++ dpsim-models/src/EMT/EMT_Ph3_Switch.cpp | 10 ++++++++++ dpsim-models/src/SP/SP_Ph1_Switch.cpp | 10 ++++++++++ dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp | 11 ++++------- dpsim/src/MNASolverDirect.cpp | 13 ++----------- 21 files changed, 127 insertions(+), 38 deletions(-) diff --git a/dpsim-models/include/dpsim-models/Base/Base_Ph1_Switch.h b/dpsim-models/include/dpsim-models/Base/Base_Ph1_Switch.h index 0ec6fe0fa5..732e30d32d 100644 --- a/dpsim-models/include/dpsim-models/Base/Base_Ph1_Switch.h +++ b/dpsim-models/include/dpsim-models/Base/Base_Ph1_Switch.h @@ -16,6 +16,9 @@ namespace Base { namespace Ph1 { /// Dynamic Phasor Three-Phase Switch class Switch { +protected: + Bool mIsClosedPrev = false; + public: /// Resistance if switch is open [ohm] const Attribute::Ptr mOpenResistance; diff --git a/dpsim-models/include/dpsim-models/Base/Base_Ph3_Switch.h b/dpsim-models/include/dpsim-models/Base/Base_Ph3_Switch.h index d74fd2bb7c..f8280df21f 100644 --- a/dpsim-models/include/dpsim-models/Base/Base_Ph3_Switch.h +++ b/dpsim-models/include/dpsim-models/Base/Base_Ph3_Switch.h @@ -15,6 +15,9 @@ namespace Base { namespace Ph3 { /// Dynamic Phasor Three-Phase Switch class Switch { +protected: + Bool mIsClosedPrev = false; + public: /// Resistance if switch is open [ohm] const CPS::Attribute::Ptr mOpenResistance; @@ -37,6 +40,9 @@ class Switch { } void closeSwitch() { **mIsClosed = true; } void openSwitch() { **mIsClosed = false; } + + /// Check if switch is closed + Bool isClosed() { return **mIsClosed; } }; } // namespace Ph3 } // namespace Base diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_RXLoadSwitch.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_RXLoadSwitch.h index 4663d01e21..d59ddc3897 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_RXLoadSwitch.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_RXLoadSwitch.h @@ -17,6 +17,7 @@ namespace Ph1 { /// Constant impedance load model consisting of RLC elements class RXLoadSwitch : public CompositePowerComp, public MNASwitchInterface, + public MNAVariableCompInterface, public SharedFactory { protected: /// Internal RXLoad @@ -73,6 +74,9 @@ class RXLoadSwitch : public CompositePowerComp, void mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow &systemMatrix, Int freqIdx) override; + + // #### MNA section for variable component #### + Bool hasParameterChanged() override; }; } // namespace Ph1 } // namespace DP diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Switch.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Switch.h index 268d8798d4..05c2ecb77e 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Switch.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Switch.h @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include namespace CPS { namespace DP { @@ -25,8 +25,8 @@ namespace Ph1 { class Switch : public MNASimPowerComp, public Base::Ph1::Switch, public SharedFactory, - public MNASwitchInterface { -protected: + public MNASwitchInterface, + public MNAVariableCompInterface { public: /// Defines UID, name, component parameters and logging level Switch(String uid, String name, Logger::Level loglevel = Logger::Level::off); @@ -68,6 +68,9 @@ class Switch : public MNASimPowerComp, void mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow &systemMatrix, Int freqIdx); + + // #### MNA section for variable component #### + Bool hasParameterChanged(); }; } // namespace Ph1 } // namespace DP diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_varResSwitch.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_varResSwitch.h index 2efaf53238..5f4d35ce44 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_varResSwitch.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_varResSwitch.h @@ -31,7 +31,6 @@ class varResSwitch : public MNASimPowerComp, public SharedFactory { protected: - Bool mPrevState = false; Real mDeltaResClosed = 0; Real mDeltaResOpen = 1.5; Real mPrevRes; // previous resistance value to multiply with rate of change @@ -94,6 +93,7 @@ class varResSwitch : public MNASimPowerComp, SparseMatrixRow &systemMatrix, Int freqIdx); + // #### MNA section for variable component #### Bool hasParameterChanged(); }; } // namespace Ph1 diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph3_SeriesSwitch.h b/dpsim-models/include/dpsim-models/DP/DP_Ph3_SeriesSwitch.h index 7bdbe2b30b..4c390ca76e 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph3_SeriesSwitch.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph3_SeriesSwitch.h @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include namespace CPS { namespace DP { @@ -27,7 +27,10 @@ namespace Ph3 { class SeriesSwitch : public MNASimPowerComp, public Base::Ph1::Switch, public SharedFactory, - public MNASwitchInterface { + public MNASwitchInterface, + public MNAVariableCompInterface { +protected: + Bool mPrevState = false; public: /// Defines UID, name and logging level @@ -68,6 +71,9 @@ class SeriesSwitch : public MNASimPowerComp, Attribute::Ptr &leftVector) override; void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + + // #### MNA section for variable component #### + Bool hasParameterChanged() override; }; } // namespace Ph3 } // namespace DP diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h index d78ffd1bc1..ae1397362a 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include namespace CPS { namespace EMT { @@ -25,8 +25,8 @@ namespace Ph1 { class Switch : public MNASimPowerComp, public Base::Ph1::Switch, public SharedFactory, + public MNAVariableCompInterface, public MNASwitchInterface { - public: /// Defines UID, name, component parameters and logging level Switch(String uid, String name, Logger::Level loglevel = Logger::Level::off); @@ -69,6 +69,8 @@ class Switch : public MNASimPowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + // #### MNA section for variable component #### + Bool hasParameterChanged() override; }; } // namespace Ph1 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SeriesSwitch.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SeriesSwitch.h index 8111aea776..7034db6a69 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SeriesSwitch.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SeriesSwitch.h @@ -10,8 +10,8 @@ #include #include -#include #include +#include namespace CPS { namespace EMT { @@ -25,7 +25,10 @@ namespace Ph3 { class SeriesSwitch : public MNASimPowerComp, public Base::Ph1::Switch, public SharedFactory, + public MNAVariableCompInterface, public MNASwitchInterface { +protected: + Bool mPrevState = false; public: /// Defines UID, name and log level @@ -68,6 +71,9 @@ class SeriesSwitch : public MNASimPowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + // #### MNA section for variable component #### + Bool hasParameterChanged() override; }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Switch.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Switch.h index 9dc44c0d08..77a378d518 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Switch.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Switch.h @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include namespace CPS { namespace EMT { @@ -25,8 +25,8 @@ namespace Ph3 { class Switch : public MNASimPowerComp, public Base::Ph3::Switch, public SharedFactory, + public MNAVariableCompInterface, public MNASwitchInterface { - public: /// Defines UID, name, component parameters and logging level Switch(String uid, String name, Logger::Level loglevel = Logger::Level::off); @@ -69,6 +69,9 @@ class Switch : public MNASimPowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + // #### MNA section for variable component #### + Bool hasParameterChanged() override; }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Switch.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Switch.h index a709663225..e1ab02c763 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Switch.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Switch.h @@ -12,8 +12,8 @@ #include #include #include -#include #include +#include namespace CPS { namespace SP { @@ -25,6 +25,7 @@ namespace Ph1 { class Switch : public MNASimPowerComp, public Base::Ph1::Switch, public SharedFactory, + public MNAVariableCompInterface, public MNASwitchInterface { public: @@ -68,6 +69,9 @@ class Switch : public MNASimPowerComp, void mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow &systemMatrix, Int freqIdx) override; + + // #### MNA section for variable component #### + Bool hasParameterChanged() override; }; } // namespace Ph1 } // namespace SP diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_varResSwitch.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_varResSwitch.h index c1585c9715..65c5d47aa4 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_varResSwitch.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_varResSwitch.h @@ -31,7 +31,6 @@ class varResSwitch : public MNASimPowerComp, public SharedFactory { protected: - Bool mPrevState = false; Real mDeltaResClosed = 0; Real mDeltaResOpen = 1.5; Real mPrevRes; // previous resistance value to multiply with rate of change @@ -94,6 +93,7 @@ class varResSwitch : public MNASimPowerComp, SparseMatrixRow &systemMatrix, Int freqIdx); + // #### MNA section for variable component #### Bool hasParameterChanged(); }; } // namespace Ph1 diff --git a/dpsim-models/src/DP/DP_Ph1_RXLoadSwitch.cpp b/dpsim-models/src/DP/DP_Ph1_RXLoadSwitch.cpp index 79d50e3a62..e1b3d48c1e 100644 --- a/dpsim-models/src/DP/DP_Ph1_RXLoadSwitch.cpp +++ b/dpsim-models/src/DP/DP_Ph1_RXLoadSwitch.cpp @@ -132,3 +132,7 @@ void DP::Ph1::RXLoadSwitch::updateSwitchState(Real time) { } } } + +Bool DP::Ph1::RXLoadSwitch::hasParameterChanged() { + return mSubSwitch->hasParameterChanged(); +}; diff --git a/dpsim-models/src/DP/DP_Ph1_Switch.cpp b/dpsim-models/src/DP/DP_Ph1_Switch.cpp index 6f7f24d35d..2f159398ed 100644 --- a/dpsim-models/src/DP/DP_Ph1_Switch.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Switch.cpp @@ -107,3 +107,13 @@ void DP::Ph1::Switch::mnaCompPostStep(Real time, Int timeStepCount, mnaCompUpdateVoltage(**leftVector); mnaCompUpdateCurrent(**leftVector); } + +Bool DP::Ph1::Switch::hasParameterChanged() { + // Check if state of switch changed + if (!(mIsClosedPrev == this->mnaIsClosed())) { + mIsClosedPrev = this->mnaIsClosed(); + return 1; //recompute system matrix + } else { + return 0; // do not recompute system matrix + } +}; diff --git a/dpsim-models/src/DP/DP_Ph1_varResSwitch.cpp b/dpsim-models/src/DP/DP_Ph1_varResSwitch.cpp index c233ea6d09..8634622c1e 100644 --- a/dpsim-models/src/DP/DP_Ph1_varResSwitch.cpp +++ b/dpsim-models/src/DP/DP_Ph1_varResSwitch.cpp @@ -103,11 +103,8 @@ void DP::Ph1::varResSwitch::mnaCompUpdateCurrent(const Matrix &leftVector) { } Bool DP::Ph1::varResSwitch::hasParameterChanged() { - //Get present state - Bool presentState = this->mnaIsClosed(); - // Check if state of switch changed from open to closed - if (!(mPrevState == presentState)) { + if (!(mIsClosedPrev == this->mnaIsClosed())) { // Switch is closed : change with 1/mDeltaRes if (this->mnaIsClosed() == true) { // mClosedResistance= 1./mDeltaRes*mPrevRes; @@ -117,7 +114,7 @@ Bool DP::Ph1::varResSwitch::hasParameterChanged() { if (**mClosedResistance < mInitClosedRes) { **mClosedResistance = mInitClosedRes; mPrevRes = **mClosedResistance; - mPrevState = this->mnaIsClosed(); + mIsClosedPrev = this->mnaIsClosed(); } } // Switch is opened : change with mDeltaRes @@ -128,7 +125,7 @@ Bool DP::Ph1::varResSwitch::hasParameterChanged() { if (**mOpenResistance > mInitOpenRes) { **mOpenResistance = mInitOpenRes; mPrevRes = **mOpenResistance; - mPrevState = this->mnaIsClosed(); + mIsClosedPrev = this->mnaIsClosed(); } } return 1; //recompute system matrix @@ -142,7 +139,7 @@ void DP::Ph1::varResSwitch::setInitParameters(Real timestep) { mDeltaResClosed = 0; // mDeltaResOpen = 1.5; // assumption for 1ms step size mDeltaResOpen = 0.5 * timestep / 0.001 + 1; - mPrevState = **mIsClosed; + mIsClosedPrev = **mIsClosed; mPrevRes = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; mInitClosedRes = **mClosedResistance; mInitOpenRes = **mOpenResistance; diff --git a/dpsim-models/src/DP/DP_Ph3_SeriesSwitch.cpp b/dpsim-models/src/DP/DP_Ph3_SeriesSwitch.cpp index 2f2e36ecdf..15563759dc 100644 --- a/dpsim-models/src/DP/DP_Ph3_SeriesSwitch.cpp +++ b/dpsim-models/src/DP/DP_Ph3_SeriesSwitch.cpp @@ -21,6 +21,9 @@ DP::Ph3::SeriesSwitch::SeriesSwitch(String uid, String name, void DP::Ph3::SeriesSwitch::initializeFromNodesAndTerminals(Real frequency) { + mTerminals[0]->setPhaseType(PhaseType::ABC); + mTerminals[1]->setPhaseType(PhaseType::ABC); + Real impedance = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; **mIntfVoltage = initialVoltage(1) - initialVoltage(0); **mIntfCurrent = **mIntfVoltage / impedance; @@ -117,3 +120,13 @@ void DP::Ph3::SeriesSwitch::mnaCompUpdateCurrent(const Matrix &leftVector) { std::abs((**mIntfCurrent)(0, 0)), std::arg((**mIntfCurrent)(0, 0))); } + +Bool DP::Ph3::SeriesSwitch::hasParameterChanged() { + // Check if state of switch changed + if (!(mIsClosedPrev == this->mnaIsClosed())) { + mIsClosedPrev = this->mnaIsClosed(); + return 1; //recompute system matrix + } else { + return 0; // do not recompute system matrix + } +}; diff --git a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp index cc3f84005a..28679afd6f 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp @@ -117,3 +117,13 @@ void EMT::Ph1::Switch::mnaCompUpdateCurrent(const Matrix &leftVector) { ? (**mIntfVoltage)(0, 0) / (**mClosedResistance) : (**mIntfVoltage)(0, 0) / (**mOpenResistance); } + +Bool EMT::Ph1::Switch::hasParameterChanged() { + // Check if state of switch changed + if (!(mIsClosedPrev == this->mnaIsClosed())) { + mIsClosedPrev = this->mnaIsClosed(); + return 1; //recompute system matrix + } else { + return 0; // do not recompute system matrix + } +}; diff --git a/dpsim-models/src/EMT/EMT_Ph3_SeriesSwitch.cpp b/dpsim-models/src/EMT/EMT_Ph3_SeriesSwitch.cpp index 7a75c76950..18ae441270 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_SeriesSwitch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_SeriesSwitch.cpp @@ -128,3 +128,13 @@ void EMT::Ph3::SeriesSwitch::mnaCompUpdateCurrent(const Matrix &leftVector) { SPDLOG_LOGGER_DEBUG(mSLog, "Current A: {}", (**mIntfCurrent)(0, 0)); } + +Bool EMT::Ph3::SeriesSwitch::hasParameterChanged() { + // Check if state of switch changed + if (!(mIsClosedPrev == this->mnaIsClosed())) { + mIsClosedPrev = this->mnaIsClosed(); + return 1; //recompute system matrix + } else { + return 0; // do not recompute system matrix + } +}; diff --git a/dpsim-models/src/EMT/EMT_Ph3_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph3_Switch.cpp index 2a832badc7..c4dc5a44a6 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Switch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Switch.cpp @@ -134,3 +134,13 @@ void EMT::Ph3::Switch::mnaCompUpdateCurrent(const Matrix &leftVector) { **mIntfCurrent = conductance * **mIntfVoltage; } + +Bool EMT::Ph3::Switch::hasParameterChanged() { + // Check if state of switch changed + if (!(mIsClosedPrev == this->mnaIsClosed())) { + mIsClosedPrev = this->mnaIsClosed(); + return 1; //recompute system matrix + } else { + return 0; // do not recompute system matrix + } +}; diff --git a/dpsim-models/src/SP/SP_Ph1_Switch.cpp b/dpsim-models/src/SP/SP_Ph1_Switch.cpp index d10ffc2bb1..b92f0bed70 100644 --- a/dpsim-models/src/SP/SP_Ph1_Switch.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Switch.cpp @@ -107,3 +107,13 @@ void SP::Ph1::Switch::mnaCompPostStep(Real time, Int timeStepCount, mnaCompUpdateVoltage(**leftVector); mnaCompUpdateCurrent(**leftVector); } + +Bool SP::Ph1::Switch::hasParameterChanged() { + // Check if state of switch changed + if (!(mIsClosedPrev == mnaIsClosed())) { + mIsClosedPrev = mnaIsClosed(); + return 1; //recompute system matrix + } else { + return 0; // do not recompute system matrix + } +}; diff --git a/dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp b/dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp index 23daa31cef..877ba6b73d 100644 --- a/dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp +++ b/dpsim-models/src/SP/SP_Ph1_varResSwitch.cpp @@ -103,11 +103,8 @@ void SP::Ph1::varResSwitch::mnaCompUpdateCurrent(const Matrix &leftVector) { } Bool SP::Ph1::varResSwitch::hasParameterChanged() { - //Get present state - Bool presentState = this->mnaIsClosed(); - // Check if state of switch changed from open to closed - if (!(mPrevState == presentState)) { + if (!(mIsClosedPrev == this->mnaIsClosed())) { // Switch is closed : change with 1/mDeltaRes if (this->mnaIsClosed() == true) { // mClosedResistance= 1./mDeltaRes*mPrevRes; @@ -117,7 +114,7 @@ Bool SP::Ph1::varResSwitch::hasParameterChanged() { if (**mClosedResistance < mInitClosedRes) { **mClosedResistance = mInitClosedRes; mPrevRes = **mClosedResistance; - mPrevState = this->mnaIsClosed(); + mIsClosedPrev = this->mnaIsClosed(); } } // Switch is opened : change with mDeltaRes @@ -128,7 +125,7 @@ Bool SP::Ph1::varResSwitch::hasParameterChanged() { if (**mOpenResistance > mInitOpenRes) { **mOpenResistance = mInitOpenRes; mPrevRes = **mOpenResistance; - mPrevState = this->mnaIsClosed(); + mIsClosedPrev = this->mnaIsClosed(); } } return 1; //recompute system matrix @@ -142,7 +139,7 @@ void SP::Ph1::varResSwitch::setInitParameters(Real timestep) { mDeltaResClosed = 0; // mDeltaResOpen = 1.5; // assumption for 1ms step size mDeltaResOpen = 0.5 * timestep / 0.001 + 1; - mPrevState = **mIsClosed; + mIsClosedPrev = **mIsClosed; mPrevRes = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; mInitClosedRes = **mClosedResistance; mInitOpenRes = **mOpenResistance; diff --git a/dpsim/src/MNASolverDirect.cpp b/dpsim/src/MNASolverDirect.cpp index 1088db00a5..40b33ad681 100644 --- a/dpsim/src/MNASolverDirect.cpp +++ b/dpsim/src/MNASolverDirect.cpp @@ -78,12 +78,7 @@ void MnaSolverDirect::stampVariableSystemMatrix() { // Continue from base matrix mVariableSystemMatrix = mBaseSystemMatrix; - // Now stamp switches into matrix - SPDLOG_LOGGER_INFO(mSLog, "Stamping switches"); - for (auto sw : mMNAIntfSwitches) - sw->mnaApplySystemMatrixStamp(mVariableSystemMatrix); - - // Now stamp initial state of variable elements into matrix + // Now stamp initial state of variable elements and switches into matrix SPDLOG_LOGGER_INFO(mSLog, "Stamping variable elements"); for (auto varElem : mMNAIntfVariableComps) varElem->mnaApplySystemMatrixStamp(mVariableSystemMatrix); @@ -139,11 +134,7 @@ void MnaSolverDirect::recomputeSystemMatrix(Real time) { // Start from base matrix mVariableSystemMatrix = mBaseSystemMatrix; - // Now stamp switches into matrix - for (auto sw : mMNAIntfSwitches) - sw->mnaApplySystemMatrixStamp(mVariableSystemMatrix); - - // Now stamp variable elements into matrix + // Now stamp variable elements and switches into matrix for (auto comp : mMNAIntfVariableComps) comp->mnaApplySystemMatrixStamp(mVariableSystemMatrix); From 75ae179dca729a86c693367b6ee7ddf2aeb92da3 Mon Sep 17 00:00:00 2001 From: cwirtz Date: Mon, 1 Dec 2025 15:41:34 +0100 Subject: [PATCH 165/168] Added missing PiLine Models: - DP_Ph3_PiLine - EMT_Ph1_PiLine Extended Examples DP_PiLine.cpp and EMT_PiLine.cpp to test new Components. To provide Diakoptics equivalent to the DP 1Ph example, minor extension of diakoptics solver to provide 3ph capability was necessary. - tearing Matrix needs to differ between 1ph and 3ph case - added mnaTearing capabilities where missing, equivalent to 1ph DP implementation Signed-off-by: cwirtz --- .../include/dpsim-models/Components.h | 2 + .../include/dpsim-models/DP/DP_Ph1_PiLine.h | 11 +- .../include/dpsim-models/DP/DP_Ph3_Inductor.h | 4 +- .../include/dpsim-models/DP/DP_Ph3_PiLine.h | 83 ++++++ .../include/dpsim-models/DP/DP_Ph3_Resistor.h | 6 +- .../dpsim-models/EMT/EMT_Ph1_Inductor.h | 9 +- .../include/dpsim-models/EMT/EMT_Ph1_PiLine.h | 85 ++++++ .../dpsim-models/EMT/EMT_Ph1_Resistor.h | 5 +- .../dpsim-models/EMT/EMT_Ph3_Inductor.h | 8 +- .../include/dpsim-models/EMT/EMT_Ph3_PiLine.h | 9 +- .../dpsim-models/EMT/EMT_Ph3_Resistor.h | 24 +- .../dpsim-models/Solver/MNATearInterface.h | 2 + dpsim-models/src/CMakeLists.txt | 2 + dpsim-models/src/DP/DP_Ph1_PiLine.cpp | 13 +- dpsim-models/src/DP/DP_Ph1_Resistor.cpp | 1 + dpsim-models/src/DP/DP_Ph3_Inductor.cpp | 28 +- dpsim-models/src/DP/DP_Ph3_PiLine.cpp | 250 +++++++++++++++++ dpsim-models/src/DP/DP_Ph3_Resistor.cpp | 15 +- dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp | 22 ++ dpsim-models/src/EMT/EMT_Ph1_PiLine.cpp | 225 +++++++++++++++ dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp | 5 + dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp | 35 +++ dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp | 37 +++ dpsim-models/src/EMT/EMT_Ph3_Resistor.cpp | 13 + dpsim/examples/cxx/Circuits/DP_PiLine.cpp | 183 ++++++++++++- dpsim/examples/cxx/Circuits/EMT_PiLine.cpp | 258 +++++++++++++++++- dpsim/include/dpsim/DiakopticsSolver.h | 2 + dpsim/src/DiakopticsSolver.cpp | 238 +++++++++++++--- 28 files changed, 1492 insertions(+), 83 deletions(-) create mode 100644 dpsim-models/include/dpsim-models/DP/DP_Ph3_PiLine.h create mode 100644 dpsim-models/include/dpsim-models/EMT/EMT_Ph1_PiLine.h create mode 100644 dpsim-models/src/DP/DP_Ph3_PiLine.cpp create mode 100644 dpsim-models/src/EMT/EMT_Ph1_PiLine.cpp diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index fabe07f6be..b30ee1a7d4 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -75,6 +75,7 @@ #include #include +#include #include #include #include @@ -86,6 +87,7 @@ #include #include #include +#include #include #include #include diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine.h index ab6e0cbb57..bf35582e6f 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine.h @@ -1,10 +1,7 @@ -/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, - * EONERC, RWTH Aachen University - * - * 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 https://mozilla.org/MPL/2.0/. - *********************************************************************************/ +/* Author: Christoph Wirtz + * SPDX-FileCopyrightText: 2025 FGH e.V. + * SPDX-License-Identifier: MPL-2.0 + */ #pragma once diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph3_Inductor.h b/dpsim-models/include/dpsim-models/DP/DP_Ph3_Inductor.h index 3634e722df..571ac07a77 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph3_Inductor.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph3_Inductor.h @@ -79,11 +79,11 @@ class Inductor : public MNASimPowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; - + // #### MNA Tear Section #### void mnaTearInitialize(Real omega, Real timestep) override; void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; void mnaTearApplyVoltageStamp(Matrix &voltageVector) override; - void mnaTearPostStep(Complex voltage, Complex current) override; + void mnaTearPostStep(MatrixComp voltage, MatrixComp current) override; }; } // namespace Ph3 } // namespace DP diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph3_PiLine.h b/dpsim-models/include/dpsim-models/DP/DP_Ph3_PiLine.h new file mode 100644 index 0000000000..d36d42c93b --- /dev/null +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph3_PiLine.h @@ -0,0 +1,83 @@ +/* Author: Christoph Wirtz + * SPDX-FileCopyrightText: 2025 FGH e.V. + * SPDX-License-Identifier: MPL-2.0 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace CPS { +namespace DP { +namespace Ph3 { +/// \brief PI-line dynamic phasor model +/// +/// This model consists sub components to represent the +/// RLC elements of a PI-line. +class PiLine : public CompositePowerComp, + public MNATearInterface, + public Base::Ph3::PiLine, + public SharedFactory { +protected: + /// Series Inductance submodel + std::shared_ptr mSubSeriesInductor; + /// Series Resistor submodel + std::shared_ptr mSubSeriesResistor; + /// Parallel Resistor submodel at Terminal 0 + std::shared_ptr mSubParallelResistor0; + // Parallel Capacitor submodel at Terminal 0 + std::shared_ptr mSubParallelCapacitor0; + /// Parallel resistor submodel at Terminal 1 + std::shared_ptr mSubParallelResistor1; + /// Parallel capacitor submodel at Terminal 1 + std::shared_ptr mSubParallelCapacitor1; + /// Right side vectors of subcomponents + std::vector mRightVectorStamps; + +public: + /// Defines UID, name and logging level + PiLine(String uid, String name, Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + PiLine(String name, Logger::Level logLevel = Logger::Level::off) + : PiLine(name, name, logLevel) {} + + SimPowerComp::Ptr clone(String copySuffix) override; + + // #### General #### + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + // #### MNA section #### + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix &leftVector) override; + /// Updates internal voltage variable of the component + void mnaCompUpdateVoltage(const Matrix &leftVector) override; + /// MNA pre and post step operations + void mnaParentPreStep(Real time, Int timeStepCount) override; + void mnaParentPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; + /// add MNA pre and post step dependencies + void mnaParentAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) override; + void + mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; + + MNAInterface::List mnaTearGroundComponents() override; + void mnaTearInitialize(Real omega, Real timeStep) override; + void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; + void mnaTearApplyVoltageStamp(Matrix &voltageVector) override; + void mnaTearPostStep(MatrixComp voltage, MatrixComp current) override; +}; +} // namespace Ph3 +} // namespace DP +} // namespace CPS diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph3_Resistor.h b/dpsim-models/include/dpsim-models/DP/DP_Ph3_Resistor.h index bd7479e75b..496a11144d 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph3_Resistor.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph3_Resistor.h @@ -12,7 +12,7 @@ #include #include #include -#include +#include namespace CPS { namespace DP { @@ -20,6 +20,7 @@ namespace Ph3 { /// class Resistor : public MNASimPowerComp, public Base::Ph3::Resistor, + public MNATearInterface, public SharedFactory { public: @@ -54,6 +55,9 @@ class Resistor : public MNASimPowerComp, Attribute::Ptr &leftVector) override; void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + + // #### MNA Tear Section #### + void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; }; } // namespace Ph3 } // namespace DP diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Inductor.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Inductor.h index d87769454c..9e953b2575 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Inductor.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Inductor.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace CPS { namespace EMT { @@ -24,6 +24,7 @@ namespace Ph1 { /// frequency and the current source changes for each iteration. class Inductor : public MNASimPowerComp, public Base::Ph1::Inductor, + public MNATearInterface, public SharedFactory { protected: /// DC equivalent current source [A] @@ -74,6 +75,12 @@ class Inductor : public MNASimPowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + // #### Tearing methods #### + void mnaTearInitialize(Real omega, Real timestep) override; + void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; + void mnaTearApplyVoltageStamp(Matrix &voltageVector) override; + void mnaTearPostStep(Complex voltage, Complex current) override; }; } // namespace Ph1 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_PiLine.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_PiLine.h new file mode 100644 index 0000000000..0e16386a63 --- /dev/null +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_PiLine.h @@ -0,0 +1,85 @@ +/* Author: Christoph Wirtz + * SPDX-FileCopyrightText: 2025 FGH e.V. + * SPDX-License-Identifier: MPL-2.0 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace CPS { +namespace EMT { +namespace Ph1 { +/// \brief PI-line dynamic phasor model +/// +/// This model consists sub components to represent the +/// RLC elements of a PI-line. +class PiLine : public CompositePowerComp, + public MNATearInterface, + public Base::Ph1::PiLine, + public SharedFactory { +protected: + /// Series Inductance submodel + std::shared_ptr mSubSeriesInductor; + /// Series Resistor submodel + std::shared_ptr mSubSeriesResistor; + /// Parallel Resistor submodel at Terminal 0 + std::shared_ptr mSubParallelResistor0; + // Parallel Capacitor submodel at Terminal 0 + std::shared_ptr mSubParallelCapacitor0; + /// Parallel resistor submodel at Terminal 1 + std::shared_ptr mSubParallelResistor1; + // Parallel capacitor submodel at Terminal 1 + std::shared_ptr mSubParallelCapacitor1; + /// solver + std::vector mRightVectorStamps; + +public: + /// Defines UID, name and logging level + PiLine(String uid, String name, Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + PiLine(String name, Logger::Level logLevel = Logger::Level::off) + : PiLine(name, name, logLevel) {} + + SimPowerComp::Ptr clone(String copySuffix) override; + + // #### General #### + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + // #### MNA section #### + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix &leftVector) override; + /// Updates internal voltage variable of the component + void mnaCompUpdateVoltage(const Matrix &leftVector) override; + /// MNA pre step operations + void mnaParentPreStep(Real time, Int timeStepCount) override; + /// MNA post step operations + void mnaParentPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; + /// Add MNA pre step dependencies + void mnaParentAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) override; + /// Add MNA post step dependencies + void + mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; + + MNAInterface::List mnaTearGroundComponents() override; + void mnaTearInitialize(Real omega, Real timeStep) override; + void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; + void mnaTearApplyVoltageStamp(Matrix &voltageVector) override; + void mnaTearPostStep(Complex voltage, Complex current) override; +}; +} // namespace Ph1 +} // namespace EMT +} // namespace CPS diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Resistor.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Resistor.h index bb7f2947ab..70317ee77f 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Resistor.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Resistor.h @@ -12,7 +12,7 @@ #include #include -#include +#include namespace CPS { namespace EMT { @@ -20,6 +20,7 @@ namespace Ph1 { /// EMT Resistor class Resistor : public MNASimPowerComp, public Base::Ph1::Resistor, + public MNATearInterface, public SharedFactory { protected: public: @@ -56,6 +57,8 @@ class Resistor : public MNASimPowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + // #### MNA Tear Section #### + void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; }; } // namespace Ph1 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Inductor.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Inductor.h index 04f50a0214..67cf010697 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Inductor.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Inductor.h @@ -10,7 +10,7 @@ #include #include -#include +#include namespace CPS { namespace EMT { @@ -24,6 +24,7 @@ namespace Ph3 { /// frequency and the current source changes for each iteration. class Inductor : public MNASimPowerComp, public Base::Ph3::Inductor, + public MNATearInterface, public SharedFactory { protected: /// DC equivalent current source [A] @@ -73,6 +74,11 @@ class Inductor : public MNASimPowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + // #### MNA Tear Section #### + void mnaTearInitialize(Real omega, Real timestep) override; + void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; + void mnaTearApplyVoltageStamp(Matrix &voltageVector) override; + void mnaTearPostStep(MatrixComp voltage, MatrixComp current) override; }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h index d63f8452c3..c494bd2265 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h @@ -13,7 +13,7 @@ #include #include #include -#include +#include namespace CPS { namespace EMT { @@ -23,6 +23,7 @@ namespace Ph3 { /// This model consists sub components to represent the /// RLC elements of a PI-line. class PiLine : public CompositePowerComp, + public MNATearInterface, public Base::Ph3::PiLine, public SharedFactory { protected: @@ -75,6 +76,12 @@ class PiLine : public CompositePowerComp, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + MNAInterface::List mnaTearGroundComponents() override; + void mnaTearInitialize(Real omega, Real timeStep) override; + void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; + void mnaTearApplyVoltageStamp(Matrix &voltageVector) override; + void mnaTearPostStep(MatrixComp voltage, MatrixComp current) override; }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Resistor.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Resistor.h index a82a4c1638..d5a9333d7f 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Resistor.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Resistor.h @@ -10,13 +10,14 @@ #include #include -#include +#include namespace CPS { namespace EMT { namespace Ph3 { /// EMT Resistor class Resistor : public MNASimPowerComp, public Base::Ph3::Resistor, + public MNATearInterface, public SharedFactory { protected: public: @@ -29,33 +30,36 @@ class Resistor : public MNASimPowerComp, // #### General #### /// - SimPowerComp::Ptr clone(String name); + SimPowerComp::Ptr clone(String name) override; /// Initializes component from power flow data - void initializeFromNodesAndTerminals(Real frequency); + void initializeFromNodesAndTerminals(Real frequency) override; /// enable DP to EMT bach transformation void enableBackShift(); // #### MNA section #### /// Initializes internal variables of the component void mnaCompInitialize(Real omega, Real timeStep, - Attribute::Ptr leftSideVector); + Attribute::Ptr leftSideVector) override; /// Stamps system matrix - void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix); + void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override; /// Stamps right side (source) vector - void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) {} + void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override {} /// Update interface voltage from MNA system result - void mnaCompUpdateVoltage(const Matrix &leftVector); + void mnaCompUpdateVoltage(const Matrix &leftVector) override; /// Update interface current from MNA system result - void mnaCompUpdateCurrent(const Matrix &leftVector); + void mnaCompUpdateCurrent(const Matrix &leftVector) override; /// MNA pre and post step operations void mnaCompPostStep(Real time, Int timeStepCount, - Attribute::Ptr &leftVector); + Attribute::Ptr &leftVector) override; /// add MNA pre and post step dependencies void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, - Attribute::Ptr &leftVector); + Attribute::Ptr &leftVector) override; + + // #### MNA Tear Section #### + void mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) override; }; } // namespace Ph3 } // namespace EMT diff --git a/dpsim-models/include/dpsim-models/Solver/MNATearInterface.h b/dpsim-models/include/dpsim-models/Solver/MNATearInterface.h index 0782176437..511d8115bf 100644 --- a/dpsim-models/include/dpsim-models/Solver/MNATearInterface.h +++ b/dpsim-models/include/dpsim-models/Solver/MNATearInterface.h @@ -28,6 +28,8 @@ class MNATearInterface { virtual void mnaTearApplyVoltageStamp(Matrix ¤tVector) {} // Update the internal state based on the solution of the complete system virtual void mnaTearPostStep(Complex voltage, Complex current) {} + // Update the internal state based on the solution of the complete system + virtual void mnaTearPostStep(MatrixComp voltage, MatrixComp current) {} void mnaTearSetIdx(UInt compIdx) { mTearIdx = compIdx; } diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index 74dc60f479..9eed2cc23b 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND MODELS_SOURCES DP/DP_Ph3_Capacitor.cpp DP/DP_Ph3_Inductor.cpp DP/DP_Ph3_Resistor.cpp + DP/DP_Ph3_PiLine.cpp DP/DP_Ph3_SeriesResistor.cpp DP/DP_Ph3_SeriesSwitch.cpp DP/DP_Ph3_SynchronGeneratorDQ.cpp @@ -69,6 +70,7 @@ list(APPEND MODELS_SOURCES EMT/EMT_Ph1_VoltageSource.cpp EMT/EMT_Ph1_VoltageSourceRamp.cpp EMT/EMT_Ph1_VoltageSourceNorton.cpp + EMT/EMT_Ph1_PiLine.cpp EMT/EMT_Ph1_Switch.cpp EMT/EMT_Ph1_SSN_Full_Serial_RLC.cpp EMT/EMT_Ph1_SSNTypeI2T.cpp diff --git a/dpsim-models/src/DP/DP_Ph1_PiLine.cpp b/dpsim-models/src/DP/DP_Ph1_PiLine.cpp index 81d08e4013..00fbe59adf 100644 --- a/dpsim-models/src/DP/DP_Ph1_PiLine.cpp +++ b/dpsim-models/src/DP/DP_Ph1_PiLine.cpp @@ -1,10 +1,7 @@ -/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, - * EONERC, RWTH Aachen University - * - * 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 https://mozilla.org/MPL/2.0/. - *********************************************************************************/ +/* Author: Christoph Wirtz + * SPDX-FileCopyrightText: 2025 FGH e.V. + * SPDX-License-Identifier: MPL-2.0 + */ #include @@ -179,6 +176,7 @@ void DP::Ph1::PiLine::mnaCompUpdateCurrent(const Matrix &leftVector) { (**mIntfCurrent)(0, 0) = mSubSeriesInductor->intfCurrent()(0, 0); } +// #### Tear Methods #### MNAInterface::List DP::Ph1::PiLine::mnaTearGroundComponents() { MNAInterface::List gndComponents; @@ -212,4 +210,5 @@ void DP::Ph1::PiLine::mnaTearApplyVoltageStamp(Matrix &voltageVector) { void DP::Ph1::PiLine::mnaTearPostStep(Complex voltage, Complex current) { mSubSeriesInductor->mnaTearPostStep(voltage - current * **mSeriesRes, current); + (**mIntfCurrent)(0, 0) = mSubSeriesInductor->intfCurrent()(0, 0); } diff --git a/dpsim-models/src/DP/DP_Ph1_Resistor.cpp b/dpsim-models/src/DP/DP_Ph1_Resistor.cpp index f9ecabcd08..c68a59fd02 100644 --- a/dpsim-models/src/DP/DP_Ph1_Resistor.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Resistor.cpp @@ -164,6 +164,7 @@ void DP::Ph1::Resistor::mnaCompUpdateCurrentHarm() { } } +// #### Tear Methods #### void DP::Ph1::Resistor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx, Complex(**mResistance, 0)); diff --git a/dpsim-models/src/DP/DP_Ph3_Inductor.cpp b/dpsim-models/src/DP/DP_Ph3_Inductor.cpp index 57474f6983..d045bd1e49 100644 --- a/dpsim-models/src/DP/DP_Ph3_Inductor.cpp +++ b/dpsim-models/src/DP/DP_Ph3_Inductor.cpp @@ -178,12 +178,34 @@ void DP::Ph3::Inductor::mnaCompUpdateCurrent(const Matrix &leftVector) { **mIntfCurrent = mEquivCond * **mIntfVoltage + mEquivCurrent; } +// #### Tear Methods #### void DP::Ph3::Inductor::mnaTearInitialize(Real omega, Real timeStep) { initVars(omega, timeStep); } -void DP::Ph3::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) {} +void DP::Ph3::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + // Set diagonal entries + Math::addToMatrixElement(tearMatrix, mTearIdx * 3, mTearIdx * 3, + 1. / mEquivCond(0, 0)); // 1 / + Math::addToMatrixElement(tearMatrix, mTearIdx * 3 + 1, mTearIdx * 3 + 1, + 1. / mEquivCond(1, 1)); + Math::addToMatrixElement(tearMatrix, mTearIdx * 3 + 2, mTearIdx * 3 + 2, + 1. / mEquivCond(2, 2)); +} -void DP::Ph3::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) {} +void DP::Ph3::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) { + mEquivCurrent = + mEquivCond * (**mIntfVoltage) + mPrevCurrFac * (**mIntfCurrent); + Math::addToVectorElement(voltageVector, mTearIdx * 3, + mEquivCurrent(0, 0) / mEquivCond(0, 0)); + Math::addToVectorElement(voltageVector, mTearIdx * 3 + 1, + mEquivCurrent(1, 0) / mEquivCond(1, 1)); + Math::addToVectorElement(voltageVector, mTearIdx * 3 + 2, + mEquivCurrent(2, 0) / mEquivCond(2, 2)); +} -void DP::Ph3::Inductor::mnaTearPostStep(Complex voltage, Complex current) {} +void DP::Ph3::Inductor::mnaTearPostStep(MatrixComp voltage, + MatrixComp current) { + (**mIntfVoltage) = voltage; + (**mIntfCurrent) = mEquivCond * voltage + mEquivCurrent; +} diff --git a/dpsim-models/src/DP/DP_Ph3_PiLine.cpp b/dpsim-models/src/DP/DP_Ph3_PiLine.cpp new file mode 100644 index 0000000000..73a66cdbf8 --- /dev/null +++ b/dpsim-models/src/DP/DP_Ph3_PiLine.cpp @@ -0,0 +1,250 @@ +/* Author: Christoph Wirtz + * SPDX-FileCopyrightText: 2025 FGH e.V. + * SPDX-License-Identifier: MPL-2.0 + */ + +#include + +using namespace CPS; + +DP::Ph3::PiLine::PiLine(String uid, String name, Logger::Level logLevel) + : Base::Ph3::PiLine(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel) { + mPhaseType = PhaseType::ABC; + setVirtualNodeNumber(1); + setTerminalNumber(2); + + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + **mIntfVoltage = MatrixComp::Zero(3, 1); + **mIntfCurrent = MatrixComp::Zero(3, 1); +} + +///DEPRECATED: Remove method +SimPowerComp::Ptr DP::Ph3::PiLine::clone(String name) { + auto copy = PiLine::make(name, mLogLevel); + copy->setParameters(**mSeriesRes, **mSeriesInd, **mParallelCap, + **mParallelCond); + return copy; +} + +void DP::Ph3::PiLine::initializeFromNodesAndTerminals(Real frequency) { + + // Static calculation + Real omega = 2. * PI * frequency; + MatrixComp impedance = MatrixComp::Zero(3, 3); + impedance << Complex((**mSeriesRes)(0, 0), omega * (**mSeriesInd)(0, 0)), + Complex((**mSeriesRes)(0, 1), omega * (**mSeriesInd)(0, 1)), + Complex((**mSeriesRes)(0, 2), omega * (**mSeriesInd)(0, 2)), + Complex((**mSeriesRes)(1, 0), omega * (**mSeriesInd)(1, 0)), + Complex((**mSeriesRes)(1, 1), omega * (**mSeriesInd)(1, 1)), + Complex((**mSeriesRes)(1, 2), omega * (**mSeriesInd)(1, 2)), + Complex((**mSeriesRes)(2, 0), omega * (**mSeriesInd)(2, 0)), + Complex((**mSeriesRes)(2, 1), omega * (**mSeriesInd)(2, 1)), + Complex((**mSeriesRes)(2, 2), omega * (**mSeriesInd)(2, 2)); + MatrixComp vInitABC = MatrixComp::Zero(3, 1); + vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(1) - + RMS3PH_TO_PEAK1PH * initialSingleVoltage(0); + vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B; + vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C; + MatrixComp iInit = impedance.inverse() * vInitABC; + **mIntfCurrent = iInit; + **mIntfVoltage = vInitABC; + + // Initialization of virtual node + // Initial voltage of phase B,C is set after A + MatrixComp vInitTerm0 = MatrixComp::Zero(3, 1); + vInitTerm0(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(0); + vInitTerm0(1, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_B; + vInitTerm0(2, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_C; + + mVirtualNodes[0]->setInitialVoltage(PEAK1PH_TO_RMS3PH * + (vInitTerm0 + **mSeriesRes * iInit)); + + // Create series sub components + mSubSeriesResistor = + std::make_shared(**mName + "_res", mLogLevel); + mSubSeriesResistor->setParameters(**mSeriesRes); + mSubSeriesResistor->connect({mTerminals[0]->node(), mVirtualNodes[0]}); + mSubSeriesResistor->initialize(mFrequencies); + mSubSeriesResistor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesResistor, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubSeriesInductor = + std::make_shared(**mName + "_ind", mLogLevel); + mSubSeriesInductor->setParameters(**mSeriesInd); + mSubSeriesInductor->connect({mVirtualNodes[0], mTerminals[1]->node()}); + mSubSeriesInductor->initialize(mFrequencies); + mSubSeriesInductor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesInductor, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // By default there is always a small conductance to ground to + // avoid problems with floating nodes. + Matrix defaultParallelCond = Matrix::Zero(3, 3); + defaultParallelCond << 1e-6, 0, 0, 0, 1e-6, 0, 0, 0, 1e-6; + **mParallelCond = + ((**mParallelCond)(0, 0) > 0) ? **mParallelCond : defaultParallelCond; + + // Create parallel sub components + mSubParallelResistor0 = + std::make_shared(**mName + "_con0", mLogLevel); + mSubParallelResistor0->setParameters(2. * (**mParallelCond).inverse()); + mSubParallelResistor0->connect( + SimNode::List{SimNode::GND, mTerminals[0]->node()}); + mSubParallelResistor0->initialize(mFrequencies); + mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor0, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubParallelResistor1 = + std::make_shared(**mName + "_con1", mLogLevel); + mSubParallelResistor1->setParameters(2. * (**mParallelCond).inverse()); + mSubParallelResistor1->connect( + SimNode::List{SimNode::GND, mTerminals[1]->node()}); + mSubParallelResistor1->initialize(mFrequencies); + mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor1, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + if ((**mParallelCap)(0, 0) > 0) { + mSubParallelCapacitor0 = + std::make_shared(**mName + "_cap0", mLogLevel); + mSubParallelCapacitor0->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor0->connect( + SimNode::List{SimNode::GND, mTerminals[0]->node()}); + mSubParallelCapacitor0->initialize(mFrequencies); + mSubParallelCapacitor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor0, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + mSubParallelCapacitor1 = + std::make_shared(**mName + "_cap1", mLogLevel); + mSubParallelCapacitor1->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor1->connect( + SimNode::List{SimNode::GND, mTerminals[1]->node()}); + mSubParallelCapacitor1->initialize(mFrequencies); + mSubParallelCapacitor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor1, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + } + + SPDLOG_LOGGER_INFO( + mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\nVirtual Node 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::matrixCompToString(**mIntfVoltage), + Logger::matrixCompToString(**mIntfCurrent), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)), + Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); +} + +void DP::Ph3::PiLine::mnaParentAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) { + // add pre-step dependencies of component itself + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); +} + +void DP::Ph3::PiLine::mnaParentPreStep(Real time, Int timeStepCount) { + // pre-step of component itself + this->mnaApplyRightSideVectorStamp(**mRightVector); +} + +void DP::Ph3::PiLine::mnaParentAddPostStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { + // add post-step dependencies of component itself + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void DP::Ph3::PiLine::mnaParentPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) { + // post-step of component itself + this->mnaUpdateVoltage(**leftVector); + this->mnaUpdateCurrent(**leftVector); +} + +void DP::Ph3::PiLine::mnaCompUpdateVoltage(const Matrix &leftVector) { + // v1 - v0 + **mIntfVoltage = MatrixComp::Zero(3, 1); + if (terminalNotGrounded(1)) { + (**mIntfVoltage)(0, 0) = + Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 0)); + (**mIntfVoltage)(1, 0) = + Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 1)); + (**mIntfVoltage)(2, 0) = + Math::complexFromVectorElement(leftVector, matrixNodeIndex(1, 2)); + } + if (terminalNotGrounded(0)) { + (**mIntfVoltage)(0, 0) = + (**mIntfVoltage)(0, 0) - + Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 0)); + (**mIntfVoltage)(1, 0) = + (**mIntfVoltage)(1, 0) - + Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 1)); + (**mIntfVoltage)(2, 0) = + (**mIntfVoltage)(2, 0) - + Math::complexFromVectorElement(leftVector, matrixNodeIndex(0, 2)); + } +} + +void DP::Ph3::PiLine::mnaCompUpdateCurrent(const Matrix &leftVector) { + **mIntfCurrent = mSubSeriesInductor->intfCurrent(); +} + +// #### Tear Methods #### +MNAInterface::List DP::Ph3::PiLine::mnaTearGroundComponents() { + MNAInterface::List gndComponents; + + gndComponents.push_back(mSubParallelResistor0); + gndComponents.push_back(mSubParallelResistor1); + + if ((**mParallelCap)(0, 0) > 0) { + gndComponents.push_back(mSubParallelCapacitor0); + gndComponents.push_back(mSubParallelCapacitor1); + } + + return gndComponents; +} + +void DP::Ph3::PiLine::mnaTearInitialize(Real omega, Real timeStep) { + mSubSeriesResistor->mnaTearSetIdx(mTearIdx); + mSubSeriesResistor->mnaTearInitialize(omega, timeStep); + mSubSeriesInductor->mnaTearSetIdx(mTearIdx); + mSubSeriesInductor->mnaTearInitialize(omega, timeStep); +} + +void DP::Ph3::PiLine::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + mSubSeriesResistor->mnaTearApplyMatrixStamp(tearMatrix); + mSubSeriesInductor->mnaTearApplyMatrixStamp(tearMatrix); +} + +void DP::Ph3::PiLine::mnaTearApplyVoltageStamp(Matrix &voltageVector) { + mSubSeriesInductor->mnaTearApplyVoltageStamp(voltageVector); +} + +void DP::Ph3::PiLine::mnaTearPostStep(MatrixComp voltage, MatrixComp current) { + mSubSeriesInductor->mnaTearPostStep(voltage - (**mSeriesRes * current), + current); + (**mIntfCurrent) = mSubSeriesInductor->intfCurrent(); +} diff --git a/dpsim-models/src/DP/DP_Ph3_Resistor.cpp b/dpsim-models/src/DP/DP_Ph3_Resistor.cpp index 7ca6a3a828..bdfb4dba6a 100644 --- a/dpsim-models/src/DP/DP_Ph3_Resistor.cpp +++ b/dpsim-models/src/DP/DP_Ph3_Resistor.cpp @@ -110,8 +110,21 @@ void DP::Ph3::Resistor::mnaCompUpdateVoltage(const Matrix &leftVector) { void DP::Ph3::Resistor::mnaCompUpdateCurrent(const Matrix &leftVector) { **mIntfCurrent = (**mResistance).inverse() * **mIntfVoltage; - SPDLOG_LOGGER_DEBUG(mSLog, "Current A: {} < {}", + std::abs((**mIntfCurrent)(0, 0)), std::arg((**mIntfCurrent)(0, 0))); } + +// #### Tear Methods #### +void DP::Ph3::Resistor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + MatrixFixedSizeComp<3, 3> conductance = Matrix::Zero(3, 3); + conductance.real() = (**mResistance).inverse(); + // Set diagonal entries + Math::addToMatrixElement(tearMatrix, mTearIdx * 3, mTearIdx * 3, + 1. / conductance(0, 0).real()); // 1 / + Math::addToMatrixElement(tearMatrix, mTearIdx * 3 + 1, mTearIdx * 3 + 1, + 1. / conductance(1, 1).real()); + Math::addToMatrixElement(tearMatrix, mTearIdx * 3 + 2, mTearIdx * 3 + 2, + 1. / conductance(2, 2).real()); +} diff --git a/dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp b/dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp index 63e8a275da..59e2022546 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp @@ -116,3 +116,25 @@ void EMT::Ph1::Inductor::mnaCompUpdateVoltage(const Matrix &leftVector) { void EMT::Ph1::Inductor::mnaCompUpdateCurrent(const Matrix &leftVector) { (**mIntfCurrent)(0, 0) = mEquivCond * (**mIntfVoltage)(0, 0) + mEquivCurrent; } + +// #### Tear Methods #### +void EMT::Ph1::Inductor::mnaTearInitialize(Real omega, Real timeStep) { + updateMatrixNodeIndices(); + mEquivCond = timeStep / (2.0 * **mInductance); + // Update internal state + mEquivCurrent = mEquivCond * (**mIntfVoltage)(0, 0) + (**mIntfCurrent)(0, 0); +} + +void EMT::Ph1::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx, 1. / mEquivCond); +} + +void EMT::Ph1::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) { + mEquivCurrent = mEquivCond * (**mIntfVoltage)(0, 0) + (**mIntfCurrent)(0, 0); + Math::addToVectorElement(voltageVector, mTearIdx, mEquivCurrent / mEquivCond); +} + +void EMT::Ph1::Inductor::mnaTearPostStep(Complex voltage, Complex current) { + (**mIntfVoltage)(0, 0) = voltage.real(); + (**mIntfCurrent)(0, 0) = mEquivCond * voltage.real() + mEquivCurrent; +} diff --git a/dpsim-models/src/EMT/EMT_Ph1_PiLine.cpp b/dpsim-models/src/EMT/EMT_Ph1_PiLine.cpp new file mode 100644 index 0000000000..b7568fd8c5 --- /dev/null +++ b/dpsim-models/src/EMT/EMT_Ph1_PiLine.cpp @@ -0,0 +1,225 @@ +/* Author: Christoph Wirtz + * SPDX-FileCopyrightText: 2025 FGH e.V. + * SPDX-License-Identifier: MPL-2.0 + */ + +#include + +using namespace CPS; + +EMT::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) + : Base::Ph1::PiLine(mAttributes), + CompositePowerComp(uid, name, true, true, logLevel) { + setVirtualNodeNumber(1); + setTerminalNumber(2); + + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + **mIntfVoltage = Matrix::Zero(1, 1); + **mIntfCurrent = Matrix::Zero(1, 1); + + mSLog->flush(); +} + +/// DEPRECATED: Delete method +SimPowerComp::Ptr EMT::Ph1::PiLine::clone(String name) { + auto copy = PiLine::make(name, mLogLevel); + copy->setParameters(**mSeriesRes, **mSeriesInd, **mParallelCap, + **mParallelCond); + return copy; +} + +void EMT::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { + + // By default there is always a small conductance to ground to + // avoid problems with floating nodes. + + Real defaultParallelCond = 1e-6; + **mParallelCond = + (**mParallelCond > 0) ? **mParallelCond : defaultParallelCond; + + // Static calculation + Real omega = 2. * PI * frequency; + Complex impedance = {**mSeriesRes, omega * **mSeriesInd}; + Complex voltage = + RMS3PH_TO_PEAK1PH * (initialSingleVoltage(1) - initialSingleVoltage(0)); + (**mIntfVoltage)(0, 0) = voltage.real(); + (**mIntfCurrent)(0, 0) = (voltage / impedance).real(); + + // Initialization of virtual node + mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(0) + + (**mIntfCurrent)(0, 0) * **mSeriesRes); + + // Create series sub components + mSubSeriesResistor = + std::make_shared(**mName + "_res", mLogLevel); + mSubSeriesResistor->setParameters(**mSeriesRes); + mSubSeriesResistor->connect({mTerminals[0]->node(), mVirtualNodes[0]}); + mSubSeriesResistor->initialize(mFrequencies); + mSubSeriesResistor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesResistor, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubSeriesInductor = + std::make_shared(**mName + "_ind", mLogLevel); + mSubSeriesInductor->setParameters(**mSeriesInd); + mSubSeriesInductor->connect({mVirtualNodes[0], mTerminals[1]->node()}); + mSubSeriesInductor->initialize(mFrequencies); + mSubSeriesInductor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesInductor, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // Create parallel sub components + mSubParallelResistor0 = + std::make_shared(**mName + "_con0", mLogLevel); + mSubParallelResistor0->setParameters(2. / (**mParallelCond)); + mSubParallelResistor0->connect( + SimNode::List{SimNode::GND, mTerminals[0]->node()}); + mSubParallelResistor0->initialize(mFrequencies); + mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor0, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubParallelResistor1 = + std::make_shared(**mName + "_con1", mLogLevel); + mSubParallelResistor1->setParameters(2. / (**mParallelCond)); + mSubParallelResistor1->connect( + SimNode::List{SimNode::GND, mTerminals[1]->node()}); + mSubParallelResistor1->initialize(mFrequencies); + mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor1, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + if ((**mParallelCap) > 0) { + mSubParallelCapacitor0 = + std::make_shared(**mName + "_cap0", mLogLevel); + mSubParallelCapacitor0->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor0->connect( + SimNode::List{SimNode::GND, mTerminals[0]->node()}); + mSubParallelCapacitor0->initialize(mFrequencies); + mSubParallelCapacitor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor0, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + mSubParallelCapacitor1 = + std::make_shared(**mName + "_cap1", mLogLevel); + mSubParallelCapacitor1->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor1->connect( + SimNode::List{SimNode::GND, mTerminals[1]->node()}); + mSubParallelCapacitor1->initialize(mFrequencies); + mSubParallelCapacitor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor1, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, + MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + } + + SPDLOG_LOGGER_DEBUG(mSLog, + "\n--debug--" + "\n seriesRes: {:s}" + "\n seriesInd: {:s}" + "\n Impedance: {:s}", + Logger::matrixToString(**mSeriesRes), + Logger::matrixToString(**mSeriesInd), + Logger::complexToString(impedance)); + + SPDLOG_LOGGER_INFO( + mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\nVirtual Node 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::matrixToString(**mIntfVoltage), + Logger::matrixToString(**mIntfCurrent), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)), + Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); + mSLog->flush(); +} + +void EMT::Ph1::PiLine::mnaParentAddPreStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes) { + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); +} + +void EMT::Ph1::PiLine::mnaParentPreStep(Real time, Int timeStepCount) { + mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void EMT::Ph1::PiLine::mnaParentAddPostStepDependencies( + AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, + AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void EMT::Ph1::PiLine::mnaParentPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); +} + +void EMT::Ph1::PiLine::mnaCompUpdateVoltage(const Matrix &leftVector) { + (**mIntfVoltage)(0, 0) = 0; + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0, 0) = + Math::realFromVectorElement(leftVector, matrixNodeIndex(1)); + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0, 0) = + (**mIntfVoltage)(0, 0) - + Math::realFromVectorElement(leftVector, matrixNodeIndex(0)); +} + +void EMT::Ph1::PiLine::mnaCompUpdateCurrent(const Matrix &leftVector) { + **mIntfCurrent = mSubSeriesInductor->intfCurrent(); +} + +// #### Tear Methods #### +MNAInterface::List EMT::Ph1::PiLine::mnaTearGroundComponents() { + MNAInterface::List gndComponents; + + gndComponents.push_back(mSubParallelResistor0); + gndComponents.push_back(mSubParallelResistor1); + + if ((**mParallelCap) > 0) { + gndComponents.push_back(mSubParallelCapacitor0); + gndComponents.push_back(mSubParallelCapacitor1); + } + + return gndComponents; +} + +void EMT::Ph1::PiLine::mnaTearInitialize(Real omega, Real timeStep) { + mSubSeriesResistor->mnaTearSetIdx(mTearIdx); + mSubSeriesResistor->mnaTearInitialize(omega, timeStep); + mSubSeriesInductor->mnaTearSetIdx(mTearIdx); + mSubSeriesInductor->mnaTearInitialize(omega, timeStep); +} + +void EMT::Ph1::PiLine::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + mSubSeriesResistor->mnaTearApplyMatrixStamp(tearMatrix); + mSubSeriesInductor->mnaTearApplyMatrixStamp(tearMatrix); +} + +void EMT::Ph1::PiLine::mnaTearApplyVoltageStamp(Matrix &voltageVector) { + mSubSeriesInductor->mnaTearApplyVoltageStamp(voltageVector); +} + +void EMT::Ph1::PiLine::mnaTearPostStep(Complex voltage, Complex current) { + mSubSeriesInductor->mnaTearPostStep(voltage - current * **mSeriesRes, + current); + (**mIntfCurrent) = mSubSeriesInductor->intfCurrent(); +} diff --git a/dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp b/dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp index a96950151c..210d87b70a 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp @@ -88,3 +88,8 @@ void EMT::Ph1::Resistor::mnaCompUpdateVoltage(const Matrix &leftVector) { void EMT::Ph1::Resistor::mnaCompUpdateCurrent(const Matrix &leftVector) { (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / **mResistance; } + +// #### Tear Methods #### +void EMT::Ph1::Resistor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx, **mResistance); +} diff --git a/dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp b/dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp index be7b68b3ec..cb1d3e7a96 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp @@ -185,3 +185,38 @@ void EMT::Ph3::Inductor::mnaCompUpdateCurrent(const Matrix &leftVector) { Logger::matrixToString(**mIntfCurrent)); mSLog->flush(); } + +// #### Tear Methods #### +void EMT::Ph3::Inductor::mnaTearInitialize(Real omega, Real timeStep) { + //initVars(omega, timeStep); + updateMatrixNodeIndices(); + mEquivCond = timeStep / 2. * (**mInductance).inverse(); + // Update internal state + mEquivCurrent = mEquivCond * **mIntfVoltage + **mIntfCurrent; +} + +void EMT::Ph3::Inductor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + // Set diagonal entries + Math::addToMatrixElement(tearMatrix, mTearIdx * 3, mTearIdx * 3, + 1. / mEquivCond(0, 0)); // 1 / + Math::addToMatrixElement(tearMatrix, mTearIdx * 3 + 1, mTearIdx * 3 + 1, + 1. / mEquivCond(1, 1)); + Math::addToMatrixElement(tearMatrix, mTearIdx * 3 + 2, mTearIdx * 3 + 2, + 1. / mEquivCond(2, 2)); +} + +void EMT::Ph3::Inductor::mnaTearApplyVoltageStamp(Matrix &voltageVector) { + mEquivCurrent = mEquivCond * **mIntfVoltage + **mIntfCurrent; + Math::addToVectorElement(voltageVector, mTearIdx * 3, + mEquivCurrent(0, 0) / mEquivCond(0, 0)); + Math::addToVectorElement(voltageVector, mTearIdx * 3 + 1, + mEquivCurrent(1, 0) / mEquivCond(1, 1)); + Math::addToVectorElement(voltageVector, mTearIdx * 3 + 2, + mEquivCurrent(2, 0) / mEquivCond(2, 2)); +} + +void EMT::Ph3::Inductor::mnaTearPostStep(MatrixComp voltage, + MatrixComp current) { + (**mIntfVoltage) = voltage.real(); + (**mIntfCurrent) = (mEquivCond * voltage).real() + mEquivCurrent; +} diff --git a/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp b/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp index 3fef318e8a..18ff43c39d 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp @@ -227,3 +227,40 @@ void EMT::Ph3::PiLine::mnaCompUpdateVoltage(const Matrix &leftVector) { void EMT::Ph3::PiLine::mnaCompUpdateCurrent(const Matrix &leftVector) { **mIntfCurrent = mSubSeriesInductor->intfCurrent(); } + +// #### Tear Methods #### +MNAInterface::List EMT::Ph3::PiLine::mnaTearGroundComponents() { + MNAInterface::List gndComponents; + + gndComponents.push_back(mSubParallelResistor0); + gndComponents.push_back(mSubParallelResistor1); + + if ((**mParallelCap)(0, 0) > 0) { + gndComponents.push_back(mSubParallelCapacitor0); + gndComponents.push_back(mSubParallelCapacitor1); + } + + return gndComponents; +} + +void EMT::Ph3::PiLine::mnaTearInitialize(Real omega, Real timeStep) { + mSubSeriesResistor->mnaTearSetIdx(mTearIdx); + mSubSeriesResistor->mnaTearInitialize(omega, timeStep); + mSubSeriesInductor->mnaTearSetIdx(mTearIdx); + mSubSeriesInductor->mnaTearInitialize(omega, timeStep); +} + +void EMT::Ph3::PiLine::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + mSubSeriesResistor->mnaTearApplyMatrixStamp(tearMatrix); + mSubSeriesInductor->mnaTearApplyMatrixStamp(tearMatrix); +} + +void EMT::Ph3::PiLine::mnaTearApplyVoltageStamp(Matrix &voltageVector) { + mSubSeriesInductor->mnaTearApplyVoltageStamp(voltageVector); +} + +void EMT::Ph3::PiLine::mnaTearPostStep(MatrixComp voltage, MatrixComp current) { + mSubSeriesInductor->mnaTearPostStep(voltage - (**mSeriesRes * current), + current); + (**mIntfCurrent) = mSubSeriesInductor->intfCurrent(); +} diff --git a/dpsim-models/src/EMT/EMT_Ph3_Resistor.cpp b/dpsim-models/src/EMT/EMT_Ph3_Resistor.cpp index 88ce5229de..dfd97dc427 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Resistor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Resistor.cpp @@ -131,3 +131,16 @@ void EMT::Ph3::Resistor::mnaCompUpdateCurrent(const Matrix &leftVector) { Logger::matrixToString(**mIntfCurrent)); mSLog->flush(); } + +// #### Tear Methods #### +void EMT::Ph3::Resistor::mnaTearApplyMatrixStamp(SparseMatrixRow &tearMatrix) { + MatrixFixedSizeComp<3, 3> conductance = Matrix::Zero(3, 3); + conductance.real() = (**mResistance).inverse(); + // Set diagonal entries + Math::addToMatrixElement(tearMatrix, mTearIdx * 3, mTearIdx * 3, + 1. / conductance(0, 0).real()); + Math::addToMatrixElement(tearMatrix, mTearIdx * 3 + 1, mTearIdx * 3 + 1, + 1. / conductance(1, 1).real()); + Math::addToMatrixElement(tearMatrix, mTearIdx * 3 + 2, mTearIdx * 3 + 2, + 1. / conductance(2, 2).real()); +} diff --git a/dpsim/examples/cxx/Circuits/DP_PiLine.cpp b/dpsim/examples/cxx/Circuits/DP_PiLine.cpp index 862b1277a5..5afec41435 100644 --- a/dpsim/examples/cxx/Circuits/DP_PiLine.cpp +++ b/dpsim/examples/cxx/Circuits/DP_PiLine.cpp @@ -61,8 +61,6 @@ void simElements() { auto sys = SystemTopology( 50, SystemNodeList{n1, n2, vn1}, SystemComponentList{vs, res, ind, cap1, cap2, con1, con2, load}); - //SystemComponentList{vs, res, ind, cap1, cap2, load}); - //SystemComponentList{vs, res, ind, load}); // Logging auto logger = DataLogger::make(simName); @@ -162,6 +160,183 @@ void simPiLineDiakoptics() { auto logger = DataLogger::make(simName); logger->logAttribute("v1", n1->attribute("v")); logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", line->attribute("i_intf")); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setTearingComponents(sys.mTearComponents); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + +void simElements3ph() { + Real timeStep = 0.00005; + Real finalTime = 1; + String simName = "DP_PiLine_Elements_3ph"; + Logger::setLogDir("logs/" + simName); + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::ABC); + auto n2 = SimNode::make("n2", PhaseType::ABC); + auto vn1 = SimNode::make("vn1", PhaseType::ABC); + + // Components + auto vs = Ph3::VoltageSource::make("v_1"); + vs->setParameters(CPS::Math::polar(100000, 0)); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + Real conductance = 1e-6; + + auto res = Ph3::Resistor::make("R_line"); + res->setParameters(CPS::Math::singlePhaseParameterToThreePhase(resistance)); + auto ind = Ph3::Inductor::make("L_line"); + ind->setParameters(CPS::Math::singlePhaseParameterToThreePhase(inductance)); + auto cap1 = Ph3::Capacitor::make("Cp_1"); + cap1->setParameters( + CPS::Math::singlePhaseParameterToThreePhase(capacitance / 2.)); + auto cap2 = Ph3::Capacitor::make("Cp_2"); + cap2->setParameters( + CPS::Math::singlePhaseParameterToThreePhase(capacitance / 2.)); + auto con1 = Ph3::Resistor::make("Gp_1"); + con1->setParameters( + CPS::Math::singlePhaseParameterToThreePhase(2. / conductance)); + auto con2 = Ph3::Resistor::make("Gp_2"); + con2->setParameters( + CPS::Math::singlePhaseParameterToThreePhase(2. / conductance)); + + auto load = Ph3::Resistor::make("R_load"); + load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); + + // Topology + vs->connect({SimNode::GND, n1}); + res->connect({n1, vn1}); + ind->connect({vn1, n2}); + cap1->connect({n1, SimNode::GND}); + cap2->connect({n2, SimNode::GND}); + con1->connect({n1, SimNode::GND}); + con2->connect({n2, SimNode::GND}); + load->connect({n2, SimNode::GND}); + + auto sys = SystemTopology( + 50, SystemNodeList{n1, n2, vn1}, + SystemComponentList{vs, res, ind, cap1, cap2, con1, con2, load}); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->attribute("v")); + logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", ind->attribute("i_intf")); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + +void simPiLine3ph() { + Real timeStep = 0.00005; + Real finalTime = 1; + String simName = "DP_PiLine_Component_3ph"; + Logger::setLogDir("logs/" + simName); + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::ABC); + auto n2 = SimNode::make("n2", PhaseType::ABC); + + // Components + auto vs = Ph3::VoltageSource::make("v_1"); + vs->setParameters(CPS::Math::polar(100000, 0)); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + Real conductance = 1e-6; + + auto line = Ph3::PiLine::make("Line"); + line->setParameters(CPS::Math::singlePhaseParameterToThreePhase(resistance), + CPS::Math::singlePhaseParameterToThreePhase(inductance), + CPS::Math::singlePhaseParameterToThreePhase(capacitance), + CPS::Math::singlePhaseParameterToThreePhase(conductance)); + + auto load = Ph3::Resistor::make("R_load"); + load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); + + // Topology + vs->connect({SimNode::GND, n1}); + line->connect({n1, n2}); + load->connect({n2, SimNode::GND}); + + auto sys = SystemTopology(50, SystemNodeList{n1, n2}, + SystemComponentList{vs, line, load}); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->attribute("v")); + logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", line->attribute("i_intf")); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + +void simPiLineDiakoptics3ph() { + Real timeStep = 0.00005; + Real finalTime = 0.1; + String simName = "DP_PiLine_Diakoptics_3ph"; + Logger::setLogDir("logs/" + simName); + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::ABC); + auto n2 = SimNode::make("n2", PhaseType::ABC); + + // Components + auto vs = Ph3::VoltageSource::make("v_1"); + vs->setParameters(CPS::Math::polar(100000, 0)); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + Real conductance = 1e-6; + + auto line = Ph3::PiLine::make("Line"); + line->setParameters(CPS::Math::singlePhaseParameterToThreePhase(resistance), + CPS::Math::singlePhaseParameterToThreePhase(inductance), + CPS::Math::singlePhaseParameterToThreePhase(capacitance), + CPS::Math::singlePhaseParameterToThreePhase(conductance)); + + auto load = Ph3::Resistor::make("R_load"); + load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); + + // Topology + vs->connect({SimNode::GND, n1}); + line->connect({n1, n2}); + load->connect({n2, SimNode::GND}); + + auto sys = + SystemTopology(50, SystemNodeList{n1, n2}, SystemComponentList{vs, load}); + sys.addTearComponent(line); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->attribute("v")); + logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", line->attribute("i_intf")); Simulation sim(simName); sim.setSystem(sys); @@ -177,4 +352,8 @@ int main(int argc, char *argv[]) { simElements(); simPiLine(); simPiLineDiakoptics(); + + simElements3ph(); + simPiLine3ph(); + simPiLineDiakoptics3ph(); } diff --git a/dpsim/examples/cxx/Circuits/EMT_PiLine.cpp b/dpsim/examples/cxx/Circuits/EMT_PiLine.cpp index 6854b459ce..6c82b5cdcc 100644 --- a/dpsim/examples/cxx/Circuits/EMT_PiLine.cpp +++ b/dpsim/examples/cxx/Circuits/EMT_PiLine.cpp @@ -10,7 +10,6 @@ using namespace DPsim; using namespace CPS::EMT; -using namespace CPS::EMT::Ph3; void simElements() { Real timeStep = 0.00005; @@ -18,13 +17,182 @@ void simElements() { String simName = "EMT_PiLine_Elements"; Logger::setLogDir("logs/" + simName); + // Nodes + auto n1 = SimNode::make("n1"); + auto n2 = SimNode::make("n2"); + auto vn1 = SimNode::make("vn1"); + + // Components + auto vs = Ph1::VoltageSource::make("v_1"); + vs->setParameters(CPS::Math::polar(100000, 0), 50); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + Real conductance = 1e-6; + + auto res = Ph1::Resistor::make("R_line"); + res->setParameters(resistance); + auto ind = Ph1::Inductor::make("L_line"); + ind->setParameters(inductance); + auto cap1 = Ph1::Capacitor::make("Cp_1"); + cap1->setParameters(capacitance / 2.); + auto cap2 = Ph1::Capacitor::make("Cp_2"); + cap2->setParameters(capacitance / 2.); + auto con1 = Ph1::Resistor::make("Gp_1"); + con1->setParameters(2. / conductance); + auto con2 = Ph1::Resistor::make("Gp_2"); + con2->setParameters(2. / conductance); + + auto load = Ph1::Resistor::make("R_load"); + load->setParameters(10000); + + // Topology + vs->connect({SimNode::GND, n1}); + res->connect({n1, vn1}); + ind->connect({vn1, n2}); + cap1->connect({n1, SimNode::GND}); + cap2->connect({n2, SimNode::GND}); + con1->connect({n1, SimNode::GND}); + con2->connect({n2, SimNode::GND}); + load->connect({n2, SimNode::GND}); + + auto sys = SystemTopology( + 50, SystemNodeList{n1, n2, vn1}, + SystemComponentList{vs, res, ind, cap1, cap2, con1, con2, load}); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->attribute("v")); + logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", ind->attribute("i_intf")); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + +void simPiLine() { + Real timeStep = 0.00005; + Real finalTime = 1; + String simName = "EMT_PiLine_Component"; + Logger::setLogDir("logs/" + simName); + + // Nodes + auto n1 = SimNode::make("n1"); + auto n2 = SimNode::make("n2"); + + // Components + auto vs = Ph1::VoltageSource::make("v_1"); + vs->setParameters(CPS::Math::polar(100000, 0), 50); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + Real conductance = 1e-6; + + auto line = Ph1::PiLine::make("Line"); + line->setParameters(resistance, inductance, capacitance, conductance); + + auto load = Ph1::Resistor::make("R_load"); + load->setParameters(10000); + + // Topology + vs->connect({SimNode::GND, n1}); + line->connect({n1, n2}); + load->connect({n2, SimNode::GND}); + + auto sys = SystemTopology(50, SystemNodeList{n1, n2}, + SystemComponentList{vs, line, load}); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->attribute("v")); + logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", line->attribute("i_intf")); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setDomain(Domain::EMT); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + +void simPiLineDiakoptics() { + Real timeStep = 0.00005; + Real finalTime = 1; + String simName = "EMT_PiLine_Diakoptics"; + Logger::setLogDir("logs/" + simName); + + // Nodes + auto n1 = SimNode::make("n1"); + auto n2 = SimNode::make("n2"); + + // Components + auto vs = Ph1::VoltageSource::make("v_1"); + vs->setParameters(CPS::Math::polar(100000, 0), 50); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + Real conductance = 1e-6; + + auto line = Ph1::PiLine::make("Line"); + line->setParameters(resistance, inductance, capacitance, conductance); + + auto load = Ph1::Resistor::make("R_load"); + load->setParameters(10000); + + // Topology + vs->connect({SimNode::GND, n1}); + line->connect({n1, n2}); + load->connect({n2, SimNode::GND}); + + auto sys = + SystemTopology(50, SystemNodeList{n1, n2}, SystemComponentList{vs, load}); + sys.addTearComponent(line); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->attribute("v")); + logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", line->attribute("i_intf")); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setDomain(Domain::EMT); + sim.setTearingComponents(sys.mTearComponents); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + +void simElements3ph() { + Real timeStep = 0.00005; + Real finalTime = 1; + String simName = "EMT_PiLine_Elements_3ph"; + Logger::setLogDir("logs/" + simName); + // Nodes auto n1 = SimNode::make("n1", PhaseType::ABC); auto n2 = SimNode::make("n2", PhaseType::ABC); auto vn1 = SimNode::make("vn1", PhaseType::ABC); // Components - auto vs = VoltageSource::make("v_1", Logger::Level::debug); + auto vs = Ph3::VoltageSource::make("v_1", Logger::Level::debug); vs->setParameters( CPS::Math::singlePhaseVariableToThreePhase(CPS::Math::polar(100000, 0)), 50); @@ -35,24 +203,24 @@ void simElements() { Real capacitance = 1.0e-6; Real conductance = 1e-6; - auto res = Resistor::make("R_line", Logger::Level::debug); + auto res = Ph3::Resistor::make("R_line", Logger::Level::debug); res->setParameters(CPS::Math::singlePhaseParameterToThreePhase(resistance)); - auto ind = Inductor::make("L_line", Logger::Level::debug); + auto ind = Ph3::Inductor::make("L_line", Logger::Level::debug); ind->setParameters(CPS::Math::singlePhaseParameterToThreePhase(inductance)); - auto cap1 = Capacitor::make("Cp_1", Logger::Level::debug); + auto cap1 = Ph3::Capacitor::make("Cp_1", Logger::Level::debug); cap1->setParameters( CPS::Math::singlePhaseParameterToThreePhase(capacitance / 2.)); - auto cap2 = Capacitor::make("Cp_2", Logger::Level::debug); + auto cap2 = Ph3::Capacitor::make("Cp_2", Logger::Level::debug); cap2->setParameters( CPS::Math::singlePhaseParameterToThreePhase(capacitance / 2.)); - auto con1 = Resistor::make("Gp_1", Logger::Level::debug); + auto con1 = Ph3::Resistor::make("Gp_1", Logger::Level::debug); con1->setParameters( CPS::Math::singlePhaseParameterToThreePhase(2. / conductance)); - auto con2 = Resistor::make("Gp_2", Logger::Level::debug); + auto con2 = Ph3::Resistor::make("Gp_2", Logger::Level::debug); con2->setParameters( CPS::Math::singlePhaseParameterToThreePhase(2. / conductance)); - auto load = Resistor::make("R_load", Logger::Level::debug); + auto load = Ph3::Resistor::make("R_load", Logger::Level::debug); load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); // Topology @@ -87,10 +255,10 @@ void simElements() { sim.run(); } -void simPiLine() { +void simPiLine3ph() { Real timeStep = 0.00005; Real finalTime = 1; - String simName = "EMT_PiLine_Component"; + String simName = "EMT_PiLine_Component_3ph"; Logger::setLogDir("logs/" + simName); // Nodes @@ -99,7 +267,7 @@ void simPiLine() { auto vn1 = SimNode::make("vn1", PhaseType::ABC); // Components - auto vs = VoltageSource::make("v_1", Logger::Level::debug); + auto vs = Ph3::VoltageSource::make("v_1", Logger::Level::debug); vs->setParameters( CPS::Math::singlePhaseVariableToThreePhase(CPS::Math::polar(100000, 0)), 50); @@ -110,13 +278,13 @@ void simPiLine() { Real capacitance = 1.0e-6; Real conductance = 1e-6; - auto line = PiLine::make("Line", Logger::Level::debug); + auto line = Ph3::PiLine::make("Line", Logger::Level::debug); line->setParameters(CPS::Math::singlePhaseParameterToThreePhase(resistance), CPS::Math::singlePhaseParameterToThreePhase(inductance), CPS::Math::singlePhaseParameterToThreePhase(capacitance), CPS::Math::singlePhaseParameterToThreePhase(conductance)); - auto load = Resistor::make("R_load", Logger::Level::debug); + auto load = Ph3::Resistor::make("R_load", Logger::Level::debug); load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); // Topology @@ -143,7 +311,69 @@ void simPiLine() { sim.run(); } +void simPiLineDiakoptics3ph() { + Real timeStep = 0.00005; + Real finalTime = 0.1; + String simName = "EMT_PiLine_Diakoptics_3ph"; + Logger::setLogDir("logs/" + simName); + + // Nodes + auto n1 = SimNode::make("n1", PhaseType::ABC); + auto n2 = SimNode::make("n2", PhaseType::ABC); + + // Components + auto vs = Ph3::VoltageSource::make("v_1", Logger::Level::debug); + vs->setParameters( + CPS::Math::singlePhaseVariableToThreePhase(CPS::Math::polar(100000, 0)), + 50); + + // Parametrization of components + Real resistance = 5; + Real inductance = 0.16; + Real capacitance = 1.0e-6; + Real conductance = 1e-6; + + auto line = Ph3::PiLine::make("Line", Logger::Level::debug); + line->setParameters(CPS::Math::singlePhaseParameterToThreePhase(resistance), + CPS::Math::singlePhaseParameterToThreePhase(inductance), + CPS::Math::singlePhaseParameterToThreePhase(capacitance), + CPS::Math::singlePhaseParameterToThreePhase(conductance)); + + auto load = Ph3::Resistor::make("R_load", Logger::Level::debug); + load->setParameters(CPS::Math::singlePhaseParameterToThreePhase(10000)); + + // Topology + vs->connect({SimNode::GND, n1}); + line->connect({n1, n2}); + load->connect({n2, SimNode::GND}); + + auto sys = + SystemTopology(50, SystemNodeList{n1, n2}, SystemComponentList{vs, load}); + sys.addTearComponent(line); + + // Logging + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->attribute("v")); + logger->logAttribute("v2", n2->attribute("v")); + logger->logAttribute("iline", line->attribute("i_intf")); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setDomain(Domain::EMT); + sim.setTearingComponents(sys.mTearComponents); + sim.setTimeStep(timeStep); + sim.setFinalTime(finalTime); + sim.addLogger(logger); + + sim.run(); +} + int main(int argc, char *argv[]) { simElements(); simPiLine(); + simPiLineDiakoptics(); + + simElements3ph(); + simPiLine3ph(); + simPiLineDiakoptics3ph(); } diff --git a/dpsim/include/dpsim/DiakopticsSolver.h b/dpsim/include/dpsim/DiakopticsSolver.h index 5bb020e1b8..d41159edb7 100644 --- a/dpsim/include/dpsim/DiakopticsSolver.h +++ b/dpsim/include/dpsim/DiakopticsSolver.h @@ -76,6 +76,8 @@ class DiakopticsSolver : public Solver, public CPS::AttributeList { Matrix mTearCurrents; /// Voltages across the removed network Matrix mTearVoltages; + /// PhaseType to identify matrix Sizes + CPS::PhaseType mPhaseType; void init(CPS::SystemTopology &system); diff --git a/dpsim/src/DiakopticsSolver.cpp b/dpsim/src/DiakopticsSolver.cpp index 5491f9cb55..309fcf655a 100644 --- a/dpsim/src/DiakopticsSolver.cpp +++ b/dpsim/src/DiakopticsSolver.cpp @@ -46,6 +46,8 @@ template void DiakopticsSolver::init(SystemTopology &system) { std::vector subnets; mSystem = system; + if (mSystem.mNodes.size() > 0) + mPhaseType = mSystem.mNodes.at(0)->phaseType(); mSystemFrequency = system.mSystemFrequency; system.splitSubnets(subnets); @@ -234,19 +236,31 @@ template void DiakopticsSolver::createMatrices() { } template <> void DiakopticsSolver::createTearMatrices(UInt totalSize) { - mTearTopology = Matrix::Zero(totalSize, mTearComponents.size()); + int phaseMultiplier = 1; + if (mPhaseType == PhaseType::ABC) { + phaseMultiplier = 3; + } + mTearTopology = + Matrix::Zero(totalSize, mTearComponents.size() * phaseMultiplier); mTearImpedance = - CPS::SparseMatrixRow(mTearComponents.size(), mTearComponents.size()); - mTearCurrents = Matrix::Zero(mTearComponents.size(), 1); - mTearVoltages = Matrix::Zero(mTearComponents.size(), 1); + CPS::SparseMatrixRow(mTearComponents.size() * phaseMultiplier, + mTearComponents.size() * phaseMultiplier); + mTearCurrents = Matrix::Zero(mTearComponents.size() * phaseMultiplier, 1); + mTearVoltages = Matrix::Zero(mTearComponents.size() * phaseMultiplier, 1); } template <> void DiakopticsSolver::createTearMatrices(UInt totalSize) { - mTearTopology = Matrix::Zero(totalSize, 2 * mTearComponents.size()); - mTearImpedance = CPS::SparseMatrixRow(2 * mTearComponents.size(), - 2 * mTearComponents.size()); - mTearCurrents = Matrix::Zero(2 * mTearComponents.size(), 1); - mTearVoltages = Matrix::Zero(2 * mTearComponents.size(), 1); + int phaseMultiplier = 1; + if (mPhaseType == PhaseType::ABC) { + phaseMultiplier = 3; + } + mTearTopology = + Matrix::Zero(totalSize, 2 * mTearComponents.size() * phaseMultiplier); + mTearImpedance = + CPS::SparseMatrixRow(2 * mTearComponents.size() * phaseMultiplier, + 2 * mTearComponents.size() * phaseMultiplier); + mTearCurrents = Matrix::Zero(2 * mTearComponents.size() * phaseMultiplier, 1); + mTearVoltages = Matrix::Zero(2 * mTearComponents.size() * phaseMultiplier, 1); } template void DiakopticsSolver::initComponents() { @@ -325,13 +339,50 @@ template void DiakopticsSolver::initMatrices() { template <> void DiakopticsSolver::applyTearComponentStamp(UInt compIdx) { auto comp = mTearComponents[compIdx]; - mTearTopology(mNodeSubnetMap[comp->node(0)]->sysOff + - comp->node(0)->matrixNodeIndex(), - compIdx) = 1; - mTearTopology(mNodeSubnetMap[comp->node(1)]->sysOff + - comp->node(1)->matrixNodeIndex(), - compIdx) = -1; + // Use triplets to populate the sparse matrix + std::vector> triplets; + + // Node 0 contributions + if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) { + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + comp->node(0)->matrixNodeIndex(PhaseType::A), + compIdx * 3, 1); + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + comp->node(0)->matrixNodeIndex(PhaseType::B), + compIdx * 3 + 1, 1); + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + comp->node(0)->matrixNodeIndex(PhaseType::C), + compIdx * 3 + 2, 1); + } else { + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + comp->node(0)->matrixNodeIndex(), + compIdx, 1); + } + + // Node 1 contributions + if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) { + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + comp->node(1)->matrixNodeIndex(PhaseType::A), + compIdx * 3, -1); + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + comp->node(1)->matrixNodeIndex(PhaseType::B), + compIdx * 3 + 1, -1); + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + comp->node(1)->matrixNodeIndex(PhaseType::C), + compIdx * 3 + 2, -1); + } else { + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + comp->node(1)->matrixNodeIndex(), + compIdx, -1); + } + + // Apply triplets to the sparse matrix + for (const auto &triplet : triplets) { + mTearTopology.coeffRef(triplet.row(), triplet.col()) += triplet.value(); + } + + // Call tear component stamp function auto tearComp = std::dynamic_pointer_cast(comp); tearComp->mnaTearApplyMatrixStamp(mTearImpedance); } @@ -340,18 +391,85 @@ template <> void DiakopticsSolver::applyTearComponentStamp(UInt compIdx) { auto comp = mTearComponents[compIdx]; - auto net1 = mNodeSubnetMap[comp->node(0)]; - auto net2 = mNodeSubnetMap[comp->node(1)]; + // Use triplets to populate the sparse matrix + std::vector> triplets; + + // Node 0 contributions + if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) { + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + comp->node(0)->matrixNodeIndex(PhaseType::A), + compIdx * 3, 1); + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + mNodeSubnetMap[comp->node(0)]->mCmplOff + + comp->node(0)->matrixNodeIndex(PhaseType::A), + mTearComponents.size() * 3 + compIdx * 3, + double(1.0)); + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + comp->node(0)->matrixNodeIndex(PhaseType::B), + compIdx * 3 + 1, 1); + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + mNodeSubnetMap[comp->node(0)]->mCmplOff + + comp->node(0)->matrixNodeIndex(PhaseType::B), + mTearComponents.size() * 3 + compIdx * 3 + 1, + double(1.0)); + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + comp->node(0)->matrixNodeIndex(PhaseType::C), + compIdx * 3 + 2, 1); + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + mNodeSubnetMap[comp->node(0)]->mCmplOff + + comp->node(0)->matrixNodeIndex(PhaseType::C), + mTearComponents.size() * 3 + compIdx * 3 + 2, + double(1.0)); + } else { + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + comp->node(0)->matrixNodeIndex(), + compIdx, 1); + triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff + + mNodeSubnetMap[comp->node(0)]->mCmplOff + + comp->node(0)->matrixNodeIndex(), + mTearComponents.size() + compIdx, double(1.0)); + } - mTearTopology(net1->sysOff + comp->node(0)->matrixNodeIndex(), compIdx) = 1; - mTearTopology(net1->sysOff + net1->mCmplOff + - comp->node(0)->matrixNodeIndex(), - mTearComponents.size() + compIdx) = 1; - mTearTopology(net2->sysOff + comp->node(1)->matrixNodeIndex(), compIdx) = -1; - mTearTopology(net2->sysOff + net2->mCmplOff + - comp->node(1)->matrixNodeIndex(), - mTearComponents.size() + compIdx) = -1; + if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) { + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + comp->node(1)->matrixNodeIndex(PhaseType::A), + compIdx * 3, -1); + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + mNodeSubnetMap[comp->node(1)]->mCmplOff + + comp->node(1)->matrixNodeIndex(PhaseType::A), + mTearComponents.size() * 3 + compIdx * 3, + double(-1.0)); + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + comp->node(1)->matrixNodeIndex(PhaseType::B), + compIdx * 3 + 1, -1); + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + mNodeSubnetMap[comp->node(1)]->mCmplOff + + comp->node(1)->matrixNodeIndex(PhaseType::B), + mTearComponents.size() * 3 + compIdx * 3 + 1, + double(-1.0)); + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + comp->node(1)->matrixNodeIndex(PhaseType::C), + compIdx * 3 + 2, -1); + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + mNodeSubnetMap[comp->node(1)]->mCmplOff + + comp->node(1)->matrixNodeIndex(PhaseType::C), + mTearComponents.size() * 3 + compIdx * 3 + 2, + double(-1.0)); + } else { + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + comp->node(1)->matrixNodeIndex(), + compIdx, -1); + triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff + + mNodeSubnetMap[comp->node(1)]->mCmplOff + + comp->node(1)->matrixNodeIndex(), + mTearComponents.size() + compIdx, double(-1.0)); + } + // Apply triplets to the sparse matrix + for (const auto &triplet : triplets) { + mTearTopology.coeffRef(triplet.row(), triplet.col()) += triplet.value(); + } + // Call tear component stamp function auto tearComp = std::dynamic_pointer_cast(comp); tearComp->mnaTearApplyMatrixStamp(mTearImpedance); } @@ -434,8 +552,46 @@ void DiakopticsSolver::SolveTask::execute(Real time, **mSubnet.leftVector = lBlock; } -template -void DiakopticsSolver::PostSolveTask::execute(Real time, +template <> +void DiakopticsSolver::PostSolveTask::execute(Real time, + Int timeStepCount) { + // pass the voltages and current of the solution to the torn components + mSolver.mTearVoltages = + -mSolver.mTearTopology.transpose() * mSolver.mLeftSideVector; + for (UInt compIdx = 0; compIdx < mSolver.mTearComponents.size(); ++compIdx) { + auto comp = mSolver.mTearComponents[compIdx]; + auto tComp = std::dynamic_pointer_cast(comp); + if (mSolver.mPhaseType == CPS::PhaseType::ABC) { + Matrix voltage = Matrix::Zero(3, 1); + voltage << mSolver.mTearVoltages(compIdx * 3), + mSolver.mTearVoltages(compIdx * 3 + 1), + mSolver.mTearVoltages(compIdx * 3 + 2); + + Matrix current = Matrix::Zero(3, 1); + current << mSolver.mTearCurrents(compIdx * 3), + mSolver.mTearCurrents(compIdx * 3 + 1), + mSolver.mTearCurrents(compIdx * 3 + 2); + tComp->mnaTearPostStep(voltage, current); + } else { + Complex voltage = + Math::complexFromVectorElement(mSolver.mTearVoltages, compIdx); + Complex current = + Math::complexFromVectorElement(mSolver.mTearCurrents, compIdx); + tComp->mnaTearPostStep(voltage, current); + } + } + + // TODO split into separate task? (dependent on x, updating all v attributes) + for (UInt net = 0; net < mSolver.mSubnets.size(); ++net) { + for (UInt node = 0; node < mSolver.mSubnets[net].mRealNetNodeNum; ++node) { + mSolver.mSubnets[net].nodes[node]->mnaUpdateVoltage( + *(mSolver.mSubnets[net].leftVector)); + } + } +} + +template <> +void DiakopticsSolver::PostSolveTask::execute(Real time, Int timeStepCount) { // pass the voltages and current of the solution to the torn components mSolver.mTearVoltages = @@ -443,11 +599,29 @@ void DiakopticsSolver::PostSolveTask::execute(Real time, for (UInt compIdx = 0; compIdx < mSolver.mTearComponents.size(); ++compIdx) { auto comp = mSolver.mTearComponents[compIdx]; auto tComp = std::dynamic_pointer_cast(comp); - Complex voltage = - Math::complexFromVectorElement(mSolver.mTearVoltages, compIdx); - Complex current = - Math::complexFromVectorElement(mSolver.mTearCurrents, compIdx); - tComp->mnaTearPostStep(voltage, current); + if (mSolver.mPhaseType == CPS::PhaseType::ABC) { + MatrixComp voltage = MatrixComp::Zero(3, 1); + voltage << Math::complexFromVectorElement(mSolver.mTearVoltages, + compIdx * 3), + Math::complexFromVectorElement(mSolver.mTearVoltages, + compIdx * 3 + 1), + Math::complexFromVectorElement(mSolver.mTearVoltages, + compIdx * 3 + 2); + MatrixComp current = MatrixComp::Zero(3, 1); + current << Math::complexFromVectorElement(mSolver.mTearCurrents, + compIdx * 3), + Math::complexFromVectorElement(mSolver.mTearCurrents, + compIdx * 3 + 1), + Math::complexFromVectorElement(mSolver.mTearCurrents, + compIdx * 3 + 2); + tComp->mnaTearPostStep(voltage, current); + } else { + Complex voltage = + Math::complexFromVectorElement(mSolver.mTearVoltages, compIdx); + Complex current = + Math::complexFromVectorElement(mSolver.mTearCurrents, compIdx); + tComp->mnaTearPostStep(voltage, current); + } } // TODO split into separate task? (dependent on x, updating all v attributes) From d061ca6cd1728113b04d6328b13ca73eade51c65 Mon Sep 17 00:00:00 2001 From: Georgii Tishenin Date: Mon, 22 Dec 2025 13:25:39 +0100 Subject: [PATCH 166/168] Remove outdated roadmap Signed-off-by: Georgii Tishenin --- docs/hugo/content/en/docs/Roadmap/index.md | 26 ---------------------- 1 file changed, 26 deletions(-) diff --git a/docs/hugo/content/en/docs/Roadmap/index.md b/docs/hugo/content/en/docs/Roadmap/index.md index d246a0eae2..f306b51510 100644 --- a/docs/hugo/content/en/docs/Roadmap/index.md +++ b/docs/hugo/content/en/docs/Roadmap/index.md @@ -7,29 +7,3 @@ weight: 8 Short-term planning for new features is done on the GitHub [Project board](https://github.com/orgs/sogno-platform/projects/1). You can also check the [Issues List](https://github.com/sogno-platform/dpsim/issues) or the [Pull Requests](https://github.com/sogno-platform/dpsim/pulls) on GitHub. - -# Under Development - -- Solver - - [ ] CUDA sparse implementation - - [ ] improve online system matrix computation and refactorization to support nonlinear elements in network solution (NICSLU integration) - - [x] merge DAE solver branch -- Interfaces - - [x] reimplement python interface using pybind and expose more models / functionalities - - [x] add python based examples using the VILLASnode interface - - [x] support matpower / pypower format for static simulation -- Tests, Examples, CI - - [x] convert most of the examples to Python and test them against reference results in CI - - [x] convert more gitlab CI jobs to github actions - - [ ] add IEEE39 system to examples -- Models - - [x] VBR generator model - - [ ] SVC - - [ ] add tap-change to transfomer - -# Ideas - -- Solver - - [ ] improve integration of diakoptics solver -- Interfaces - - [ ] implement CIM reader in Python using new pybind interface and cimpy library From d3bdc42b6cf874ee0f1f2a7da633e4dcfd424f98 Mon Sep 17 00:00:00 2001 From: Charan Dande Date: Tue, 11 Mar 2025 14:29:23 +0100 Subject: [PATCH 167/168] implement functions for mapDisconnector and mapBreaker Signed-off-by: Charan Dande --- .../include/dpsim-models/CIM/Reader.h | 4 + dpsim-models/src/CIM/Reader.cpp | 153 +++++++++++++++++- dpsim/examples/cxx/CMakeLists.txt | 1 + 3 files changed, 157 insertions(+), 1 deletion(-) diff --git a/dpsim-models/include/dpsim-models/CIM/Reader.h b/dpsim-models/include/dpsim-models/CIM/Reader.h index b8c4cef03b..262b6cf034 100644 --- a/dpsim-models/include/dpsim-models/CIM/Reader.h +++ b/dpsim-models/include/dpsim-models/CIM/Reader.h @@ -49,6 +49,8 @@ class PowerTransformer; class EquivalentShunt; class TopologicalNode; class ConductingEquipment; +class Disconnector; +class Breaker; }; // namespace CIMPP #else #include @@ -164,6 +166,8 @@ class Reader { mapExternalNetworkInjection(CIMPP::ExternalNetworkInjection *extnet); /// Returns a shunt TopologicalPowerComp::Ptr mapEquivalentShunt(CIMPP::EquivalentShunt *shunt); + TopologicalPowerComp::Ptr mapDisconnector(CIMPP::Disconnector *disc); + TopologicalPowerComp::Ptr mapBreaker(CIMPP::Breaker *cb); // #### Helper Functions #### /// Determine base voltage associated with object diff --git a/dpsim-models/src/CIM/Reader.cpp b/dpsim-models/src/CIM/Reader.cpp index 9c4816578f..2d593fbfd1 100644 --- a/dpsim-models/src/CIM/Reader.cpp +++ b/dpsim-models/src/CIM/Reader.cpp @@ -115,7 +115,10 @@ TopologicalPowerComp::Ptr Reader::mapComponent(BaseClass *obj) { if (CIMPP::EquivalentShunt *shunt = dynamic_cast(obj)) return mapEquivalentShunt(shunt); - + if (CIMPP::Disconnector *disc = dynamic_cast(obj)) + return mapDisconnector(disc); + if (CIMPP::Breaker *cb = dynamic_cast(obj)) + return mapBreaker(cb); return nullptr; } @@ -349,6 +352,21 @@ Reader::mapEnergyConsumer(CIMPP::EnergyConsumer *consumer) { auto load = std::make_shared(consumerRid, consumerName, mComponentLogLevel); + // TODO: Use EnergyConsumer.P and EnergyConsumer.Q if available, overwrite if existent SvPowerFlow data + + Real p = 0; + Real q = 0; + if (consumer->p){ + p = unitValue(consumer->p,UnitMultiplier::M); + } + if (consumer->q){ + q = unitValue(consumer->q,UnitMultiplier::M); + } + + Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(consumer); + load->setParameters(p, q, baseVoltage); + + // P and Q values will be set according to SvPowerFlow data load->modifyPowerFlowBusType( PowerflowBusType:: @@ -1101,6 +1119,137 @@ Reader::mapEquivalentShunt(CIMPP::EquivalentShunt *shunt) { return cpsShunt; } +TopologicalPowerComp::Ptr +Reader::mapDisconnector(CIMPP::Disconnector *disc) { + + SPDLOG_LOGGER_INFO(mSLog, "Found Disconnector {} with status {}", disc->name, + (bool)disc->open.value); + +std::cout<< disc->open.value << std::endl; + + Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(disc); + Real resistance = 0; + Real inductance = 0; + Real capacitance = 0; + Real conductance = 0; + + Bool status = disc->open.value; + if (status == true){ + + resistance = 1e9; + inductance = 1e9; + capacitance = 10^(-20); + conductance = 10^(-20); + + } else { + + resistance = 10^(-20); + inductance = 10^(-20); + capacitance = 1e9; + conductance = 1e9; + + } + + + if (mDomain == Domain::EMT) { + if (mPhase == PhaseType::ABC) { + Matrix res_3ph = CPS::Math::singlePhaseParameterToThreePhase(resistance); + Matrix ind_3ph = CPS::Math::singlePhaseParameterToThreePhase(inductance); + Matrix cap_3ph = CPS::Math::singlePhaseParameterToThreePhase(capacitance); + Matrix cond_3ph = + CPS::Math::singlePhaseParameterToThreePhase(conductance); + + auto cpsLine = std::make_shared(disc->mRID, disc->name, + mComponentLogLevel); + cpsLine->setParameters(res_3ph, ind_3ph, cap_3ph, cond_3ph); + return cpsLine; + } else { + SPDLOG_LOGGER_INFO(mSLog, " PiLine for EMT not implemented yet"); + auto cpsLine = std::make_shared(disc->mRID, disc->name, + mComponentLogLevel); + cpsLine->setParameters(resistance, inductance, capacitance, conductance); + return cpsLine; + } + } else if (mDomain == Domain::SP) { + auto cpsLine = std::make_shared(disc->mRID, disc->name, + mComponentLogLevel); + cpsLine->setParameters(resistance, inductance, capacitance, conductance); + cpsLine->setBaseVoltage(baseVoltage); + return cpsLine; + } else { + auto cpsLine = std::make_shared(disc->mRID, disc->name, + mComponentLogLevel); + cpsLine->setParameters(resistance, inductance, capacitance, conductance); + return cpsLine; + } +} + +TopologicalPowerComp::Ptr +Reader::mapBreaker(CIMPP::Breaker *cb) { + SPDLOG_LOGGER_INFO(mSLog, + "Found Breaker {} with status {}", + cb->name, + (bool)cb->open.value); + + Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(cb); + + Real resistance = 0; + Real inductance = 0; + Real capacitance = 0; + Real conductance = 0; + + Bool status = cb->open.value; + + if (status == true){ + + resistance = 1e9; + inductance = 1e9; + capacitance = 10^(-10); + conductance = 10^(-10); + + } else { + + resistance = 10^(-10); + inductance = 10^(-10); + capacitance = 1e9; + conductance = 1e9; + + } + + if (mDomain == Domain::EMT) { + if (mPhase == PhaseType::ABC) { + Matrix res_3ph = CPS::Math::singlePhaseParameterToThreePhase(resistance); + Matrix ind_3ph = CPS::Math::singlePhaseParameterToThreePhase(inductance); + Matrix cap_3ph = CPS::Math::singlePhaseParameterToThreePhase(capacitance); + Matrix cond_3ph = + CPS::Math::singlePhaseParameterToThreePhase(conductance); + + auto cpsLine = std::make_shared(cb->mRID, cb->name, + mComponentLogLevel); + cpsLine->setParameters(res_3ph, ind_3ph, cap_3ph, cond_3ph); + return cpsLine; + } else { + SPDLOG_LOGGER_INFO(mSLog, " PiLine for EMT not implemented yet"); + auto cpsLine = std::make_shared(cb->mRID, cb->name, + mComponentLogLevel); + cpsLine->setParameters(resistance, inductance, capacitance, conductance); + return cpsLine; + } + } else if (mDomain == Domain::SP) { + auto cpsLine = std::make_shared(cb->mRID, cb->name, + mComponentLogLevel); + cpsLine->setParameters(resistance, inductance, capacitance, conductance); + cpsLine->setBaseVoltage(baseVoltage); + return cpsLine; + } else { + auto cpsLine = std::make_shared(cb->mRID, cb->name, + mComponentLogLevel); + cpsLine->setParameters(resistance, inductance, capacitance, conductance); + return cpsLine; + } + +} + Real Reader::determineBaseVoltageAssociatedWithEquipment( CIMPP::ConductingEquipment *equipment) { Real baseVoltage = 0; @@ -1211,6 +1360,8 @@ void Reader::processTopologicalNode(CIMPP::TopologicalNode *topNode) { } } + + template void Reader::processTopologicalNode(CIMPP::TopologicalNode *topNode); template void diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index 3965d6b3ae..ee9390cc41 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -180,6 +180,7 @@ if(WITH_CIM) CIM/EMT_WSCC-9bus_FullOrderSG.cpp CIM/EMT_WSCC-9bus_VBR.cpp CIM/DP_WSCC-9bus_IdealVS.cpp + CIM/SEGURO.cpp # WSCC Reduced Order CIM/SP_WSCC9bus_SGReducedOrderVBR.cpp From f742f63577ad7ce0d508ed08ddaa08b02e2c8f57 Mon Sep 17 00:00:00 2001 From: Felix Wege Date: Tue, 17 Feb 2026 16:46:33 +0100 Subject: [PATCH 168/168] fix: remove unused example and errorenous logs Signed-off-by: Felix Wege --- dpsim-models/src/CIM/Reader.cpp | 16 ++++++++-------- dpsim/examples/cxx/CMakeLists.txt | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/dpsim-models/src/CIM/Reader.cpp b/dpsim-models/src/CIM/Reader.cpp index 2d593fbfd1..2b1478f90b 100644 --- a/dpsim-models/src/CIM/Reader.cpp +++ b/dpsim-models/src/CIM/Reader.cpp @@ -1122,10 +1122,10 @@ Reader::mapEquivalentShunt(CIMPP::EquivalentShunt *shunt) { TopologicalPowerComp::Ptr Reader::mapDisconnector(CIMPP::Disconnector *disc) { - SPDLOG_LOGGER_INFO(mSLog, "Found Disconnector {} with status {}", disc->name, - (bool)disc->open.value); + // SPDLOG_LOGGER_INFO(mSLog, "Found Disconnector {} with status {}", disc->name, + // (bool)disc->open.value); -std::cout<< disc->open.value << std::endl; + std::cout << disc->open.value << std::endl; Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(disc); Real resistance = 0; @@ -1186,10 +1186,10 @@ std::cout<< disc->open.value << std::endl; TopologicalPowerComp::Ptr Reader::mapBreaker(CIMPP::Breaker *cb) { - SPDLOG_LOGGER_INFO(mSLog, - "Found Breaker {} with status {}", - cb->name, - (bool)cb->open.value); + // SPDLOG_LOGGER_INFO(mSLog, + // "Found Breaker {} with status {}", + // cb->name, + // (bool)cb->open.value); Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(cb); @@ -1229,7 +1229,7 @@ Reader::mapBreaker(CIMPP::Breaker *cb) { cpsLine->setParameters(res_3ph, ind_3ph, cap_3ph, cond_3ph); return cpsLine; } else { - SPDLOG_LOGGER_INFO(mSLog, " PiLine for EMT not implemented yet"); + // SPDLOG_LOGGER_INFO(mSLog, " PiLine for EMT not implemented yet"); auto cpsLine = std::make_shared(cb->mRID, cb->name, mComponentLogLevel); cpsLine->setParameters(resistance, inductance, capacitance, conductance); diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index ee9390cc41..fd913843fc 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -180,7 +180,7 @@ if(WITH_CIM) CIM/EMT_WSCC-9bus_FullOrderSG.cpp CIM/EMT_WSCC-9bus_VBR.cpp CIM/DP_WSCC-9bus_IdealVS.cpp - CIM/SEGURO.cpp + # CIM/SEGURO.cpp # WSCC Reduced Order CIM/SP_WSCC9bus_SGReducedOrderVBR.cpp