From 1aff0f6c350da37761c8d18cf8cf6c9d596241e1 Mon Sep 17 00:00:00 2001 From: Marvin Tollnitsch Date: Sat, 29 Jun 2024 17:11:24 +0200 Subject: [PATCH 1/6] [Initial commit] Added Ph1::Switch model - added Ph1::Switch header and cpp files - added header to Components.h - added cpp to CMakeLists.txt - made Ph1::Switch usable in pybind by adding it in EMTComponents.cpp - added simple example circuit (VS_sw_R_L) for new EMT::Ph1::Switch model Signed-off-by: Marvin Tollnitsch --- .../include/dpsim-models/Components.h | 1 + .../include/dpsim-models/EMT/EMT_Ph1_Switch.h | 68 ++++++++ dpsim-models/src/CMakeLists.txt | 1 + dpsim-models/src/EMT/EMT_Ph1_Switch.cpp | 135 ++++++++++++++++ dpsim/src/pybind/EMTComponents.cpp | 10 +- .../Notebooks/Components/Ph1_Switch.ipynb | 153 ++++++++++++++++++ 6 files changed, 367 insertions(+), 1 deletion(-) create mode 100644 dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h create mode 100644 dpsim-models/src/EMT/EMT_Ph1_Switch.cpp create mode 100644 examples/Notebooks/Components/Ph1_Switch.ipynb diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index 64ef2489c7..d92170fe28 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -87,6 +87,7 @@ #include #include #include +#include #include #include diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h new file mode 100644 index 0000000000..adfab9c932 --- /dev/null +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h @@ -0,0 +1,68 @@ +/* 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 +#include +#include +#include +#include +#include + +namespace CPS { +namespace EMT { +namespace Ph1 { + /// \brief One phase EMT switch + /// + /// The switch can be opened and closed. + /// Each state has a specific resistance value. + class Switch : + public MNASimPowerComp, + public Base::Ph1::Switch, + public SharedFactory, + public MNASwitchInterface { + + public: + /// Defines UID, name, component parameters and logging level + Switch(String uid, String name, Logger::Level loglevel = Logger::Level::off); + /// Defines name, component parameters and logging level + Switch(String name, Logger::Level logLevel = Logger::Level::off) + : Switch(name, name, logLevel) { } + + SimPowerComp::Ptr clone(String name); + + // #### General #### + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency); + + // #### General MNA section #### + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector); + /// Stamps system matrix + void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix); + /// Stamps right side (source) vector + void mnaCompApplyRightSideVectorStamp(Matrix& rightVector); + /// Update interface voltage from MNA system result + void mnaCompUpdateVoltage(const Matrix& leftVector); + /// Update interface current from MNA system result + void mnaCompUpdateCurrent(const Matrix& leftVector); + + // #### MNA section for switches #### + /// Check if switch is closed + Bool mnaIsClosed() override; + /// Stamps system matrix considering the defined switch position + void mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow& systemMatrix, Int freqIdx); + /// MNA post step operations + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + + /// Add MNA post step dependencies + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + }; +} +} +} diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index 50cafa8a3d..795c44cd97 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -69,6 +69,7 @@ list(APPEND MODELS_SOURCES EMT/EMT_Ph1_VoltageSource.cpp EMT/EMT_Ph1_VoltageSourceRamp.cpp EMT/EMT_Ph1_VoltageSourceNorton.cpp + EMT/EMT_Ph1_Switch.cpp EMT/EMT_Ph3_CurrentSource.cpp EMT/EMT_Ph3_VoltageSource.cpp diff --git a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp new file mode 100644 index 0000000000..9775fd63fa --- /dev/null +++ b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp @@ -0,0 +1,135 @@ +/* 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 + +using namespace CPS; + +// !!! TODO: Adaptions to use in EMT_Ph1 models phase-to-ground peak variables +// !!! with initialization from phase-to-phase RMS variables + +///FIXME: Inconsistent naming in ph1 and p3 switches: (mIsClosed, mSwitchClosed) + +EMT::Ph1::Switch::Switch(String uid, String name, Logger::Level logLevel) + : MNASimPowerComp(uid, name, false, true, logLevel), Base::Ph1::Switch(mAttributes) { + setTerminalNumber(2); + **mIntfVoltage = Matrix::Zero(1,1); + **mIntfCurrent = Matrix::Zero(1,1); +} + +SimPowerComp::Ptr EMT::Ph1::Switch::clone(String name) { + auto copy = Switch::make(name, mLogLevel); + copy->setParameters(**mOpenResistance, **mClosedResistance, **mIsClosed); + return copy; +} + +void EMT::Ph1::Switch::initializeFromNodesAndTerminals(Real frequency) { + + Real resistance = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; + + (**mIntfVoltage)(0,0) = (initialSingleVoltage(1) - initialSingleVoltage(0)).real(); + (**mIntfCurrent)(0,0) = (**mIntfVoltage)(0, 0) / resistance; + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::matrixToString(**mIntfVoltage), + Logger::matrixToString(**mIntfCurrent), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1))); +} + +void EMT::Ph1::Switch::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + + updateMatrixNodeIndices(); + + mMnaTasks.push_back(std::make_shared(*this, leftVector)); +} + +Bool EMT::Ph1::Switch::mnaIsClosed() { return **mIsClosed; } + +void EMT::Ph1::Switch::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { + Real conductance; + + conductance = (**mIsClosed) ? + 1./(**mClosedResistance) : 1./(**mOpenResistance); + + // Set diagonal entries + if (terminalNotGrounded(0)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(0, 0), conductance); + } + if (terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(1, 0), conductance); + } + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(1, 0), -conductance); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 0), -conductance); + } + SPDLOG_LOGGER_TRACE(mSLog, + "\nConductance matrix: {:s}", + Logger::realToString(conductance)); +} + +void EMT::Ph1::Switch::mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow& systemMatrix, Int freqIdx) { + Real conductance; + + conductance = (closed) ? + 1./(**mClosedResistance) : 1./(**mOpenResistance); + + // Set diagonal entries + if (terminalNotGrounded(0)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(0, 0), conductance); + + } + if (terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(1, 0), conductance); + } + // Set off diagonal blocks, 2x3x3 entries + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(1, 0), -conductance); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 0), -conductance); + } + + SPDLOG_LOGGER_TRACE(mSLog, + "\nConductance matrix: {:s}", + Logger::realToString(conductance)); +} + +void EMT::Ph1::Switch::mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { } + +void EMT::Ph1::Switch::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::Switch::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); +} + +void EMT::Ph1::Switch::mnaCompUpdateVoltage(const Matrix& leftVector) { + // Voltage across component is defined as V1 - V0 + **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)); + } +} + +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/src/pybind/EMTComponents.cpp b/dpsim/src/pybind/EMTComponents.cpp index 633d328dd0..92afccbe00 100644 --- a/dpsim/src/pybind/EMTComponents.cpp +++ b/dpsim/src/pybind/EMTComponents.cpp @@ -102,6 +102,13 @@ void addEMTPh1Components(py::module_ mEMTPh1) { .def("connect", &CPS::EMT::Ph1::Inductor::connect) .def_property("L", createAttributeGetter("L"), createAttributeSetter("L")); + + py::class_, CPS::SimPowerComp, CPS::Base::Ph1::Switch>(mEMTPh1, "Switch", py::multiple_inheritance()) + .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) + .def("set_parameters", &CPS::EMT::Ph1::Switch::setParameters, "open_resistance"_a, "closed_resistance"_a, "closed"_a = false) // cppcheck-suppress assignBoolToPointer + .def("open", &CPS::EMT::Ph1::Switch::open) + .def("close", &CPS::EMT::Ph1::Switch::close) + .def("connect", &CPS::EMT::Ph1::Switch::connect); } void addEMTPh3Components(py::module_ mEMTPh3) { @@ -121,6 +128,7 @@ void addEMTPh3Components(py::module_ mEMTPh3) { .def_property("f_src", createAttributeGetter("f_src"), createAttributeSetter("f_src")); + py::class_, CPS::SimPowerComp>(mEMTPh3, "Resistor", py::multiple_inheritance()) @@ -128,7 +136,7 @@ void addEMTPh3Components(py::module_ mEMTPh3) { .def(py::init()) .def("set_parameters", &CPS::EMT::Ph3::Resistor::setParameters, "R"_a) .def("connect", &CPS::EMT::Ph3::Resistor::connect); - ; + py::class_, diff --git a/examples/Notebooks/Components/Ph1_Switch.ipynb b/examples/Notebooks/Components/Ph1_Switch.ipynb new file mode 100644 index 0000000000..7b19a1cd8b --- /dev/null +++ b/examples/Notebooks/Components/Ph1_Switch.ipynb @@ -0,0 +1,153 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# EMT::Ph1::Switch Test" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import villas.dataprocessing.readtools as rt\n", + "from villas.dataprocessing.timeseries import TimeSeries as ts\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import dpsimpy\n", + "\n", + "#%matplotlib widget" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## VS_SW_R_L - Circuit" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "time_step = 0.00001\n", + "final_time = 0.1\n", + "sim_name = 'EMT_VS_SW_RL1'\n", + "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode('n1')\n", + "n2 = dpsimpy.emt.SimNode('n2')\n", + "n3 = dpsimpy.emt.SimNode('n3')\n", + "\n", + "resistance = 5\n", + "inductance = 0.02\n", + "open_resistance = 1e6\n", + "closed_resistance = 0.001\n", + "\n", + "vs = dpsimpy.emt.ph1.VoltageSource('vs')\n", + "vs.set_parameters(complex(10, 0), 50)\n", + "res = dpsimpy.emt.ph1.Resistor('Resistor')\n", + "res.set_parameters(resistance)\n", + "ind = dpsimpy.emt.ph1.Inductor('Inductance')\n", + "ind.set_parameters(inductance)\n", + "sw = dpsimpy.emt.ph1.Switch('Switch')\n", + "sw.set_parameters(open_resistance, closed_resistance, False)\n", + "\n", + "vs.connect([gnd, n1])\n", + "sw.connect([n1, n2])\n", + "res.connect([n2, n3])\n", + "ind.connect([n3, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [n1, n2, n3], [vs, sw, res, ind])\n", + "\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute('v2', 'v', n2)\n", + "logger.log_attribute('v3', 'v', n3)\n", + "logger.log_attribute('i_res', 'i_intf', res)\n", + "\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.set_solver(dpsimpy.Solver.MNA)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.add_logger(logger)\n", + "\n", + "event_sw = dpsimpy.event.SwitchEvent(0.04, sw, True)\n", + "sim.add_event(event_sw)\n", + "\n", + "sim.run()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "work_dir = 'logs/EMT_VS_SW_RL1/'\n", + "log_name = 'EMT_VS_SW_RL1'\n", + "print(work_dir + log_name + '.csv')\n", + "EMTseries = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.plot(EMTseries['v2'].time, EMTseries['v3'].values - EMTseries['v2'].values, label='V_res')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure()\n", + "plt.plot(EMTseries['i_res'].time, EMTseries['i_res'].values, label='I')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "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 9f6fb9d636bfc80221772ba400c39be003511689 Mon Sep 17 00:00:00 2001 From: Marvin Tollnitsch Date: Wed, 3 Jul 2024 20:08:48 +0200 Subject: [PATCH 2/6] "EMT::Ph1::Switch" class adjustments - declare methods as "override" implementations - encapsulate system matrix stamps using "MNAStampUtils::stampConductance()" Signed-off-by: Marvin Tollnitsch --- .../include/dpsim-models/EMT/EMT_Ph1_Switch.h | 16 ++++---- dpsim-models/src/EMT/EMT_Ph1_Switch.cpp | 41 +++---------------- 2 files changed, 14 insertions(+), 43 deletions(-) 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 adfab9c932..5d648c41ba 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h @@ -35,28 +35,28 @@ namespace Ph1 { Switch(String name, Logger::Level logLevel = Logger::Level::off) : Switch(name, name, logLevel) { } - SimPowerComp::Ptr clone(String name); + SimPowerComp::Ptr clone(String name) override; // #### General #### /// Initializes component from power flow data - void initializeFromNodesAndTerminals(Real frequency); + void initializeFromNodesAndTerminals(Real frequency) override; // #### General MNA section #### - void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector); + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) 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 section for switches #### /// Check if switch is closed Bool mnaIsClosed() override; /// Stamps system matrix considering the defined switch position - void mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow& systemMatrix, Int freqIdx); + void mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow& systemMatrix, Int freqIdx) override; /// MNA post step operations void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; diff --git a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp index 9775fd63fa..d5966f82e1 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp @@ -10,10 +10,6 @@ using namespace CPS; -// !!! TODO: Adaptions to use in EMT_Ph1 models phase-to-ground peak variables -// !!! with initialization from phase-to-phase RMS variables - -///FIXME: Inconsistent naming in ph1 and p3 switches: (mIsClosed, mSwitchClosed) EMT::Ph1::Switch::Switch(String uid, String name, Logger::Level logLevel) : MNASimPowerComp(uid, name, false, true, logLevel), Base::Ph1::Switch(mAttributes) { @@ -63,20 +59,9 @@ void EMT::Ph1::Switch::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatr conductance = (**mIsClosed) ? 1./(**mClosedResistance) : 1./(**mOpenResistance); - // Set diagonal entries - if (terminalNotGrounded(0)) { - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(0, 0), conductance); - } - if (terminalNotGrounded(1)) { - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(1, 0), conductance); - } - if (terminalNotGrounded(0) && terminalNotGrounded(1)) { - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(1, 0), -conductance); - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 0), -conductance); - } - SPDLOG_LOGGER_TRACE(mSLog, - "\nConductance matrix: {:s}", - Logger::realToString(conductance)); + MNAStampUtils::stampConductance(conductance, systemMatrix, matrixNodeIndex(0), + matrixNodeIndex(1), terminalNotGrounded(0), + terminalNotGrounded(1), mSLog); } void EMT::Ph1::Switch::mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow& systemMatrix, Int freqIdx) { @@ -85,23 +70,9 @@ void EMT::Ph1::Switch::mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMa conductance = (closed) ? 1./(**mClosedResistance) : 1./(**mOpenResistance); - // Set diagonal entries - if (terminalNotGrounded(0)) { - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(0, 0), conductance); - - } - if (terminalNotGrounded(1)) { - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(1, 0), conductance); - } - // Set off diagonal blocks, 2x3x3 entries - if (terminalNotGrounded(0) && terminalNotGrounded(1)) { - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(1, 0), -conductance); - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 0), -conductance); - } - - SPDLOG_LOGGER_TRACE(mSLog, - "\nConductance matrix: {:s}", - Logger::realToString(conductance)); + MNAStampUtils::stampConductance(conductance, systemMatrix, matrixNodeIndex(0), + matrixNodeIndex(1), terminalNotGrounded(0), + terminalNotGrounded(1), mSLog); } void EMT::Ph1::Switch::mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { } From 5ed747548839e873cfcfe818a913825469d2ffce Mon Sep 17 00:00:00 2001 From: Marvin Tollnitsch Date: Sat, 6 Jul 2024 15:59:41 +0200 Subject: [PATCH 3/6] Reformatted code using clang-format reformatted files: - EMT_Ph1_Switch.h - EMT_Ph1_Switch.cpp Signed-off-by: Marvin Tollnitsch --- .../include/dpsim-models/EMT/EMT_Ph1_Switch.h | 101 +++++++------ dpsim-models/src/EMT/EMT_Ph1_Switch.cpp | 134 ++++++++++-------- 2 files changed, 126 insertions(+), 109 deletions(-) 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 5d648c41ba..d78ffd1bc1 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_Switch.h @@ -8,61 +8,68 @@ #pragma once -#include -#include -#include +#include #include #include -#include +#include +#include +#include namespace CPS { namespace EMT { namespace Ph1 { - /// \brief One phase EMT switch - /// - /// The switch can be opened and closed. - /// Each state has a specific resistance value. - class Switch : - public MNASimPowerComp, - public Base::Ph1::Switch, - public SharedFactory, - public MNASwitchInterface { +/// \brief One phase EMT switch +/// +/// The switch can be opened and closed. +/// Each state has a specific resistance value. +class Switch : public MNASimPowerComp, + public Base::Ph1::Switch, + public SharedFactory, + public MNASwitchInterface { + +public: + /// Defines UID, name, component parameters and logging level + Switch(String uid, String name, Logger::Level loglevel = Logger::Level::off); + /// Defines name, component parameters and logging level + Switch(String name, Logger::Level logLevel = Logger::Level::off) + : Switch(name, name, logLevel) {} - public: - /// Defines UID, name, component parameters and logging level - Switch(String uid, String name, Logger::Level loglevel = Logger::Level::off); - /// Defines name, component parameters and logging level - Switch(String name, Logger::Level logLevel = Logger::Level::off) - : Switch(name, name, logLevel) { } + SimPowerComp::Ptr clone(String name) override; - SimPowerComp::Ptr clone(String name) override; + // #### General #### + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; - // #### General #### - /// Initializes component from power flow data - void initializeFromNodesAndTerminals(Real frequency) override; + // #### General MNA section #### + 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; - // #### General MNA section #### - 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 section for switches #### + /// Check if switch is closed + Bool mnaIsClosed() override; + /// Stamps system matrix considering the defined switch position + void mnaCompApplySwitchSystemMatrixStamp(Bool closed, + SparseMatrixRow &systemMatrix, + Int freqIdx) override; + /// MNA post step operations + void mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) override; - // #### MNA section for switches #### - /// Check if switch is closed - Bool mnaIsClosed() override; - /// Stamps system matrix considering the defined switch position - void mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow& systemMatrix, Int freqIdx) override; - /// MNA post step operations - void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; - - /// Add MNA post step dependencies - void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) 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/src/EMT/EMT_Ph1_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp index d5966f82e1..eff02868ad 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp @@ -10,97 +10,107 @@ using namespace CPS; - EMT::Ph1::Switch::Switch(String uid, String name, Logger::Level logLevel) - : MNASimPowerComp(uid, name, false, true, logLevel), Base::Ph1::Switch(mAttributes) { - setTerminalNumber(2); - **mIntfVoltage = Matrix::Zero(1,1); - **mIntfCurrent = Matrix::Zero(1,1); + : MNASimPowerComp(uid, name, false, true, logLevel), + Base::Ph1::Switch(mAttributes) { + setTerminalNumber(2); + **mIntfVoltage = Matrix::Zero(1, 1); + **mIntfCurrent = Matrix::Zero(1, 1); } SimPowerComp::Ptr EMT::Ph1::Switch::clone(String name) { - auto copy = Switch::make(name, mLogLevel); - copy->setParameters(**mOpenResistance, **mClosedResistance, **mIsClosed); - return copy; + auto copy = Switch::make(name, mLogLevel); + copy->setParameters(**mOpenResistance, **mClosedResistance, **mIsClosed); + return copy; } void EMT::Ph1::Switch::initializeFromNodesAndTerminals(Real frequency) { - Real resistance = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; - - (**mIntfVoltage)(0,0) = (initialSingleVoltage(1) - initialSingleVoltage(0)).real(); - (**mIntfCurrent)(0,0) = (**mIntfVoltage)(0, 0) / resistance; - - SPDLOG_LOGGER_INFO(mSLog, - "\n--- Initialization from powerflow ---" - "\nVoltage across: {:s}" - "\nCurrent: {:s}" - "\nTerminal 0 voltage: {:s}" - "\nTerminal 1 voltage: {:s}" - "\n--- Initialization from powerflow finished ---", - Logger::matrixToString(**mIntfVoltage), - Logger::matrixToString(**mIntfCurrent), - Logger::phasorToString(initialSingleVoltage(0)), - Logger::phasorToString(initialSingleVoltage(1))); + Real resistance = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; + + (**mIntfVoltage)(0, 0) = + (initialSingleVoltage(1) - initialSingleVoltage(0)).real(); + (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / resistance; + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::matrixToString(**mIntfVoltage), + Logger::matrixToString(**mIntfCurrent), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1))); } -void EMT::Ph1::Switch::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { - - updateMatrixNodeIndices(); - - mMnaTasks.push_back(std::make_shared(*this, leftVector)); +void EMT::Ph1::Switch::mnaCompInitialize(Real omega, Real timeStep, + Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); + mMnaTasks.push_back(std::make_shared(*this, leftVector)); } Bool EMT::Ph1::Switch::mnaIsClosed() { return **mIsClosed; } -void EMT::Ph1::Switch::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { - Real conductance; +void EMT::Ph1::Switch::mnaCompApplySystemMatrixStamp( + SparseMatrixRow &systemMatrix) { + Real conductance; - conductance = (**mIsClosed) ? - 1./(**mClosedResistance) : 1./(**mOpenResistance); + conductance = + (**mIsClosed) ? 1. / (**mClosedResistance) : 1. / (**mOpenResistance); - MNAStampUtils::stampConductance(conductance, systemMatrix, matrixNodeIndex(0), + MNAStampUtils::stampConductance(conductance, systemMatrix, matrixNodeIndex(0), matrixNodeIndex(1), terminalNotGrounded(0), terminalNotGrounded(1), mSLog); } -void EMT::Ph1::Switch::mnaCompApplySwitchSystemMatrixStamp(Bool closed, SparseMatrixRow& systemMatrix, Int freqIdx) { - Real conductance; +void EMT::Ph1::Switch::mnaCompApplySwitchSystemMatrixStamp( + Bool closed, SparseMatrixRow &systemMatrix, Int freqIdx) { + Real conductance; - conductance = (closed) ? - 1./(**mClosedResistance) : 1./(**mOpenResistance); + conductance = + (closed) ? 1. / (**mClosedResistance) : 1. / (**mOpenResistance); - MNAStampUtils::stampConductance(conductance, systemMatrix, matrixNodeIndex(0), - matrixNodeIndex(1), terminalNotGrounded(0), - terminalNotGrounded(1), mSLog); + MNAStampUtils::stampConductance(conductance, systemMatrix, matrixNodeIndex(0), + matrixNodeIndex(1), terminalNotGrounded(0), + terminalNotGrounded(1), mSLog); } -void EMT::Ph1::Switch::mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { } +void EMT::Ph1::Switch::mnaCompApplyRightSideVectorStamp(Matrix &rightVector) {} -void EMT::Ph1::Switch::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::Switch::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::Switch::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { - mnaCompUpdateVoltage(**leftVector); - mnaCompUpdateCurrent(**leftVector); +void EMT::Ph1::Switch::mnaCompPostStep(Real time, Int timeStepCount, + Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); } -void EMT::Ph1::Switch::mnaCompUpdateVoltage(const Matrix& leftVector) { - // Voltage across component is defined as V1 - V0 - **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)); - } +void EMT::Ph1::Switch::mnaCompUpdateVoltage(const Matrix &leftVector) { + // Voltage across component is defined as V1 - V0 + **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)); + } } -void EMT::Ph1::Switch::mnaCompUpdateCurrent(const Matrix& leftVector) { - (**mIntfCurrent)(0, 0) = (**mIsClosed) ? - (**mIntfVoltage)(0, 0)/(**mClosedResistance): - (**mIntfVoltage)(0, 0)/(**mOpenResistance); +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 From b972a96b5fe2f1f3de56a12611d9687063b33433 Mon Sep 17 00:00:00 2001 From: Ghassen Nakti Date: Wed, 10 Jul 2024 13:50:47 +0200 Subject: [PATCH 4/6] fix initialization Signed-off-by: Ghassen Nakti --- dpsim-models/src/EMT/EMT_Ph1_Switch.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp index eff02868ad..67221aa6bc 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Switch.cpp @@ -29,7 +29,7 @@ void EMT::Ph1::Switch::initializeFromNodesAndTerminals(Real frequency) { Real resistance = (**mIsClosed) ? **mClosedResistance : **mOpenResistance; (**mIntfVoltage)(0, 0) = - (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 +41,8 @@ void EMT::Ph1::Switch::initializeFromNodesAndTerminals(Real frequency) { "\n--- Initialization from powerflow finished ---", Logger::matrixToString(**mIntfVoltage), Logger::matrixToString(**mIntfCurrent), - Logger::phasorToString(initialSingleVoltage(0)), - Logger::phasorToString(initialSingleVoltage(1))); + 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, From 6e79a6250c2eaecc0e3a7ce922a2e29ca7d61c8b Mon Sep 17 00:00:00 2001 From: Ghassen Nakti Date: Wed, 10 Jul 2024 13:55:28 +0200 Subject: [PATCH 5/6] Test NB for VS_SW_RL1 circuit in EMT, DP and SP Signed-off-by: Ghassen Nakti --- examples/Notebooks/Circuits/VS_SW_RL1.ipynb | 575 ++++++++++++++++++ .../Notebooks/Components/Ph1_Switch.ipynb | 153 ----- 2 files changed, 575 insertions(+), 153 deletions(-) create mode 100644 examples/Notebooks/Circuits/VS_SW_RL1.ipynb delete mode 100644 examples/Notebooks/Components/Ph1_Switch.ipynb diff --git a/examples/Notebooks/Circuits/VS_SW_RL1.ipynb b/examples/Notebooks/Circuits/VS_SW_RL1.ipynb new file mode 100644 index 0000000000..2c0e555e7d --- /dev/null +++ b/examples/Notebooks/Circuits/VS_SW_RL1.ipynb @@ -0,0 +1,575 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Circuit VS_SW_RL1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import math\n", + "import villas.dataprocessing.readtools as rt\n", + "import villas.dataprocessing.plottools as pt\n", + "from villas.dataprocessing.timeseries import TimeSeries as ts\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import dpsimpy\n", + "\n", + "# %matplotlib widget" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## SP for Initialization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sim_name_pf = 'SP_1Ph_VS_SW_RL1_Init'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", + "\n", + "# Nodes\n", + "gnd_pf = dpsimpy.sp.SimNode.gnd\n", + "n1_pf = dpsimpy.sp.SimNode('n1_pf')\n", + "n2_pf = dpsimpy.sp.SimNode('n2_pf')\n", + "n3_pf = dpsimpy.sp.SimNode('n2_pf')\n", + "\n", + "resistance = 5\n", + "inductance = 0.02\n", + "open_resistance = 1e6\n", + "closed_resistance = 0.001\n", + "\n", + "# Components\n", + "vs_pf = dpsimpy.sp.ph1.VoltageSource('vs')\n", + "vs_pf.set_parameters(V_ref=complex(10,0), f_src=50) # Vref is phase-to-phase RMS\n", + "sw_pf = dpsimpy.sp.ph1.Resistor('r1_pf')\n", + "sw_pf.set_parameters(closed_resistance)\n", + "r1_pf = dpsimpy.sp.ph1.Resistor('r1_pf')\n", + "r1_pf.set_parameters(resistance)\n", + "l1_pf = dpsimpy.sp.ph1.Inductor('l1_pf')\n", + "l1_pf.set_parameters(inductance)\n", + "\n", + "\n", + "# Connections\n", + "vs_pf.connect([gnd_pf, n1_pf])\n", + "sw_pf.connect([n1_pf, n2_pf])\n", + "r1_pf.connect([n2_pf, n3_pf])\n", + "l1_pf.connect([gnd_pf, n3_pf])\n", + "\n", + "# Define system topology\n", + "system_pf = dpsimpy.SystemTopology(50, [n1_pf, n2_pf, n3_pf], [vs_pf, sw_pf, r1_pf, l1_pf])\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('n2.v', 'v', n3_pf)\n", + "\n", + "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", + "sim_pf.set_system(system_pf)\n", + "sim_pf.set_domain(dpsimpy.Domain.SP)\n", + "sim_pf.set_time_step(0.1)\n", + "sim_pf.set_final_time(0.5)\n", + "sim_pf.add_logger(logger_pf)\n", + "sim_pf.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## EMT 1Ph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "time_step = 0.00001\n", + "final_time = 1\n", + "sim_name = 'EMT_1Ph_VS_SW_RL1'\n", + "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode('n1')\n", + "n1.set_initial_voltage(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0])\n", + "n2 = dpsimpy.emt.SimNode('n2')\n", + "n2.set_initial_voltage(sim_pf.get_idobj_attr(n2_pf.name(), 'v').get()[0][0])\n", + "n3 = dpsimpy.emt.SimNode('n3')\n", + "n3.set_initial_voltage(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0][0])\n", + "\n", + "resistance = 5\n", + "inductance = 0.02\n", + "open_resistance = 1e6\n", + "closed_resistance = 0.001\n", + "\n", + "vs = dpsimpy.emt.ph1.VoltageSource('vs')\n", + "vs.set_parameters(complex(10, 0)* math.sqrt(2/3), 50) # still using deprecated class that is initialised with Vref phase-to-ground peak voltage\n", + "res = dpsimpy.emt.ph1.Resistor('Resistor')\n", + "res.set_parameters(resistance)\n", + "ind = dpsimpy.emt.ph1.Inductor('Inductance')\n", + "ind.set_parameters(inductance)\n", + "sw = dpsimpy.emt.ph1.Switch('Switch')\n", + "sw.set_parameters(open_resistance, closed_resistance, True)\n", + "\n", + "vs.connect([gnd, n1])\n", + "sw.connect([n1, n2])\n", + "res.connect([n2, n3])\n", + "ind.connect([n3, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [n1, n2, n3], [vs, sw, res, ind])\n", + "\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute('n1.v', 'v', n1)\n", + "logger.log_attribute('n2.v', 'v', n2)\n", + "logger.log_attribute('n3.v', 'v', n3)\n", + "logger.log_attribute('r1.i_intf', 'i_intf', res)\n", + "\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.set_solver(dpsimpy.Solver.MNA)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.add_logger(logger)\n", + "\n", + "event_sw = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", + "sim.add_event(event_sw)\n", + "\n", + "sim.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## DP 1Ph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "time_step = 0.00001\n", + "final_time = 1\n", + "sim_name = 'DP_1Ph_VS_SW_RL1'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.dp.SimNode.gnd\n", + "n1 = dpsimpy.dp.SimNode('n1')\n", + "n1.set_initial_voltage(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0])\n", + "n2 = dpsimpy.dp.SimNode('n2')\n", + "n2.set_initial_voltage(sim_pf.get_idobj_attr(n2_pf.name(), 'v').get()[0][0])\n", + "n3 = dpsimpy.dp.SimNode('n3')\n", + "n3.set_initial_voltage(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0][0])\n", + "\n", + "resistance = 5\n", + "inductance = 0.02\n", + "open_resistance = 1e6\n", + "closed_resistance = 0.001\n", + "\n", + "# Components\n", + "vs = dpsimpy.dp.ph1.VoltageSource('vs')\n", + "vs.set_parameters(V_ref=complex(10,0), f_src=50)\n", + "res = dpsimpy.dp.ph1.Resistor('r1')\n", + "res.set_parameters(resistance)\n", + "ind = dpsimpy.dp.ph1.Inductor('l1')\n", + "ind.set_parameters(inductance)\n", + "sw = dpsimpy.dp.ph1.Switch('Switch')\n", + "sw.set_parameters(open_resistance, closed_resistance, True)\n", + "\n", + "vs.connect([gnd, n1])\n", + "sw.connect([n1, n2])\n", + "res.connect([n2, n3])\n", + "ind.connect([n3, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [gnd, n1, n2, n3], [vs, sw, ind, res])\n", + "\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute('n1.v', 'v', n1);\n", + "logger.log_attribute('n2.v', 'v', n2);\n", + "logger.log_attribute('n3.v', 'v', n3);\n", + "logger.log_attribute('r1.i_intf', 'i_intf', res);\n", + "\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_domain(dpsimpy.Domain.DP)\n", + "sim.set_solver(dpsimpy.Solver.MNA)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.add_logger(logger)\n", + "\n", + "event_sw = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", + "sim.add_event(event_sw)\n", + "\n", + "sim.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## SP 1Ph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "time_step = 0.00001\n", + "final_time = 1\n", + "sim_name = 'SP_1Ph_VS_SW_RL1'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.sp.SimNode.gnd\n", + "n1 = dpsimpy.sp.SimNode('n1')\n", + "n1.set_initial_voltage(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0])\n", + "n2 = dpsimpy.sp.SimNode('n2')\n", + "n2.set_initial_voltage(sim_pf.get_idobj_attr(n2_pf.name(), 'v').get()[0][0])\n", + "n3 = dpsimpy.sp.SimNode('n3')\n", + "n3.set_initial_voltage(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0][0])\n", + "\n", + "resistance = 5\n", + "inductance = 0.02\n", + "open_resistance = 1e6\n", + "closed_resistance = 0.001\n", + "\n", + "# Components\n", + "vs = dpsimpy.sp.ph1.VoltageSource('vs')\n", + "vs.set_parameters(V_ref=complex(10,0), f_src=50)\n", + "res = dpsimpy.sp.ph1.Resistor('r1')\n", + "res.set_parameters(resistance)\n", + "ind = dpsimpy.sp.ph1.Inductor('l1')\n", + "ind.set_parameters(inductance)\n", + "sw = dpsimpy.sp.ph1.Switch('Switch')\n", + "sw.set_parameters(open_resistance, closed_resistance, True)\n", + "\n", + "vs.connect([gnd, n1])\n", + "sw.connect([n1, n2])\n", + "res.connect([n2, n3])\n", + "ind.connect([n3, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [gnd, n1, n2, n3], [vs, sw, ind, res])\n", + "\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute('n1.v', 'v', n1);\n", + "logger.log_attribute('n2.v', 'v', n2);\n", + "logger.log_attribute('n3.v', 'v', n3);\n", + "logger.log_attribute('r1.i_intf', 'i_intf', res);\n", + "\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_domain(dpsimpy.Domain.SP)\n", + "sim.set_solver(dpsimpy.Solver.MNA)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.add_logger(logger)\n", + "\n", + "event_sw = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", + "sim.add_event(event_sw)\n", + "\n", + "sim.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## EMT 3Ph" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "time_step = 0.00001\n", + "final_time = 1\n", + "sim_name = 'EMT_3Ph_VS_SW_RL1'\n", + "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", + "\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", + "n1.set_initial_voltage(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0])\n", + "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "n2.set_initial_voltage(sim_pf.get_idobj_attr(n2_pf.name(), 'v').get()[0][0])\n", + "n3 = dpsimpy.emt.SimNode('n3', dpsimpy.PhaseType.ABC)\n", + "n3.set_initial_voltage(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0][0])\n", + "\n", + "resistance = 5\n", + "inductance = 0.02\n", + "open_resistance = 1e6\n", + "closed_resistance = 0.001\n", + "\n", + "vs = dpsimpy.emt.ph3.VoltageSource('vs')\n", + "vs.set_parameters(V_ref=dpsimpy.Math.single_phase_variable_to_three_phase(complex(10, 0)), f_src=50)\n", + "res = dpsimpy.emt.ph3.Resistor('Resistor')\n", + "res.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(resistance))\n", + "ind = dpsimpy.emt.ph3.Inductor('Inductance')\n", + "ind.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(inductance))\n", + "sw = dpsimpy.emt.ph3.Switch('Switch')\n", + "sw.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(open_resistance), dpsimpy.Math.single_phase_parameter_to_three_phase(closed_resistance), True)\n", + "sw.close()\n", + "\n", + "vs.connect([gnd, n1])\n", + "sw.connect([n1, n2])\n", + "res.connect([n2, n3])\n", + "ind.connect([n3, gnd])\n", + "\n", + "sys = dpsimpy.SystemTopology(50, [gnd, n1, n2, n3], [vs, sw, res, ind])\n", + "\n", + "logger = dpsimpy.Logger(sim_name)\n", + "logger.log_attribute('n1.v', 'v', n1);\n", + "logger.log_attribute('n2.v', 'v', n2);\n", + "logger.log_attribute('n3.v', 'v', n3);\n", + "logger.log_attribute('r1.i_intf', 'i_intf', res)\n", + "\n", + "sim = dpsimpy.Simulation(sim_name)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.set_solver(dpsimpy.Solver.MNA)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.add_logger(logger)\n", + "\n", + "event_sw = dpsimpy.event.SwitchEvent3Ph(0.5, sw, False)\n", + "sim.add_event(event_sw)\n", + "\n", + "sim.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Read results" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## EMT 3Ph results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# read \n", + "work_dir = 'logs/EMT_3Ph_VS_SW_RL1/'\n", + "log_name = 'EMT_3Ph_VS_SW_RL1'\n", + "print(work_dir + log_name + '.csv')\n", + "\n", + "ts_dpsim_emt_3ph = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## EMT 1Ph results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "work_dir = 'logs/EMT_1Ph_VS_SW_RL1/'\n", + "log_name = 'EMT_1Ph_VS_SW_RL1'\n", + "print(work_dir + log_name + '.csv')\n", + "\n", + "ts_dpsim_emt_1ph = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "## DP 1Ph results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "work_dir = 'logs/DP_1Ph_VS_SW_RL1/'\n", + "log_name = 'DP_1Ph_VS_SW_RL1'\n", + "print(work_dir + log_name + '.csv')\n", + "\n", + "ts_dpsim_dp_1ph = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "\n", + "# shifted\n", + "ts_dpsim_dp_1ph_shift = ts.frequency_shift_list(ts_dpsim_dp_1ph, 50)\n", + "\n", + "# phase-to-phase RMS to phase-to-ground Peak\n", + "for name, ts in ts_dpsim_dp_1ph_shift.items():\n", + " ts.values = ts.values * math.sqrt(2/3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "jp-MarkdownHeadingCollapsed": true, + "tags": [] + }, + "source": [ + "## SP 1Ph results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "work_dir = 'logs/SP_1Ph_VS_SW_RL1/'\n", + "log_name = 'SP_1Ph_VS_SW_RL1'\n", + "print(work_dir + log_name + '.csv')\n", + "\n", + "ts_dpsim_sp_1ph = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", + "\n", + "# shifted\n", + "ts_dpsim_sp_1ph_shift = ts.frequency_shift_list(ts_dpsim_sp_1ph, 50)\n", + "\n", + "# phase-to-phase RMS to phase-to-ground Peak\n", + "for name, ts in ts_dpsim_sp_1ph_shift.items():\n", + " ts.values = ts.values * math.sqrt(2/3)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "# Plot results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "plt.close('all')\n", + "\n", + "# EMT 3Ph\n", + "ts_dpsim_emt_3ph['n1.v_0'].label = 'v1 EMT 3Ph'\n", + "ts_dpsim_emt_3ph['n2.v_0'].label = 'v2 EMT 3Ph'\n", + "ts_dpsim_emt_3ph['n3.v_0'].label = 'v3 EMT 3Ph'\n", + "ts_dpsim_emt_3ph['r1.i_intf_0'].label = 'i12 EMT 3Ph'\n", + "pt.plot_timeseries(1, ts_dpsim_emt_3ph['n1.v_0'], plt_linestyle=':')\n", + "pt.plot_timeseries(2, ts_dpsim_emt_3ph['n2.v_0'], plt_linestyle=':')\n", + "pt.plot_timeseries(3, ts_dpsim_emt_3ph['n3.v_0'], plt_linestyle=':')\n", + "pt.plot_timeseries(4, ts_dpsim_emt_3ph['r1.i_intf_0'], plt_linestyle=':')\n", + "\n", + "# EMT 1Ph\n", + "ts_dpsim_emt_1ph['n1.v'].label = 'v1 EMT 1Ph'\n", + "ts_dpsim_emt_1ph['n2.v'].label = 'v2 EMT 1Ph'\n", + "ts_dpsim_emt_1ph['n3.v'].label = 'v3 EMT 1Ph'\n", + "ts_dpsim_emt_1ph['r1.i_intf'].label = 'i12 EMT 1Ph'\n", + "pt.plot_timeseries(1, ts_dpsim_emt_1ph['n1.v'], plt_linestyle='-')\n", + "pt.plot_timeseries(2, ts_dpsim_emt_1ph['n2.v'], plt_linestyle='-')\n", + "pt.plot_timeseries(3, ts_dpsim_emt_1ph['n3.v'], plt_linestyle='-')\n", + "pt.plot_timeseries(4, ts_dpsim_emt_1ph['r1.i_intf'], plt_linestyle='-')\n", + "\n", + "# DP 1Ph shifted\n", + "ts_dpsim_dp_1ph_shift['n1.v_shift'].label = 'v1 DP 1Ph'\n", + "ts_dpsim_dp_1ph_shift['n2.v_shift'].label = 'v2 DP 1Ph'\n", + "ts_dpsim_dp_1ph_shift['n3.v_shift'].label = 'v3 DP 1Ph'\n", + "ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].label = 'i12 DP 1Ph'\n", + "pt.plot_timeseries(1, ts_dpsim_dp_1ph_shift['n1.v_shift'], plt_linestyle='-')\n", + "pt.plot_timeseries(2, ts_dpsim_dp_1ph_shift['n2.v_shift'], plt_linestyle='-')\n", + "pt.plot_timeseries(3, ts_dpsim_dp_1ph_shift['n3.v_shift'], plt_linestyle='-')\n", + "pt.plot_timeseries(4, ts_dpsim_dp_1ph_shift['r1.i_intf_shift'], plt_linestyle='-')\n", + "\n", + "# SP 1Ph shifted\n", + "ts_dpsim_sp_1ph_shift['n1.v_shift'].label = 'v1 SP 1Ph'\n", + "ts_dpsim_sp_1ph_shift['n2.v_shift'].label = 'v2 SP 1Ph'\n", + "ts_dpsim_sp_1ph_shift['n3.v_shift'].label = 'v3 SP 1Ph'\n", + "ts_dpsim_sp_1ph_shift['r1.i_intf_shift'].label = 'i12 SP 1Ph'\n", + "pt.plot_timeseries(1, ts_dpsim_sp_1ph_shift['n1.v_shift'], plt_linestyle=':')\n", + "pt.plot_timeseries(2, ts_dpsim_sp_1ph_shift['n2.v_shift'], plt_linestyle=':')\n", + "pt.plot_timeseries(3, ts_dpsim_sp_1ph_shift['n3.v_shift'], plt_linestyle=':')\n", + "pt.plot_timeseries(4, ts_dpsim_sp_1ph_shift['r1.i_intf_shift'], plt_linestyle=':')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Assertions" + ] + } + ], + "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 +} diff --git a/examples/Notebooks/Components/Ph1_Switch.ipynb b/examples/Notebooks/Components/Ph1_Switch.ipynb deleted file mode 100644 index 7b19a1cd8b..0000000000 --- a/examples/Notebooks/Components/Ph1_Switch.ipynb +++ /dev/null @@ -1,153 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# EMT::Ph1::Switch Test" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import villas.dataprocessing.readtools as rt\n", - "from villas.dataprocessing.timeseries import TimeSeries as ts\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import dpsimpy\n", - "\n", - "#%matplotlib widget" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## VS_SW_R_L - Circuit" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "time_step = 0.00001\n", - "final_time = 0.1\n", - "sim_name = 'EMT_VS_SW_RL1'\n", - "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", - "\n", - "gnd = dpsimpy.emt.SimNode.gnd\n", - "n1 = dpsimpy.emt.SimNode('n1')\n", - "n2 = dpsimpy.emt.SimNode('n2')\n", - "n3 = dpsimpy.emt.SimNode('n3')\n", - "\n", - "resistance = 5\n", - "inductance = 0.02\n", - "open_resistance = 1e6\n", - "closed_resistance = 0.001\n", - "\n", - "vs = dpsimpy.emt.ph1.VoltageSource('vs')\n", - "vs.set_parameters(complex(10, 0), 50)\n", - "res = dpsimpy.emt.ph1.Resistor('Resistor')\n", - "res.set_parameters(resistance)\n", - "ind = dpsimpy.emt.ph1.Inductor('Inductance')\n", - "ind.set_parameters(inductance)\n", - "sw = dpsimpy.emt.ph1.Switch('Switch')\n", - "sw.set_parameters(open_resistance, closed_resistance, False)\n", - "\n", - "vs.connect([gnd, n1])\n", - "sw.connect([n1, n2])\n", - "res.connect([n2, n3])\n", - "ind.connect([n3, gnd])\n", - "\n", - "sys = dpsimpy.SystemTopology(50, [n1, n2, n3], [vs, sw, res, ind])\n", - "\n", - "logger = dpsimpy.Logger(sim_name)\n", - "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('v3', 'v', n3)\n", - "logger.log_attribute('i_res', 'i_intf', res)\n", - "\n", - "sim = dpsimpy.Simulation(sim_name)\n", - "sim.set_domain(dpsimpy.Domain.EMT)\n", - "sim.set_solver(dpsimpy.Solver.MNA)\n", - "sim.set_system(sys)\n", - "sim.set_time_step(time_step)\n", - "sim.set_final_time(final_time)\n", - "sim.add_logger(logger)\n", - "\n", - "event_sw = dpsimpy.event.SwitchEvent(0.04, sw, True)\n", - "sim.add_event(event_sw)\n", - "\n", - "sim.run()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "work_dir = 'logs/EMT_VS_SW_RL1/'\n", - "log_name = 'EMT_VS_SW_RL1'\n", - "print(work_dir + log_name + '.csv')\n", - "EMTseries = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.figure()\n", - "plt.plot(EMTseries['v2'].time, EMTseries['v3'].values - EMTseries['v2'].values, label='V_res')\n", - "plt.legend()\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "plt.figure()\n", - "plt.plot(EMTseries['i_res'].time, EMTseries['i_res'].values, label='I')\n", - "plt.legend()\n", - "plt.show()" - ] - }, - { - "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 64b502193c6c56ba15baed12830dd67d7fe73418 Mon Sep 17 00:00:00 2001 From: Marvin Tollnitsch Date: Thu, 18 Jul 2024 16:49:50 +0200 Subject: [PATCH 6/6] Adjust switch test notebook - increase simulation time to 2 seconds - add another switch event to close switch at 1.5 seconds - fix vs parameters by removing frequency for dp and sp domains - add assertions to check Ph1::EMT against Ph3::EMT, Ph1::EMT against dp and dp against sp Signed-off-by: Marvin Tollnitsch --- examples/Notebooks/Circuits/VS_SW_RL1.ipynb | 119 +++++++++++++++++--- 1 file changed, 101 insertions(+), 18 deletions(-) diff --git a/examples/Notebooks/Circuits/VS_SW_RL1.ipynb b/examples/Notebooks/Circuits/VS_SW_RL1.ipynb index 2c0e555e7d..54b5b41a2f 100644 --- a/examples/Notebooks/Circuits/VS_SW_RL1.ipynb +++ b/examples/Notebooks/Circuits/VS_SW_RL1.ipynb @@ -23,7 +23,7 @@ "import numpy as np\n", "import dpsimpy\n", "\n", - "# %matplotlib widget" + "#%matplotlib widget" ] }, { @@ -108,7 +108,7 @@ "outputs": [], "source": [ "time_step = 0.00001\n", - "final_time = 1\n", + "final_time = 2\n", "sim_name = 'EMT_1Ph_VS_SW_RL1'\n", "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", "\n", @@ -155,8 +155,10 @@ "sim.set_final_time(final_time)\n", "sim.add_logger(logger)\n", "\n", - "event_sw = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", - "sim.add_event(event_sw)\n", + "event_sw1 = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", + "event_sw2 = dpsimpy.event.SwitchEvent(1.5, sw, True)\n", + "sim.add_event(event_sw1)\n", + "sim.add_event(event_sw2)\n", "\n", "sim.run()" ] @@ -177,7 +179,7 @@ "outputs": [], "source": [ "time_step = 0.00001\n", - "final_time = 1\n", + "final_time = 2\n", "sim_name = 'DP_1Ph_VS_SW_RL1'\n", "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", @@ -197,7 +199,7 @@ "\n", "# Components\n", "vs = dpsimpy.dp.ph1.VoltageSource('vs')\n", - "vs.set_parameters(V_ref=complex(10,0), f_src=50)\n", + "vs.set_parameters(V_ref=complex(10,0))\n", "res = dpsimpy.dp.ph1.Resistor('r1')\n", "res.set_parameters(resistance)\n", "ind = dpsimpy.dp.ph1.Inductor('l1')\n", @@ -226,8 +228,10 @@ "sim.set_final_time(final_time)\n", "sim.add_logger(logger)\n", "\n", - "event_sw = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", - "sim.add_event(event_sw)\n", + "event_sw1 = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", + "event_sw2 = dpsimpy.event.SwitchEvent(1.5, sw, True)\n", + "sim.add_event(event_sw1)\n", + "sim.add_event(event_sw2)\n", "\n", "sim.run()" ] @@ -248,7 +252,7 @@ "outputs": [], "source": [ "time_step = 0.00001\n", - "final_time = 1\n", + "final_time = 2\n", "sim_name = 'SP_1Ph_VS_SW_RL1'\n", "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name)\n", "\n", @@ -268,7 +272,7 @@ "\n", "# Components\n", "vs = dpsimpy.sp.ph1.VoltageSource('vs')\n", - "vs.set_parameters(V_ref=complex(10,0), f_src=50)\n", + "vs.set_parameters(V_ref=complex(10,0))\n", "res = dpsimpy.sp.ph1.Resistor('r1')\n", "res.set_parameters(resistance)\n", "ind = dpsimpy.sp.ph1.Inductor('l1')\n", @@ -297,8 +301,10 @@ "sim.set_final_time(final_time)\n", "sim.add_logger(logger)\n", "\n", - "event_sw = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", - "sim.add_event(event_sw)\n", + "event_sw1 = dpsimpy.event.SwitchEvent(0.5, sw, False)\n", + "event_sw2 = dpsimpy.event.SwitchEvent(1.5, sw, True)\n", + "sim.add_event(event_sw1)\n", + "sim.add_event(event_sw2)\n", "\n", "sim.run()" ] @@ -317,7 +323,7 @@ "outputs": [], "source": [ "time_step = 0.00001\n", - "final_time = 1\n", + "final_time = 2\n", "sim_name = 'EMT_3Ph_VS_SW_RL1'\n", "dpsimpy.Logger.set_log_dir('logs/' + sim_name)\n", "\n", @@ -365,8 +371,10 @@ "sim.set_final_time(final_time)\n", "sim.add_logger(logger)\n", "\n", - "event_sw = dpsimpy.event.SwitchEvent3Ph(0.5, sw, False)\n", - "sim.add_event(event_sw)\n", + "event_sw1 = dpsimpy.event.SwitchEvent3Ph(0.5, sw, False)\n", + "event_sw2 = dpsimpy.event.SwitchEvent3Ph(1.5, sw, True)\n", + "sim.add_event(event_sw1)\n", + "sim.add_event(event_sw2)\n", "\n", "sim.run()" ] @@ -381,7 +389,6 @@ { "cell_type": "markdown", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -456,7 +463,6 @@ { "cell_type": "markdown", "metadata": { - "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ @@ -547,7 +553,84 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "# Assertions" + "# Assertions: Compare current through all components" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#1 s ≙ 100'000 steps\n", + "#0.025 s ≙ 2500 steps\n", + "#0.001 s ≙ 100 steps\n", + "\n", + "\n", + "#EMT::Ph1 vs EMT::Ph3 assertions\n", + "\n", + "tolerance = 1e-6\n", + "\n", + "#simulation start: Check between 0.025s and 0.03s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[2500:3000] - ts_dpsim_emt_3ph['r1.i_intf_0'].values[2500:3000]) < tolerance))\n", + "#before open switch: Check between 0.47 and 0.495s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[47000:49500] - ts_dpsim_emt_3ph['r1.i_intf_0'].values[47000:49500]) < tolerance))\n", + "#after open switch: Check between 0.525s and 0.53s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[52500:53000] - ts_dpsim_emt_3ph['r1.i_intf_0'].values[52500:53000]) < tolerance))\n", + "#before close switch: Check between 1.47 and 1.495s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[147000:149500] - ts_dpsim_emt_3ph['r1.i_intf_0'].values[147000:149500]) < tolerance))\n", + "#after close switch: Check between 1.525s and 1.505s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[152500:153000] - ts_dpsim_emt_3ph['r1.i_intf_0'].values[152500:153000]) < tolerance))\n", + "#simulation end: Check between 1.995s and 2s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[199500:200000] - ts_dpsim_emt_3ph['r1.i_intf_0'].values[199500:200000]) < tolerance))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#EMT::Ph1 vs DP\n", + "\n", + "tolerance = 1e-5\n", + "\n", + "#simulation start: Check between 0.025s and 0.03s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[2500:3000] - ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[2500:3000]) < tolerance))\n", + "#before open switch: Check between 0.47 and 0.495s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[47000:49500] - ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[47000:49500]) < tolerance))\n", + "#after open switch: Check between 0.525s and 0.53s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[52500:53000] - ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[52500:53000]) < tolerance))\n", + "#before close switch: Check between 1.47 and 1.495s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[147000:149500] - ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[147000:149500]) < tolerance))\n", + "#after close switch: Check between 1.525s and 1.505s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[152500:153000] - ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[152500:153000]) < tolerance))\n", + "#simulation end: Check between 1.995s and 2s\n", + "assert(np.all(abs(ts_dpsim_emt_1ph['r1.i_intf'].values[199500:200000] - ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[199500:200000]) < tolerance))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#SP vs DP\n", + "\n", + "tolerance = 0.00125\n", + "\n", + "#simulation start: Check between 0.025s and 0.03s\n", + "assert(np.all(abs(ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[2500:3000] - ts_dpsim_sp_1ph_shift['r1.i_intf_shift'].values[2500:3000]) < tolerance))\n", + "#before open switch: Check between 0.47 and 0.495s\n", + "assert(np.all(abs(ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[47000:49500] - ts_dpsim_sp_1ph_shift['r1.i_intf_shift'].values[47000:49500]) < tolerance))\n", + "#after open switch: Check between 0.525s and 0.53s\n", + "assert(np.all(abs(ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[52500:53000] - ts_dpsim_sp_1ph_shift['r1.i_intf_shift'].values[52500:53000]) < tolerance))\n", + "#before close switch: Check between 1.47 and 1.495s\n", + "assert(np.all(abs(ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[147000:149500] - ts_dpsim_sp_1ph_shift['r1.i_intf_shift'].values[147000:149500]) < tolerance))\n", + "#after close switch: Check between 1.525s and 1.505s\n", + "assert(np.all(abs(ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[152500:153000] - ts_dpsim_sp_1ph_shift['r1.i_intf_shift'].values[152500:153000]) < tolerance))\n", + "#simulation end: Check between 1.995s and 2s\n", + "assert(np.all(abs(ts_dpsim_dp_1ph_shift['r1.i_intf_shift'].values[199500:200000] - ts_dpsim_sp_1ph_shift['r1.i_intf_shift'].values[199500:200000]) < tolerance))" ] } ],