From 18a8552095fd770c01ef21ac32e1e18ae87d7bb0 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 29 Sep 2023 13:47:23 +0200 Subject: [PATCH 01/39] Implemented SP_Ph1_CurrentSource Signed-off-by: pipeacosta --- .../include/dpsim-models/Components.h | 1 + .../dpsim-models/SP/SP_Ph1_CurrentSource.h | 64 +++++++++++++ dpsim-models/src/CMakeLists.txt | 1 + dpsim-models/src/SP/SP_Ph1_CurrentSource.cpp | 94 +++++++++++++++++++ dpsim/src/pybind/SPComponents.cpp | 7 ++ 5 files changed, 167 insertions(+) create mode 100644 dpsim-models/include/dpsim-models/SP/SP_Ph1_CurrentSource.h create mode 100644 dpsim-models/src/SP/SP_Ph1_CurrentSource.cpp diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index 3326608c27..cab8e25b4a 100644 --- a/dpsim-models/include/dpsim-models/Components.h +++ b/dpsim-models/include/dpsim-models/Components.h @@ -11,6 +11,7 @@ #include #include +#include #include #include #include diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_CurrentSource.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_CurrentSource.h new file mode 100644 index 0000000000..619a03bdf2 --- /dev/null +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_CurrentSource.h @@ -0,0 +1,64 @@ +/* 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 + +namespace CPS { +namespace SP { +namespace Ph1 { + /// \brief Dynamic phasor ideal current source + /// + /// A positive current is flowing out of node1 and into node2. + class CurrentSource : + public MNASimPowerComp, + public SharedFactory { + public: + const Attribute::Ptr mCurrentRef; + /// Defines UID, name and logging level + CurrentSource(String uid, String name, Logger::Level loglevel = Logger::Level::off); + /// Defines name and logging level + CurrentSource(String name, Logger::Level logLevel = Logger::Level::off) + : CurrentSource(name, name, logLevel) { } + /// Defines name, component parameters and logging level + CurrentSource(String name, Complex current, + Logger::Level logLevel = Logger::Level::off); + + void setParameters(Complex current); + + SimPowerComp::Ptr clone(String copySuffix); + + // #### General #### + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency); + + // #### 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); + /// + void mnaCompUpdateVoltage(const Matrix& leftVector); + + /// 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; + void mnaCompPreStep(Real time, Int timeStepCount) override; + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + + }; +} +} +} diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index 79334c602c..ba782c9a7b 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -100,6 +100,7 @@ list(APPEND MODELS_SOURCES EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp SP/SP_Ph1_VoltageSource.cpp + SP/SP_Ph1_CurrentSource.cpp SP/SP_Ph1_Capacitor.cpp SP/SP_Ph1_Inductor.cpp SP/SP_Ph1_Resistor.cpp diff --git a/dpsim-models/src/SP/SP_Ph1_CurrentSource.cpp b/dpsim-models/src/SP/SP_Ph1_CurrentSource.cpp new file mode 100644 index 0000000000..48b3c7bb33 --- /dev/null +++ b/dpsim-models/src/SP/SP_Ph1_CurrentSource.cpp @@ -0,0 +1,94 @@ +/* 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; + +SP::Ph1::CurrentSource::CurrentSource(String uid, String name, Logger::Level logLevel) + : MNASimPowerComp(uid, name, true, true, logLevel), + mCurrentRef(mAttributes->createDynamic("I_ref")) { + setTerminalNumber(2); + **mIntfVoltage = MatrixComp::Zero(1,1); + **mIntfCurrent = MatrixComp::Zero(1,1); +} + +SP::Ph1::CurrentSource::CurrentSource(String name, Complex current, Logger::Level logLevel) + : CurrentSource(name, logLevel) { + setParameters(current); +} + +void SP::Ph1::CurrentSource::setParameters(Complex current) { + **mCurrentRef = current; + mParametersSet = true; +} + +SimPowerComp::Ptr SP::Ph1::CurrentSource::clone(String name) { + auto copy = CurrentSource::make(name, mLogLevel); + copy->setParameters(**mCurrentRef); + return copy; +} + +void SP::Ph1::CurrentSource::initializeFromNodesAndTerminals(Real frequency) { + + (**mIntfVoltage)(0,0) = initialSingleVoltage(0) - initialSingleVoltage(1); + (**mIntfCurrent)(0,0) = **mCurrentRef; + + 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::phasorToString((**mIntfVoltage)(0,0)), + Logger::phasorToString((**mIntfCurrent)(0,0)), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1))); +} + +void SP::Ph1::CurrentSource::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); + (**mIntfCurrent)(0,0) = **mCurrentRef; +} + +void SP::Ph1::CurrentSource::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { + attributeDependencies.push_back(mCurrentRef); + modifiedAttributes.push_back(mRightVector); + modifiedAttributes.push_back(mIntfCurrent); +} + +void SP::Ph1::CurrentSource::mnaCompPreStep(Real time, Int timeStepCount) { + mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void SP::Ph1::CurrentSource::mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { + (**mIntfCurrent)(0,0) = **mCurrentRef; + + if (terminalNotGrounded(0)) + Math::setVectorElement(rightVector, matrixNodeIndex(0), -(**mIntfCurrent)(0,0)); + if (terminalNotGrounded(1)) + Math::setVectorElement(rightVector, matrixNodeIndex(1), (**mIntfCurrent)(0,0)); +} + +void SP::Ph1::CurrentSource::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); +} + +void SP::Ph1::CurrentSource::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); +} + +void SP::Ph1::CurrentSource::mnaCompUpdateVoltage(const Matrix& leftVector) { + (**mIntfVoltage)(0,0) = 0; + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0,0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(0)); + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0,0) = (**mIntfVoltage)(0,0) - Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); +} diff --git a/dpsim/src/pybind/SPComponents.cpp b/dpsim/src/pybind/SPComponents.cpp index c0084eea31..21386ab994 100644 --- a/dpsim/src/pybind/SPComponents.cpp +++ b/dpsim/src/pybind/SPComponents.cpp @@ -34,6 +34,13 @@ void addSPPh1Components(py::module_ mSPPh1) { .def_property("V_ref", createAttributeGetter("V_ref"), createAttributeSetter("V_ref")) .def_property("f_src", createAttributeGetter("f_src"), createAttributeSetter("f_src")); + py::class_, CPS::SimPowerComp>(mSPPh1, "CurrentSource", py::multiple_inheritance()) + .def(py::init()) + .def(py::init()) + .def("set_parameters", &CPS::SP::Ph1::CurrentSource::setParameters, "I_ref"_a) + .def("connect", &CPS::SP::Ph1::CurrentSource::connect) + .def_property("I_ref", createAttributeGetter("I_ref"), createAttributeSetter("I_ref")); + py::class_, CPS::SimPowerComp>(mSPPh1, "Resistor", py::multiple_inheritance()) .def(py::init()) .def(py::init()) From 21f58e6406877f8d0afc9594a37f24c32d62d917 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Wed, 12 Oct 2022 17:04:38 -0500 Subject: [PATCH 02/39] First version of the dpsim-mqtt-distributed-villas example Signed-off-by: pipeacosta --- .../villas/dpsim-mqtt-distributed-villas.py | 365 ++++++++++++++++++ 1 file changed, 365 insertions(+) create mode 100644 examples/villas/dpsim-mqtt-distributed-villas.py diff --git a/examples/villas/dpsim-mqtt-distributed-villas.py b/examples/villas/dpsim-mqtt-distributed-villas.py new file mode 100644 index 0000000000..c4685943f4 --- /dev/null +++ b/examples/villas/dpsim-mqtt-distributed-villas.py @@ -0,0 +1,365 @@ +# This example reads a sine signal from villas that modifies the active power set point +# of the PQ load. The n2 voltage is exported to a file via MQTT and VILLASnode. + +import sys +import os.path +import logging +import json +import time + +from datetime import datetime +from villas.node.node import Node as VILLASnode + +from multiprocessing import Process + +import dpsimpy +import dpsimpyvillas + +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') + + # nodes = { + # 'mqtt0': { + # 'type': 'mqtt', + # 'format': 'json', + # 'host': 'mqtt', + # 'in': { + # 'subscribe': '/dpsim0-mqtt0', + # 'signals': [ + # { + # 'name': 'i_intf', + # 'type': 'complex' + # } + # ] + # }, + # 'out': { + # 'publish': '/mqtt0-dpsim0' + # } + # }, + # 'mqtt1': { + # 'type': 'mqtt', + # 'format': 'json', + # 'host': 'mqtt', + # 'in': { + # 'subscribe': '/dpsim1-mqtt1', + # 'signals': [ + # { + # 'name': 'v_intf', + # 'type': 'complex' + # } + # ] + # }, + # 'out': { + # 'publish': '/mqtt1-dpsim1' + # } + # } + # } + + # paths = [ + # { + # 'in': 'mqtt0', + # 'out': 'mqtt1', + # 'reverse': True, + # 'hooks': [{'type':'print'}] + # } + # ] + + # config = { + # 'nodes': nodes, + # 'paths': paths + # } + # config['nodes']['mqtt0']['out']['hooks'] = [{'type':'print'}] + # config['nodes']['mqtt1']['out']['hooks'] = [{'type':'print'}] + + # nodes = { + # 'mqtt0': { + # 'type': 'mqtt', + # 'format': 'json', + # 'host': 'mqtt', + # 'in': { + # 'subscribe': '/dpsim0-mqtt0', + # 'signals': [ + # { + # 'name': 'i_intf', + # 'type': 'complex' + # } + # ] + # }, + # 'out': { + # 'publish': '/mqtt0-dpsim0' + # } + # }, + # 'mqtt1': { + # 'type': 'mqtt', + # 'format': 'json', + # 'host': 'mqtt', + # 'in': { + # 'subscribe': '/dpsim1-mqtt1', + # 'signals': [ + # { + # 'name': 'v_intf', + # 'type': 'complex' + # } + # ] + # }, + # 'out': { + # 'publish': '/mqtt1-dpsim1' + # } + # }, + # 'file1': { + # 'type': 'file', + # 'uri': f'{base}-results-%y-%m-%d_%H_%M_%S.csv' + # } + # } + + # paths = [ + # { + # 'in': 'mqtt1', + # 'out': 'file1', + # 'hooks': [{'type':'print'}] + # } + # ] + + # config = { + # 'nodes': nodes, + # 'paths': paths + # } + # config['nodes']['mqtt0']['out']['hooks'] = [{'type':'print'}] + + # log.info('VILLASnode config: \n%s', json.dumps(config, indent=2)) + + # node = VILLASnode(config=config, log_filename=log_filename) + # node.start() + + # return VILLASnode(config=config, log_filename=log_filename) + + villas_conf = """ + { + "nodes": { + "mqtt0": { + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": { + "subscribe": "/dpsim0-mqtt0", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] + }, + "out": { + "publish": "/mqtt0-dpsim0", + "hooks": [ + { + "type": "print" + } + ] + } + }, + "mqtt1": { + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": { + "subscribe": "/dpsim1-mqtt1", + "signals": [ + { + "name": "v_intf", + "type": "complex" + } + ] + }, + "out": { + "publish": "/mqtt1-dpsim1", + "hooks": [ + { + "type": "print" + } + ] + } + } + }, + "paths": [ + { + "in": "mqtt0", + "out": "mqtt1", + "hooks": [ + { + "type": "print" + } + ] + }, + { + "in": "mqtt1", + "out": "mqtt0", + "hooks": [ + { + "type": "print" + } + ] + } + ] + } + """ + + with open("villas-node.conf", "w") as text_file: + text_file.write("%s" % villas_conf) + + os.system('villas-node villas-node.conf') + +def dpsim0(): + sim_name = "DistributedVILLAS0" + 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]) + + 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.set_parameters(complex(10, 0)) + + r12 = dpsimpy.dp.ph1.Resistor('r_12', dpsimpy.LogLevel.debug) + r12.set_parameters(1) + + evs.connect([dpsimpy.dp.SimNode.gnd, n2]) + vs1.connect([dpsimpy.dp.SimNode.gnd, n1]) + r12.connect([n1, n2]) + + sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, vs1, r12]) + + 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) + + sim = dpsimpy.RealTimeSimulation(sim_name) + sim.set_system(sys) + sim.set_time_step(time_step) + sim.set_final_time(final_time) + + intf_config = { + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": { + "subscribe": "/mqtt0-dpsim0" + }, + "out": { + "publish": "/dpsim0-mqtt0" + } + } + + # file_config = '''{ + # "type": "file", + # "format": "csv", + # "uri": "dpsim-mqtt-distributed-villas-results-22-09-12_16_27_53.csv", + # "in": { + # "signals": [ + # { + # "name": "v_intf", + # "type": "complex" + # } + # ] + # } + # }''' + + intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-mqtt0", config=intf_config) + # intf = dpsimpyvillas.InterfaceVillas(name="file-dpsim0", config=file_config) + + sim.add_interface(intf, True) + sim.import_attribute(evs.attr('V_ref'), 0) + sim.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0) + + sim.run(1) + # return sim, intf + +def dpsim1(): + sim_name = "DistributedVILLAS1" + time_step = 0.01 + final_time = 10 + + n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) + + 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.set_parameters(1) + + ecs.connect([dpsimpy.dp.SimNode.gnd, n2]) + r02.connect([dpsimpy.dp.SimNode.gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [n2], [ecs, r02]) + + 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) + + sim = dpsimpy.RealTimeSimulation(sim_name) + sim.set_system(sys) + sim.set_time_step(time_step) + sim.set_final_time(final_time) + + intf_config = { + "type": "mqtt", + "format": "json", + "host": "mqtt", + "in": { + "subscribe": "/mqtt1-dpsim1" + }, + "out": { + "publish": "/dpsim1-mqtt1" + } + } + + intf = dpsimpyvillas.InterfaceVillas(name="dpsim1-mqtt1", config=intf_config) + sim.add_interface(intf, True) + 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.run(1) + + # return sim, intf + +if __name__ == '__main__': + logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) + + # p_node = villas() + p_node = Process(target=villas) + p_sim0 = Process(target=dpsim0) + p_sim1 = Process(target=dpsim1) + + p_node.start() + p_sim0.start() + p_sim1.start() + + p_sim0.join() + p_sim1.join() + + print('Both simulations have ended!') + + p_node.join() + # p_node.stop() + + # sim, intf = dpsim0() #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() \ No newline at end of file From 2cec8ec2a6e76acbd766ddadf69b3d9d6ab3319f Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Wed, 12 Oct 2022 17:08:58 -0500 Subject: [PATCH 03/39] Cleaned commented code in dpsim-mqtt-distributed-villas.py Signed-off-by: pipeacosta --- .../villas/dpsim-mqtt-distributed-villas.py | 146 ------------------ 1 file changed, 146 deletions(-) diff --git a/examples/villas/dpsim-mqtt-distributed-villas.py b/examples/villas/dpsim-mqtt-distributed-villas.py index c4685943f4..e5ece22a1e 100644 --- a/examples/villas/dpsim-mqtt-distributed-villas.py +++ b/examples/villas/dpsim-mqtt-distributed-villas.py @@ -1,6 +1,3 @@ -# This example reads a sine signal from villas that modifies the active power set point -# of the PQ load. The n2 voltage is exported to a file via MQTT and VILLASnode. - import sys import os.path import logging @@ -20,123 +17,6 @@ def villas(): - # log_filename=datetime.now().strftime(f'{base}-villas-%y-%m-%d_%H_%M_%S.log') - - # nodes = { - # 'mqtt0': { - # 'type': 'mqtt', - # 'format': 'json', - # 'host': 'mqtt', - # 'in': { - # 'subscribe': '/dpsim0-mqtt0', - # 'signals': [ - # { - # 'name': 'i_intf', - # 'type': 'complex' - # } - # ] - # }, - # 'out': { - # 'publish': '/mqtt0-dpsim0' - # } - # }, - # 'mqtt1': { - # 'type': 'mqtt', - # 'format': 'json', - # 'host': 'mqtt', - # 'in': { - # 'subscribe': '/dpsim1-mqtt1', - # 'signals': [ - # { - # 'name': 'v_intf', - # 'type': 'complex' - # } - # ] - # }, - # 'out': { - # 'publish': '/mqtt1-dpsim1' - # } - # } - # } - - # paths = [ - # { - # 'in': 'mqtt0', - # 'out': 'mqtt1', - # 'reverse': True, - # 'hooks': [{'type':'print'}] - # } - # ] - - # config = { - # 'nodes': nodes, - # 'paths': paths - # } - # config['nodes']['mqtt0']['out']['hooks'] = [{'type':'print'}] - # config['nodes']['mqtt1']['out']['hooks'] = [{'type':'print'}] - - # nodes = { - # 'mqtt0': { - # 'type': 'mqtt', - # 'format': 'json', - # 'host': 'mqtt', - # 'in': { - # 'subscribe': '/dpsim0-mqtt0', - # 'signals': [ - # { - # 'name': 'i_intf', - # 'type': 'complex' - # } - # ] - # }, - # 'out': { - # 'publish': '/mqtt0-dpsim0' - # } - # }, - # 'mqtt1': { - # 'type': 'mqtt', - # 'format': 'json', - # 'host': 'mqtt', - # 'in': { - # 'subscribe': '/dpsim1-mqtt1', - # 'signals': [ - # { - # 'name': 'v_intf', - # 'type': 'complex' - # } - # ] - # }, - # 'out': { - # 'publish': '/mqtt1-dpsim1' - # } - # }, - # 'file1': { - # 'type': 'file', - # 'uri': f'{base}-results-%y-%m-%d_%H_%M_%S.csv' - # } - # } - - # paths = [ - # { - # 'in': 'mqtt1', - # 'out': 'file1', - # 'hooks': [{'type':'print'}] - # } - # ] - - # config = { - # 'nodes': nodes, - # 'paths': paths - # } - # config['nodes']['mqtt0']['out']['hooks'] = [{'type':'print'}] - - # log.info('VILLASnode config: \n%s', json.dumps(config, indent=2)) - - # node = VILLASnode(config=config, log_filename=log_filename) - # node.start() - - # return VILLASnode(config=config, log_filename=log_filename) - villas_conf = """ { "nodes": { @@ -261,30 +141,14 @@ def dpsim0(): "publish": "/dpsim0-mqtt0" } } - - # file_config = '''{ - # "type": "file", - # "format": "csv", - # "uri": "dpsim-mqtt-distributed-villas-results-22-09-12_16_27_53.csv", - # "in": { - # "signals": [ - # { - # "name": "v_intf", - # "type": "complex" - # } - # ] - # } - # }''' intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-mqtt0", config=intf_config) - # intf = dpsimpyvillas.InterfaceVillas(name="file-dpsim0", config=file_config) sim.add_interface(intf, True) sim.import_attribute(evs.attr('V_ref'), 0) sim.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0) sim.run(1) - # return sim, intf def dpsim1(): sim_name = "DistributedVILLAS1" @@ -335,8 +199,6 @@ def dpsim1(): sim.run(1) - # return sim, intf - if __name__ == '__main__': logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) @@ -355,11 +217,3 @@ def dpsim1(): print('Both simulations have ended!') p_node.join() - # p_node.stop() - - # sim, intf = dpsim0() #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() \ No newline at end of file From 7da353775493ea250fda6f3fc1b980ac2fc1fbb0 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Thu, 20 Oct 2022 12:03:15 -0500 Subject: [PATCH 04/39] Fixed relative path in docker-compose of mqtt example Signed-off-by: pipeacosta --- examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml b/examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml index fab32160f2..3891ef1878 100644 --- a/examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml +++ b/examples/villas/docker-compose-dpsim-mqtt/docker-compose.yml @@ -1,14 +1,14 @@ services: dpsim: build: - context: ../../../../ #dpsim top-level folder + context: ../../../ #dpsim top-level folder dockerfile: packaging/Docker/Dockerfile.dev environment: PYTHONPATH: /dpsim/build:/dpsim/build/Source/Python:/dpsim/Source/Python ports: - "8888:8888" volumes: - - ../../../../:/dpsim + - ../../../:/dpsim privileged: true stdin_open: true tty: true From 3895055706b4bde88054c916bafa1b525c152c42 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Thu, 20 Oct 2022 12:04:12 -0500 Subject: [PATCH 05/39] Minor improvements to the dpsim-mqtt example Signed-off-by: pipeacosta --- examples/villas/dpsim-mqtt-distributed-villas.py | 2 +- examples/villas/dpsim-mqtt.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/examples/villas/dpsim-mqtt-distributed-villas.py b/examples/villas/dpsim-mqtt-distributed-villas.py index e5ece22a1e..d99326eaa2 100644 --- a/examples/villas/dpsim-mqtt-distributed-villas.py +++ b/examples/villas/dpsim-mqtt-distributed-villas.py @@ -216,4 +216,4 @@ def dpsim1(): print('Both simulations have ended!') - p_node.join() + p_node.join(1) diff --git a/examples/villas/dpsim-mqtt.py b/examples/villas/dpsim-mqtt.py index f50007efe2..8d2803384b 100644 --- a/examples/villas/dpsim-mqtt.py +++ b/examples/villas/dpsim-mqtt.py @@ -56,7 +56,11 @@ 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) +sim.add_interface(intf, True) + +sim.import_attribute(evs.attr('V_ref'), 0) +sim.export_attribute(r12.attr('i_intf').derive_coeff(0, 0), 0) +sim.export_attribute(evs.attr('v_intf').derive_coeff(0, 0).derive_scaled(complex(-1,0)), 1) sim.add_logger(logger) From 77093856efbc3627fbd977ed8273578c6f13b06c Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 23 Dec 2022 08:41:54 -0500 Subject: [PATCH 06/39] First version of SocketExample.cpp Signed-off-by: pipeacosta --- dpsim-villas/examples/cxx/CMakeLists.txt | 1 + dpsim-villas/examples/cxx/SocketExample.cpp | 92 +++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 dpsim-villas/examples/cxx/SocketExample.cpp diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index 4ea80b857f..4995281d05 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -16,6 +16,7 @@ set(SHMEM_SOURCES FileExample.cpp MqttExample.cpp SharedMemExample.cpp + SocketExample.cpp #ShmemExample.cpp #ShmemDistributedReference.cpp #ShmemDistributedDirect.cpp diff --git a/dpsim-villas/examples/cxx/SocketExample.cpp b/dpsim-villas/examples/cxx/SocketExample.cpp new file mode 100644 index 0000000000..c6972b74c4 --- /dev/null +++ b/dpsim-villas/examples/cxx/SocketExample.cpp @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include +#include + +using namespace DPsim; +using namespace CPS::DP; +using namespace CPS::DP::Ph1; + +int main(int argc, char* argv[]) { + // Very simple test circuit. Just a few resistors and an inductance. + // Voltage is read from VILLASnode and current through everything is written back. + String simName = "Sockets_example"; + CPS::Logger::setLogDir("logs/"+simName); + Real timeStep = 0.01; + + // Nodes + auto n1 = SimNode::make("n1"); + auto n2 = SimNode::make("n2"); + auto n3 = SimNode::make("n3"); + auto n4 = SimNode::make("n4"); + + // Components + auto evs = VoltageSource::make("v_s"); + evs->setParameters(Complex(5, 0)); + auto rs = Resistor::make("r_s"); + rs->setParameters(1); + auto rl = Resistor::make("r_line"); + rl->setParameters(1); + auto ll = Inductor::make("l_line"); + ll->setParameters(1); + auto rL = Resistor::make("r_load"); + rL->setParameters(1000); + + // Topology + evs->connect({ SimNode::GND, n1 }); + rs->connect({ n1, n2 }); + rl->connect({ n2, n3 }); + ll->connect({ n3, n4 }); + rL->connect({ n4, SimNode::GND }); + + auto sys = SystemTopology(50, + SystemNodeList{SimNode::GND, n1, n2, n3, n4}, + SystemComponentList{evs, rs, rl, ll, rL}); + + RealTimeSimulation sim(simName); + sim.setSystem(sys); + sim.setTimeStep(timeStep); + sim.setFinalTime(10.0); + + std::string socketConfig = R"STRING({ + "type": "socket", + "layer": "udp", + "in": { + "address": "127.0.0.1:12009", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] + }, + "out": { + "address": "127.0.0.1:12008" + } + })STRING"; + + // Logger + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->mVoltage); + logger->logAttribute("v2", n2->mVoltage); + logger->logAttribute("v3", n3->mVoltage); + logger->logAttribute("v4", n4->mVoltage); + logger->logAttribute("v_src", evs->mVoltageRef); + logger->logAttribute("i_r", rl->mIntfCurrent, 1, 1); + logger->logAttribute("i_evs", evs->mIntfCurrent, 1, 1); + logger->logAttribute("v_evs", evs->mIntfVoltage, 1, 1); + sim.addLogger(logger); + + auto intf = std::make_shared(socketConfig); + intf->exportAttribute(ll->mIntfCurrent->deriveCoeff(0, 0), 1, true, "v_load"); + + // Interface + sim.addInterface(intf); + + sim.run(1); + + //std::ofstream of("task_dependencies.svg"); + //sim.dependencyGraph().render(of); +} From 49c50e08320e85c9ed03cf238eb69329928bb2d1 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 3 Feb 2023 07:43:45 -0500 Subject: [PATCH 07/39] First version of SocketCosimExample Signed-off-by: pipeacosta --- dpsim-villas/examples/cxx/CMakeLists.txt | 1 + .../examples/cxx/SocketCosimExample.cpp | 164 ++++++++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 dpsim-villas/examples/cxx/SocketCosimExample.cpp diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index 4995281d05..900cccb88a 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -17,6 +17,7 @@ set(SHMEM_SOURCES MqttExample.cpp SharedMemExample.cpp SocketExample.cpp + SocketCosimExample.cpp #ShmemExample.cpp #ShmemDistributedReference.cpp #ShmemDistributedDirect.cpp diff --git a/dpsim-villas/examples/cxx/SocketCosimExample.cpp b/dpsim-villas/examples/cxx/SocketCosimExample.cpp new file mode 100644 index 0000000000..bf3ce19d52 --- /dev/null +++ b/dpsim-villas/examples/cxx/SocketCosimExample.cpp @@ -0,0 +1,164 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include + +#include +#include + +using namespace DPsim; +using namespace CPS::DP; +using namespace CPS::DP::Ph1; + +int main(int argc, char* argv[]) { + // Very simple test circuit. Just a few resistors and an inductance. + // Voltage is read from VILLASnode and current through everything is written back. + + if (argc < 2) { + std::cerr << "not enough arguments (either 0 or 1 for the test number)" << std::endl; + std::exit(1); + } + + Real timeStep = 0.01; + + if (String(argv[1]) == "0") { + String simName = "SocketsCosim_example1"; + CPS::Logger::setLogDir("logs/"+simName); + + // Nodes + auto n1 = SimNode::make("n1"); + auto n2 = SimNode::make("n2"); + + // Components + auto evs = VoltageSource::make("v_intf"); + evs->setParameters(Complex(5, 0)); + auto vs1 = VoltageSource::make("vs_1"); + vs1->setParameters(Complex(10, 0)); + auto r12 = Resistor::make("r_12"); + r12->setParameters(1); + + // Topology + evs->connect({ SimNode::GND, n2 }); + vs1->connect({ SimNode::GND, n1 }); + r12->connect({ n1, n2 }); + + auto sys = SystemTopology(50, + SystemNodeList{SimNode::GND, n1, n2}, + SystemComponentList{evs, vs1, r12}); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setTimeStep(timeStep); + sim.setFinalTime(10.0); + + // Make sure the format is set to json!! + std::string socketConfig = R"STRING({ + "type": "socket", + "layer": "udp", + "format": "json", + "in": { + "address": "127.0.0.1:12008", + "signals": [ + { + "name": "v_intf", + "type": "complex" + } + ] + }, + "out": { + "address": "127.0.0.1:12009", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] + } + })STRING"; + + // Logger. The logger must be added before the interface! + auto logger = DataLogger::make(simName); + logger->logAttribute("v1", n1->mVoltage); + logger->logAttribute("v2", n2->mVoltage); + logger->logAttribute("i_r", r12->mIntfCurrent, 1, 1); + logger->logAttribute("i_evs", evs->mIntfCurrent, 1, 1); + logger->logAttribute("v_evs", evs->mIntfVoltage, 1, 1); + sim.addLogger(logger); + + auto intf = std::make_shared(socketConfig); + intf->importAttribute(evs->mVoltageRef, 0, true, true); + intf->exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0, true, "i_intf"); + + // Interface + sim.addInterface(intf); + + sim.run(); + } + else if (String(argv[1]) == "1") { + String simName = "SocketsCosim_example2"; + CPS::Logger::setLogDir("logs/"+simName); + + // Nodes + auto n2 = SimNode::make("n2"); + + // Components + auto ecs = CurrentSource::make("i_intf"); + ecs->setParameters(Complex(5, 0)); + auto r02 = Resistor::make("r_02"); + r02->setParameters(1); + + // Topology + ecs->connect({ SimNode::GND, n2 }); + r02->connect({ SimNode::GND, n2 }); + + auto sys = SystemTopology(50, + SystemNodeList{SimNode::GND, n2}, + SystemComponentList{ecs, r02}); + + Simulation sim(simName); + sim.setSystem(sys); + sim.setTimeStep(timeStep); + sim.setFinalTime(10.0); + + // Make sure the format is set to json!! + std::string socketConfig = R"STRING({ + "type": "socket", + "layer": "udp", + "format": "json", + "in": { + "address": "127.0.0.1:12009", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] + }, + "out": { + "address": "127.0.0.1:12008", + "signals": [ + { + "name": "v_intf", + "type": "complex" + } + ] + } + })STRING"; + + // Logger. The logger must be added before the interface! + auto logger = DataLogger::make(simName); + logger->logAttribute("v2", n2->mVoltage); + logger->logAttribute("i_intf", r02->mIntfCurrent, 1, 1); + logger->logAttribute("v_ecs", ecs->mIntfVoltage, 1, 1); + logger->logAttribute("i_ecs", ecs->mIntfCurrent, 1, 1); + sim.addLogger(logger); + + auto intf = std::make_shared(socketConfig); + intf->importAttribute(ecs->mCurrentRef, 0, true, true); + intf->exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0, true, "v_intf"); + + // Interface + sim.addInterface(intf); + + sim.run(); + } +} From 467af6bc264832307085a133496bc02a824835a3 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 3 Feb 2023 07:45:04 -0500 Subject: [PATCH 08/39] Improvements to SocketExample, first working version Signed-off-by: pipeacosta --- dpsim-villas/examples/cxx/SocketExample.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dpsim-villas/examples/cxx/SocketExample.cpp b/dpsim-villas/examples/cxx/SocketExample.cpp index c6972b74c4..3794ddf04e 100644 --- a/dpsim-villas/examples/cxx/SocketExample.cpp +++ b/dpsim-villas/examples/cxx/SocketExample.cpp @@ -45,14 +45,16 @@ int main(int argc, char* argv[]) { SystemNodeList{SimNode::GND, n1, n2, n3, n4}, SystemComponentList{evs, rs, rl, ll, rL}); - RealTimeSimulation sim(simName); + Simulation sim(simName); sim.setSystem(sys); sim.setTimeStep(timeStep); sim.setFinalTime(10.0); + // Make sure the format is set to json!! std::string socketConfig = R"STRING({ "type": "socket", "layer": "udp", + "format": "json", "in": { "address": "127.0.0.1:12009", "signals": [ @@ -67,7 +69,7 @@ int main(int argc, char* argv[]) { } })STRING"; - // Logger + // Logger. The logger must be added before the interface! auto logger = DataLogger::make(simName); logger->logAttribute("v1", n1->mVoltage); logger->logAttribute("v2", n2->mVoltage); @@ -85,7 +87,7 @@ int main(int argc, char* argv[]) { // Interface sim.addInterface(intf); - sim.run(1); + sim.run(); //std::ofstream of("task_dependencies.svg"); //sim.dependencyGraph().render(of); From 384cacf44387e5d984ba67c90b412a2c233ee5c0 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 3 Feb 2023 08:37:23 -0500 Subject: [PATCH 09/39] Specify name and type of signal to which subscription is made Signed-off-by: pipeacosta --- examples/villas/dpsim-mqtt-distributed-villas.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/examples/villas/dpsim-mqtt-distributed-villas.py b/examples/villas/dpsim-mqtt-distributed-villas.py index d99326eaa2..7de6696903 100644 --- a/examples/villas/dpsim-mqtt-distributed-villas.py +++ b/examples/villas/dpsim-mqtt-distributed-villas.py @@ -135,7 +135,13 @@ def dpsim0(): "format": "json", "host": "mqtt", "in": { - "subscribe": "/mqtt0-dpsim0" + "subscribe": "/mqtt0-dpsim0", + "signals": [ + { + "name": "v_intf", + "type": "complex" + } + ] }, "out": { "publish": "/dpsim0-mqtt0" @@ -185,7 +191,13 @@ def dpsim1(): "format": "json", "host": "mqtt", "in": { - "subscribe": "/mqtt1-dpsim1" + "subscribe": "/mqtt1-dpsim1", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] }, "out": { "publish": "/dpsim1-mqtt1" From df93085b4cd24163fddbf88c00bedf3ed82adedd Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 3 Feb 2023 09:00:58 -0500 Subject: [PATCH 10/39] Implemented first version of co-simulation using sockets in Python Signed-off-by: pipeacosta --- examples/villas/dpsim-villas-cosim.py | 167 ++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 examples/villas/dpsim-villas-cosim.py diff --git a/examples/villas/dpsim-villas-cosim.py b/examples/villas/dpsim-villas-cosim.py new file mode 100644 index 0000000000..cab124ae69 --- /dev/null +++ b/examples/villas/dpsim-villas-cosim.py @@ -0,0 +1,167 @@ +import sys +import os.path +import logging +import json +import time + +from datetime import datetime +from villas.node.node import Node as VILLASnode + +from multiprocessing import Process + +import dpsimpy +import dpsimpyvillas + +base = os.path.splitext(os.path.basename(sys.argv[0]))[0] +log = logging.getLogger(base) + +def dpsim0(): + sim_name = "DistributedVILLAS0" + 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]) + + 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.set_parameters(complex(10, 0)) + + r12 = dpsimpy.dp.ph1.Resistor('r_12', dpsimpy.LogLevel.debug) + r12.set_parameters(1) + + evs.connect([dpsimpy.dp.SimNode.gnd, n2]) + vs1.connect([dpsimpy.dp.SimNode.gnd, n1]) + r12.connect([n1, n2]) + + sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, vs1, r12]) + + sim = dpsimpy.RealTimeSimulation(sim_name) + sim.set_system(sys) + sim.set_time_step(time_step) + sim.set_final_time(final_time) + + intf_config = { + "type": "socket", + "layer": "udp", + "format": "json", + "hooks": [ + {"type": "print"} + ], + "in": { + "address": "127.0.0.1:12008", + "signals": [ + { + "name": "v_intf", + "type": "complex" + } + ] + }, + "out": { + "address": "127.0.0.1:12009", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] + } + } + + 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) + + intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-dpsim1", config=intf_config) + + sim.add_interface(intf) + intf.import_attribute(evs.attr('V_ref'), 0) + intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0) + + sim.run(1) + +def dpsim1(): + sim_name = "DistributedVILLAS1" + time_step = 0.01 + final_time = 10 + + n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) + + 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.set_parameters(1) + + ecs.connect([dpsimpy.dp.SimNode.gnd, n2]) + r02.connect([dpsimpy.dp.SimNode.gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [n2], [ecs, r02]) + + sim = dpsimpy.RealTimeSimulation(sim_name) + sim.set_system(sys) + sim.set_time_step(time_step) + sim.set_final_time(final_time) + + intf_config = { + "type": "socket", + "layer": "udp", + "format": "json", + "hooks": [ + {"type": "print"} + ], + "in": { + "address": "127.0.0.1:12009", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] + }, + "out": { + "address": "127.0.0.1:12008", + "signals": [ + { + "name": "v_intf", + "type": "complex" + } + ] + } + } + + 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) + + intf = dpsimpyvillas.InterfaceVillas(name="dpsim1-dpsim0", config=intf_config) + + sim.add_interface(intf) + intf.import_attribute(ecs.attr('I_ref'), 0) + intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0) + + sim.run(1) + +if __name__ == '__main__': + logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) + + p_sim0 = Process(target=dpsim0) + p_sim1 = Process(target=dpsim1) + + p_sim0.start() + p_sim1.start() + + p_sim0.join() + p_sim1.join() + + print('Both simulations have ended!') From ff1da65b639deca73f5f7124f0ea7946e0a110ac Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Wed, 8 Feb 2023 10:25:20 -0500 Subject: [PATCH 11/39] Improvements to SocketCosimExample: added hooks and start script Signed-off-by: pipeacosta --- configs/start_SocketCosimExample.sh | 8 ++++++ .../examples/cxx/SocketCosimExample.cpp | 27 +++++++++++++------ 2 files changed, 27 insertions(+), 8 deletions(-) create mode 100755 configs/start_SocketCosimExample.sh diff --git a/configs/start_SocketCosimExample.sh b/configs/start_SocketCosimExample.sh new file mode 100755 index 0000000000..43f296e1b6 --- /dev/null +++ b/configs/start_SocketCosimExample.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +CPS_LOG_PREFIX="[Left ] " build/dpsim-villas/examples/cxx/SocketCosimExample 0 & P1=$! +CPS_LOG_PREFIX="[Right] " build/dpsim-villas/examples/cxx/SocketCosimExample 1 & P2=$! + +for job in $P1 $P2; do + wait $job || exit 1 +done diff --git a/dpsim-villas/examples/cxx/SocketCosimExample.cpp b/dpsim-villas/examples/cxx/SocketCosimExample.cpp index bf3ce19d52..ea54db9d93 100644 --- a/dpsim-villas/examples/cxx/SocketCosimExample.cpp +++ b/dpsim-villas/examples/cxx/SocketCosimExample.cpp @@ -45,16 +45,19 @@ int main(int argc, char* argv[]) { SystemNodeList{SimNode::GND, n1, n2}, SystemComponentList{evs, vs1, r12}); - Simulation sim(simName); + RealTimeSimulation sim(simName); sim.setSystem(sys); sim.setTimeStep(timeStep); - sim.setFinalTime(10.0); + sim.setFinalTime(0.1); // Make sure the format is set to json!! std::string socketConfig = R"STRING({ "type": "socket", "layer": "udp", "format": "json", + "hooks": [ + {"type": "print"} + ], "in": { "address": "127.0.0.1:12008", "signals": [ @@ -85,13 +88,18 @@ int main(int argc, char* argv[]) { sim.addLogger(logger); auto intf = std::make_shared(socketConfig); - intf->importAttribute(evs->mVoltageRef, 0, true, true); + + Eigen::MatrixXcd intfCurrent0(1,1); + intfCurrent0(0,0) = std::complex(5.0,0.0); + evs->setIntfCurrent(intfCurrent0); + + intf->importAttribute(evs->mVoltageRef, 0, false, false); intf->exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0, true, "i_intf"); // Interface sim.addInterface(intf); - sim.run(); + sim.run(1); } else if (String(argv[1]) == "1") { String simName = "SocketsCosim_example2"; @@ -114,16 +122,19 @@ int main(int argc, char* argv[]) { SystemNodeList{SimNode::GND, n2}, SystemComponentList{ecs, r02}); - Simulation sim(simName); + RealTimeSimulation sim(simName); sim.setSystem(sys); sim.setTimeStep(timeStep); - sim.setFinalTime(10.0); + sim.setFinalTime(0.1); // Make sure the format is set to json!! std::string socketConfig = R"STRING({ "type": "socket", "layer": "udp", "format": "json", + "hooks": [ + {"type": "print"} + ], "in": { "address": "127.0.0.1:12009", "signals": [ @@ -153,12 +164,12 @@ int main(int argc, char* argv[]) { sim.addLogger(logger); auto intf = std::make_shared(socketConfig); - intf->importAttribute(ecs->mCurrentRef, 0, true, true); + intf->importAttribute(ecs->mCurrentRef, 0, false, false); intf->exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0, true, "v_intf"); // Interface sim.addInterface(intf); - sim.run(); + sim.run(1); } } From c85dc3222e892129717198953a767a16f33f4dc8 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Wed, 8 Feb 2023 10:38:10 -0500 Subject: [PATCH 12/39] Improvements to the example dpsim-villas-cosim: first working version Signed-off-by: pipeacosta --- examples/villas/dpsim-villas-cosim.py | 37 +++++++++++++++------------ 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/examples/villas/dpsim-villas-cosim.py b/examples/villas/dpsim-villas-cosim.py index cab124ae69..979df552bf 100644 --- a/examples/villas/dpsim-villas-cosim.py +++ b/examples/villas/dpsim-villas-cosim.py @@ -18,7 +18,7 @@ def dpsim0(): sim_name = "DistributedVILLAS0" time_step = 0.01 - final_time = 10 + final_time = 1.0 n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [10]) n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) @@ -34,7 +34,7 @@ def dpsim0(): evs.connect([dpsimpy.dp.SimNode.gnd, n2]) vs1.connect([dpsimpy.dp.SimNode.gnd, n1]) - r12.connect([n1, n2]) + r12.connect([n2, n1]) sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, vs1, r12]) @@ -73,24 +73,28 @@ def dpsim0(): 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('1_v_1', 'v', n1) + logger.log_attribute('2_v_2', 'v', n2) + logger.log_attribute('3_i_r12', 'i_intf', r12) + logger.log_attribute('4_i_evs', 'i_intf', evs) + logger.log_attribute('5_v_evs', 'v_intf', evs) intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-dpsim1", config=intf_config) sim.add_interface(intf) - intf.import_attribute(evs.attr('V_ref'), 0) - intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0) + sim.add_logger(logger) + + evs.set_intf_current([[complex(5, 0)]]) + + intf.import_attribute(evs.attr('V_ref'), 0, False, False) + intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, True) sim.run(1) def dpsim1(): sim_name = "DistributedVILLAS1" time_step = 0.01 - final_time = 10 + final_time = 1.0 n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) @@ -139,16 +143,17 @@ def dpsim1(): 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('1_v_2', 'v', n2) + logger.log_attribute('2_i_r02', 'i_intf', r02) + logger.log_attribute('3_v_ecs', 'v_intf', ecs) + logger.log_attribute('4_i_ecs', 'i_intf', ecs) intf = dpsimpyvillas.InterfaceVillas(name="dpsim1-dpsim0", config=intf_config) sim.add_interface(intf) - intf.import_attribute(ecs.attr('I_ref'), 0) - intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0) + sim.add_logger(logger) + intf.import_attribute(ecs.attr('I_ref'), 0, False, False) + intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, True) sim.run(1) From 92c1903ca0c2760aff794f5d8e3c01e132d0fdc6 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Wed, 8 Feb 2023 10:39:35 -0500 Subject: [PATCH 13/39] Implemented dpsim-villas-cosim-base for comparison Signed-off-by: pipeacosta --- examples/villas/dpsim-villas-cosim-base.py | 44 ++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 examples/villas/dpsim-villas-cosim-base.py diff --git a/examples/villas/dpsim-villas-cosim-base.py b/examples/villas/dpsim-villas-cosim-base.py new file mode 100644 index 0000000000..bfeca6078f --- /dev/null +++ b/examples/villas/dpsim-villas-cosim-base.py @@ -0,0 +1,44 @@ +import sys +import os.path +import logging + +import dpsimpy + +sim_name = "DistributedVILLAS_base" +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]) + +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.set_parameters(1) + +r02 = dpsimpy.dp.ph1.Resistor('r_02', dpsimpy.LogLevel.debug) +r02.set_parameters(1) + +vs1.connect([dpsimpy.dp.SimNode.gnd, n1]) +r12.connect([n1, n2]) +r02.connect([dpsimpy.dp.SimNode.gnd, n2]) + +sys = dpsimpy.SystemTopology(50, [n1, n2], [vs1, r12, r02]) + +sim = dpsimpy.RealTimeSimulation(sim_name) +sim.set_system(sys) +sim.set_time_step(time_step) +sim.set_final_time(final_time) + +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', 'v_intf', r02) + +sim.add_logger(logger) + +sim.run(1) From f94ab9798540724602746a92635d0462503c99ff Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Wed, 8 Feb 2023 10:40:20 -0500 Subject: [PATCH 14/39] First version of the weakly-coupled co-simulation example Signed-off-by: pipeacosta --- .../dpsim-villas-weakly-coupled-cosim.ipynb | 336 ++++++++++++++++++ .../dpsim-villas-weakly-coupled-cosim.py | 179 ++++++++++ 2 files changed, 515 insertions(+) create mode 100644 examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb create mode 100644 examples/villas/dpsim-villas-weakly-coupled-cosim.py diff --git a/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb b/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb new file mode 100644 index 0000000000..ca1f87fed8 --- /dev/null +++ b/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb @@ -0,0 +1,336 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Weakly coupled Co-simulation\n", + "================\n", + "\n", + "This guides shows how to implement a simplified weakly-coupled co-simulation in DPsim\n", + "\n", + "Test circuit\n", + "--------------------\n", + "\n", + "As a first simple, test we will simulate a small static network. The network consists of 4 nodes and 4 elements:\n", + "\n", + "| Component | Type | Python Class | Node A | Node B | Paramter |\n", + "| :---------| :---- | :---------------------------------------- | :----- | :----- | :------- |\n", + "| r_1 | Source resistance | `dpsimpy.dp.ph1.Resistor` | 0 | GND | 0.1 Ohm |\n", + "| c_1 | Line capacitance | `dpsimpy.dp.ph1.Capacitor` | 0 | GND | 1 Farad |\n", + "| c_2 | Line capacitance | `dpsimpy.dp.ph1.Capacitor` | 1 | GND | 1 Farad |\n", + "| r_line | Line resistance | `dpsimpy.dp.ph1.Resistor` | 1 | 0 | 0.1 Ohm |\n", + "| r_load | Load | `dpsimpy.dp.ph1.Resistor` | 1 | GND | 1 Ohm |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before we can start, we must import the DPsim Python module.\n", + "We also add `dp` as an alias for the dynamic phasor components." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "import dpsimpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we can define the model by creating a couple of components.\n", + "Each component is identified by a name which is passed as the first argument.\n", + "Following arguments are used to define the topology by assigning the component to a specific node / bus or to pass parameters." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "# Nodes\n", + "gnd = dpsimpy.dp.SimNode.gnd\n", + "n0 = dpsimpy.dp.SimNode(\"n0\")\n", + "n1 = dpsimpy.dp.SimNode(\"n1\")\n", + "\n", + "r_1 = dpsimpy.dp.ph1.Resistor(\"r_1\")\n", + "r_1.R = 0.1\n", + "r_line = dpsimpy.dp.ph1.Resistor(\"r_line\")\n", + "r_line.R = 0.1\n", + "c_1 = dpsimpy.dp.ph1.Capacitor(\"c_1\")\n", + "c_1.C = 1\n", + "c_2 = dpsimpy.dp.ph1.Capacitor(\"c_2\")\n", + "c_2.C = 1\n", + "r_load = dpsimpy.dp.ph1.Resistor(\"r_load\")\n", + "r_load.R = 1\n", + "\n", + "# Initial conditions\n", + "n0.set_initial_voltage(5)\n", + "n1.set_initial_voltage(2)\n", + "\n", + "# Connections \n", + "r_1.connect([n0, gnd])\n", + "r_line.connect([n0, n1])\n", + "c_1.connect([n0, gnd])\n", + "c_2.connect([n1, gnd])\n", + "r_load.connect([n1, gnd])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we have to create a simulation object:" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "sys = dpsimpy.SystemTopology(50, [ n0, n1 ], [ r_1, r_line, c_1, c_2, r_load ])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also visualize the system topology:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": "\n\n\n\n\n\ntopology\n\n\n\nn0\n\n\n\n\nn0\n(5.00 V > 0.00°)\n\n\n\nn1\n\n\n\n\nn1\n(2.00 V > 0.00°)\n\n\n\nr_1\n\n\nr_1\nDP::Ph1::Resistor\n\n\n\n\n\nr_1--n0\n\n\n\n\nr_line\n\n\nr_line\nDP::Ph1::Resistor\n\n\n\n\n\nr_line--n0\n\n\n\n\nr_line--n1\n\n\n\n\nc_1\n\n\nc_1\nDP::Ph1::Capacitor\n\n\n\n\n\nc_1--n0\n\n\n\n\nc_2\n\n\nc_2\nDP::Ph1::Capacitor\n\n\n\n\n\nc_2--n1\n\n\n\n\nr_load\n\n\nr_load\nDP::Ph1::Resistor\n\n\n\n\n\nr_load--n1\n\n\n\n\n", + "text/plain": [ + "" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sys" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we can start the simulation and wait for its completion:" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[22:20:55.083288 WeaklyCoupledCosim info] Initialize simulation: WeaklyCoupledCosim\n", + "[22:20:55.083715 MnaSolverFactory info] creating EigenDense solver implementation\n", + "[22:20:55.085142 WeaklyCoupledCosim info] Scheduling tasks.\n", + "[22:20:55.086106 WeaklyCoupledCosim info] Scheduling done.\n", + "[22:20:55.086143 WeaklyCoupledCosim info] Opening interfaces.\n", + "[22:20:55.086149 WeaklyCoupledCosim info] Start synchronization with remotes on interfaces\n", + "[22:20:55.086154 WeaklyCoupledCosim info] Synchronized simulation start with remotes\n", + "[22:20:55.086166 WeaklyCoupledCosim info] Start simulation: WeaklyCoupledCosim\n", + "[22:20:55.086195 WeaklyCoupledCosim info] Time step: 1.000000e-03\n", + "[22:20:55.086206 WeaklyCoupledCosim info] Final time: 1.000000e+00\n", + "[22:20:55.121149 WeaklyCoupledCosim info] Simulation calculation time: 0.034930\n", + "[22:20:55.121229 WeaklyCoupledCosim info] Simulation finished.\n" + ] + } + ], + "source": [ + "sim = dpsimpy.Simulation(\"WeaklyCoupledCosim\", loglevel=dpsimpy.LogLevel.debug)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(1e-3)\n", + "sim.set_final_time(1.0)\n", + "\n", + "log = dpsimpy.Logger(\"WeaklyCoupledCosim\")\n", + "for i in range(0, len(sys.nodes)):\n", + " log.log_attribute(\"v\" + str(i), \"v\", sys.nodes[i])\n", + "\n", + "sim.add_logger(log)\n", + " \n", + "sim.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Results can be analyzed and plotted by the `villas.dataprocessing` package:" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "column number: 2\n", + "results length: 1000\n", + "real column names: []\n", + "complex column names: ['v0', 'v1']\n", + "column number: 5\n", + "results length: 1000\n", + "real column names: []\n", + "complex column names: ['1_v_1', '2_v_2', '3_i_rline', '4_i_evs', '5_v_evs']\n" + ] + }, + { + "data": { + "image/svg+xml": "\n\n\n \n \n \n \n 2023-02-07T22:24:34.324348\n image/svg+xml\n \n \n Matplotlib v3.6.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'svg'\n", + "%config InlineBackend.rc = {'font.size': 10, 'figure.figsize': (6.0, 4.0), 'figure.facecolor': 'white', 'savefig.dpi': 72, 'figure.subplot.bottom': 0.125, 'figure.edgecolor': 'white'}\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import villas.dataprocessing.plottools as pt\n", + "import villas.dataprocessing.readtools as rt\n", + "import villas.dataprocessing.timeseries as ts\n", + "\n", + "results = rt.read_timeseries_dpsim('logs/WeaklyCoupledCosim.csv')\n", + "results_emt = [ results[series].frequency_shift(freq=50) for series in results ]\n", + "\n", + "results_strongly_coupled0 = rt.read_timeseries_dpsim('../../logs/WeaklyCoupledCosim0/WeaklyCoupledCosim0.csv')\n", + "results_strongly_coupled0_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", + "\n", + "for series in results_strongly_coupled0_emt:\n", + " pt.plot_timeseries('Results EMT', series, '--')\n", + "\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "5373.24s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[I] ---- Start initialization ----\n", + "[I] -- Process topology\n", + "[I] Added DP::Ph1::VoltageSource 'v_s' to simulation.\n", + "[I] Added DP::Ph1::Resistor 'r_line' to simulation.\n", + "[I] Added DP::Ph1::Inductor 'l_line' to simulation.\n", + "[I] Added DP::Ph1::Resistor 'r_load' to simulation.\n", + "[I] Added node n0\n", + "[I] Added node n1\n", + "[I] Added node n2\n", + "[I] Collected virtual node 2 of 0\n", + "[I] Created virtual nodes:\n", + "[I] Number of network nodes: 3\n", + "[I] Number of network and virtual nodes: 4\n", + "[I] Assigned index 0 to phase A of node 0\n", + "[I] Assigned index 1 to phase A of node 1\n", + "[I] Assigned index 2 to phase A of node 2\n", + "[I] Assigned index 3 to phase A of node 3\n", + "[I] Assigned simulation nodes to topology nodes:\n", + "[I] Number of network simulation nodes: 3\n", + "[I] Number of simulation nodes: 4\n", + "[I] Number of harmonic simulation nodes: 0\n", + "[I] -- Create empty MNA system matrices and vectors\n", + "[I] -- Initialize components from power flow\n", + "[I] -- Initialize MNA properties of components\n", + "[I] -- Initialize MNA system matrices and source vector\n", + "[I] --- Initialization finished ---\n", + "[I] --- Initial system matrices and vectors ---\n", + "[I] System matrix: \n", + " 1 -1 0 -1 0 0 0 -0\n", + " -1 1.00005 -4.99877e-05 0 0 7.85204e-07 -7.85204e-07 0\n", + " 0 -4.99877e-05 0.00104999 0 0 -7.85204e-07 7.85204e-07 0\n", + " -1 0 0 0 -0 0 0 0\n", + " 0 0 0 0 1 -1 0 -1\n", + " 0 -7.85204e-07 7.85204e-07 0 -1 1.00005 -4.99877e-05 0\n", + " 0 7.85204e-07 -7.85204e-07 0 0 -4.99877e-05 0.00104999 0\n", + " 0 0 0 0 -1 0 0 0\n", + "[I] Right side vector: \n", + " 0\n", + " 0\n", + " -0\n", + "10000\n", + " 0\n", + " 0\n", + " -0\n", + " 0\n" + ] + } + ], + "source": [ + "!cat logs/Example1_Solver.log" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "interpreter": { + "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a" + }, + "kernelspec": { + "display_name": "Python 3.9.7 64-bit", + "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/villas/dpsim-villas-weakly-coupled-cosim.py b/examples/villas/dpsim-villas-weakly-coupled-cosim.py new file mode 100644 index 0000000000..fef85a3274 --- /dev/null +++ b/examples/villas/dpsim-villas-weakly-coupled-cosim.py @@ -0,0 +1,179 @@ +import sys +import os.path +import logging +import json +import time + +from datetime import datetime +from villas.node.node import Node as VILLASnode + +from multiprocessing import Process + +import dpsimpy +import dpsimpyvillas + +base = os.path.splitext(os.path.basename(sys.argv[0]))[0] +log = logging.getLogger(base) + +def dpsim0(): + sim_name = "WeaklyCoupledCosim0" + time_step = 1e-3 + final_time = 1.0 + + gnd = dpsimpy.dp.SimNode.gnd + n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [5]) + n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [2]) + + evs = dpsimpy.dp.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.debug) + evs.set_parameters(complex(2, 0)) + + r_1 = dpsimpy.dp.ph1.Resistor("r_1") + r_1.set_parameters(0.1) + c_1 = dpsimpy.dp.ph1.Capacitor("c_1") + c_1.set_parameters(1) + r_line = dpsimpy.dp.ph1.Resistor('r_line', dpsimpy.LogLevel.debug) + r_line.set_parameters(0.1) + + r_1.connect([n1, gnd]) + r_line.connect([n1, n2]) + c_1.connect([n1, gnd]) + evs.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, r_1, c_1, r_line]) + + sim = dpsimpy.RealTimeSimulation(sim_name) + sim.set_system(sys) + sim.set_time_step(time_step) + sim.set_final_time(final_time) + + intf_config = { + "type": "socket", + "layer": "udp", + "format": "json", + "hooks": [ + {"type": "print"} + ], + "in": { + "address": "127.0.0.1:12008", + "signals": [ + { + "name": "v_intf", + "type": "complex" + } + ] + }, + "out": { + "address": "127.0.0.1:12009", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] + } + } + + dpsimpy.Logger.set_log_dir('logs/' + sim_name) + + logger = dpsimpy.Logger(sim_name) + logger.log_attribute('1_v_1', 'v', n1) + logger.log_attribute('2_v_2', 'v', n2) + logger.log_attribute('3_i_rline', 'i_intf', r_line) + logger.log_attribute('4_i_evs', 'i_intf', evs) + logger.log_attribute('5_v_evs', 'v_intf', evs) + + intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-dpsim1", config=intf_config) + + sim.add_interface(intf) + sim.add_logger(logger) + + evs.set_intf_current([[complex(3, 0)]]) + + intf.import_attribute(evs.attr('V_ref'), 0, False, False) + intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, True) + + sim.run(1) + +def dpsim1(): + sim_name = "WeaklyCoupledCosim1" + time_step = 1e-3 + final_time = 1.0 + + gnd = dpsimpy.dp.SimNode.gnd + n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [2]) + + ecs = dpsimpy.dp.ph1.CurrentSource('i_intf', dpsimpy.LogLevel.debug) + ecs.set_parameters(complex(3, 0)) + c_2 = dpsimpy.dp.ph1.Capacitor("c_2") + c_2.set_parameters(1) + r_load = dpsimpy.dp.ph1.Resistor('r_load', dpsimpy.LogLevel.debug) + r_load.set_parameters(1) + + ecs.connect([gnd, n2]) + c_2.connect([gnd, n2]) + r_load.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [n2], [ecs, c_2, r_load]) + + sim = dpsimpy.RealTimeSimulation(sim_name) + sim.set_system(sys) + sim.set_time_step(time_step) + sim.set_final_time(final_time) + + intf_config = { + "type": "socket", + "layer": "udp", + "format": "json", + "hooks": [ + {"type": "print"} + ], + "in": { + "address": "127.0.0.1:12009", + "signals": [ + { + "name": "i_intf", + "type": "complex" + } + ] + }, + "out": { + "address": "127.0.0.1:12008", + "signals": [ + { + "name": "v_intf", + "type": "complex" + } + ] + } + } + + dpsimpy.Logger.set_log_dir('logs/' + sim_name) + + logger = dpsimpy.Logger(sim_name) + logger.log_attribute('1_v_2', 'v', n2) + logger.log_attribute('2_i_rload', 'i_intf', r_load) + logger.log_attribute('3_v_ecs', 'v_intf', ecs) + logger.log_attribute('4_i_ecs', 'i_intf', ecs) + + intf = dpsimpyvillas.InterfaceVillas(name="dpsim1-dpsim0", config=intf_config) + + sim.add_interface(intf) + sim.add_logger(logger) + intf.import_attribute(ecs.attr('I_ref'), 0, False, False) + intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, True) + + sim.run(1) + +if __name__ == '__main__': + logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) + + p_sim0 = Process(target=dpsim0) + p_sim1 = Process(target=dpsim1) + + p_sim0.start() + p_sim1.start() + + p_sim0.join() + p_sim1.join() + + print('Both simulations have ended!') From 824ab10c9facc3b52dd87afbbbfbb39bd4ffaa99 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Tue, 21 Mar 2023 09:25:20 +0100 Subject: [PATCH 15/39] Changed RealTimeSimulation to Simulation in cosim examples Signed-off-by: pipeacosta --- dpsim-villas/examples/cxx/SocketCosimExample.cpp | 12 ++++++------ examples/villas/dpsim-villas-cosim-base.py | 9 +++++++-- examples/villas/dpsim-villas-cosim.py | 16 ++++++++-------- .../villas/dpsim-villas-weakly-coupled-cosim.py | 16 ++++++++-------- 4 files changed, 29 insertions(+), 24 deletions(-) diff --git a/dpsim-villas/examples/cxx/SocketCosimExample.cpp b/dpsim-villas/examples/cxx/SocketCosimExample.cpp index ea54db9d93..4571844358 100644 --- a/dpsim-villas/examples/cxx/SocketCosimExample.cpp +++ b/dpsim-villas/examples/cxx/SocketCosimExample.cpp @@ -45,7 +45,7 @@ int main(int argc, char* argv[]) { SystemNodeList{SimNode::GND, n1, n2}, SystemComponentList{evs, vs1, r12}); - RealTimeSimulation sim(simName); + Simulation sim(simName); sim.setSystem(sys); sim.setTimeStep(timeStep); sim.setFinalTime(0.1); @@ -93,13 +93,13 @@ int main(int argc, char* argv[]) { intfCurrent0(0,0) = std::complex(5.0,0.0); evs->setIntfCurrent(intfCurrent0); - intf->importAttribute(evs->mVoltageRef, 0, false, false); + intf->importAttribute(evs->mVoltageRef, 0, false, true); intf->exportAttribute(evs->mIntfCurrent->deriveCoeff(0, 0), 0, true, "i_intf"); // Interface sim.addInterface(intf); - sim.run(1); + sim.run(); } else if (String(argv[1]) == "1") { String simName = "SocketsCosim_example2"; @@ -122,7 +122,7 @@ int main(int argc, char* argv[]) { SystemNodeList{SimNode::GND, n2}, SystemComponentList{ecs, r02}); - RealTimeSimulation sim(simName); + Simulation sim(simName); sim.setSystem(sys); sim.setTimeStep(timeStep); sim.setFinalTime(0.1); @@ -164,12 +164,12 @@ int main(int argc, char* argv[]) { sim.addLogger(logger); auto intf = std::make_shared(socketConfig); - intf->importAttribute(ecs->mCurrentRef, 0, false, false); + intf->importAttribute(ecs->mCurrentRef, 0, false, true); intf->exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0, true, "v_intf"); // Interface sim.addInterface(intf); - sim.run(1); + sim.run(); } } diff --git a/examples/villas/dpsim-villas-cosim-base.py b/examples/villas/dpsim-villas-cosim-base.py index bfeca6078f..980eb08fb7 100644 --- a/examples/villas/dpsim-villas-cosim-base.py +++ b/examples/villas/dpsim-villas-cosim-base.py @@ -26,7 +26,7 @@ sys = dpsimpy.SystemTopology(50, [n1, n2], [vs1, r12, r02]) -sim = dpsimpy.RealTimeSimulation(sim_name) +sim = dpsimpy.Simulation(sim_name) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) @@ -41,4 +41,9 @@ sim.add_logger(logger) -sim.run(1) +sim.start() + +k_i = sim.next() + +while(k_i <= final_time): + k_i = sim.next() diff --git a/examples/villas/dpsim-villas-cosim.py b/examples/villas/dpsim-villas-cosim.py index 979df552bf..92e5c6f00f 100644 --- a/examples/villas/dpsim-villas-cosim.py +++ b/examples/villas/dpsim-villas-cosim.py @@ -38,7 +38,7 @@ def dpsim0(): sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, vs1, r12]) - sim = dpsimpy.RealTimeSimulation(sim_name) + sim = dpsimpy.Simulation(sim_name) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) @@ -86,10 +86,10 @@ def dpsim0(): evs.set_intf_current([[complex(5, 0)]]) - intf.import_attribute(evs.attr('V_ref'), 0, False, False) - intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, True) + intf.import_attribute(evs.attr('V_ref'), 0, True, True) + intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, False) - sim.run(1) + sim.run() def dpsim1(): sim_name = "DistributedVILLAS1" @@ -108,7 +108,7 @@ def dpsim1(): sys = dpsimpy.SystemTopology(50, [n2], [ecs, r02]) - sim = dpsimpy.RealTimeSimulation(sim_name) + sim = dpsimpy.Simulation(sim_name) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) @@ -152,10 +152,10 @@ def dpsim1(): sim.add_interface(intf) sim.add_logger(logger) - intf.import_attribute(ecs.attr('I_ref'), 0, False, False) - intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, True) + intf.import_attribute(ecs.attr('I_ref'), 0, True, True) + intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, False) - sim.run(1) + sim.run() if __name__ == '__main__': logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) diff --git a/examples/villas/dpsim-villas-weakly-coupled-cosim.py b/examples/villas/dpsim-villas-weakly-coupled-cosim.py index fef85a3274..a299b9a332 100644 --- a/examples/villas/dpsim-villas-weakly-coupled-cosim.py +++ b/examples/villas/dpsim-villas-weakly-coupled-cosim.py @@ -41,7 +41,7 @@ def dpsim0(): sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, r_1, c_1, r_line]) - sim = dpsimpy.RealTimeSimulation(sim_name) + sim = dpsimpy.Simulation(sim_name) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) @@ -89,10 +89,10 @@ def dpsim0(): evs.set_intf_current([[complex(3, 0)]]) - intf.import_attribute(evs.attr('V_ref'), 0, False, False) - intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, True) + intf.import_attribute(evs.attr('V_ref'), 0, block_on_read=False, sync_on_start=False) + intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, wait_for_on_write=True) - sim.run(1) + sim.run() def dpsim1(): sim_name = "WeaklyCoupledCosim1" @@ -115,7 +115,7 @@ def dpsim1(): sys = dpsimpy.SystemTopology(50, [n2], [ecs, c_2, r_load]) - sim = dpsimpy.RealTimeSimulation(sim_name) + sim = dpsimpy.Simulation(sim_name) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) @@ -159,10 +159,10 @@ def dpsim1(): sim.add_interface(intf) sim.add_logger(logger) - intf.import_attribute(ecs.attr('I_ref'), 0, False, False) - intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, True) + intf.import_attribute(ecs.attr('I_ref'), 0, block_on_read=False, sync_on_start=False) + intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, wait_for_on_write=True) - sim.run(1) + sim.run() if __name__ == '__main__': logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) From 636369141fc78af67c28b73c016757d537fdc555 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Tue, 21 Mar 2023 14:59:06 +0100 Subject: [PATCH 16/39] Minor changes to the dpsim-villas-weakly-coupled-cosim Notebook Signed-off-by: pipeacosta --- .../dpsim-villas-weakly-coupled-cosim.ipynb | 85 +++++++++++-------- 1 file changed, 49 insertions(+), 36 deletions(-) diff --git a/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb b/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb index ca1f87fed8..8c704cdcfc 100644 --- a/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb +++ b/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -93,7 +93,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -109,17 +109,17 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/svg+xml": "\n\n\n\n\n\ntopology\n\n\n\nn0\n\n\n\n\nn0\n(5.00 V > 0.00°)\n\n\n\nn1\n\n\n\n\nn1\n(2.00 V > 0.00°)\n\n\n\nr_1\n\n\nr_1\nDP::Ph1::Resistor\n\n\n\n\n\nr_1--n0\n\n\n\n\nr_line\n\n\nr_line\nDP::Ph1::Resistor\n\n\n\n\n\nr_line--n0\n\n\n\n\nr_line--n1\n\n\n\n\nc_1\n\n\nc_1\nDP::Ph1::Capacitor\n\n\n\n\n\nc_1--n0\n\n\n\n\nc_2\n\n\nc_2\nDP::Ph1::Capacitor\n\n\n\n\n\nc_2--n1\n\n\n\n\nr_load\n\n\nr_load\nDP::Ph1::Resistor\n\n\n\n\n\nr_load--n1\n\n\n\n\n", "text/plain": [ - "" + "" ] }, - "execution_count": 13, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -137,25 +137,25 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "[22:20:55.083288 WeaklyCoupledCosim info] Initialize simulation: WeaklyCoupledCosim\n", - "[22:20:55.083715 MnaSolverFactory info] creating EigenDense solver implementation\n", - "[22:20:55.085142 WeaklyCoupledCosim info] Scheduling tasks.\n", - "[22:20:55.086106 WeaklyCoupledCosim info] Scheduling done.\n", - "[22:20:55.086143 WeaklyCoupledCosim info] Opening interfaces.\n", - "[22:20:55.086149 WeaklyCoupledCosim info] Start synchronization with remotes on interfaces\n", - "[22:20:55.086154 WeaklyCoupledCosim info] Synchronized simulation start with remotes\n", - "[22:20:55.086166 WeaklyCoupledCosim info] Start simulation: WeaklyCoupledCosim\n", - "[22:20:55.086195 WeaklyCoupledCosim info] Time step: 1.000000e-03\n", - "[22:20:55.086206 WeaklyCoupledCosim info] Final time: 1.000000e+00\n", - "[22:20:55.121149 WeaklyCoupledCosim info] Simulation calculation time: 0.034930\n", - "[22:20:55.121229 WeaklyCoupledCosim info] Simulation finished.\n" + "[15:39:30.578825 WeaklyCoupledCosim info] Initialize simulation: WeaklyCoupledCosim\n", + "[15:39:30.579027 MnaSolverFactory info] creating EigenDense solver implementation\n", + "[15:39:30.580037 WeaklyCoupledCosim info] Scheduling tasks.\n", + "[15:39:30.580491 WeaklyCoupledCosim info] Scheduling done.\n", + "[15:39:30.580495 WeaklyCoupledCosim info] Opening interfaces.\n", + "[15:39:30.580496 WeaklyCoupledCosim info] Start synchronization with remotes on interfaces\n", + "[15:39:30.580498 WeaklyCoupledCosim info] Synchronized simulation start with remotes\n", + "[15:39:30.580500 WeaklyCoupledCosim info] Start simulation: WeaklyCoupledCosim\n", + "[15:39:30.580504 WeaklyCoupledCosim info] Time step: 1.000000e-03\n", + "[15:39:30.580507 WeaklyCoupledCosim info] Final time: 1.000000e+00\n", + "[15:39:30.611497 WeaklyCoupledCosim info] Simulation calculation time: 0.030977\n", + "[15:39:30.611581 WeaklyCoupledCosim info] Simulation finished.\n" ] } ], @@ -183,7 +183,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -193,22 +193,29 @@ "column number: 2\n", "results length: 1000\n", "real column names: []\n", - "complex column names: ['v0', 'v1']\n", - "column number: 5\n", - "results length: 1000\n", - "real column names: []\n", - "complex column names: ['1_v_1', '2_v_2', '3_i_rline', '4_i_evs', '5_v_evs']\n" + "complex column names: ['v0', 'v1']\n" ] }, { - "data": { - "image/svg+xml": "\n\n\n \n \n \n \n 2023-02-07T22:24:34.324348\n image/svg+xml\n \n \n Matplotlib v3.6.2, https://matplotlib.org/\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\n", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" + "ename": "EmptyDataError", + "evalue": "No columns to parse from file", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mEmptyDataError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn [2], line 18\u001b[0m\n\u001b[1;32m 14\u001b[0m results_emt\u001b[39m.\u001b[39mappend(results[series]\u001b[39m.\u001b[39mfrequency_shift(freq\u001b[39m=\u001b[39m\u001b[39m50\u001b[39m))\n\u001b[1;32m 16\u001b[0m results_emt \u001b[39m=\u001b[39m [ results[series]\u001b[39m.\u001b[39mfrequency_shift(freq\u001b[39m=\u001b[39m\u001b[39m50\u001b[39m) \u001b[39mfor\u001b[39;00m series \u001b[39min\u001b[39;00m results ]\n\u001b[0;32m---> 18\u001b[0m results_strongly_coupled0 \u001b[39m=\u001b[39m rt\u001b[39m.\u001b[39;49mread_timeseries_dpsim(\u001b[39m'\u001b[39;49m\u001b[39m../../logs/WeaklyCoupledCosim0/WeaklyCoupledCosim0.csv\u001b[39;49m\u001b[39m'\u001b[39;49m)\n\u001b[1;32m 19\u001b[0m results_strongly_coupled0_emt \u001b[39m=\u001b[39m [ results[series]\u001b[39m.\u001b[39mfrequency_shift(freq\u001b[39m=\u001b[39m\u001b[39m50\u001b[39m) \u001b[39mfor\u001b[39;00m series \u001b[39min\u001b[39;00m results ]\n\u001b[1;32m 21\u001b[0m \u001b[39mfor\u001b[39;00m series \u001b[39min\u001b[39;00m results_emt:\n", + "File \u001b[0;32m/usr/local/lib/python3.9/site-packages/villas/dataprocessing/readtools.py:130\u001b[0m, in \u001b[0;36mread_timeseries_dpsim\u001b[0;34m(filename, timeseries_names, print_status)\u001b[0m\n\u001b[1;32m 129\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mread_timeseries_dpsim\u001b[39m(filename, timeseries_names\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, print_status\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m):\n\u001b[0;32m--> 130\u001b[0m \u001b[39mreturn\u001b[39;00m read_timeseries_csv(filename, timeseries_names, print_status)\n", + "File \u001b[0;32m/usr/local/lib/python3.9/site-packages/villas/dataprocessing/readtools.py:69\u001b[0m, in \u001b[0;36mread_timeseries_csv\u001b[0;34m(filename, timeseries_names, print_status)\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mread_timeseries_csv\u001b[39m(filename, timeseries_names\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, print_status\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m):\n\u001b[1;32m 63\u001b[0m \u001b[39m\"\"\"Reads complex time series data from DPsim log file. Real and\u001b[39;00m\n\u001b[1;32m 64\u001b[0m \u001b[39m imaginary part are stored in one complex variable.\u001b[39;00m\n\u001b[1;32m 65\u001b[0m \u001b[39m :param filename: name of the csv file that has the data\u001b[39;00m\n\u001b[1;32m 66\u001b[0m \u001b[39m :param timeseries_names: column name which should be read\u001b[39;00m\n\u001b[1;32m 67\u001b[0m \u001b[39m :return: list of Timeseries objects\u001b[39;00m\n\u001b[1;32m 68\u001b[0m \u001b[39m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 69\u001b[0m pd_df \u001b[39m=\u001b[39m pd\u001b[39m.\u001b[39;49mread_csv(filename)\n\u001b[1;32m 70\u001b[0m timeseries_list \u001b[39m=\u001b[39m {}\n\u001b[1;32m 71\u001b[0m cmpl_result_columns \u001b[39m=\u001b[39m []\n", + "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/util/_decorators.py:211\u001b[0m, in \u001b[0;36mdeprecate_kwarg.._deprecate_kwarg..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 209\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m 210\u001b[0m kwargs[new_arg_name] \u001b[39m=\u001b[39m new_arg_value\n\u001b[0;32m--> 211\u001b[0m \u001b[39mreturn\u001b[39;00m func(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n", + "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/util/_decorators.py:331\u001b[0m, in \u001b[0;36mdeprecate_nonkeyword_arguments..decorate..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 325\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mlen\u001b[39m(args) \u001b[39m>\u001b[39m num_allow_args:\n\u001b[1;32m 326\u001b[0m warnings\u001b[39m.\u001b[39mwarn(\n\u001b[1;32m 327\u001b[0m msg\u001b[39m.\u001b[39mformat(arguments\u001b[39m=\u001b[39m_format_argument_list(allow_args)),\n\u001b[1;32m 328\u001b[0m \u001b[39mFutureWarning\u001b[39;00m,\n\u001b[1;32m 329\u001b[0m stacklevel\u001b[39m=\u001b[39mfind_stack_level(),\n\u001b[1;32m 330\u001b[0m )\n\u001b[0;32m--> 331\u001b[0m \u001b[39mreturn\u001b[39;00m func(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n", + "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/readers.py:950\u001b[0m, in \u001b[0;36mread_csv\u001b[0;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, error_bad_lines, warn_bad_lines, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options)\u001b[0m\n\u001b[1;32m 935\u001b[0m kwds_defaults \u001b[39m=\u001b[39m _refine_defaults_read(\n\u001b[1;32m 936\u001b[0m dialect,\n\u001b[1;32m 937\u001b[0m delimiter,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 946\u001b[0m defaults\u001b[39m=\u001b[39m{\u001b[39m\"\u001b[39m\u001b[39mdelimiter\u001b[39m\u001b[39m\"\u001b[39m: \u001b[39m\"\u001b[39m\u001b[39m,\u001b[39m\u001b[39m\"\u001b[39m},\n\u001b[1;32m 947\u001b[0m )\n\u001b[1;32m 948\u001b[0m kwds\u001b[39m.\u001b[39mupdate(kwds_defaults)\n\u001b[0;32m--> 950\u001b[0m \u001b[39mreturn\u001b[39;00m _read(filepath_or_buffer, kwds)\n", + "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/readers.py:605\u001b[0m, in \u001b[0;36m_read\u001b[0;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[1;32m 602\u001b[0m _validate_names(kwds\u001b[39m.\u001b[39mget(\u001b[39m\"\u001b[39m\u001b[39mnames\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39mNone\u001b[39;00m))\n\u001b[1;32m 604\u001b[0m \u001b[39m# Create the parser.\u001b[39;00m\n\u001b[0;32m--> 605\u001b[0m parser \u001b[39m=\u001b[39m TextFileReader(filepath_or_buffer, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[1;32m 607\u001b[0m \u001b[39mif\u001b[39;00m chunksize \u001b[39mor\u001b[39;00m iterator:\n\u001b[1;32m 608\u001b[0m \u001b[39mreturn\u001b[39;00m parser\n", + "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/readers.py:1442\u001b[0m, in \u001b[0;36mTextFileReader.__init__\u001b[0;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[1;32m 1439\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39moptions[\u001b[39m\"\u001b[39m\u001b[39mhas_index_names\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m kwds[\u001b[39m\"\u001b[39m\u001b[39mhas_index_names\u001b[39m\u001b[39m\"\u001b[39m]\n\u001b[1;32m 1441\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles: IOHandles \u001b[39m|\u001b[39m \u001b[39mNone\u001b[39;00m \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[0;32m-> 1442\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_engine \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_make_engine(f, \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mengine)\n", + "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/readers.py:1753\u001b[0m, in \u001b[0;36mTextFileReader._make_engine\u001b[0;34m(self, f, engine)\u001b[0m\n\u001b[1;32m 1750\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(msg)\n\u001b[1;32m 1752\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m-> 1753\u001b[0m \u001b[39mreturn\u001b[39;00m mapping[engine](f, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49m\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49moptions)\n\u001b[1;32m 1754\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mException\u001b[39;00m:\n\u001b[1;32m 1755\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n", + "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/c_parser_wrapper.py:79\u001b[0m, in \u001b[0;36mCParserWrapper.__init__\u001b[0;34m(self, src, **kwds)\u001b[0m\n\u001b[1;32m 76\u001b[0m kwds\u001b[39m.\u001b[39mpop(key, \u001b[39mNone\u001b[39;00m)\n\u001b[1;32m 78\u001b[0m kwds[\u001b[39m\"\u001b[39m\u001b[39mdtype\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m ensure_dtype_objs(kwds\u001b[39m.\u001b[39mget(\u001b[39m\"\u001b[39m\u001b[39mdtype\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39mNone\u001b[39;00m))\n\u001b[0;32m---> 79\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_reader \u001b[39m=\u001b[39m parsers\u001b[39m.\u001b[39;49mTextReader(src, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[1;32m 81\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39munnamed_cols \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_reader\u001b[39m.\u001b[39munnamed_cols\n\u001b[1;32m 83\u001b[0m \u001b[39m# error: Cannot determine type of 'names'\u001b[39;00m\n", + "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/_libs/parsers.pyx:554\u001b[0m, in \u001b[0;36mpandas._libs.parsers.TextReader.__cinit__\u001b[0;34m()\u001b[0m\n", + "\u001b[0;31mEmptyDataError\u001b[0m: No columns to parse from file" + ] } ], "source": [ @@ -221,7 +228,12 @@ "import villas.dataprocessing.readtools as rt\n", "import villas.dataprocessing.timeseries as ts\n", "\n", - "results = rt.read_timeseries_dpsim('logs/WeaklyCoupledCosim.csv')\n", + "results = rt.read_timeseries_dpsim('logs/WeaklyCoupledCosim.csv')\n", + "\n", + "results_emt = []\n", + "for series in results:\n", + " results_emt.append(results[series].frequency_shift(freq=50))\n", + "\n", "results_emt = [ results[series].frequency_shift(freq=50) for series in results ]\n", "\n", "results_strongly_coupled0 = rt.read_timeseries_dpsim('../../logs/WeaklyCoupledCosim0/WeaklyCoupledCosim0.csv')\n", @@ -233,19 +245,20 @@ "for series in results_strongly_coupled0_emt:\n", " pt.plot_timeseries('Results EMT', series, '--')\n", "\n", + "plt.grid()\n", "plt.show()" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 14, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "5373.24s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + "515.87s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" ] }, { From 3afc1508df9051785cd75873d59e55ff4e0e2c7f Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sat, 1 Apr 2023 10:19:03 +0200 Subject: [PATCH 17/39] First version of co-simulation examples with Python coordination Signed-off-by: pipeacosta --- dpsim-villas/examples/cxx/CMakeLists.txt | 1 + .../cxx/SocketCosimExample_ext_control.cpp | 158 ++++++++++++++++++ ...villas-weakly-coupled-cosim-ext-control.py | 133 +++++++++++++++ 3 files changed, 292 insertions(+) create mode 100644 dpsim-villas/examples/cxx/SocketCosimExample_ext_control.cpp create mode 100644 examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index 4ea80b857f..3fb6f93307 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -16,6 +16,7 @@ set(SHMEM_SOURCES FileExample.cpp MqttExample.cpp SharedMemExample.cpp + SocketCosimExample_ext_control.cpp #ShmemExample.cpp #ShmemDistributedReference.cpp #ShmemDistributedDirect.cpp diff --git a/dpsim-villas/examples/cxx/SocketCosimExample_ext_control.cpp b/dpsim-villas/examples/cxx/SocketCosimExample_ext_control.cpp new file mode 100644 index 0000000000..aa2c7bf1f5 --- /dev/null +++ b/dpsim-villas/examples/cxx/SocketCosimExample_ext_control.cpp @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include +#include + +using namespace DPsim; +using namespace CPS::EMT; +using namespace CPS::EMT::Ph1; +using namespace std; + +Simulation setDPsim1(float ts, float tf, float u10) { + String simName = "SocketsCosim_example1"; + CPS::Logger::setLogDir("logs/"+simName); + + // Nodes + auto n1 = SimNode::make("n1"); + auto n2 = SimNode::make("n2"); + + // Components + auto evs = VoltageSource::make("v_intf"); + evs->setParameters(u10); + + auto r1 = Resistor::make("r_1"); + r1->setParameters(0.1); + auto c1 = Capacitor::make("c_1"); + c1->setParameters(1); + auto rLine = Resistor::make("r_line"); + rLine->setParameters(0.1); + + // Topology + r1->connect({ n1, SimNode::GND }); + rLine->connect({ n1, n2 }); + c1->connect({ n1, SimNode::GND }); + evs->connect({ SimNode::GND, n2 }); + + auto sys = SystemTopology(50, + SystemNodeList{SimNode::GND, n1, n2}, + SystemComponentList{r1, c1, rLine, evs}); + + Simulation sim(simName); + sim.setDomain(CPS::Domain::EMT); + sim.setSystem(sys); + sim.setTimeStep(ts); + sim.setFinalTime(0.1); + sim.doSteadyStateInit(true); + + auto logger = DataLogger::make(simName); + logger->logAttribute("1_v_1", n1->mVoltage); + logger->logAttribute("2_v_2", n2->mVoltage); + logger->logAttribute("3_i_rline", rLine->mIntfCurrent, 1, 1); + logger->logAttribute("4_i_evs", evs->mIntfCurrent, 1, 1); + logger->logAttribute("5_v_evs", evs->mIntfVoltage, 1, 1); + sim.addLogger(logger); + + // Eigen::MatrixXcd intfCurrent0(1,1); + // intfCurrent0(0,0) = std::complex(5.0,0.0); + // evs->setIntfCurrent(intfCurrent0); + + return sim; +} + +int main(int argc, char* argv[]) { + + float timeStep = 0.01; + float finalTime = 1.0; + + // Communication y20 -> S_1 and initialization of S_1 + float y20 = 2.0; + Simulation sim1 = setDPsim1(timeStep, finalTime, y20); + sim1.start(); + CPS::AttributeBase *y10 = sim1.getIdObjAttribute("v_intf", "i_intf").get(); + cout << "Output value: " << y10->toString() << endl; + float ki1 = sim1.next(); + y10 = sim1.getIdObjAttribute("v_intf", "i_intf").get(); + cout << "Step: " << ki1 << ", Output value: " << y10->toString() << endl; + + sim1.stop(); + + // if (String(argv[1]) == "0") { + + + // sim.run(); + // } + // else if (String(argv[1]) == "1") { + // String simName = "SocketsCosim_example2"; + // CPS::Logger::setLogDir("logs/"+simName); + + // // Nodes + // auto n2 = SimNode::make("n2"); + + // // Components + // auto ecs = CurrentSource::make("i_intf"); + // ecs->setParameters(Complex(5, 0)); + // auto r02 = Resistor::make("r_02"); + // r02->setParameters(1); + + // // Topology + // ecs->connect({ SimNode::GND, n2 }); + // r02->connect({ SimNode::GND, n2 }); + + // auto sys = SystemTopology(50, + // SystemNodeList{SimNode::GND, n2}, + // SystemComponentList{ecs, r02}); + + // Simulation sim(simName); + // sim.setSystem(sys); + // sim.setTimeStep(timeStep); + // sim.setFinalTime(0.1); + + // // Make sure the format is set to json!! + // std::string socketConfig = R"STRING({ + // "type": "socket", + // "layer": "udp", + // "format": "json", + // "hooks": [ + // {"type": "print"} + // ], + // "in": { + // "address": "127.0.0.1:12009", + // "signals": [ + // { + // "name": "i_intf", + // "type": "complex" + // } + // ] + // }, + // "out": { + // "address": "127.0.0.1:12008", + // "signals": [ + // { + // "name": "v_intf", + // "type": "complex" + // } + // ] + // } + // })STRING"; + + // // Logger. The logger must be added before the interface! + // auto logger = DataLogger::make(simName); + // logger->logAttribute("v2", n2->mVoltage); + // logger->logAttribute("i_intf", r02->mIntfCurrent, 1, 1); + // logger->logAttribute("v_ecs", ecs->mIntfVoltage, 1, 1); + // logger->logAttribute("i_ecs", ecs->mIntfCurrent, 1, 1); + // sim.addLogger(logger); + + // auto intf = std::make_shared(socketConfig); + // intf->importAttribute(ecs->mCurrentRef, 0, false, true); + // intf->exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0, true, "v_intf"); + + // // Interface + // sim.addInterface(intf); + + // sim.run(); + // } +} diff --git a/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py b/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py new file mode 100644 index 0000000000..280948be44 --- /dev/null +++ b/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py @@ -0,0 +1,133 @@ +import sys +import os.path +import logging + +import dpsimpy +import villas.dataprocessing.timeseries as ts +import numpy as np + +base = os.path.splitext(os.path.basename(sys.argv[0]))[0] +log = logging.getLogger(base) + +def set_dpsim1(t_s, t_f, u_1_0): + sim_name = "WeaklyCoupledCosim0" + + gnd = dpsimpy.emt.SimNode.gnd + n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.Single, [5]) + n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.Single, [u_1_0]) + + evs = dpsimpy.emt.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.debug) + evs.set_parameters(u_1_0) + + r_1 = dpsimpy.emt.ph1.Resistor("r_1") + r_1.set_parameters(0.1) + c_1 = dpsimpy.emt.ph1.Capacitor("c_1") + c_1.set_parameters(1) + r_line = dpsimpy.emt.ph1.Resistor('r_line', dpsimpy.LogLevel.debug) + r_line.set_parameters(0.1) + + r_1.connect([n1, gnd]) + r_line.connect([n1, n2]) + c_1.connect([n1, gnd]) + evs.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [gnd, n1, n2], [evs, r_1, c_1, r_line]) + + sim = dpsimpy.Simulation(sim_name) + sim.set_domain(dpsimpy.Domain.EMT) + sim.set_system(sys) + sim.set_time_step(t_s) + sim.set_final_time(t_f) + # sim.do_steady_state_init(True) + + dpsimpy.Logger.set_log_dir('logs/' + sim_name) + + logger = dpsimpy.Logger(sim_name) + logger.log_attribute('1_v_1', 'v', n1) + logger.log_attribute('2_v_2', 'v', n2) + logger.log_attribute('3_i_rline', 'i_intf', r_line) + logger.log_attribute('4_i_evs', 'i_intf', evs) + logger.log_attribute('5_v_evs', 'v_intf', evs) + + sim.add_logger(logger) + + return sim + + +def set_dpsim2(t_s, t_f, u_2_0): + sim_name = "WeaklyCoupledCosim1" + + gnd = dpsimpy.emt.SimNode.gnd + n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.Single, [2]) + + ecs = dpsimpy.emt.ph1.CurrentSource('i_intf', dpsimpy.LogLevel.debug) + ecs.set_parameters(u_2_0) + c_2 = dpsimpy.emt.ph1.Capacitor("c_2") + c_2.set_parameters(1) + r_load = dpsimpy.emt.ph1.Resistor('r_load', dpsimpy.LogLevel.debug) + r_load.set_parameters(1) + + ecs.connect([gnd, n2]) + c_2.connect([gnd, n2]) + r_load.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [gnd, n2], [ecs, c_2, r_load]) + + sim = dpsimpy.Simulation(sim_name) + sim.set_system(sys) + sim.set_time_step(t_s) + sim.set_final_time(t_f) + + dpsimpy.Logger.set_log_dir('logs/' + sim_name) + + logger = dpsimpy.Logger(sim_name) + logger.log_attribute('1_v_2', 'v', n2) + logger.log_attribute('2_i_rload', 'i_intf', r_load) + logger.log_attribute('3_v_ecs', 'v_intf', ecs) + logger.log_attribute('4_i_ecs', 'i_intf', ecs) + + sim.add_logger(logger) + + return sim + +if __name__ == '__main__': + logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) + + time_step = 1e-3 + final_time = 1.0 + t_k = 0.0 + + # Communication y_2_0 -> S_1 and initialization of S_1 + y_2_0 = 2 + sim1 = set_dpsim1(time_step, final_time, y_2_0) + sim1.start() + y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() + print(y_1_0) + k1_i = sim1.next() + y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() + print(y_1_0) + # y_1_0_ts = ts.TimeSeries("v2", t_k, y_1_0_dp) + # y_1_0_emt = y_1_0_ts.frequency_shift(freq=50) + + # Communication y_1_0 -> S_2 and initialization of S_2 + # sim2 = set_dpsim2(time_step, final_time, y_1_0) + # sim2.start() + + # Switch to S_2 and get initial output + # y_2_0_dp = sim2.get_idobj_attr("n2", "v").derive_coeff(0,0).get() + # y_2_0_ts = ts.TimeSeries("v2", t_k, y_2_0_dp) + # y_2_0 = y_2_0_ts.frequency_shift(freq=50) + + # Communication y_1_0 -> S_2 + # u_1_0 = y_2_0 + # sim1. + + # Switch to S_2 + # y_1_0 = sim2.get_idobj_attr("n2", "v").derive_coeff(0,0).get() + + # k1_i = sim1.next() + # k2_i = sim2.next() + + # while(k1_i <= final_time and k2_i <= final_time): + # k1_i = sim1.next() + # k2_i = sim2.next() From 275df7f5c139f78503c54bed9dc0b7ae91d751d0 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sun, 9 Apr 2023 23:59:26 +0200 Subject: [PATCH 18/39] Rename co-simulation example Signed-off-by: pipeacosta --- ...ntrol.cpp => CosimExample_ext_control.cpp} | 126 ++++-- ..._SimExample_ResistiveCompanion_Task2.ipynb | 376 ++++++++++++++++++ 2 files changed, 479 insertions(+), 23 deletions(-) rename dpsim-villas/examples/cxx/{SocketCosimExample_ext_control.cpp => CosimExample_ext_control.cpp} (52%) create mode 100644 examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb diff --git a/dpsim-villas/examples/cxx/SocketCosimExample_ext_control.cpp b/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp similarity index 52% rename from dpsim-villas/examples/cxx/SocketCosimExample_ext_control.cpp rename to dpsim-villas/examples/cxx/CosimExample_ext_control.cpp index aa2c7bf1f5..4d6d6e753a 100644 --- a/dpsim-villas/examples/cxx/SocketCosimExample_ext_control.cpp +++ b/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp @@ -7,53 +7,133 @@ #include using namespace DPsim; -using namespace CPS::EMT; -using namespace CPS::EMT::Ph1; +using namespace CPS; using namespace std; Simulation setDPsim1(float ts, float tf, float u10) { - String simName = "SocketsCosim_example1"; + float r1_r = 0.1; + float c1_c = 1; + float rLine_r = 0.1; + + // ----- POWERFLOW FOR INITIALIZATION ----- + // String simNamePF = "Cosim_example1"; + // CPS::Logger::setLogDir("logs/"+simNamePF); + + // auto n1PF = SP::SimNode::make("n1"); + // auto n2PF = SP::SimNode::make("n2"); + + // auto evsPF = SP::Ph1::VoltageSource::make("v_intf"); + // evsPF->setParameters(u10); + + // auto r1PF = SP::Ph1::Resistor::make("r_1"); + // r1PF->setParameters(r1_r); + // auto c1PF = SP::Ph1::Capacitor::make("c_1"); + // c1PF->setParameters(c1_c); + // auto rLinePF = SP::Ph1::Resistor::make("r_line"); + // rLinePF->setParameters(rLine_r); + + // r1PF->connect({ n1PF, SP::SimNode::GND }); + // rLinePF->connect({ n1PF, n2PF }); + // c1PF->connect({ n1PF, SP::SimNode::GND }); + // evsPF->connect({ SP::SimNode::GND, n2PF }); + // auto systemPF = SystemTopology(50, + // SystemNodeList{n1PF, n2PF}, + // SystemComponentList{c1PF, r1PF, rLinePF, evsPF}); + + // auto loggerPF = DataLogger::make(simNamePF); + // loggerPF->logAttribute("1_v_1", n1PF->mVoltage); + // loggerPF->logAttribute("2_v_2", n2PF->mVoltage); + + // Simulation simPF(simNamePF, CPS::Logger::Level::debug); + // simPF.setSystem(systemPF); + // simPF.setTimeStep(0.1); + // simPF.setFinalTime(0.1); + // simPF.setDomain(Domain::SP); + // simPF.setSolverType(Solver::Type::NRP); + // simPF.doInitFromNodesAndTerminals(false); + // simPF.addLogger(loggerPF); + // simPF.run(); + + + // ----- DYNAMIC SIMULATION ----- + String simName = "Cosim_example1"; CPS::Logger::setLogDir("logs/"+simName); // Nodes - auto n1 = SimNode::make("n1"); - auto n2 = SimNode::make("n2"); + auto n1 = EMT::SimNode::make("n1"); + auto n2 = EMT::SimNode::make("n2"); // Components - auto evs = VoltageSource::make("v_intf"); + auto evs = EMT::Ph1::VoltageSource::make("v_intf"); evs->setParameters(u10); - auto r1 = Resistor::make("r_1"); - r1->setParameters(0.1); - auto c1 = Capacitor::make("c_1"); - c1->setParameters(1); - auto rLine = Resistor::make("r_line"); - rLine->setParameters(0.1); + auto r1 = EMT::Ph1::Resistor::make("r_1"); + r1->setParameters(r1_r); + auto c1 = EMT::Ph1::Capacitor::make("c_1"); + c1->setParameters(c1_c); + auto rLine = EMT::Ph1::Resistor::make("r_line"); + rLine->setParameters(rLine_r); // Topology - r1->connect({ n1, SimNode::GND }); + r1->connect({ n1, EMT::SimNode::GND }); rLine->connect({ n1, n2 }); - c1->connect({ n1, SimNode::GND }); - evs->connect({ SimNode::GND, n2 }); + c1->connect({ n1, EMT::SimNode::GND }); + evs->connect({ EMT::SimNode::GND, n2 }); auto sys = SystemTopology(50, - SystemNodeList{SimNode::GND, n1, n2}, + SystemNodeList{EMT::SimNode::GND, n1, n2}, SystemComponentList{r1, c1, rLine, evs}); - Simulation sim(simName); - sim.setDomain(CPS::Domain::EMT); - sim.setSystem(sys); - sim.setTimeStep(ts); - sim.setFinalTime(0.1); - sim.doSteadyStateInit(true); - auto logger = DataLogger::make(simName); logger->logAttribute("1_v_1", n1->mVoltage); logger->logAttribute("2_v_2", n2->mVoltage); logger->logAttribute("3_i_rline", rLine->mIntfCurrent, 1, 1); logger->logAttribute("4_i_evs", evs->mIntfCurrent, 1, 1); logger->logAttribute("5_v_evs", evs->mIntfVoltage, 1, 1); + + Simulation sim(simName); + sim.setDomain(CPS::Domain::EMT); sim.addLogger(logger); + sim.setSystem(sys); + sim.setTimeStep(ts); + sim.setFinalTime(0.1); + // sim.doSteadyStateInit(true); + sim.doInitFromNodesAndTerminals(false); + + // initialize currents and voltages + // Eigen::VectorXd n_v0(2); + // n_v0 << 5, 5; + + Eigen::MatrixXd n1_v0(1,1); + n1_v0(0,0) = 5; + Eigen::MatrixXd n2_v0(1,1); + n2_v0(0,0) = 2; + + Eigen::MatrixXd ir1_0(1,1); + ir1_0(0,0) = n1_v0(0,0) / r1_r; + Eigen::MatrixXd irLine_0(1,1); + irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; + + r1->setIntfVoltage(n1_v0); + r1->setIntfCurrent(ir1_0); + c1->setIntfVoltage(n1_v0); + c1->setIntfCurrent(ir1_0 - irLine_0); + rLine->setIntfVoltage(n1_v0 - n2_v0); + rLine->setIntfCurrent(irLine_0); + // cout << "rLine voltage: " << rLine->mIntfVoltage->toString() << endl; + // cout << "r1 current: " << r1->mIntfCurrent->toString() << endl; + // cout << "c1 current: " << c1->mIntfCurrent->toString() << endl; + + evs->setIntfVoltage(n2_v0); + evs->setIntfCurrent(irLine_0); + cout << "evs current: " << evs->mIntfCurrent->toString() << endl; + + // Eigen::MatrixXd r1_i(1,1); + // r1_i(0,0) = n1_v0(0,0) / r1_r; + // r1->setIntfCurrent(r1_i); + // c1->setIntfCurrent(Eigen::MatrixXd(20)); + // rLine->setIntfVoltage(Eigen::MatrixXd(3)); + // rLine->setIntfCurrent(Eigen::MatrixXd(30)); // Eigen::MatrixXcd intfCurrent0(1,1); // intfCurrent0(0,0) = std::complex(5.0,0.0); diff --git a/examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb b/examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb new file mode 100644 index 0000000000..0a561cd658 --- /dev/null +++ b/examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb @@ -0,0 +1,376 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# MSP Simulation Example - Resistive Companion - Exercise 3 - Task 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Sample circuit" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$R_1$ $=1 \\Omega$
\n", + "$R_2$ $=1 \\Omega$
\n", + "$C$ $=1mF$
\n", + "$L$ $=1mH$
\n", + "$I$ $=10A$
\n", + "$v_C(0)$=0
\n", + "$i_L(0)=0 $
" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Circuit and Simulation Setup" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import ipywidgets as widget\n", + "import matplotlib.pyplot as plt\n", + "np.set_printoptions(sign=' ')\n", + "\n", + "# Circuit parameters\n", + "R1 = 1\n", + "R2 = 1\n", + "C1 = 1e-3\n", + "L1 = 1e-3\n", + "I_src= 10\n", + "G1 = 1/R1\n", + "G2 = 1/R2" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## DC equivalent of Inductor" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Equation of the inductor:\n", + "\n", + "$v_L(t) =L\\cdot\\frac{di_L}{dt}$\n", + "\n", + "### Integration: \n", + "\n", + "$i_L(t+\\Delta{t}) =i_L(t) + \\frac{1}{L} \\int_{t}^{t+\\Delta{t}} \\ v_L(\\tau) d\\tau$\n", + "\n", + "### Discretization: \n", + "\n", + "$i_L(k+1)= i_L(k) + \\frac{1}{L} \\int_{t_k}^{t_k+\\Delta{t}} \\ v_L(\\tau) d\\tau$\n", + "\n", + "### Application of trapezoidal rule: \n", + "\n", + "$i_L(k)= i_L(k) + \\frac{1}{L} \\frac{v_L(k)+v_L(k+1)}{2} \\Delta{t} $\n", + "\n", + "$i_L(k+1)=\\frac{\\Delta{t}}{2L} v_L(k+1) + (i_L(k) + \\frac{\\Delta{t}}{2L} v_L(k)) $\n", + "\n", + "The inductor in the calculation step (k + 1) can be substituted with an inductance $G_L = \\frac{\\Delta{t}}{2L}$ in parallel with a current source $A_L(k) = i_L(k) + \\frac{\\Delta{t}}{2L} v_L(k) $ " + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Initialize circuit" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "module 'dpsimpy.sp.ph1' has no attribute 'CurrentSource'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m/dpsim/examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb Cell 11\u001b[0m in \u001b[0;36m1\n\u001b[1;32m 15\u001b[0m r2_pf \u001b[39m=\u001b[39m dpsimpy\u001b[39m.\u001b[39msp\u001b[39m.\u001b[39mph1\u001b[39m.\u001b[39mResistor(\u001b[39m'\u001b[39m\u001b[39mr2_pf\u001b[39m\u001b[39m'\u001b[39m, dpsimpy\u001b[39m.\u001b[39mLogLevel\u001b[39m.\u001b[39mdebug)\n\u001b[1;32m 16\u001b[0m r2_pf\u001b[39m.\u001b[39mset_parameters(\u001b[39m1\u001b[39m)\n\u001b[0;32m---> 18\u001b[0m cs_pf \u001b[39m=\u001b[39m dpsimpy\u001b[39m.\u001b[39;49msp\u001b[39m.\u001b[39;49mph1\u001b[39m.\u001b[39;49mCurrentSource(\u001b[39m'\u001b[39m\u001b[39mcs_pf\u001b[39m\u001b[39m'\u001b[39m, dpsimpy\u001b[39m.\u001b[39mLogLevel\u001b[39m.\u001b[39mdebug)\n\u001b[1;32m 19\u001b[0m cs_pf\u001b[39m.\u001b[39mI_ref \u001b[39m=\u001b[39m \u001b[39mcomplex\u001b[39m(\u001b[39m10\u001b[39m,\u001b[39m0\u001b[39m)\n\u001b[1;32m 20\u001b[0m cs_pf\u001b[39m.\u001b[39mf_src \u001b[39m=\u001b[39m \u001b[39m0\u001b[39m\n", + "\u001b[0;31mAttributeError\u001b[0m: module 'dpsimpy.sp.ph1' has no attribute 'CurrentSource'" + ] + } + ], + "source": [ + "# Initialize simulation with DPsim\n", + "import dpsimpy\n", + "\n", + "model_name_pf = 'CS_R1R2C1L1_PF'\n", + "time_step = 1e-3\n", + "final_time = 2e-2\n", + "\n", + "# Nodes\n", + "gnd_pf = dpsimpy.sp.SimNode.gnd\n", + "n1_pf = dpsimpy.sp.SimNode('n1_pf', dpsimpy.PhaseType.Single)\n", + "\n", + "# Components\n", + "r1_pf = dpsimpy.sp.ph1.Resistor('r1_pf', dpsimpy.LogLevel.debug)\n", + "r1_pf.set_parameters(1)\n", + "r2_pf = dpsimpy.sp.ph1.Resistor('r2_pf', dpsimpy.LogLevel.debug)\n", + "r2_pf.set_parameters(1)\n", + "\n", + "cs_pf = dpsimpy.sp.ph1.CurrentSource('cs_pf', dpsimpy.LogLevel.debug)\n", + "cs_pf.I_ref = complex(10,0)\n", + "cs_pf.f_src = 0\n", + "\n", + "cs_pf.connect([gnd_pf, n1_pf])\n", + "r1_pf.connect([n1_pf, gnd_pf])\n", + "r2_pf.connect([n1_pf, gnd_pf])\n", + "\n", + "system_pf = dpsimpy.SystemTopology(50, [gnd_pf, n1_pf], [cs_pf, r1_pf, r2_pf])\n", + "\n", + "logger_pf = dpsimpy.Logger(model_name_pf)\n", + "logger_pf.log_attribute('n1.v', 'v', n1_pf)\n", + "logger_pf.log_attribute('i_r1', 'i_intf', r1_pf)\n", + "logger_pf.log_attribute('i_r2', 'i_intf', r2_pf)\n", + "\n", + "sim_pf = dpsimpy.Simulation(model_name_pf, dpsimpy.LogLevel.debug)\n", + "sim_pf.set_system(system_pf)\n", + "sim_pf.set_domain(dpsimpy.Domain.SP)\n", + "sim_pf.set_solver_component_behaviour(dpsimpy.SolverBehaviour.Initialization)\n", + "sim_pf.set_time_step(time_step)\n", + "sim_pf.set_final_time(final_time)\n", + "sim_pf.add_logger(logger_pf)\n", + "sim_pf.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Run Simulation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Simulation parameters\n", + "model_name = 'CS_R1R2C1L1'\n", + "npoint = int(np.round(final_time/time_step))\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode('n1')\n", + "n1.set_initial_voltage(complex(5,0), 0)\n", + "n2 = dpsimpy.emt.SimNode('n2')\n", + "n2.set_initial_voltage(complex(5,0), 0)\n", + "\n", + "# Components\n", + "r1 = dpsimpy.emt.ph1.Resistor('r1', dpsimpy.LogLevel.debug)\n", + "r1.R = 1\n", + "r2 = dpsimpy.emt.ph1.Resistor('r2', dpsimpy.LogLevel.debug)\n", + "r2.R = 1\n", + "\n", + "c1 = dpsimpy.emt.ph1.Capacitor('c1', dpsimpy.LogLevel.debug)\n", + "c1.C = 1e-3\n", + "l1 = dpsimpy.emt.ph1.Inductor('l1', dpsimpy.LogLevel.debug)\n", + "l1.L = 1e-3\n", + "cs = dpsimpy.emt.ph1.CurrentSource('cs', dpsimpy.LogLevel.debug)\n", + "cs.I_ref = complex(10,0)\n", + "cs.f_src = 0\n", + "\n", + "cs.connect([gnd, n1])\n", + "r1.connect([n1, gnd])\n", + "c1.connect([n1, n2])\n", + "l1.connect([n2, gnd])\n", + "r2.connect([n2, gnd])\n", + "\n", + "\n", + "system = dpsimpy.SystemTopology(50, [gnd, n1, n2], [cs, r1, r2, c1, l1])\n", + "\n", + "logger = dpsimpy.Logger(model_name)\n", + "logger.log_attribute('n1.v', 'v', n1)\n", + "logger.log_attribute('n2.v', 'v', n2)\n", + "logger.log_attribute('3_i_r1', 'i_intf', r1)\n", + "logger.log_attribute('4_v_c1', 'v_intf', c1)\n", + "logger.log_attribute('5_i_l1', 'i_intf', l1)\n", + "logger.log_attribute('6_i_r2', 'i_intf', r2)\n", + "\n", + "# sim = dpsimpy.Simulation(model_name, system, timestep=time_step, duration=final_time, pbar=True, sim_type=1, log_level=1)\n", + "sim = dpsimpy.Simulation(model_name)\n", + "sim.set_system(system)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.add_logger(logger)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", + "sim.do_init_from_nodes_and_terminals(False)\n", + "\n", + "# initialize currents and voltages\n", + "print(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0])\n", + "r1.set_intf_current([[complex(5,0)]])\n", + "r1.set_intf_voltage([[5]])\n", + "r2.set_intf_current([[5]])\n", + "r2.set_intf_voltage([[5]])\n", + "c1.set_intf_current([[5]])\n", + "c1.set_intf_voltage([[0]])\n", + "l1.set_intf_current([[0]])\n", + "l1.set_intf_voltage([[5]])\n", + "\n", + "sim.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Read log" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from villas.dataprocessing.readtools import *\n", + "from villas.dataprocessing.timeseries import *\n", + "import re\n", + "\n", + "work_dir = 'logs/'\n", + "log_path = work_dir + model_name + '.csv'\n", + "# log_lines, log_sections = read_dpsim_log(log_path)\n" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Read solution log" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "log_path = work_dir + model_name + '.csv'\n", + "ts_dpsim_emt = read_timeseries_dpsim(log_path, print_status=False)\n", + "\n", + "# for key, val in ts_dpsim_emt.items():\n", + " # print(key + ': ' + str(val.values))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Plot results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "\n", + "#Extract plot data\n", + "plot_data_1=ts_dpsim_emt[\"n1.v\"]\n", + "y_values_1= np.asarray(plot_data_1.values)\n", + "\n", + "plot_data_2=ts_dpsim_emt[\"n2.v\"]\n", + "y_values_2= np.asarray(plot_data_2.values)\n", + "\n", + "t = np.arange(npoint)*time_step\n", + "\n", + "plt.figure(figsize=(10,8))\n", + "plt.xlabel('Time [s]')\n", + "plt.ylabel('Voltage [V]')\n", + "plt.axis([0, final_time+time_step , -2, 11])\n", + "plt.scatter(t,y_values_1, label='$e_{1}$(t)')\n", + "plt.scatter(t,y_values_2, label='$e_{2}$(t)')\n", + "\n", + "#show corresponding values on the plot\n", + "for i in np.arange(3):\n", + " plt.annotate(' ' + str(np.round(y_values_1[i], 2)), (t[i], y_values_1[i]))\n", + " plt.annotate(' ' + str(np.round(y_values_2[i], 2)), (t[i], y_values_2[i]))\n", + "plt.grid()\n", + "plt.legend(loc='upper right')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "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" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 66c9e5033bafef05657c39d501559805acd0881c Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sat, 3 Jun 2023 12:07:16 +0200 Subject: [PATCH 19/39] Implemented second subsystem (second partition) Signed-off-by: pipeacosta --- dpsim-models/src/EMT/EMT_Ph1_Capacitor.cpp | 2 +- dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp | 3 +- dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp | 1 + dpsim-villas/examples/cxx/CMakeLists.txt | 1 + .../examples/cxx/CosimExample_ext_control.cpp | 193 +++++++++++++++++- .../cxx/CosimExample_ext_control_base.cpp | 96 +++++++++ dpsim/src/Simulation.cpp | 3 + packaging/Docker/Dockerfile.dev | 18 +- 8 files changed, 296 insertions(+), 21 deletions(-) create mode 100644 dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp diff --git a/dpsim-models/src/EMT/EMT_Ph1_Capacitor.cpp b/dpsim-models/src/EMT/EMT_Ph1_Capacitor.cpp index af095071b6..80d025c9a1 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Capacitor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Capacitor.cpp @@ -25,7 +25,6 @@ SimPowerComp::Ptr EMT::Ph1::Capacitor::clone(String name) { } void EMT::Ph1::Capacitor::initializeFromNodesAndTerminals(Real frequency) { - Real omega = 2 * PI * frequency; Complex impedance = { 0, - 1. / (omega * **mCapacitance) }; (**mIntfVoltage)(0,0) = (initialSingleVoltage(1) - initialSingleVoltage(0)).real(); @@ -42,6 +41,7 @@ void EMT::Ph1::Capacitor::initializeFromNodesAndTerminals(Real frequency) { (**mIntfCurrent)(0,0), initialSingleVoltage(0).real(), initialSingleVoltage(1).real()); + mSLog->flush(); } void EMT::Ph1::Capacitor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { diff --git a/dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp b/dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp index f10766a7d6..69f7b0df2f 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Inductor.cpp @@ -25,7 +25,7 @@ SimPowerComp::Ptr EMT::Ph1::Inductor::clone(String name) { } void EMT::Ph1::Inductor::initializeFromNodesAndTerminals(Real frequency) { - + Real omega = 2 * PI * frequency; Complex impedance = { 0, omega * **mInductance }; (**mIntfVoltage)(0,0) = (initialSingleVoltage(1) - initialSingleVoltage(0)).real(); @@ -42,6 +42,7 @@ void EMT::Ph1::Inductor::initializeFromNodesAndTerminals(Real frequency) { (**mIntfCurrent)(0,0), initialSingleVoltage(0).real(), initialSingleVoltage(1).real()); + mSLog->flush(); } void EMT::Ph1::Inductor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { diff --git a/dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp b/dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp index b7b2456201..48185dc590 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_Resistor.cpp @@ -39,6 +39,7 @@ void EMT::Ph1::Resistor::initializeFromNodesAndTerminals(Real frequency) { (**mIntfCurrent)(0,0), initialSingleVoltage(0).real(), initialSingleVoltage(1).real()); + mSLog->flush(); } void EMT::Ph1::Resistor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index 3fb6f93307..7fe82a93e9 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -17,6 +17,7 @@ set(SHMEM_SOURCES MqttExample.cpp SharedMemExample.cpp SocketCosimExample_ext_control.cpp + CosimExample_ext_control_base.cpp #ShmemExample.cpp #ShmemDistributedReference.cpp #ShmemDistributedDirect.cpp diff --git a/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp b/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp index 4d6d6e753a..075b56acb1 100644 --- a/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp +++ b/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp @@ -78,7 +78,7 @@ Simulation setDPsim1(float ts, float tf, float u10) { r1->connect({ n1, EMT::SimNode::GND }); rLine->connect({ n1, n2 }); c1->connect({ n1, EMT::SimNode::GND }); - evs->connect({ EMT::SimNode::GND, n2 }); + evs->connect({ n2, EMT::SimNode::GND }); auto sys = SystemTopology(50, SystemNodeList{EMT::SimNode::GND, n1, n2}, @@ -96,7 +96,7 @@ Simulation setDPsim1(float ts, float tf, float u10) { sim.addLogger(logger); sim.setSystem(sys); sim.setTimeStep(ts); - sim.setFinalTime(0.1); + sim.setFinalTime(tf); // sim.doSteadyStateInit(true); sim.doInitFromNodesAndTerminals(false); @@ -104,10 +104,11 @@ Simulation setDPsim1(float ts, float tf, float u10) { // Eigen::VectorXd n_v0(2); // n_v0 << 5, 5; + // Initial conditions, given by the problem Eigen::MatrixXd n1_v0(1,1); - n1_v0(0,0) = 5; + n1_v0(0,0) = 5.0; Eigen::MatrixXd n2_v0(1,1); - n2_v0(0,0) = 2; + n2_v0(0,0) = u10; Eigen::MatrixXd ir1_0(1,1); ir1_0(0,0) = n1_v0(0,0) / r1_r; @@ -142,22 +143,194 @@ Simulation setDPsim1(float ts, float tf, float u10) { return sim; } +Simulation setDPsim2(float ts, float tf, float u20) { + float r3_r = 1; + float c2_c = 1; + + // ----- POWERFLOW FOR INITIALIZATION ----- + // String simNamePF = "Cosim_example1"; + // CPS::Logger::setLogDir("logs/"+simNamePF); + + // auto n1PF = SP::SimNode::make("n1"); + // auto n2PF = SP::SimNode::make("n2"); + + // auto evsPF = SP::Ph1::VoltageSource::make("v_intf"); + // evsPF->setParameters(u10); + + // auto r1PF = SP::Ph1::Resistor::make("r_1"); + // r1PF->setParameters(r1_r); + // auto c1PF = SP::Ph1::Capacitor::make("c_1"); + // c1PF->setParameters(c1_c); + // auto rLinePF = SP::Ph1::Resistor::make("r_line"); + // rLinePF->setParameters(rLine_r); + + // r1PF->connect({ n1PF, SP::SimNode::GND }); + // rLinePF->connect({ n1PF, n2PF }); + // c1PF->connect({ n1PF, SP::SimNode::GND }); + // evsPF->connect({ SP::SimNode::GND, n2PF }); + // auto systemPF = SystemTopology(50, + // SystemNodeList{n1PF, n2PF}, + // SystemComponentList{c1PF, r1PF, rLinePF, evsPF}); + + // auto loggerPF = DataLogger::make(simNamePF); + // loggerPF->logAttribute("1_v_1", n1PF->mVoltage); + // loggerPF->logAttribute("2_v_2", n2PF->mVoltage); + + // Simulation simPF(simNamePF, CPS::Logger::Level::debug); + // simPF.setSystem(systemPF); + // simPF.setTimeStep(0.1); + // simPF.setFinalTime(0.1); + // simPF.setDomain(Domain::SP); + // simPF.setSolverType(Solver::Type::NRP); + // simPF.doInitFromNodesAndTerminals(false); + // simPF.addLogger(loggerPF); + // simPF.run(); + + + // ----- DYNAMIC SIMULATION ----- + String simName = "Cosim_example2"; + CPS::Logger::setLogDir("logs/"+simName); + + // Nodes + auto n2 = EMT::SimNode::make("n2"); + + // Components + auto is = EMT::Ph1::CurrentSource::make("i_intf"); + is->setParameters(u20); + + auto r3 = EMT::Ph1::Resistor::make("r_3"); + r3->setParameters(r3_r); + auto c2 = EMT::Ph1::Capacitor::make("c_2"); + c2->setParameters(c2_c); + + // Topology + r3->connect({ n2, EMT::SimNode::GND }); + c2->connect({ n2, EMT::SimNode::GND }); + is->connect({ EMT::SimNode::GND, n2 }); + + auto sys = SystemTopology(50, + SystemNodeList{EMT::SimNode::GND, n2}, + SystemComponentList{r3, c2, is}); + + auto logger = DataLogger::make(simName); + logger->logAttribute("2_v_2", n2->mVoltage); + logger->logAttribute("4_i_evs", is->mIntfCurrent, 1, 1); + logger->logAttribute("5_v_evs", is->mIntfVoltage, 1, 1); + + Simulation sim(simName); + sim.setDomain(CPS::Domain::EMT); + sim.addLogger(logger); + sim.setSystem(sys); + sim.setTimeStep(ts); + sim.setFinalTime(tf); + // sim.doSteadyStateInit(true); + sim.doInitFromNodesAndTerminals(false); + + // initialize currents and voltages + // Eigen::VectorXd n_v0(2); + // n_v0 << 5, 5; + + // Initial conditions, given by the problem + Eigen::MatrixXd n2_v0(1,1); + n2_v0(0,0) = 2.0; + Eigen::MatrixXd i_rLine0(1,1); + i_rLine0(0,0) = u20; + + Eigen::MatrixXd ir3_0(1,1); + ir3_0(0,0) = n2_v0(0,0) / r3_r; + + r3->setIntfVoltage(n2_v0); + r3->setIntfCurrent(ir3_0); + c2->setIntfVoltage(n2_v0); + c2->setIntfCurrent(i_rLine0 - ir3_0); + // cout << "rLine voltage: " << rLine->mIntfVoltage->toString() << endl; + // cout << "r1 current: " << r1->mIntfCurrent->toString() << endl; + // cout << "c1 current: " << c1->mIntfCurrent->toString() << endl; + + is->setIntfVoltage(n2_v0); + is->setIntfCurrent(i_rLine0); + cout << "is current: " << is->mIntfCurrent->toString() << endl; + + // Eigen::MatrixXd r1_i(1,1); + // r1_i(0,0) = n1_v0(0,0) / r1_r; + // r1->setIntfCurrent(r1_i); + // c1->setIntfCurrent(Eigen::MatrixXd(20)); + // rLine->setIntfVoltage(Eigen::MatrixXd(3)); + // rLine->setIntfCurrent(Eigen::MatrixXd(30)); + + // Eigen::MatrixXcd intfCurrent0(1,1); + // intfCurrent0(0,0) = std::complex(5.0,0.0); + // evs->setIntfCurrent(intfCurrent0); + + return sim; +} + int main(int argc, char* argv[]) { float timeStep = 0.01; - float finalTime = 1.0; + float finalTime = 0.02; + // ** Initialization ** // Communication y20 -> S_1 and initialization of S_1 float y20 = 2.0; + + // Set up subsytem 1 Simulation sim1 = setDPsim1(timeStep, finalTime, y20); sim1.start(); - CPS::AttributeBase *y10 = sim1.getIdObjAttribute("v_intf", "i_intf").get(); - cout << "Output value: " << y10->toString() << endl; - float ki1 = sim1.next(); - y10 = sim1.getIdObjAttribute("v_intf", "i_intf").get(); - cout << "Step: " << ki1 << ", Output value: " << y10->toString() << endl; + + CPS::AttributeBase::Ptr y10_base = sim1.getIdObjAttribute("v_intf", "i_intf"); + // try { + auto y10_matrix = std::dynamic_pointer_cast>(y10_base.getPtr()); + Attribute::Ptr y10 = y10_matrix->deriveCoeff(0,0); + cout << "Output value from S1: " << y10->toString() << endl; + // } catch(...) { + // throw CPS::InvalidAttributeException(); + // } + + // "Communication" y10 -> S_2 and initialization of S_2 + CPS::AttributeBase::Ptr u20_base = y10->cloneValueOntoNewAttribute(); + auto u20Attr = std::dynamic_pointer_cast>(u20_base.getPtr()); + cout << "Input value to S2: " << u20Attr->toString() << endl; + + float u20 = u20Attr->get(); + + Simulation sim2 = setDPsim2(timeStep, finalTime, u20); + sim2.start(); + + // Main loop + float t = 0.0; + + while (t < finalTime) { + t = sim1.next(); + + cout << "t = " << t << endl; + + y10_base = sim1.getIdObjAttribute("v_intf", "i_intf"); + y10_matrix = std::dynamic_pointer_cast>(y10_base.getPtr()); + y10 = y10_matrix->deriveCoeff(0,0); + cout << "Output value from S1: " << y10->toString() << endl; + + // "Communication" y10 -> S_2 and initialization of S_2 + CPS::AttributeBase::Ptr u20_base = y10->cloneValueOntoNewAttribute(); + auto u20Attr = std::dynamic_pointer_cast>(u20_base.getPtr()); + cout << "Input value to S2: " << u20Attr->toString() << endl; + + float u20 = u20Attr->get(); + } + + // Get only works for the typed ones + // AttributeBase::Ptr attr = AttributeStatic::make(0.001); + + // Attribute::Ptr attr = AttributeStatic::make(0.001); + // Real read1 = attr->get(); + // cout << read1 << endl; + + // Set up subsystem 2 + // Simulation sim1 = setDPsim1(timeStep, finalTime, y20); + // sim1.start(); sim1.stop(); + sim2.stop(); // if (String(argv[1]) == "0") { diff --git a/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp b/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp new file mode 100644 index 0000000000..f38da70ba7 --- /dev/null +++ b/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include +#include + +using namespace DPsim; +using namespace CPS; +using namespace std; + +int main(int argc, char* argv[]) { + + float r1_r = 0.1; + float c1_c = 1; + float rLine_r = 0.1; + float r3_r = 1; + float c2_c = 1; + + // ----- DYNAMIC SIMULATION ----- + String simName = "Cosim_example_base"; + CPS::Logger::setLogDir("logs/"+simName); + + // Nodes + auto n1 = EMT::SimNode::make("n1"); + auto n2 = EMT::SimNode::make("n2"); + + // Components + auto r1 = EMT::Ph1::Resistor::make("r_1"); + r1->setParameters(r1_r); + auto c1 = EMT::Ph1::Capacitor::make("c_1"); + c1->setParameters(c1_c); + auto rLine = EMT::Ph1::Resistor::make("r_line"); + rLine->setParameters(rLine_r); + auto r3 = EMT::Ph1::Resistor::make("r_3"); + r3->setParameters(r3_r); + auto c2 = EMT::Ph1::Capacitor::make("c_2"); + c2->setParameters(c2_c); + + // Topology + r1->connect({ n1, EMT::SimNode::GND }); + rLine->connect({ n1, n2 }); + c1->connect({ n1, EMT::SimNode::GND }); + r3->connect({ n2, EMT::SimNode::GND }); + c2->connect({ n2, EMT::SimNode::GND }); + + auto sys = SystemTopology(50, + SystemNodeList{EMT::SimNode::GND, n1, n2}, + SystemComponentList{r1, c1, rLine, c2, r3}); + + auto logger = DataLogger::make(simName); + logger->logAttribute("1_v_1", n1->mVoltage); + logger->logAttribute("2_v_2", n2->mVoltage); + logger->logAttribute("3_i_rline", rLine->mIntfCurrent, 1, 1); + + Simulation sim(simName); + sim.setDomain(CPS::Domain::EMT); + sim.addLogger(logger); + sim.setSystem(sys); + sim.setTimeStep(0.01); + sim.setFinalTime(1.0); + // sim.doSteadyStateInit(true); + sim.doInitFromNodesAndTerminals(false); + + // initialize currents and voltages + // Eigen::VectorXd n_v0(2); + // n_v0 << 5, 5; + + // Initial conditions, given by the problem + Eigen::MatrixXd n1_v0(1,1); + n1_v0(0,0) = 5.0; + Eigen::MatrixXd n2_v0(1,1); + n2_v0(0,0) = 2.0; + + Eigen::MatrixXd ir1_0(1,1); + ir1_0(0,0) = n1_v0(0,0) / r1_r; + Eigen::MatrixXd irLine_0(1,1); + irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; + + Eigen::MatrixXd ir3_0(1,1); + ir3_0(0,0) = n2_v0(0,0) / r3_r; + + r1->setIntfVoltage(n1_v0); + r1->setIntfCurrent(ir1_0); + c1->setIntfVoltage(n1_v0); + c1->setIntfCurrent(ir1_0 - irLine_0); + rLine->setIntfVoltage(n1_v0 - n2_v0); + rLine->setIntfCurrent(irLine_0); + r3->setIntfVoltage(n2_v0); + r3->setIntfCurrent(ir3_0); + c2->setIntfVoltage(n2_v0); + c2->setIntfCurrent(irLine_0 - ir3_0); + + sim.run(); +} diff --git a/dpsim/src/Simulation.cpp b/dpsim/src/Simulation.cpp index a1c94d00c0..5d7ed2d09b 100644 --- a/dpsim/src/Simulation.cpp +++ b/dpsim/src/Simulation.cpp @@ -173,8 +173,11 @@ void Simulation::sync() const { for (auto intf : mInterfaces) { intf->syncExports(); + mLog->info("Synchronization step 1: syncExports completed!"); intf->syncImports(); + mLog->info("Synchronization step 2: syncImports completed!"); intf->syncExports(); + mLog->info("Synchronization step 3: syncExports completed!"); } SPDLOG_LOGGER_INFO(mLog, "Synchronized simulation start with remotes"); diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index e793b4b874..53ad9b0e89 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -85,15 +85,15 @@ RUN cd /tmp && \ 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 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 # Remove this part in the future and use dedicated Jupyter Dockerfile # Activate Jupyter extensions From 25b10fdd6b366c59b540c004dc4a632f28451589 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sun, 11 Jun 2023 22:34:54 +0200 Subject: [PATCH 20/39] Completed a first version of the co-simulation example Signed-off-by: pipeacosta --- .../examples/cxx/CosimExample_ext_control.cpp | 111 ++++++++++++++---- 1 file changed, 86 insertions(+), 25 deletions(-) diff --git a/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp b/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp index 075b56acb1..5ad9460cf7 100644 --- a/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp +++ b/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp @@ -17,7 +17,7 @@ Simulation setDPsim1(float ts, float tf, float u10) { // ----- POWERFLOW FOR INITIALIZATION ----- // String simNamePF = "Cosim_example1"; - // CPS::Logger::setLogDir("logs/"+simNamePF); + // Logger::setLogDir("logs/"+simNamePF); // auto n1PF = SP::SimNode::make("n1"); // auto n2PF = SP::SimNode::make("n2"); @@ -44,7 +44,7 @@ Simulation setDPsim1(float ts, float tf, float u10) { // loggerPF->logAttribute("1_v_1", n1PF->mVoltage); // loggerPF->logAttribute("2_v_2", n2PF->mVoltage); - // Simulation simPF(simNamePF, CPS::Logger::Level::debug); + // Simulation simPF(simNamePF, Logger::Level::debug); // simPF.setSystem(systemPF); // simPF.setTimeStep(0.1); // simPF.setFinalTime(0.1); @@ -64,7 +64,7 @@ Simulation setDPsim1(float ts, float tf, float u10) { auto n2 = EMT::SimNode::make("n2"); // Components - auto evs = EMT::Ph1::VoltageSource::make("v_intf"); + auto evs = EMT::Ph1::VoltageSource::make("v_in_1"); evs->setParameters(u10); auto r1 = EMT::Ph1::Resistor::make("r_1"); @@ -92,7 +92,7 @@ Simulation setDPsim1(float ts, float tf, float u10) { logger->logAttribute("5_v_evs", evs->mIntfVoltage, 1, 1); Simulation sim(simName); - sim.setDomain(CPS::Domain::EMT); + sim.setDomain(Domain::EMT); sim.addLogger(logger); sim.setSystem(sys); sim.setTimeStep(ts); @@ -149,7 +149,7 @@ Simulation setDPsim2(float ts, float tf, float u20) { // ----- POWERFLOW FOR INITIALIZATION ----- // String simNamePF = "Cosim_example1"; - // CPS::Logger::setLogDir("logs/"+simNamePF); + // Logger::setLogDir("logs/"+simNamePF); // auto n1PF = SP::SimNode::make("n1"); // auto n2PF = SP::SimNode::make("n2"); @@ -176,7 +176,7 @@ Simulation setDPsim2(float ts, float tf, float u20) { // loggerPF->logAttribute("1_v_1", n1PF->mVoltage); // loggerPF->logAttribute("2_v_2", n2PF->mVoltage); - // Simulation simPF(simNamePF, CPS::Logger::Level::debug); + // Simulation simPF(simNamePF, Logger::Level::debug); // simPF.setSystem(systemPF); // simPF.setTimeStep(0.1); // simPF.setFinalTime(0.1); @@ -195,7 +195,7 @@ Simulation setDPsim2(float ts, float tf, float u20) { auto n2 = EMT::SimNode::make("n2"); // Components - auto is = EMT::Ph1::CurrentSource::make("i_intf"); + auto is = EMT::Ph1::CurrentSource::make("i_in_2"); is->setParameters(u20); auto r3 = EMT::Ph1::Resistor::make("r_3"); @@ -218,7 +218,7 @@ Simulation setDPsim2(float ts, float tf, float u20) { logger->logAttribute("5_v_evs", is->mIntfVoltage, 1, 1); Simulation sim(simName); - sim.setDomain(CPS::Domain::EMT); + sim.setDomain(Domain::EMT); sim.addLogger(logger); sim.setSystem(sys); sim.setTimeStep(ts); @@ -268,34 +268,45 @@ Simulation setDPsim2(float ts, float tf, float u20) { int main(int argc, char* argv[]) { float timeStep = 0.01; - float finalTime = 0.02; + float finalTime = 0.05; // ** Initialization ** // Communication y20 -> S_1 and initialization of S_1 - float y20 = 2.0; + // float y20 = 2.0; // Set up subsytem 1 - Simulation sim1 = setDPsim1(timeStep, finalTime, y20); + Simulation sim1 = setDPsim1(timeStep, finalTime, 2.0); sim1.start(); - CPS::AttributeBase::Ptr y10_base = sim1.getIdObjAttribute("v_intf", "i_intf"); + AttributeBase::Ptr y10_base = sim1.getIdObjAttribute("v_in_1", "i_intf"); + // try { - auto y10_matrix = std::dynamic_pointer_cast>(y10_base.getPtr()); + auto y10_matrix = std::dynamic_pointer_cast>(y10_base.getPtr()); Attribute::Ptr y10 = y10_matrix->deriveCoeff(0,0); cout << "Output value from S1: " << y10->toString() << endl; + cout << "Output value from S1: " << **y10 << endl; + // } catch(...) { - // throw CPS::InvalidAttributeException(); + // throw InvalidAttributeException(); // } // "Communication" y10 -> S_2 and initialization of S_2 - CPS::AttributeBase::Ptr u20_base = y10->cloneValueOntoNewAttribute(); - auto u20Attr = std::dynamic_pointer_cast>(u20_base.getPtr()); + AttributeBase::Ptr u20_base = y10->cloneValueOntoNewAttribute(); + auto u20Attr = std::dynamic_pointer_cast>(u20_base.getPtr()); + // std::shared_ptr u20_base_ptr = u20_base.getPtr(); + // cout << "Input value to S2: " << *u20_base_ptr << endl; cout << "Input value to S2: " << u20Attr->toString() << endl; float u20 = u20Attr->get(); Simulation sim2 = setDPsim2(timeStep, finalTime, u20); sim2.start(); + + AttributeBase::Ptr y20_base = sim2.getIdObjAttribute("i_in_2", "v_intf"); + // auto y20_matrix = std::dynamic_pointer_cast>(y20_base.getPtr()); + // Attribute::Ptr y20 = y20_matrix->deriveCoeff(0,0); + // cout << "Output value from S2: " << y20->toString() << endl; + cout << "Output value from S2: " << y20_base->toString() << endl; // Main loop float t = 0.0; @@ -305,17 +316,65 @@ int main(int argc, char* argv[]) { cout << "t = " << t << endl; - y10_base = sim1.getIdObjAttribute("v_intf", "i_intf"); - y10_matrix = std::dynamic_pointer_cast>(y10_base.getPtr()); - y10 = y10_matrix->deriveCoeff(0,0); - cout << "Output value from S1: " << y10->toString() << endl; + AttributeBase::Ptr y1_base = sim1.getIdObjAttribute("v_in_1", "i_intf"); + auto y1_matrix = std::dynamic_pointer_cast>(y1_base.getPtr()); + Attribute::Ptr y1 = y1_matrix->deriveCoeff(0,0); + cout << "Output value from S1: " << **y1 << endl; + // cout << "Output value from S1: " << y1->toString() << endl; + // cout << "Output value from S1: " << y1_base->toString() << endl; // "Communication" y10 -> S_2 and initialization of S_2 - CPS::AttributeBase::Ptr u20_base = y10->cloneValueOntoNewAttribute(); - auto u20Attr = std::dynamic_pointer_cast>(u20_base.getPtr()); - cout << "Input value to S2: " << u20Attr->toString() << endl; + // AttributeBase::Ptr u2_base = y1->cloneValueOntoNewAttribute(); + // auto u2Attr = std::dynamic_pointer_cast>(u2_base.getPtr()); + // cout << "Input value to S2: " << u2Attr->toString() << endl; + + // Get corresponding attribute in S_2 + AttributeBase::Ptr u2_base = sim2.getIdObjAttribute("i_in_2", "i_intf"); + auto u2_matrix = std::dynamic_pointer_cast>(u2_base.getPtr()); + Attribute::Ptr u2 = u2_matrix->deriveCoeff(0,0); + cout << "Current value in S2: " << **u2 << endl; + // cout << "Current value in S2: " << u2->toString() << endl; + // cout << "Current value in S2: " << u2_base->toString() << endl; + + // Put value + // *u2_base = *y1_base; + // *u2_base.getPtr() = *y1_base.getPtr(); + **u2 = 27.2727; + Real u2_test = **u2; + + // Verify + // u2_matrix = std::dynamic_pointer_cast>(u2_base.getPtr()); + // u2 = u2_matrix->deriveCoeff(0,0); + cout << "Input value to S2: " << u2_test << endl; + + AttributeBase::Ptr u2_base_test = sim2.getIdObjAttribute("i_in_2", "i_intf"); + // auto u2_matrix_test = std::dynamic_pointer_cast>(u2_base_test.getPtr()); + // Attribute::Ptr u2_test = u2_matrix_test->deriveCoeff(0,0); + // cout << "Current value in S2: " << u2_test->toString() << endl; + cout << "Current value in S2: " << u2_base_test->toString() << endl; + + sim2.next(); + + AttributeBase::Ptr y2_base = sim2.getIdObjAttribute("i_in_2", "v_intf"); + // auto y2_matrix = std::dynamic_pointer_cast>(y2_base.getPtr()); + // Attribute::Ptr y2 = y2_matrix->deriveCoeff(0,0); + // cout << "Output value from S2: " << y2->toString() << endl; + cout << "Output value from S2: " << y2_base->toString() << endl; + + // Get corresponding attribute in S_1 + AttributeBase::Ptr u1_base = sim1.getIdObjAttribute("v_in_1", "v_intf"); + auto u1_matrix = std::dynamic_pointer_cast>(u1_base.getPtr()); + Attribute::Ptr u1 = u1_matrix->deriveCoeff(0,0); + cout << "Current value in S1: " << u1->toString() << endl; + + // Put value + *u1_base = *y2_base; + + // Verify + u1_matrix = std::dynamic_pointer_cast>(u1_base.getPtr()); + u1 = u1_matrix->deriveCoeff(0,0); + cout << "Input value to S1: " << u1->toString() << endl; - float u20 = u20Attr->get(); } // Get only works for the typed ones @@ -339,7 +398,7 @@ int main(int argc, char* argv[]) { // } // else if (String(argv[1]) == "1") { // String simName = "SocketsCosim_example2"; - // CPS::Logger::setLogDir("logs/"+simName); + // Logger::setLogDir("logs/"+simName); // // Nodes // auto n2 = SimNode::make("n2"); @@ -408,4 +467,6 @@ int main(int argc, char* argv[]) { // sim.run(); // } + + return 0; } From 50c5ae72c481e824383327c5e7b67301d3462208 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sun, 11 Jun 2023 22:35:41 +0200 Subject: [PATCH 21/39] Created a simplified test of DPSim attributes and how they work with the Simulation's getIdObjAttribute method Signed-off-by: pipeacosta --- dpsim-villas/examples/cxx/CMakeLists.txt | 1 + dpsim-villas/examples/cxx/attributes_test.cpp | 245 ++++++++++++++++++ 2 files changed, 246 insertions(+) create mode 100644 dpsim-villas/examples/cxx/attributes_test.cpp diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index 7fe82a93e9..e2d0d0e5ea 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -18,6 +18,7 @@ set(SHMEM_SOURCES SharedMemExample.cpp SocketCosimExample_ext_control.cpp CosimExample_ext_control_base.cpp + attributes_test.cpp #ShmemExample.cpp #ShmemDistributedReference.cpp #ShmemDistributedDirect.cpp diff --git a/dpsim-villas/examples/cxx/attributes_test.cpp b/dpsim-villas/examples/cxx/attributes_test.cpp new file mode 100644 index 0000000000..667151661d --- /dev/null +++ b/dpsim-villas/examples/cxx/attributes_test.cpp @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include +#include + +using namespace DPsim; +using namespace CPS; +using namespace std; + +Simulation setDPsim1(float ts, float tf, float u10) { + float r1_r = 0.1; + float c1_c = 1; + float rLine_r = 0.1; + + // ----- DYNAMIC SIMULATION ----- + String simName = "Cosim_example1"; + CPS::Logger::setLogDir("logs/"+simName); + + // Nodes + auto n1 = EMT::SimNode::make("n1"); + auto n2 = EMT::SimNode::make("n2"); + + // Components + auto evs = EMT::Ph1::VoltageSource::make("v_in_1"); + evs->setParameters(u10); + + auto r1 = EMT::Ph1::Resistor::make("r_1"); + r1->setParameters(r1_r); + auto c1 = EMT::Ph1::Capacitor::make("c_1"); + c1->setParameters(c1_c); + auto rLine = EMT::Ph1::Resistor::make("r_line"); + rLine->setParameters(rLine_r); + + // Topology + r1->connect({ n1, EMT::SimNode::GND }); + rLine->connect({ n1, n2 }); + c1->connect({ n1, EMT::SimNode::GND }); + evs->connect({ n2, EMT::SimNode::GND }); + + auto sys = SystemTopology(50, + SystemNodeList{EMT::SimNode::GND, n1, n2}, + SystemComponentList{r1, c1, rLine, evs}); + + auto logger = DataLogger::make(simName); + logger->logAttribute("1_v_1", n1->mVoltage); + logger->logAttribute("2_v_2", n2->mVoltage); + logger->logAttribute("3_i_rline", rLine->mIntfCurrent, 1, 1); + logger->logAttribute("4_i_evs", evs->mIntfCurrent, 1, 1); + logger->logAttribute("5_v_evs", evs->mIntfVoltage, 1, 1); + + Simulation sim(simName); + sim.setDomain(Domain::EMT); + sim.addLogger(logger); + sim.setSystem(sys); + sim.setTimeStep(ts); + sim.setFinalTime(tf); + // sim.doSteadyStateInit(true); + sim.doInitFromNodesAndTerminals(false); + + // Initial conditions, given by the problem + Eigen::MatrixXd n1_v0(1,1); + n1_v0(0,0) = 5.0; + Eigen::MatrixXd n2_v0(1,1); + n2_v0(0,0) = u10; + + Eigen::MatrixXd ir1_0(1,1); + ir1_0(0,0) = n1_v0(0,0) / r1_r; + Eigen::MatrixXd irLine_0(1,1); + irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; + + r1->setIntfVoltage(n1_v0); + r1->setIntfCurrent(ir1_0); + c1->setIntfVoltage(n1_v0); + c1->setIntfCurrent(ir1_0 - irLine_0); + rLine->setIntfVoltage(n1_v0 - n2_v0); + rLine->setIntfCurrent(irLine_0); + + evs->setIntfVoltage(n2_v0); + evs->setIntfCurrent(irLine_0); + + return sim; +} + +Simulation setDPsim2(float ts, float tf, float u20) { + float r3_r = 1; + float c2_c = 1; + + // ----- POWERFLOW FOR INITIALIZATION ----- + // String simNamePF = "Cosim_example1"; + // Logger::setLogDir("logs/"+simNamePF); + + // auto n1PF = SP::SimNode::make("n1"); + // auto n2PF = SP::SimNode::make("n2"); + + // auto evsPF = SP::Ph1::VoltageSource::make("v_intf"); + // evsPF->setParameters(u10); + + // auto r1PF = SP::Ph1::Resistor::make("r_1"); + // r1PF->setParameters(r1_r); + // auto c1PF = SP::Ph1::Capacitor::make("c_1"); + // c1PF->setParameters(c1_c); + // auto rLinePF = SP::Ph1::Resistor::make("r_line"); + // rLinePF->setParameters(rLine_r); + + // r1PF->connect({ n1PF, SP::SimNode::GND }); + // rLinePF->connect({ n1PF, n2PF }); + // c1PF->connect({ n1PF, SP::SimNode::GND }); + // evsPF->connect({ SP::SimNode::GND, n2PF }); + // auto systemPF = SystemTopology(50, + // SystemNodeList{n1PF, n2PF}, + // SystemComponentList{c1PF, r1PF, rLinePF, evsPF}); + + // auto loggerPF = DataLogger::make(simNamePF); + // loggerPF->logAttribute("1_v_1", n1PF->mVoltage); + // loggerPF->logAttribute("2_v_2", n2PF->mVoltage); + + // Simulation simPF(simNamePF, Logger::Level::debug); + // simPF.setSystem(systemPF); + // simPF.setTimeStep(0.1); + // simPF.setFinalTime(0.1); + // simPF.setDomain(Domain::SP); + // simPF.setSolverType(Solver::Type::NRP); + // simPF.doInitFromNodesAndTerminals(false); + // simPF.addLogger(loggerPF); + // simPF.run(); + + + // ----- DYNAMIC SIMULATION ----- + String simName = "Cosim_example2"; + CPS::Logger::setLogDir("logs/"+simName); + + // Nodes + auto n2 = EMT::SimNode::make("n2"); + + // Components + auto is = EMT::Ph1::CurrentSource::make("i_in_2"); + is->setParameters(u20); + + auto r3 = EMT::Ph1::Resistor::make("r_3"); + r3->setParameters(r3_r); + auto c2 = EMT::Ph1::Capacitor::make("c_2"); + c2->setParameters(c2_c); + + // Topology + r3->connect({ n2, EMT::SimNode::GND }); + c2->connect({ n2, EMT::SimNode::GND }); + is->connect({ EMT::SimNode::GND, n2 }); + + auto sys = SystemTopology(50, + SystemNodeList{EMT::SimNode::GND, n2}, + SystemComponentList{r3, c2, is}); + + auto logger = DataLogger::make(simName); + logger->logAttribute("2_v_2", n2->mVoltage); + logger->logAttribute("4_i_evs", is->mIntfCurrent, 1, 1); + logger->logAttribute("5_v_evs", is->mIntfVoltage, 1, 1); + + Simulation sim(simName); + sim.setDomain(Domain::EMT); + sim.addLogger(logger); + sim.setSystem(sys); + sim.setTimeStep(ts); + sim.setFinalTime(tf); + // sim.doSteadyStateInit(true); + sim.doInitFromNodesAndTerminals(false); + + // initialize currents and voltages + // Eigen::VectorXd n_v0(2); + // n_v0 << 5, 5; + + // Initial conditions, given by the problem + Eigen::MatrixXd n2_v0(1,1); + n2_v0(0,0) = 2.0; + Eigen::MatrixXd i_rLine0(1,1); + i_rLine0(0,0) = u20; + + Eigen::MatrixXd ir3_0(1,1); + ir3_0(0,0) = n2_v0(0,0) / r3_r; + + r3->setIntfVoltage(n2_v0); + r3->setIntfCurrent(ir3_0); + c2->setIntfVoltage(n2_v0); + c2->setIntfCurrent(i_rLine0 - ir3_0); + // cout << "rLine voltage: " << rLine->mIntfVoltage->toString() << endl; + // cout << "r1 current: " << r1->mIntfCurrent->toString() << endl; + // cout << "c1 current: " << c1->mIntfCurrent->toString() << endl; + + is->setIntfVoltage(n2_v0); + is->setIntfCurrent(i_rLine0); + cout << "is current: " << is->mIntfCurrent->toString() << endl; + + // Eigen::MatrixXd r1_i(1,1); + // r1_i(0,0) = n1_v0(0,0) / r1_r; + // r1->setIntfCurrent(r1_i); + // c1->setIntfCurrent(Eigen::MatrixXd(20)); + // rLine->setIntfVoltage(Eigen::MatrixXd(3)); + // rLine->setIntfCurrent(Eigen::MatrixXd(30)); + + // Eigen::MatrixXcd intfCurrent0(1,1); + // intfCurrent0(0,0) = std::complex(5.0,0.0); + // evs->setIntfCurrent(intfCurrent0); + + return sim; +} + +int main(int argc, char* argv[]) { + + Attribute::Ptr attr = AttributeStatic::make(0.001); + + Real read1 = **attr; //read1 = 0.001 + cout << "attr value: " << read1 << endl; + + **attr = 0.002; + Real read2 = **attr; //read2 = 0.002 + cout << "attr value: " << read2 << endl; + + attr->set(0.003); + Real read3 = **attr; //read3 = 0.003 + cout << "attr value: " << read3 << endl; + + // ** Initialization ** + float timeStep = 0.01; + float finalTime = 0.05; + + Simulation sim1 = setDPsim1(timeStep, finalTime, 2.0); + sim1.start(); + + AttributeBase::Ptr y10_base = sim1.getIdObjAttribute("v_in_1", "i_intf"); + auto y10_matrix = std::dynamic_pointer_cast>(y10_base.getPtr()); + Attribute::Ptr y10 = y10_matrix->deriveCoeff(0,0); + cout << "Output value from S1: " << **y10 << endl; + + **y10 = 27.2727; + Real u2_test = **y10; + cout << "New y10 value: " << u2_test << endl; + + y10->set(27.2727); + Real u2_test2 = **y10; + cout << "New y10 value: " << u2_test2 << endl; + + return 0; +} From c3755090152875cdcfb90df5ba70109c024291bc Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Tue, 17 Oct 2023 08:49:15 +0200 Subject: [PATCH 22/39] Update dpsim-mqtt to support the new VILLASnode interface Signed-off-by: pipeacosta --- examples/villas/dpsim-mqtt.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/villas/dpsim-mqtt.py b/examples/villas/dpsim-mqtt.py index 8d2803384b..029ab9998d 100644 --- a/examples/villas/dpsim-mqtt.py +++ b/examples/villas/dpsim-mqtt.py @@ -56,11 +56,12 @@ 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, True) +sim.add_interface(intf) -sim.import_attribute(evs.attr('V_ref'), 0) -sim.export_attribute(r12.attr('i_intf').derive_coeff(0, 0), 0) -sim.export_attribute(evs.attr('v_intf').derive_coeff(0, 0).derive_scaled(complex(-1,0)), 1) +# TODO: Find out for what were those functions, and which functions from the new version can replace them, if required +# sim.import_attribute(evs.attr('V_ref'), 0) +# sim.export_attribute(r12.attr('i_intf').derive_coeff(0, 0), 0) +# sim.export_attribute(evs.attr('v_intf').derive_coeff(0, 0).derive_scaled(complex(-1,0)), 1) sim.add_logger(logger) From f5fbefd9120344703b0fc5c5e0f494c12e4d65f6 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Tue, 17 Oct 2023 11:34:27 +0200 Subject: [PATCH 23/39] Update dpsim-mqtt-distributed-villas to support the new VILLASnode interface Signed-off-by: pipeacosta --- examples/villas/dpsim-mqtt-distributed-villas.py | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/villas/dpsim-mqtt-distributed-villas.py b/examples/villas/dpsim-mqtt-distributed-villas.py index 7de6696903..bb7a97956c 100644 --- a/examples/villas/dpsim-mqtt-distributed-villas.py +++ b/examples/villas/dpsim-mqtt-distributed-villas.py @@ -150,9 +150,11 @@ def dpsim0(): intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-mqtt0", config=intf_config) - sim.add_interface(intf, True) - sim.import_attribute(evs.attr('V_ref'), 0) - sim.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0) + sim.add_interface(intf) + + # TODO: Find out for what were those functions, and which functions from the new version can replace them, if required + # sim.import_attribute(evs.attr('V_ref'), 0) + # sim.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0) sim.run(1) @@ -205,9 +207,11 @@ def dpsim1(): } intf = dpsimpyvillas.InterfaceVillas(name="dpsim1-mqtt1", config=intf_config) - sim.add_interface(intf, True) - 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) + + # TODO: Find out for what were those functions, and which functions from the new version can replace them, if required + # 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.run(1) From 21c1cf0b25da441c864d8eada428a70161196b28 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Tue, 17 Oct 2023 11:35:20 +0200 Subject: [PATCH 24/39] Improved import/export calls in dpsim-villas-cosim.py Signed-off-by: pipeacosta --- examples/villas/dpsim-villas-cosim.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/villas/dpsim-villas-cosim.py b/examples/villas/dpsim-villas-cosim.py index 92e5c6f00f..66b6a4ad1b 100644 --- a/examples/villas/dpsim-villas-cosim.py +++ b/examples/villas/dpsim-villas-cosim.py @@ -86,8 +86,8 @@ def dpsim0(): evs.set_intf_current([[complex(5, 0)]]) - intf.import_attribute(evs.attr('V_ref'), 0, True, True) - intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, False) + intf.import_attribute(evs.attr('V_ref'), 0, block_on_read=True, sync_on_start=True) + intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, wait_for_on_write=False) sim.run() @@ -152,8 +152,8 @@ def dpsim1(): sim.add_interface(intf) sim.add_logger(logger) - intf.import_attribute(ecs.attr('I_ref'), 0, True, True) - intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, False) + intf.import_attribute(ecs.attr('I_ref'), 0, block_on_read=True, sync_on_start=True) + intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, wait_for_on_write=False) sim.run() From 044c31b12f54b68248a76a6edb8a9bb5af6c2b7c Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Mon, 23 Oct 2023 10:10:44 +0200 Subject: [PATCH 25/39] Corrected a co-simulation example name in CMakeLists Signed-off-by: pipeacosta --- 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 e2d0d0e5ea..35ecaa453b 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -16,7 +16,7 @@ set(SHMEM_SOURCES FileExample.cpp MqttExample.cpp SharedMemExample.cpp - SocketCosimExample_ext_control.cpp + CosimExample_ext_control.cpp CosimExample_ext_control_base.cpp attributes_test.cpp #ShmemExample.cpp From bd22a7fd528b8a4b7748960c5c14dbd4babf0ac1 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Wed, 8 Nov 2023 13:50:05 +0100 Subject: [PATCH 26/39] Fixed attribute exchange in C++ cosimulation Signed-off-by: pipeacosta --- .../examples/cxx/CosimExample_ext_control.cpp | 50 +++++++--- .../cxx/CosimExample_ext_control_base.cpp | 12 ++- ...villas-weakly-coupled-cosim-ext-control.py | 94 ++++++++++++++++--- packaging/Docker/Dockerfile.dev | 18 ++-- 4 files changed, 134 insertions(+), 40 deletions(-) diff --git a/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp b/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp index 5ad9460cf7..2a147e89e1 100644 --- a/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp +++ b/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp @@ -111,9 +111,11 @@ Simulation setDPsim1(float ts, float tf, float u10) { n2_v0(0,0) = u10; Eigen::MatrixXd ir1_0(1,1); - ir1_0(0,0) = n1_v0(0,0) / r1_r; + // ir1_0(0,0) = n1_v0(0,0) / r1_r; + ir1_0(0,0) = 50; Eigen::MatrixXd irLine_0(1,1); - irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; + // irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; + irLine_0(0,0) = 30; r1->setIntfVoltage(n1_v0); r1->setIntfCurrent(ir1_0); @@ -268,7 +270,7 @@ Simulation setDPsim2(float ts, float tf, float u20) { int main(int argc, char* argv[]) { float timeStep = 0.01; - float finalTime = 0.05; + float finalTime = 1.0; // ** Initialization ** // Communication y20 -> S_1 and initialization of S_1 @@ -302,6 +304,10 @@ int main(int argc, char* argv[]) { Simulation sim2 = setDPsim2(timeStep, finalTime, u20); sim2.start(); + // Verify initialization + AttributeBase::Ptr u20_base_test = sim2.getIdObjAttribute("i_in_2", "i_intf"); + cout << "Current value in S2: " << u20_base_test->toString() << endl; + AttributeBase::Ptr y20_base = sim2.getIdObjAttribute("i_in_2", "v_intf"); // auto y20_matrix = std::dynamic_pointer_cast>(y20_base.getPtr()); // Attribute::Ptr y20 = y20_matrix->deriveCoeff(0,0); @@ -339,13 +345,20 @@ int main(int argc, char* argv[]) { // Put value // *u2_base = *y1_base; // *u2_base.getPtr() = *y1_base.getPtr(); - **u2 = 27.2727; - Real u2_test = **u2; + + // This way doesn't work + // **u2 = 27.2727; + // Real u2_test = **u2; + + // this way does work + u2->set(**y1); + Real u2_test2 = **u2; // Verify // u2_matrix = std::dynamic_pointer_cast>(u2_base.getPtr()); // u2 = u2_matrix->deriveCoeff(0,0); - cout << "Input value to S2: " << u2_test << endl; + // cout << "Input value to S2: " << u2_test << endl; + cout << "Input value to S2 (option 2): " << u2_test2 << endl; AttributeBase::Ptr u2_base_test = sim2.getIdObjAttribute("i_in_2", "i_intf"); // auto u2_matrix_test = std::dynamic_pointer_cast>(u2_base_test.getPtr()); @@ -356,10 +369,11 @@ int main(int argc, char* argv[]) { sim2.next(); AttributeBase::Ptr y2_base = sim2.getIdObjAttribute("i_in_2", "v_intf"); - // auto y2_matrix = std::dynamic_pointer_cast>(y2_base.getPtr()); - // Attribute::Ptr y2 = y2_matrix->deriveCoeff(0,0); + auto y2_matrix = std::dynamic_pointer_cast>(y2_base.getPtr()); + Attribute::Ptr y2 = y2_matrix->deriveCoeff(0,0); + cout << "Output value from S2: " << **y2 << endl; // cout << "Output value from S2: " << y2->toString() << endl; - cout << "Output value from S2: " << y2_base->toString() << endl; + // cout << "Output value from S2: " << y2_base->toString() << endl; // Get corresponding attribute in S_1 AttributeBase::Ptr u1_base = sim1.getIdObjAttribute("v_in_1", "v_intf"); @@ -368,12 +382,22 @@ int main(int argc, char* argv[]) { cout << "Current value in S1: " << u1->toString() << endl; // Put value - *u1_base = *y2_base; + // *u1_base = *y2_base; + + u1->set(**y2); + Real u1_test2 = **u1; // Verify - u1_matrix = std::dynamic_pointer_cast>(u1_base.getPtr()); - u1 = u1_matrix->deriveCoeff(0,0); - cout << "Input value to S1: " << u1->toString() << endl; + // u1_matrix = std::dynamic_pointer_cast>(u1_base.getPtr()); + // u1 = u1_matrix->deriveCoeff(0,0); + // cout << "Input value to S1: " << u1->toString() << endl; + cout << "Input value to S1 (option 2): " << u1_test2 << endl; + + AttributeBase::Ptr u1_base_test = sim1.getIdObjAttribute("v_in_1", "v_intf"); + // auto u2_matrix_test = std::dynamic_pointer_cast>(u2_base_test.getPtr()); + // Attribute::Ptr u2_test = u2_matrix_test->deriveCoeff(0,0); + // cout << "Current value in S2: " << u2_test->toString() << endl; + cout << "Current value in S1: " << u1_base_test->toString() << endl; } diff --git a/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp b/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp index f38da70ba7..cd3aa39143 100644 --- a/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp +++ b/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp @@ -74,23 +74,27 @@ int main(int argc, char* argv[]) { n2_v0(0,0) = 2.0; Eigen::MatrixXd ir1_0(1,1); - ir1_0(0,0) = n1_v0(0,0) / r1_r; + ir1_0(0,0) = -n1_v0(0,0) / r1_r; Eigen::MatrixXd irLine_0(1,1); irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; Eigen::MatrixXd ir3_0(1,1); ir3_0(0,0) = n2_v0(0,0) / r3_r; + Eigen::MatrixXd ic1_0 = ir1_0 - irLine_0; + Eigen::MatrixXd vrLine_0 = n1_v0 - n2_v0; + Eigen::MatrixXd ic2_0 = irLine_0 - ir3_0; + r1->setIntfVoltage(n1_v0); r1->setIntfCurrent(ir1_0); c1->setIntfVoltage(n1_v0); - c1->setIntfCurrent(ir1_0 - irLine_0); - rLine->setIntfVoltage(n1_v0 - n2_v0); + c1->setIntfCurrent(ic1_0); + rLine->setIntfVoltage(vrLine_0); rLine->setIntfCurrent(irLine_0); r3->setIntfVoltage(n2_v0); r3->setIntfCurrent(ir3_0); c2->setIntfVoltage(n2_v0); - c2->setIntfCurrent(irLine_0 - ir3_0); + c2->setIntfCurrent(ic2_0); sim.run(); } diff --git a/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py b/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py index 280948be44..a623135f8f 100644 --- a/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py +++ b/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py @@ -10,6 +10,10 @@ log = logging.getLogger(base) def set_dpsim1(t_s, t_f, u_1_0): + r_1_r = 0.1 + c_1_c = 1 + r_line_r = 0.1 + sim_name = "WeaklyCoupledCosim0" gnd = dpsimpy.emt.SimNode.gnd @@ -20,11 +24,11 @@ def set_dpsim1(t_s, t_f, u_1_0): evs.set_parameters(u_1_0) r_1 = dpsimpy.emt.ph1.Resistor("r_1") - r_1.set_parameters(0.1) + r_1.set_parameters(r_1_r) c_1 = dpsimpy.emt.ph1.Capacitor("c_1") - c_1.set_parameters(1) + c_1.set_parameters(c_1_c) r_line = dpsimpy.emt.ph1.Resistor('r_line', dpsimpy.LogLevel.debug) - r_line.set_parameters(0.1) + r_line.set_parameters(r_line_r) r_1.connect([n1, gnd]) r_line.connect([n1, n2]) @@ -50,11 +54,47 @@ def set_dpsim1(t_s, t_f, u_1_0): logger.log_attribute('5_v_evs', 'v_intf', evs) sim.add_logger(logger) + + # Initialize currents and voltages + # r = np.array([[1/r_1_r, 0.0], [0.0, 1/r_line_r]]) + # n_v_0 = np.array([5.0, 5.0 - u_1_0]).T + + # i_0 = np.matmul(r, n_v_0) + + + n1_v0 = np.array([5.0]) + n2_v0 = np.array([u_1_0]) + + ir_1_0 = n1_v0 / r_1_r + i_r_line_0 = (n1_v0 - n2_v0) / r_line_r + + # r_1.set_intf_voltage([n_v_0[0]]) + # r_1.set_intf_current([i_0[0]]) + # c_1.set_intf_voltage([n_v_0[0]]) + # c_1.set_intf_current([i_0[0] - i_0[1]]) + # r_line.set_intf_voltage([n_v_0[1]]) + # r_line.set_intf_current([i_0[1]]) + + # evs.set_intf_voltage([n_v_0[0] - n_v_0[1]]) + # evs.set_intf_current([i_0[1]]) + + r_1.set_intf_voltage(n1_v0) + r_1.set_intf_current(ir_1_0) + c_1.set_intf_voltage(n1_v0) + c_1.set_intf_current(ir_1_0 - i_r_line_0) + r_line.set_intf_voltage(n1_v0 - n2_v0) + r_line.set_intf_current(i_r_line_0) + + evs.set_intf_voltage(n2_v0) + evs.set_intf_current(i_r_line_0) return sim def set_dpsim2(t_s, t_f, u_2_0): + r_load_r = 1.0 + c_2_c = 1.0 + sim_name = "WeaklyCoupledCosim1" gnd = dpsimpy.emt.SimNode.gnd @@ -63,9 +103,9 @@ def set_dpsim2(t_s, t_f, u_2_0): ecs = dpsimpy.emt.ph1.CurrentSource('i_intf', dpsimpy.LogLevel.debug) ecs.set_parameters(u_2_0) c_2 = dpsimpy.emt.ph1.Capacitor("c_2") - c_2.set_parameters(1) + c_2.set_parameters(c_2_c) r_load = dpsimpy.emt.ph1.Resistor('r_load', dpsimpy.LogLevel.debug) - r_load.set_parameters(1) + r_load.set_parameters(r_load_r) ecs.connect([gnd, n2]) c_2.connect([gnd, n2]) @@ -74,6 +114,7 @@ def set_dpsim2(t_s, t_f, u_2_0): sys = dpsimpy.SystemTopology(50, [gnd, n2], [ecs, c_2, r_load]) sim = dpsimpy.Simulation(sim_name) + sim.set_domain(dpsimpy.Domain.EMT) sim.set_system(sys) sim.set_time_step(t_s) sim.set_final_time(t_f) @@ -87,32 +128,57 @@ def set_dpsim2(t_s, t_f, u_2_0): logger.log_attribute('4_i_ecs', 'i_intf', ecs) sim.add_logger(logger) - + + # Initialize currents and voltages + n2_v0 = [2.0] + i_r_line_0 = [u_2_0] + i_r_load_0 = [n2_v0[0] / r_load_r] + + r_load.set_intf_voltage(n2_v0) + r_load.set_intf_current(i_r_load_0) + c_2.set_intf_voltage([n2_v0]) + c_2.set_intf_current([i_r_line_0[0] - i_r_load_0[0]]) + + ecs.set_intf_voltage(n2_v0) + ecs.set_intf_current(i_r_line_0) + return sim if __name__ == '__main__': logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) - time_step = 1e-3 + time_step = 0.01 final_time = 1.0 t_k = 0.0 # Communication y_2_0 -> S_1 and initialization of S_1 - y_2_0 = 2 + y_2_0 = 2.0 sim1 = set_dpsim1(time_step, final_time, y_2_0) sim1.start() y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() - print(y_1_0) + print("Output value from S1: {:f}".format(y_1_0)) + + # Communication y_1_0 -> S_2 and initialization of S_2 + sim2 = set_dpsim2(time_step, final_time, y_1_0) + sim2.start() + y_2_0 = sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() + print("Output value from S2: {:f}".format(y_2_0)) + + + + + + + + + + k1_i = sim1.next() y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() - print(y_1_0) + print("Output value from S1: {:f}".format(y_1_0)) # y_1_0_ts = ts.TimeSeries("v2", t_k, y_1_0_dp) # y_1_0_emt = y_1_0_ts.frequency_shift(freq=50) - # Communication y_1_0 -> S_2 and initialization of S_2 - # sim2 = set_dpsim2(time_step, final_time, y_1_0) - # sim2.start() - # Switch to S_2 and get initial output # y_2_0_dp = sim2.get_idobj_attr("n2", "v").derive_coeff(0,0).get() # y_2_0_ts = ts.TimeSeries("v2", t_k, y_2_0_dp) diff --git a/packaging/Docker/Dockerfile.dev b/packaging/Docker/Dockerfile.dev index 53ad9b0e89..e793b4b874 100644 --- a/packaging/Docker/Dockerfile.dev +++ b/packaging/Docker/Dockerfile.dev @@ -85,15 +85,15 @@ RUN cd /tmp && \ 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 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 # Remove this part in the future and use dedicated Jupyter Dockerfile # Activate Jupyter extensions From 6a29f6786767b2f986fd283f86be5f2f62b60d0f Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Thu, 9 Nov 2023 09:51:57 +0000 Subject: [PATCH 27/39] Refactor: file names and locations Signed-off-by: pipeacosta --- dpsim-villas/examples/cxx/CMakeLists.txt | 4 +- ...osimExample.cpp => CosimSocketExample.cpp} | 0 dpsim-villas/examples/cxx/attributes_test.cpp | 245 ------------------ dpsim/examples/cxx/Attributes/Attributes.cpp | 28 ++ .../cxx/Attributes/CosimExampleAttributes.cpp | 1 - .../CosimExampleAttributesReference.cpp | 1 - dpsim/examples/cxx/CMakeLists.txt | 8 +- .../dpsim-villas-weakly-coupled-cosim.ipynb | 146 +---------- 8 files changed, 48 insertions(+), 385 deletions(-) rename dpsim-villas/examples/cxx/{SocketCosimExample.cpp => CosimSocketExample.cpp} (100%) delete mode 100644 dpsim-villas/examples/cxx/attributes_test.cpp create mode 100644 dpsim/examples/cxx/Attributes/Attributes.cpp rename dpsim-villas/examples/cxx/CosimExample_ext_control.cpp => dpsim/examples/cxx/Attributes/CosimExampleAttributes.cpp (99%) rename dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp => dpsim/examples/cxx/Attributes/CosimExampleAttributesReference.cpp (98%) diff --git a/dpsim-villas/examples/cxx/CMakeLists.txt b/dpsim-villas/examples/cxx/CMakeLists.txt index 273665fffc..1f4dd9b01f 100644 --- a/dpsim-villas/examples/cxx/CMakeLists.txt +++ b/dpsim-villas/examples/cxx/CMakeLists.txt @@ -16,10 +16,8 @@ set(SHMEM_SOURCES FileExample.cpp MqttExample.cpp SharedMemExample.cpp - CosimExample_ext_control.cpp - CosimExample_ext_control_base.cpp SocketExample.cpp - SocketCosimExample.cpp + CosimSocketExample.cpp #ShmemExample.cpp #ShmemDistributedReference.cpp #ShmemDistributedDirect.cpp diff --git a/dpsim-villas/examples/cxx/SocketCosimExample.cpp b/dpsim-villas/examples/cxx/CosimSocketExample.cpp similarity index 100% rename from dpsim-villas/examples/cxx/SocketCosimExample.cpp rename to dpsim-villas/examples/cxx/CosimSocketExample.cpp diff --git a/dpsim-villas/examples/cxx/attributes_test.cpp b/dpsim-villas/examples/cxx/attributes_test.cpp deleted file mode 100644 index 667151661d..0000000000 --- a/dpsim-villas/examples/cxx/attributes_test.cpp +++ /dev/null @@ -1,245 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -#include -#include - -#include -#include - -using namespace DPsim; -using namespace CPS; -using namespace std; - -Simulation setDPsim1(float ts, float tf, float u10) { - float r1_r = 0.1; - float c1_c = 1; - float rLine_r = 0.1; - - // ----- DYNAMIC SIMULATION ----- - String simName = "Cosim_example1"; - CPS::Logger::setLogDir("logs/"+simName); - - // Nodes - auto n1 = EMT::SimNode::make("n1"); - auto n2 = EMT::SimNode::make("n2"); - - // Components - auto evs = EMT::Ph1::VoltageSource::make("v_in_1"); - evs->setParameters(u10); - - auto r1 = EMT::Ph1::Resistor::make("r_1"); - r1->setParameters(r1_r); - auto c1 = EMT::Ph1::Capacitor::make("c_1"); - c1->setParameters(c1_c); - auto rLine = EMT::Ph1::Resistor::make("r_line"); - rLine->setParameters(rLine_r); - - // Topology - r1->connect({ n1, EMT::SimNode::GND }); - rLine->connect({ n1, n2 }); - c1->connect({ n1, EMT::SimNode::GND }); - evs->connect({ n2, EMT::SimNode::GND }); - - auto sys = SystemTopology(50, - SystemNodeList{EMT::SimNode::GND, n1, n2}, - SystemComponentList{r1, c1, rLine, evs}); - - auto logger = DataLogger::make(simName); - logger->logAttribute("1_v_1", n1->mVoltage); - logger->logAttribute("2_v_2", n2->mVoltage); - logger->logAttribute("3_i_rline", rLine->mIntfCurrent, 1, 1); - logger->logAttribute("4_i_evs", evs->mIntfCurrent, 1, 1); - logger->logAttribute("5_v_evs", evs->mIntfVoltage, 1, 1); - - Simulation sim(simName); - sim.setDomain(Domain::EMT); - sim.addLogger(logger); - sim.setSystem(sys); - sim.setTimeStep(ts); - sim.setFinalTime(tf); - // sim.doSteadyStateInit(true); - sim.doInitFromNodesAndTerminals(false); - - // Initial conditions, given by the problem - Eigen::MatrixXd n1_v0(1,1); - n1_v0(0,0) = 5.0; - Eigen::MatrixXd n2_v0(1,1); - n2_v0(0,0) = u10; - - Eigen::MatrixXd ir1_0(1,1); - ir1_0(0,0) = n1_v0(0,0) / r1_r; - Eigen::MatrixXd irLine_0(1,1); - irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; - - r1->setIntfVoltage(n1_v0); - r1->setIntfCurrent(ir1_0); - c1->setIntfVoltage(n1_v0); - c1->setIntfCurrent(ir1_0 - irLine_0); - rLine->setIntfVoltage(n1_v0 - n2_v0); - rLine->setIntfCurrent(irLine_0); - - evs->setIntfVoltage(n2_v0); - evs->setIntfCurrent(irLine_0); - - return sim; -} - -Simulation setDPsim2(float ts, float tf, float u20) { - float r3_r = 1; - float c2_c = 1; - - // ----- POWERFLOW FOR INITIALIZATION ----- - // String simNamePF = "Cosim_example1"; - // Logger::setLogDir("logs/"+simNamePF); - - // auto n1PF = SP::SimNode::make("n1"); - // auto n2PF = SP::SimNode::make("n2"); - - // auto evsPF = SP::Ph1::VoltageSource::make("v_intf"); - // evsPF->setParameters(u10); - - // auto r1PF = SP::Ph1::Resistor::make("r_1"); - // r1PF->setParameters(r1_r); - // auto c1PF = SP::Ph1::Capacitor::make("c_1"); - // c1PF->setParameters(c1_c); - // auto rLinePF = SP::Ph1::Resistor::make("r_line"); - // rLinePF->setParameters(rLine_r); - - // r1PF->connect({ n1PF, SP::SimNode::GND }); - // rLinePF->connect({ n1PF, n2PF }); - // c1PF->connect({ n1PF, SP::SimNode::GND }); - // evsPF->connect({ SP::SimNode::GND, n2PF }); - // auto systemPF = SystemTopology(50, - // SystemNodeList{n1PF, n2PF}, - // SystemComponentList{c1PF, r1PF, rLinePF, evsPF}); - - // auto loggerPF = DataLogger::make(simNamePF); - // loggerPF->logAttribute("1_v_1", n1PF->mVoltage); - // loggerPF->logAttribute("2_v_2", n2PF->mVoltage); - - // Simulation simPF(simNamePF, Logger::Level::debug); - // simPF.setSystem(systemPF); - // simPF.setTimeStep(0.1); - // simPF.setFinalTime(0.1); - // simPF.setDomain(Domain::SP); - // simPF.setSolverType(Solver::Type::NRP); - // simPF.doInitFromNodesAndTerminals(false); - // simPF.addLogger(loggerPF); - // simPF.run(); - - - // ----- DYNAMIC SIMULATION ----- - String simName = "Cosim_example2"; - CPS::Logger::setLogDir("logs/"+simName); - - // Nodes - auto n2 = EMT::SimNode::make("n2"); - - // Components - auto is = EMT::Ph1::CurrentSource::make("i_in_2"); - is->setParameters(u20); - - auto r3 = EMT::Ph1::Resistor::make("r_3"); - r3->setParameters(r3_r); - auto c2 = EMT::Ph1::Capacitor::make("c_2"); - c2->setParameters(c2_c); - - // Topology - r3->connect({ n2, EMT::SimNode::GND }); - c2->connect({ n2, EMT::SimNode::GND }); - is->connect({ EMT::SimNode::GND, n2 }); - - auto sys = SystemTopology(50, - SystemNodeList{EMT::SimNode::GND, n2}, - SystemComponentList{r3, c2, is}); - - auto logger = DataLogger::make(simName); - logger->logAttribute("2_v_2", n2->mVoltage); - logger->logAttribute("4_i_evs", is->mIntfCurrent, 1, 1); - logger->logAttribute("5_v_evs", is->mIntfVoltage, 1, 1); - - Simulation sim(simName); - sim.setDomain(Domain::EMT); - sim.addLogger(logger); - sim.setSystem(sys); - sim.setTimeStep(ts); - sim.setFinalTime(tf); - // sim.doSteadyStateInit(true); - sim.doInitFromNodesAndTerminals(false); - - // initialize currents and voltages - // Eigen::VectorXd n_v0(2); - // n_v0 << 5, 5; - - // Initial conditions, given by the problem - Eigen::MatrixXd n2_v0(1,1); - n2_v0(0,0) = 2.0; - Eigen::MatrixXd i_rLine0(1,1); - i_rLine0(0,0) = u20; - - Eigen::MatrixXd ir3_0(1,1); - ir3_0(0,0) = n2_v0(0,0) / r3_r; - - r3->setIntfVoltage(n2_v0); - r3->setIntfCurrent(ir3_0); - c2->setIntfVoltage(n2_v0); - c2->setIntfCurrent(i_rLine0 - ir3_0); - // cout << "rLine voltage: " << rLine->mIntfVoltage->toString() << endl; - // cout << "r1 current: " << r1->mIntfCurrent->toString() << endl; - // cout << "c1 current: " << c1->mIntfCurrent->toString() << endl; - - is->setIntfVoltage(n2_v0); - is->setIntfCurrent(i_rLine0); - cout << "is current: " << is->mIntfCurrent->toString() << endl; - - // Eigen::MatrixXd r1_i(1,1); - // r1_i(0,0) = n1_v0(0,0) / r1_r; - // r1->setIntfCurrent(r1_i); - // c1->setIntfCurrent(Eigen::MatrixXd(20)); - // rLine->setIntfVoltage(Eigen::MatrixXd(3)); - // rLine->setIntfCurrent(Eigen::MatrixXd(30)); - - // Eigen::MatrixXcd intfCurrent0(1,1); - // intfCurrent0(0,0) = std::complex(5.0,0.0); - // evs->setIntfCurrent(intfCurrent0); - - return sim; -} - -int main(int argc, char* argv[]) { - - Attribute::Ptr attr = AttributeStatic::make(0.001); - - Real read1 = **attr; //read1 = 0.001 - cout << "attr value: " << read1 << endl; - - **attr = 0.002; - Real read2 = **attr; //read2 = 0.002 - cout << "attr value: " << read2 << endl; - - attr->set(0.003); - Real read3 = **attr; //read3 = 0.003 - cout << "attr value: " << read3 << endl; - - // ** Initialization ** - float timeStep = 0.01; - float finalTime = 0.05; - - Simulation sim1 = setDPsim1(timeStep, finalTime, 2.0); - sim1.start(); - - AttributeBase::Ptr y10_base = sim1.getIdObjAttribute("v_in_1", "i_intf"); - auto y10_matrix = std::dynamic_pointer_cast>(y10_base.getPtr()); - Attribute::Ptr y10 = y10_matrix->deriveCoeff(0,0); - cout << "Output value from S1: " << **y10 << endl; - - **y10 = 27.2727; - Real u2_test = **y10; - cout << "New y10 value: " << u2_test << endl; - - y10->set(27.2727); - Real u2_test2 = **y10; - cout << "New y10 value: " << u2_test2 << endl; - - return 0; -} diff --git a/dpsim/examples/cxx/Attributes/Attributes.cpp b/dpsim/examples/cxx/Attributes/Attributes.cpp new file mode 100644 index 0000000000..819d2b99f4 --- /dev/null +++ b/dpsim/examples/cxx/Attributes/Attributes.cpp @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: Apache-2.0 + +#include +#include + +#include + +using namespace DPsim; +using namespace CPS; +using namespace std; + +int main(int argc, char* argv[]) { + + Attribute::Ptr attr = AttributeStatic::make(0.001); + + Real read1 = **attr; //read1 = 0.001 + cout << "attr value: " << read1 << endl; + + **attr = 0.002; + Real read2 = **attr; //read2 = 0.002 + cout << "attr value: " << read2 << endl; + + attr->set(0.003); + Real read3 = **attr; //read3 = 0.003 + cout << "attr value: " << read3 << endl; + + return 0; +} diff --git a/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp b/dpsim/examples/cxx/Attributes/CosimExampleAttributes.cpp similarity index 99% rename from dpsim-villas/examples/cxx/CosimExample_ext_control.cpp rename to dpsim/examples/cxx/Attributes/CosimExampleAttributes.cpp index 2a147e89e1..3f1aaaeeec 100644 --- a/dpsim-villas/examples/cxx/CosimExample_ext_control.cpp +++ b/dpsim/examples/cxx/Attributes/CosimExampleAttributes.cpp @@ -4,7 +4,6 @@ #include #include -#include using namespace DPsim; using namespace CPS; diff --git a/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp b/dpsim/examples/cxx/Attributes/CosimExampleAttributesReference.cpp similarity index 98% rename from dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp rename to dpsim/examples/cxx/Attributes/CosimExampleAttributesReference.cpp index cd3aa39143..df68d9e7d6 100644 --- a/dpsim-villas/examples/cxx/CosimExample_ext_control_base.cpp +++ b/dpsim/examples/cxx/Attributes/CosimExampleAttributesReference.cpp @@ -4,7 +4,6 @@ #include #include -#include using namespace DPsim; using namespace CPS; diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index dba9ec1117..841a3061de 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -111,6 +111,12 @@ set(INVERTER_SOURCES Components/DP_Inverter_Grid_Sequential_FreqSplit.cpp ) +set(ATTRIBUTES_SOURCES + Attributes/Attributes.cpp + Attributes/CosimExampleAttributes.cpp + Attributes/CosimExampleAttributesReference.cpp +) + # Targets required for tests in the Jupyter Notebooks. This list is only for grouping the (already configured) targets, so every entry # also has to appear in another list in this file. list(APPEND TEST_SOURCES @@ -221,7 +227,7 @@ endif() add_custom_target(tests) -foreach(SOURCE ${CIRCUIT_SOURCES} ${SYNCGEN_SOURCES} ${VARFREQ_SOURCES} ${RT_SOURCES} ${CIM_SOURCES} ${CIM_SOURCES_POSIX} ${DAE_SOURCES} ${INVERTER_SOURCES}) +foreach(SOURCE ${CIRCUIT_SOURCES} ${SYNCGEN_SOURCES} ${VARFREQ_SOURCES} ${RT_SOURCES} ${CIM_SOURCES} ${CIM_SOURCES_POSIX} ${DAE_SOURCES} ${INVERTER_SOURCES} ${ATTRIBUTES_SOURCES}) get_filename_component(TARGET ${SOURCE} NAME_WE) add_executable(${TARGET} ${SOURCE}) diff --git a/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb b/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb index 8c704cdcfc..c0dd345980 100644 --- a/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb +++ b/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -93,7 +93,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -109,21 +109,9 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "image/svg+xml": "\n\n\n\n\n\ntopology\n\n\n\nn0\n\n\n\n\nn0\n(5.00 V > 0.00°)\n\n\n\nn1\n\n\n\n\nn1\n(2.00 V > 0.00°)\n\n\n\nr_1\n\n\nr_1\nDP::Ph1::Resistor\n\n\n\n\n\nr_1--n0\n\n\n\n\nr_line\n\n\nr_line\nDP::Ph1::Resistor\n\n\n\n\n\nr_line--n0\n\n\n\n\nr_line--n1\n\n\n\n\nc_1\n\n\nc_1\nDP::Ph1::Capacitor\n\n\n\n\n\nc_1--n0\n\n\n\n\nc_2\n\n\nc_2\nDP::Ph1::Capacitor\n\n\n\n\n\nc_2--n1\n\n\n\n\nr_load\n\n\nr_load\nDP::Ph1::Resistor\n\n\n\n\n\nr_load--n1\n\n\n\n\n", - "text/plain": [ - "" - ] - }, - "execution_count": 11, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "sys" ] @@ -137,28 +125,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[15:39:30.578825 WeaklyCoupledCosim info] Initialize simulation: WeaklyCoupledCosim\n", - "[15:39:30.579027 MnaSolverFactory info] creating EigenDense solver implementation\n", - "[15:39:30.580037 WeaklyCoupledCosim info] Scheduling tasks.\n", - "[15:39:30.580491 WeaklyCoupledCosim info] Scheduling done.\n", - "[15:39:30.580495 WeaklyCoupledCosim info] Opening interfaces.\n", - "[15:39:30.580496 WeaklyCoupledCosim info] Start synchronization with remotes on interfaces\n", - "[15:39:30.580498 WeaklyCoupledCosim info] Synchronized simulation start with remotes\n", - "[15:39:30.580500 WeaklyCoupledCosim info] Start simulation: WeaklyCoupledCosim\n", - "[15:39:30.580504 WeaklyCoupledCosim info] Time step: 1.000000e-03\n", - "[15:39:30.580507 WeaklyCoupledCosim info] Final time: 1.000000e+00\n", - "[15:39:30.611497 WeaklyCoupledCosim info] Simulation calculation time: 0.030977\n", - "[15:39:30.611581 WeaklyCoupledCosim info] Simulation finished.\n" - ] - } - ], + "outputs": [], "source": [ "sim = dpsimpy.Simulation(\"WeaklyCoupledCosim\", loglevel=dpsimpy.LogLevel.debug)\n", "sim.set_system(sys)\n", @@ -183,41 +152,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "column number: 2\n", - "results length: 1000\n", - "real column names: []\n", - "complex column names: ['v0', 'v1']\n" - ] - }, - { - "ename": "EmptyDataError", - "evalue": "No columns to parse from file", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mEmptyDataError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn [2], line 18\u001b[0m\n\u001b[1;32m 14\u001b[0m results_emt\u001b[39m.\u001b[39mappend(results[series]\u001b[39m.\u001b[39mfrequency_shift(freq\u001b[39m=\u001b[39m\u001b[39m50\u001b[39m))\n\u001b[1;32m 16\u001b[0m results_emt \u001b[39m=\u001b[39m [ results[series]\u001b[39m.\u001b[39mfrequency_shift(freq\u001b[39m=\u001b[39m\u001b[39m50\u001b[39m) \u001b[39mfor\u001b[39;00m series \u001b[39min\u001b[39;00m results ]\n\u001b[0;32m---> 18\u001b[0m results_strongly_coupled0 \u001b[39m=\u001b[39m rt\u001b[39m.\u001b[39;49mread_timeseries_dpsim(\u001b[39m'\u001b[39;49m\u001b[39m../../logs/WeaklyCoupledCosim0/WeaklyCoupledCosim0.csv\u001b[39;49m\u001b[39m'\u001b[39;49m)\n\u001b[1;32m 19\u001b[0m results_strongly_coupled0_emt \u001b[39m=\u001b[39m [ results[series]\u001b[39m.\u001b[39mfrequency_shift(freq\u001b[39m=\u001b[39m\u001b[39m50\u001b[39m) \u001b[39mfor\u001b[39;00m series \u001b[39min\u001b[39;00m results ]\n\u001b[1;32m 21\u001b[0m \u001b[39mfor\u001b[39;00m series \u001b[39min\u001b[39;00m results_emt:\n", - "File \u001b[0;32m/usr/local/lib/python3.9/site-packages/villas/dataprocessing/readtools.py:130\u001b[0m, in \u001b[0;36mread_timeseries_dpsim\u001b[0;34m(filename, timeseries_names, print_status)\u001b[0m\n\u001b[1;32m 129\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mread_timeseries_dpsim\u001b[39m(filename, timeseries_names\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, print_status\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m):\n\u001b[0;32m--> 130\u001b[0m \u001b[39mreturn\u001b[39;00m read_timeseries_csv(filename, timeseries_names, print_status)\n", - "File \u001b[0;32m/usr/local/lib/python3.9/site-packages/villas/dataprocessing/readtools.py:69\u001b[0m, in \u001b[0;36mread_timeseries_csv\u001b[0;34m(filename, timeseries_names, print_status)\u001b[0m\n\u001b[1;32m 62\u001b[0m \u001b[39mdef\u001b[39;00m \u001b[39mread_timeseries_csv\u001b[39m(filename, timeseries_names\u001b[39m=\u001b[39m\u001b[39mNone\u001b[39;00m, print_status\u001b[39m=\u001b[39m\u001b[39mTrue\u001b[39;00m):\n\u001b[1;32m 63\u001b[0m \u001b[39m\"\"\"Reads complex time series data from DPsim log file. Real and\u001b[39;00m\n\u001b[1;32m 64\u001b[0m \u001b[39m imaginary part are stored in one complex variable.\u001b[39;00m\n\u001b[1;32m 65\u001b[0m \u001b[39m :param filename: name of the csv file that has the data\u001b[39;00m\n\u001b[1;32m 66\u001b[0m \u001b[39m :param timeseries_names: column name which should be read\u001b[39;00m\n\u001b[1;32m 67\u001b[0m \u001b[39m :return: list of Timeseries objects\u001b[39;00m\n\u001b[1;32m 68\u001b[0m \u001b[39m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 69\u001b[0m pd_df \u001b[39m=\u001b[39m pd\u001b[39m.\u001b[39;49mread_csv(filename)\n\u001b[1;32m 70\u001b[0m timeseries_list \u001b[39m=\u001b[39m {}\n\u001b[1;32m 71\u001b[0m cmpl_result_columns \u001b[39m=\u001b[39m []\n", - "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/util/_decorators.py:211\u001b[0m, in \u001b[0;36mdeprecate_kwarg.._deprecate_kwarg..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 209\u001b[0m \u001b[39melse\u001b[39;00m:\n\u001b[1;32m 210\u001b[0m kwargs[new_arg_name] \u001b[39m=\u001b[39m new_arg_value\n\u001b[0;32m--> 211\u001b[0m \u001b[39mreturn\u001b[39;00m func(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n", - "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/util/_decorators.py:331\u001b[0m, in \u001b[0;36mdeprecate_nonkeyword_arguments..decorate..wrapper\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 325\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mlen\u001b[39m(args) \u001b[39m>\u001b[39m num_allow_args:\n\u001b[1;32m 326\u001b[0m warnings\u001b[39m.\u001b[39mwarn(\n\u001b[1;32m 327\u001b[0m msg\u001b[39m.\u001b[39mformat(arguments\u001b[39m=\u001b[39m_format_argument_list(allow_args)),\n\u001b[1;32m 328\u001b[0m \u001b[39mFutureWarning\u001b[39;00m,\n\u001b[1;32m 329\u001b[0m stacklevel\u001b[39m=\u001b[39mfind_stack_level(),\n\u001b[1;32m 330\u001b[0m )\n\u001b[0;32m--> 331\u001b[0m \u001b[39mreturn\u001b[39;00m func(\u001b[39m*\u001b[39;49margs, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwargs)\n", - "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/readers.py:950\u001b[0m, in \u001b[0;36mread_csv\u001b[0;34m(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, error_bad_lines, warn_bad_lines, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options)\u001b[0m\n\u001b[1;32m 935\u001b[0m kwds_defaults \u001b[39m=\u001b[39m _refine_defaults_read(\n\u001b[1;32m 936\u001b[0m dialect,\n\u001b[1;32m 937\u001b[0m delimiter,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 946\u001b[0m defaults\u001b[39m=\u001b[39m{\u001b[39m\"\u001b[39m\u001b[39mdelimiter\u001b[39m\u001b[39m\"\u001b[39m: \u001b[39m\"\u001b[39m\u001b[39m,\u001b[39m\u001b[39m\"\u001b[39m},\n\u001b[1;32m 947\u001b[0m )\n\u001b[1;32m 948\u001b[0m kwds\u001b[39m.\u001b[39mupdate(kwds_defaults)\n\u001b[0;32m--> 950\u001b[0m \u001b[39mreturn\u001b[39;00m _read(filepath_or_buffer, kwds)\n", - "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/readers.py:605\u001b[0m, in \u001b[0;36m_read\u001b[0;34m(filepath_or_buffer, kwds)\u001b[0m\n\u001b[1;32m 602\u001b[0m _validate_names(kwds\u001b[39m.\u001b[39mget(\u001b[39m\"\u001b[39m\u001b[39mnames\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39mNone\u001b[39;00m))\n\u001b[1;32m 604\u001b[0m \u001b[39m# Create the parser.\u001b[39;00m\n\u001b[0;32m--> 605\u001b[0m parser \u001b[39m=\u001b[39m TextFileReader(filepath_or_buffer, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[1;32m 607\u001b[0m \u001b[39mif\u001b[39;00m chunksize \u001b[39mor\u001b[39;00m iterator:\n\u001b[1;32m 608\u001b[0m \u001b[39mreturn\u001b[39;00m parser\n", - "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/readers.py:1442\u001b[0m, in \u001b[0;36mTextFileReader.__init__\u001b[0;34m(self, f, engine, **kwds)\u001b[0m\n\u001b[1;32m 1439\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39moptions[\u001b[39m\"\u001b[39m\u001b[39mhas_index_names\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m kwds[\u001b[39m\"\u001b[39m\u001b[39mhas_index_names\u001b[39m\u001b[39m\"\u001b[39m]\n\u001b[1;32m 1441\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles: IOHandles \u001b[39m|\u001b[39m \u001b[39mNone\u001b[39;00m \u001b[39m=\u001b[39m \u001b[39mNone\u001b[39;00m\n\u001b[0;32m-> 1442\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_engine \u001b[39m=\u001b[39m \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49m_make_engine(f, \u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49mengine)\n", - "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/readers.py:1753\u001b[0m, in \u001b[0;36mTextFileReader._make_engine\u001b[0;34m(self, f, engine)\u001b[0m\n\u001b[1;32m 1750\u001b[0m \u001b[39mraise\u001b[39;00m \u001b[39mValueError\u001b[39;00m(msg)\n\u001b[1;32m 1752\u001b[0m \u001b[39mtry\u001b[39;00m:\n\u001b[0;32m-> 1753\u001b[0m \u001b[39mreturn\u001b[39;00m mapping[engine](f, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49m\u001b[39mself\u001b[39;49m\u001b[39m.\u001b[39;49moptions)\n\u001b[1;32m 1754\u001b[0m \u001b[39mexcept\u001b[39;00m \u001b[39mException\u001b[39;00m:\n\u001b[1;32m 1755\u001b[0m \u001b[39mif\u001b[39;00m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39mhandles \u001b[39mis\u001b[39;00m \u001b[39mnot\u001b[39;00m \u001b[39mNone\u001b[39;00m:\n", - "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/io/parsers/c_parser_wrapper.py:79\u001b[0m, in \u001b[0;36mCParserWrapper.__init__\u001b[0;34m(self, src, **kwds)\u001b[0m\n\u001b[1;32m 76\u001b[0m kwds\u001b[39m.\u001b[39mpop(key, \u001b[39mNone\u001b[39;00m)\n\u001b[1;32m 78\u001b[0m kwds[\u001b[39m\"\u001b[39m\u001b[39mdtype\u001b[39m\u001b[39m\"\u001b[39m] \u001b[39m=\u001b[39m ensure_dtype_objs(kwds\u001b[39m.\u001b[39mget(\u001b[39m\"\u001b[39m\u001b[39mdtype\u001b[39m\u001b[39m\"\u001b[39m, \u001b[39mNone\u001b[39;00m))\n\u001b[0;32m---> 79\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_reader \u001b[39m=\u001b[39m parsers\u001b[39m.\u001b[39;49mTextReader(src, \u001b[39m*\u001b[39;49m\u001b[39m*\u001b[39;49mkwds)\n\u001b[1;32m 81\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39munnamed_cols \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_reader\u001b[39m.\u001b[39munnamed_cols\n\u001b[1;32m 83\u001b[0m \u001b[39m# error: Cannot determine type of 'names'\u001b[39;00m\n", - "File \u001b[0;32m/usr/local/lib64/python3.9/site-packages/pandas/_libs/parsers.pyx:554\u001b[0m, in \u001b[0;36mpandas._libs.parsers.TextReader.__cinit__\u001b[0;34m()\u001b[0m\n", - "\u001b[0;31mEmptyDataError\u001b[0m: No columns to parse from file" - ] - } - ], + "outputs": [], "source": [ "%matplotlib inline\n", "%config InlineBackend.figure_format = 'svg'\n", @@ -251,68 +188,9 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "515.87s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "[I] ---- Start initialization ----\n", - "[I] -- Process topology\n", - "[I] Added DP::Ph1::VoltageSource 'v_s' to simulation.\n", - "[I] Added DP::Ph1::Resistor 'r_line' to simulation.\n", - "[I] Added DP::Ph1::Inductor 'l_line' to simulation.\n", - "[I] Added DP::Ph1::Resistor 'r_load' to simulation.\n", - "[I] Added node n0\n", - "[I] Added node n1\n", - "[I] Added node n2\n", - "[I] Collected virtual node 2 of 0\n", - "[I] Created virtual nodes:\n", - "[I] Number of network nodes: 3\n", - "[I] Number of network and virtual nodes: 4\n", - "[I] Assigned index 0 to phase A of node 0\n", - "[I] Assigned index 1 to phase A of node 1\n", - "[I] Assigned index 2 to phase A of node 2\n", - "[I] Assigned index 3 to phase A of node 3\n", - "[I] Assigned simulation nodes to topology nodes:\n", - "[I] Number of network simulation nodes: 3\n", - "[I] Number of simulation nodes: 4\n", - "[I] Number of harmonic simulation nodes: 0\n", - "[I] -- Create empty MNA system matrices and vectors\n", - "[I] -- Initialize components from power flow\n", - "[I] -- Initialize MNA properties of components\n", - "[I] -- Initialize MNA system matrices and source vector\n", - "[I] --- Initialization finished ---\n", - "[I] --- Initial system matrices and vectors ---\n", - "[I] System matrix: \n", - " 1 -1 0 -1 0 0 0 -0\n", - " -1 1.00005 -4.99877e-05 0 0 7.85204e-07 -7.85204e-07 0\n", - " 0 -4.99877e-05 0.00104999 0 0 -7.85204e-07 7.85204e-07 0\n", - " -1 0 0 0 -0 0 0 0\n", - " 0 0 0 0 1 -1 0 -1\n", - " 0 -7.85204e-07 7.85204e-07 0 -1 1.00005 -4.99877e-05 0\n", - " 0 7.85204e-07 -7.85204e-07 0 0 -4.99877e-05 0.00104999 0\n", - " 0 0 0 0 -1 0 0 0\n", - "[I] Right side vector: \n", - " 0\n", - " 0\n", - " -0\n", - "10000\n", - " 0\n", - " 0\n", - " -0\n", - " 0\n" - ] - } - ], + "outputs": [], "source": [ "!cat logs/Example1_Solver.log" ] @@ -341,7 +219,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.13" + "version": "3.10.11" } }, "nbformat": 4, From 18b6e657cc77be5815b12482bb00b03bfd78c751 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Thu, 30 Nov 2023 10:48:08 +0000 Subject: [PATCH 28/39] Refactoring co-simulation example's filenames and locations Signed-off-by: pipeacosta --- .../cxx/Attributes/CosimExampleAttributes.cpp | 495 ------------------ .../CosimExampleAttributesReference.cpp | 99 ---- dpsim/examples/cxx/CMakeLists.txt | 6 - ..._SimExample_ResistiveCompanion_Task2.ipynb | 376 ------------- .../dpsim-villas-weakly-coupled-cosim.ipynb | 227 -------- examples/villas/dpsim-villas-cosim-base.py | 49 -- examples/villas/dpsim-villas-cosim.py | 172 ------ ...villas-weakly-coupled-cosim-ext-control.py | 199 ------- ...y-coupled-cosim.py => emt-cosim-villas.py} | 73 +-- 9 files changed, 42 insertions(+), 1654 deletions(-) delete mode 100644 dpsim/examples/cxx/Attributes/CosimExampleAttributes.cpp delete mode 100644 dpsim/examples/cxx/Attributes/CosimExampleAttributesReference.cpp delete mode 100644 examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb delete mode 100644 examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb delete mode 100644 examples/villas/dpsim-villas-cosim-base.py delete mode 100644 examples/villas/dpsim-villas-cosim.py delete mode 100644 examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py rename examples/villas/{dpsim-villas-weakly-coupled-cosim.py => emt-cosim-villas.py} (65%) diff --git a/dpsim/examples/cxx/Attributes/CosimExampleAttributes.cpp b/dpsim/examples/cxx/Attributes/CosimExampleAttributes.cpp deleted file mode 100644 index 3f1aaaeeec..0000000000 --- a/dpsim/examples/cxx/Attributes/CosimExampleAttributes.cpp +++ /dev/null @@ -1,495 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -#include -#include - -#include - -using namespace DPsim; -using namespace CPS; -using namespace std; - -Simulation setDPsim1(float ts, float tf, float u10) { - float r1_r = 0.1; - float c1_c = 1; - float rLine_r = 0.1; - - // ----- POWERFLOW FOR INITIALIZATION ----- - // String simNamePF = "Cosim_example1"; - // Logger::setLogDir("logs/"+simNamePF); - - // auto n1PF = SP::SimNode::make("n1"); - // auto n2PF = SP::SimNode::make("n2"); - - // auto evsPF = SP::Ph1::VoltageSource::make("v_intf"); - // evsPF->setParameters(u10); - - // auto r1PF = SP::Ph1::Resistor::make("r_1"); - // r1PF->setParameters(r1_r); - // auto c1PF = SP::Ph1::Capacitor::make("c_1"); - // c1PF->setParameters(c1_c); - // auto rLinePF = SP::Ph1::Resistor::make("r_line"); - // rLinePF->setParameters(rLine_r); - - // r1PF->connect({ n1PF, SP::SimNode::GND }); - // rLinePF->connect({ n1PF, n2PF }); - // c1PF->connect({ n1PF, SP::SimNode::GND }); - // evsPF->connect({ SP::SimNode::GND, n2PF }); - // auto systemPF = SystemTopology(50, - // SystemNodeList{n1PF, n2PF}, - // SystemComponentList{c1PF, r1PF, rLinePF, evsPF}); - - // auto loggerPF = DataLogger::make(simNamePF); - // loggerPF->logAttribute("1_v_1", n1PF->mVoltage); - // loggerPF->logAttribute("2_v_2", n2PF->mVoltage); - - // Simulation simPF(simNamePF, Logger::Level::debug); - // simPF.setSystem(systemPF); - // simPF.setTimeStep(0.1); - // simPF.setFinalTime(0.1); - // simPF.setDomain(Domain::SP); - // simPF.setSolverType(Solver::Type::NRP); - // simPF.doInitFromNodesAndTerminals(false); - // simPF.addLogger(loggerPF); - // simPF.run(); - - - // ----- DYNAMIC SIMULATION ----- - String simName = "Cosim_example1"; - CPS::Logger::setLogDir("logs/"+simName); - - // Nodes - auto n1 = EMT::SimNode::make("n1"); - auto n2 = EMT::SimNode::make("n2"); - - // Components - auto evs = EMT::Ph1::VoltageSource::make("v_in_1"); - evs->setParameters(u10); - - auto r1 = EMT::Ph1::Resistor::make("r_1"); - r1->setParameters(r1_r); - auto c1 = EMT::Ph1::Capacitor::make("c_1"); - c1->setParameters(c1_c); - auto rLine = EMT::Ph1::Resistor::make("r_line"); - rLine->setParameters(rLine_r); - - // Topology - r1->connect({ n1, EMT::SimNode::GND }); - rLine->connect({ n1, n2 }); - c1->connect({ n1, EMT::SimNode::GND }); - evs->connect({ n2, EMT::SimNode::GND }); - - auto sys = SystemTopology(50, - SystemNodeList{EMT::SimNode::GND, n1, n2}, - SystemComponentList{r1, c1, rLine, evs}); - - auto logger = DataLogger::make(simName); - logger->logAttribute("1_v_1", n1->mVoltage); - logger->logAttribute("2_v_2", n2->mVoltage); - logger->logAttribute("3_i_rline", rLine->mIntfCurrent, 1, 1); - logger->logAttribute("4_i_evs", evs->mIntfCurrent, 1, 1); - logger->logAttribute("5_v_evs", evs->mIntfVoltage, 1, 1); - - Simulation sim(simName); - sim.setDomain(Domain::EMT); - sim.addLogger(logger); - sim.setSystem(sys); - sim.setTimeStep(ts); - sim.setFinalTime(tf); - // sim.doSteadyStateInit(true); - sim.doInitFromNodesAndTerminals(false); - - // initialize currents and voltages - // Eigen::VectorXd n_v0(2); - // n_v0 << 5, 5; - - // Initial conditions, given by the problem - Eigen::MatrixXd n1_v0(1,1); - n1_v0(0,0) = 5.0; - Eigen::MatrixXd n2_v0(1,1); - n2_v0(0,0) = u10; - - Eigen::MatrixXd ir1_0(1,1); - // ir1_0(0,0) = n1_v0(0,0) / r1_r; - ir1_0(0,0) = 50; - Eigen::MatrixXd irLine_0(1,1); - // irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; - irLine_0(0,0) = 30; - - r1->setIntfVoltage(n1_v0); - r1->setIntfCurrent(ir1_0); - c1->setIntfVoltage(n1_v0); - c1->setIntfCurrent(ir1_0 - irLine_0); - rLine->setIntfVoltage(n1_v0 - n2_v0); - rLine->setIntfCurrent(irLine_0); - // cout << "rLine voltage: " << rLine->mIntfVoltage->toString() << endl; - // cout << "r1 current: " << r1->mIntfCurrent->toString() << endl; - // cout << "c1 current: " << c1->mIntfCurrent->toString() << endl; - - evs->setIntfVoltage(n2_v0); - evs->setIntfCurrent(irLine_0); - cout << "evs current: " << evs->mIntfCurrent->toString() << endl; - - // Eigen::MatrixXd r1_i(1,1); - // r1_i(0,0) = n1_v0(0,0) / r1_r; - // r1->setIntfCurrent(r1_i); - // c1->setIntfCurrent(Eigen::MatrixXd(20)); - // rLine->setIntfVoltage(Eigen::MatrixXd(3)); - // rLine->setIntfCurrent(Eigen::MatrixXd(30)); - - // Eigen::MatrixXcd intfCurrent0(1,1); - // intfCurrent0(0,0) = std::complex(5.0,0.0); - // evs->setIntfCurrent(intfCurrent0); - - return sim; -} - -Simulation setDPsim2(float ts, float tf, float u20) { - float r3_r = 1; - float c2_c = 1; - - // ----- POWERFLOW FOR INITIALIZATION ----- - // String simNamePF = "Cosim_example1"; - // Logger::setLogDir("logs/"+simNamePF); - - // auto n1PF = SP::SimNode::make("n1"); - // auto n2PF = SP::SimNode::make("n2"); - - // auto evsPF = SP::Ph1::VoltageSource::make("v_intf"); - // evsPF->setParameters(u10); - - // auto r1PF = SP::Ph1::Resistor::make("r_1"); - // r1PF->setParameters(r1_r); - // auto c1PF = SP::Ph1::Capacitor::make("c_1"); - // c1PF->setParameters(c1_c); - // auto rLinePF = SP::Ph1::Resistor::make("r_line"); - // rLinePF->setParameters(rLine_r); - - // r1PF->connect({ n1PF, SP::SimNode::GND }); - // rLinePF->connect({ n1PF, n2PF }); - // c1PF->connect({ n1PF, SP::SimNode::GND }); - // evsPF->connect({ SP::SimNode::GND, n2PF }); - // auto systemPF = SystemTopology(50, - // SystemNodeList{n1PF, n2PF}, - // SystemComponentList{c1PF, r1PF, rLinePF, evsPF}); - - // auto loggerPF = DataLogger::make(simNamePF); - // loggerPF->logAttribute("1_v_1", n1PF->mVoltage); - // loggerPF->logAttribute("2_v_2", n2PF->mVoltage); - - // Simulation simPF(simNamePF, Logger::Level::debug); - // simPF.setSystem(systemPF); - // simPF.setTimeStep(0.1); - // simPF.setFinalTime(0.1); - // simPF.setDomain(Domain::SP); - // simPF.setSolverType(Solver::Type::NRP); - // simPF.doInitFromNodesAndTerminals(false); - // simPF.addLogger(loggerPF); - // simPF.run(); - - - // ----- DYNAMIC SIMULATION ----- - String simName = "Cosim_example2"; - CPS::Logger::setLogDir("logs/"+simName); - - // Nodes - auto n2 = EMT::SimNode::make("n2"); - - // Components - auto is = EMT::Ph1::CurrentSource::make("i_in_2"); - is->setParameters(u20); - - auto r3 = EMT::Ph1::Resistor::make("r_3"); - r3->setParameters(r3_r); - auto c2 = EMT::Ph1::Capacitor::make("c_2"); - c2->setParameters(c2_c); - - // Topology - r3->connect({ n2, EMT::SimNode::GND }); - c2->connect({ n2, EMT::SimNode::GND }); - is->connect({ EMT::SimNode::GND, n2 }); - - auto sys = SystemTopology(50, - SystemNodeList{EMT::SimNode::GND, n2}, - SystemComponentList{r3, c2, is}); - - auto logger = DataLogger::make(simName); - logger->logAttribute("2_v_2", n2->mVoltage); - logger->logAttribute("4_i_evs", is->mIntfCurrent, 1, 1); - logger->logAttribute("5_v_evs", is->mIntfVoltage, 1, 1); - - Simulation sim(simName); - sim.setDomain(Domain::EMT); - sim.addLogger(logger); - sim.setSystem(sys); - sim.setTimeStep(ts); - sim.setFinalTime(tf); - // sim.doSteadyStateInit(true); - sim.doInitFromNodesAndTerminals(false); - - // initialize currents and voltages - // Eigen::VectorXd n_v0(2); - // n_v0 << 5, 5; - - // Initial conditions, given by the problem - Eigen::MatrixXd n2_v0(1,1); - n2_v0(0,0) = 2.0; - Eigen::MatrixXd i_rLine0(1,1); - i_rLine0(0,0) = u20; - - Eigen::MatrixXd ir3_0(1,1); - ir3_0(0,0) = n2_v0(0,0) / r3_r; - - r3->setIntfVoltage(n2_v0); - r3->setIntfCurrent(ir3_0); - c2->setIntfVoltage(n2_v0); - c2->setIntfCurrent(i_rLine0 - ir3_0); - // cout << "rLine voltage: " << rLine->mIntfVoltage->toString() << endl; - // cout << "r1 current: " << r1->mIntfCurrent->toString() << endl; - // cout << "c1 current: " << c1->mIntfCurrent->toString() << endl; - - is->setIntfVoltage(n2_v0); - is->setIntfCurrent(i_rLine0); - cout << "is current: " << is->mIntfCurrent->toString() << endl; - - // Eigen::MatrixXd r1_i(1,1); - // r1_i(0,0) = n1_v0(0,0) / r1_r; - // r1->setIntfCurrent(r1_i); - // c1->setIntfCurrent(Eigen::MatrixXd(20)); - // rLine->setIntfVoltage(Eigen::MatrixXd(3)); - // rLine->setIntfCurrent(Eigen::MatrixXd(30)); - - // Eigen::MatrixXcd intfCurrent0(1,1); - // intfCurrent0(0,0) = std::complex(5.0,0.0); - // evs->setIntfCurrent(intfCurrent0); - - return sim; -} - -int main(int argc, char* argv[]) { - - float timeStep = 0.01; - float finalTime = 1.0; - - // ** Initialization ** - // Communication y20 -> S_1 and initialization of S_1 - // float y20 = 2.0; - - // Set up subsytem 1 - Simulation sim1 = setDPsim1(timeStep, finalTime, 2.0); - sim1.start(); - - AttributeBase::Ptr y10_base = sim1.getIdObjAttribute("v_in_1", "i_intf"); - - // try { - auto y10_matrix = std::dynamic_pointer_cast>(y10_base.getPtr()); - Attribute::Ptr y10 = y10_matrix->deriveCoeff(0,0); - cout << "Output value from S1: " << y10->toString() << endl; - cout << "Output value from S1: " << **y10 << endl; - - // } catch(...) { - // throw InvalidAttributeException(); - // } - - // "Communication" y10 -> S_2 and initialization of S_2 - AttributeBase::Ptr u20_base = y10->cloneValueOntoNewAttribute(); - auto u20Attr = std::dynamic_pointer_cast>(u20_base.getPtr()); - // std::shared_ptr u20_base_ptr = u20_base.getPtr(); - // cout << "Input value to S2: " << *u20_base_ptr << endl; - cout << "Input value to S2: " << u20Attr->toString() << endl; - - float u20 = u20Attr->get(); - - Simulation sim2 = setDPsim2(timeStep, finalTime, u20); - sim2.start(); - - // Verify initialization - AttributeBase::Ptr u20_base_test = sim2.getIdObjAttribute("i_in_2", "i_intf"); - cout << "Current value in S2: " << u20_base_test->toString() << endl; - - AttributeBase::Ptr y20_base = sim2.getIdObjAttribute("i_in_2", "v_intf"); - // auto y20_matrix = std::dynamic_pointer_cast>(y20_base.getPtr()); - // Attribute::Ptr y20 = y20_matrix->deriveCoeff(0,0); - // cout << "Output value from S2: " << y20->toString() << endl; - cout << "Output value from S2: " << y20_base->toString() << endl; - - // Main loop - float t = 0.0; - - while (t < finalTime) { - t = sim1.next(); - - cout << "t = " << t << endl; - - AttributeBase::Ptr y1_base = sim1.getIdObjAttribute("v_in_1", "i_intf"); - auto y1_matrix = std::dynamic_pointer_cast>(y1_base.getPtr()); - Attribute::Ptr y1 = y1_matrix->deriveCoeff(0,0); - cout << "Output value from S1: " << **y1 << endl; - // cout << "Output value from S1: " << y1->toString() << endl; - // cout << "Output value from S1: " << y1_base->toString() << endl; - - // "Communication" y10 -> S_2 and initialization of S_2 - // AttributeBase::Ptr u2_base = y1->cloneValueOntoNewAttribute(); - // auto u2Attr = std::dynamic_pointer_cast>(u2_base.getPtr()); - // cout << "Input value to S2: " << u2Attr->toString() << endl; - - // Get corresponding attribute in S_2 - AttributeBase::Ptr u2_base = sim2.getIdObjAttribute("i_in_2", "i_intf"); - auto u2_matrix = std::dynamic_pointer_cast>(u2_base.getPtr()); - Attribute::Ptr u2 = u2_matrix->deriveCoeff(0,0); - cout << "Current value in S2: " << **u2 << endl; - // cout << "Current value in S2: " << u2->toString() << endl; - // cout << "Current value in S2: " << u2_base->toString() << endl; - - // Put value - // *u2_base = *y1_base; - // *u2_base.getPtr() = *y1_base.getPtr(); - - // This way doesn't work - // **u2 = 27.2727; - // Real u2_test = **u2; - - // this way does work - u2->set(**y1); - Real u2_test2 = **u2; - - // Verify - // u2_matrix = std::dynamic_pointer_cast>(u2_base.getPtr()); - // u2 = u2_matrix->deriveCoeff(0,0); - // cout << "Input value to S2: " << u2_test << endl; - cout << "Input value to S2 (option 2): " << u2_test2 << endl; - - AttributeBase::Ptr u2_base_test = sim2.getIdObjAttribute("i_in_2", "i_intf"); - // auto u2_matrix_test = std::dynamic_pointer_cast>(u2_base_test.getPtr()); - // Attribute::Ptr u2_test = u2_matrix_test->deriveCoeff(0,0); - // cout << "Current value in S2: " << u2_test->toString() << endl; - cout << "Current value in S2: " << u2_base_test->toString() << endl; - - sim2.next(); - - AttributeBase::Ptr y2_base = sim2.getIdObjAttribute("i_in_2", "v_intf"); - auto y2_matrix = std::dynamic_pointer_cast>(y2_base.getPtr()); - Attribute::Ptr y2 = y2_matrix->deriveCoeff(0,0); - cout << "Output value from S2: " << **y2 << endl; - // cout << "Output value from S2: " << y2->toString() << endl; - // cout << "Output value from S2: " << y2_base->toString() << endl; - - // Get corresponding attribute in S_1 - AttributeBase::Ptr u1_base = sim1.getIdObjAttribute("v_in_1", "v_intf"); - auto u1_matrix = std::dynamic_pointer_cast>(u1_base.getPtr()); - Attribute::Ptr u1 = u1_matrix->deriveCoeff(0,0); - cout << "Current value in S1: " << u1->toString() << endl; - - // Put value - // *u1_base = *y2_base; - - u1->set(**y2); - Real u1_test2 = **u1; - - // Verify - // u1_matrix = std::dynamic_pointer_cast>(u1_base.getPtr()); - // u1 = u1_matrix->deriveCoeff(0,0); - // cout << "Input value to S1: " << u1->toString() << endl; - cout << "Input value to S1 (option 2): " << u1_test2 << endl; - - AttributeBase::Ptr u1_base_test = sim1.getIdObjAttribute("v_in_1", "v_intf"); - // auto u2_matrix_test = std::dynamic_pointer_cast>(u2_base_test.getPtr()); - // Attribute::Ptr u2_test = u2_matrix_test->deriveCoeff(0,0); - // cout << "Current value in S2: " << u2_test->toString() << endl; - cout << "Current value in S1: " << u1_base_test->toString() << endl; - - } - - // Get only works for the typed ones - // AttributeBase::Ptr attr = AttributeStatic::make(0.001); - - // Attribute::Ptr attr = AttributeStatic::make(0.001); - // Real read1 = attr->get(); - // cout << read1 << endl; - - // Set up subsystem 2 - // Simulation sim1 = setDPsim1(timeStep, finalTime, y20); - // sim1.start(); - - sim1.stop(); - sim2.stop(); - - // if (String(argv[1]) == "0") { - - - // sim.run(); - // } - // else if (String(argv[1]) == "1") { - // String simName = "SocketsCosim_example2"; - // Logger::setLogDir("logs/"+simName); - - // // Nodes - // auto n2 = SimNode::make("n2"); - - // // Components - // auto ecs = CurrentSource::make("i_intf"); - // ecs->setParameters(Complex(5, 0)); - // auto r02 = Resistor::make("r_02"); - // r02->setParameters(1); - - // // Topology - // ecs->connect({ SimNode::GND, n2 }); - // r02->connect({ SimNode::GND, n2 }); - - // auto sys = SystemTopology(50, - // SystemNodeList{SimNode::GND, n2}, - // SystemComponentList{ecs, r02}); - - // Simulation sim(simName); - // sim.setSystem(sys); - // sim.setTimeStep(timeStep); - // sim.setFinalTime(0.1); - - // // Make sure the format is set to json!! - // std::string socketConfig = R"STRING({ - // "type": "socket", - // "layer": "udp", - // "format": "json", - // "hooks": [ - // {"type": "print"} - // ], - // "in": { - // "address": "127.0.0.1:12009", - // "signals": [ - // { - // "name": "i_intf", - // "type": "complex" - // } - // ] - // }, - // "out": { - // "address": "127.0.0.1:12008", - // "signals": [ - // { - // "name": "v_intf", - // "type": "complex" - // } - // ] - // } - // })STRING"; - - // // Logger. The logger must be added before the interface! - // auto logger = DataLogger::make(simName); - // logger->logAttribute("v2", n2->mVoltage); - // logger->logAttribute("i_intf", r02->mIntfCurrent, 1, 1); - // logger->logAttribute("v_ecs", ecs->mIntfVoltage, 1, 1); - // logger->logAttribute("i_ecs", ecs->mIntfCurrent, 1, 1); - // sim.addLogger(logger); - - // auto intf = std::make_shared(socketConfig); - // intf->importAttribute(ecs->mCurrentRef, 0, false, true); - // intf->exportAttribute(ecs->mIntfVoltage->deriveCoeff(0, 0), 0, true, "v_intf"); - - // // Interface - // sim.addInterface(intf); - - // sim.run(); - // } - - return 0; -} diff --git a/dpsim/examples/cxx/Attributes/CosimExampleAttributesReference.cpp b/dpsim/examples/cxx/Attributes/CosimExampleAttributesReference.cpp deleted file mode 100644 index df68d9e7d6..0000000000 --- a/dpsim/examples/cxx/Attributes/CosimExampleAttributesReference.cpp +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -#include -#include - -#include - -using namespace DPsim; -using namespace CPS; -using namespace std; - -int main(int argc, char* argv[]) { - - float r1_r = 0.1; - float c1_c = 1; - float rLine_r = 0.1; - float r3_r = 1; - float c2_c = 1; - - // ----- DYNAMIC SIMULATION ----- - String simName = "Cosim_example_base"; - CPS::Logger::setLogDir("logs/"+simName); - - // Nodes - auto n1 = EMT::SimNode::make("n1"); - auto n2 = EMT::SimNode::make("n2"); - - // Components - auto r1 = EMT::Ph1::Resistor::make("r_1"); - r1->setParameters(r1_r); - auto c1 = EMT::Ph1::Capacitor::make("c_1"); - c1->setParameters(c1_c); - auto rLine = EMT::Ph1::Resistor::make("r_line"); - rLine->setParameters(rLine_r); - auto r3 = EMT::Ph1::Resistor::make("r_3"); - r3->setParameters(r3_r); - auto c2 = EMT::Ph1::Capacitor::make("c_2"); - c2->setParameters(c2_c); - - // Topology - r1->connect({ n1, EMT::SimNode::GND }); - rLine->connect({ n1, n2 }); - c1->connect({ n1, EMT::SimNode::GND }); - r3->connect({ n2, EMT::SimNode::GND }); - c2->connect({ n2, EMT::SimNode::GND }); - - auto sys = SystemTopology(50, - SystemNodeList{EMT::SimNode::GND, n1, n2}, - SystemComponentList{r1, c1, rLine, c2, r3}); - - auto logger = DataLogger::make(simName); - logger->logAttribute("1_v_1", n1->mVoltage); - logger->logAttribute("2_v_2", n2->mVoltage); - logger->logAttribute("3_i_rline", rLine->mIntfCurrent, 1, 1); - - Simulation sim(simName); - sim.setDomain(CPS::Domain::EMT); - sim.addLogger(logger); - sim.setSystem(sys); - sim.setTimeStep(0.01); - sim.setFinalTime(1.0); - // sim.doSteadyStateInit(true); - sim.doInitFromNodesAndTerminals(false); - - // initialize currents and voltages - // Eigen::VectorXd n_v0(2); - // n_v0 << 5, 5; - - // Initial conditions, given by the problem - Eigen::MatrixXd n1_v0(1,1); - n1_v0(0,0) = 5.0; - Eigen::MatrixXd n2_v0(1,1); - n2_v0(0,0) = 2.0; - - Eigen::MatrixXd ir1_0(1,1); - ir1_0(0,0) = -n1_v0(0,0) / r1_r; - Eigen::MatrixXd irLine_0(1,1); - irLine_0(0,0) = (n1_v0(0,0) - n2_v0(0,0)) / rLine_r; - - Eigen::MatrixXd ir3_0(1,1); - ir3_0(0,0) = n2_v0(0,0) / r3_r; - - Eigen::MatrixXd ic1_0 = ir1_0 - irLine_0; - Eigen::MatrixXd vrLine_0 = n1_v0 - n2_v0; - Eigen::MatrixXd ic2_0 = irLine_0 - ir3_0; - - r1->setIntfVoltage(n1_v0); - r1->setIntfCurrent(ir1_0); - c1->setIntfVoltage(n1_v0); - c1->setIntfCurrent(ic1_0); - rLine->setIntfVoltage(vrLine_0); - rLine->setIntfCurrent(irLine_0); - r3->setIntfVoltage(n2_v0); - r3->setIntfCurrent(ir3_0); - c2->setIntfVoltage(n2_v0); - c2->setIntfCurrent(ic2_0); - - sim.run(); -} diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index 841a3061de..d10d856309 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -111,12 +111,6 @@ set(INVERTER_SOURCES Components/DP_Inverter_Grid_Sequential_FreqSplit.cpp ) -set(ATTRIBUTES_SOURCES - Attributes/Attributes.cpp - Attributes/CosimExampleAttributes.cpp - Attributes/CosimExampleAttributesReference.cpp -) - # Targets required for tests in the Jupyter Notebooks. This list is only for grouping the (already configured) targets, so every entry # also has to appear in another list in this file. list(APPEND TEST_SOURCES diff --git a/examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb b/examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb deleted file mode 100644 index 0a561cd658..0000000000 --- a/examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb +++ /dev/null @@ -1,376 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# MSP Simulation Example - Resistive Companion - Exercise 3 - Task 2" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Sample circuit" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "$R_1$ $=1 \\Omega$
\n", - "$R_2$ $=1 \\Omega$
\n", - "$C$ $=1mF$
\n", - "$L$ $=1mH$
\n", - "$I$ $=10A$
\n", - "$v_C(0)$=0
\n", - "$i_L(0)=0 $
" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Circuit and Simulation Setup" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import numpy as np\n", - "import ipywidgets as widget\n", - "import matplotlib.pyplot as plt\n", - "np.set_printoptions(sign=' ')\n", - "\n", - "# Circuit parameters\n", - "R1 = 1\n", - "R2 = 1\n", - "C1 = 1e-3\n", - "L1 = 1e-3\n", - "I_src= 10\n", - "G1 = 1/R1\n", - "G2 = 1/R2" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## DC equivalent of Inductor" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Equation of the inductor:\n", - "\n", - "$v_L(t) =L\\cdot\\frac{di_L}{dt}$\n", - "\n", - "### Integration: \n", - "\n", - "$i_L(t+\\Delta{t}) =i_L(t) + \\frac{1}{L} \\int_{t}^{t+\\Delta{t}} \\ v_L(\\tau) d\\tau$\n", - "\n", - "### Discretization: \n", - "\n", - "$i_L(k+1)= i_L(k) + \\frac{1}{L} \\int_{t_k}^{t_k+\\Delta{t}} \\ v_L(\\tau) d\\tau$\n", - "\n", - "### Application of trapezoidal rule: \n", - "\n", - "$i_L(k)= i_L(k) + \\frac{1}{L} \\frac{v_L(k)+v_L(k+1)}{2} \\Delta{t} $\n", - "\n", - "$i_L(k+1)=\\frac{\\Delta{t}}{2L} v_L(k+1) + (i_L(k) + \\frac{\\Delta{t}}{2L} v_L(k)) $\n", - "\n", - "The inductor in the calculation step (k + 1) can be substituted with an inductance $G_L = \\frac{\\Delta{t}}{2L}$ in parallel with a current source $A_L(k) = i_L(k) + \\frac{\\Delta{t}}{2L} v_L(k) $ " - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Initialize circuit" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "module 'dpsimpy.sp.ph1' has no attribute 'CurrentSource'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "\u001b[1;32m/dpsim/examples/Notebooks/Circuits/Exercise_SimExample_ResistiveCompanion_Task2.ipynb Cell 11\u001b[0m in \u001b[0;36m1\n\u001b[1;32m 15\u001b[0m r2_pf \u001b[39m=\u001b[39m dpsimpy\u001b[39m.\u001b[39msp\u001b[39m.\u001b[39mph1\u001b[39m.\u001b[39mResistor(\u001b[39m'\u001b[39m\u001b[39mr2_pf\u001b[39m\u001b[39m'\u001b[39m, dpsimpy\u001b[39m.\u001b[39mLogLevel\u001b[39m.\u001b[39mdebug)\n\u001b[1;32m 16\u001b[0m r2_pf\u001b[39m.\u001b[39mset_parameters(\u001b[39m1\u001b[39m)\n\u001b[0;32m---> 18\u001b[0m cs_pf \u001b[39m=\u001b[39m dpsimpy\u001b[39m.\u001b[39;49msp\u001b[39m.\u001b[39;49mph1\u001b[39m.\u001b[39;49mCurrentSource(\u001b[39m'\u001b[39m\u001b[39mcs_pf\u001b[39m\u001b[39m'\u001b[39m, dpsimpy\u001b[39m.\u001b[39mLogLevel\u001b[39m.\u001b[39mdebug)\n\u001b[1;32m 19\u001b[0m cs_pf\u001b[39m.\u001b[39mI_ref \u001b[39m=\u001b[39m \u001b[39mcomplex\u001b[39m(\u001b[39m10\u001b[39m,\u001b[39m0\u001b[39m)\n\u001b[1;32m 20\u001b[0m cs_pf\u001b[39m.\u001b[39mf_src \u001b[39m=\u001b[39m \u001b[39m0\u001b[39m\n", - "\u001b[0;31mAttributeError\u001b[0m: module 'dpsimpy.sp.ph1' has no attribute 'CurrentSource'" - ] - } - ], - "source": [ - "# Initialize simulation with DPsim\n", - "import dpsimpy\n", - "\n", - "model_name_pf = 'CS_R1R2C1L1_PF'\n", - "time_step = 1e-3\n", - "final_time = 2e-2\n", - "\n", - "# Nodes\n", - "gnd_pf = dpsimpy.sp.SimNode.gnd\n", - "n1_pf = dpsimpy.sp.SimNode('n1_pf', dpsimpy.PhaseType.Single)\n", - "\n", - "# Components\n", - "r1_pf = dpsimpy.sp.ph1.Resistor('r1_pf', dpsimpy.LogLevel.debug)\n", - "r1_pf.set_parameters(1)\n", - "r2_pf = dpsimpy.sp.ph1.Resistor('r2_pf', dpsimpy.LogLevel.debug)\n", - "r2_pf.set_parameters(1)\n", - "\n", - "cs_pf = dpsimpy.sp.ph1.CurrentSource('cs_pf', dpsimpy.LogLevel.debug)\n", - "cs_pf.I_ref = complex(10,0)\n", - "cs_pf.f_src = 0\n", - "\n", - "cs_pf.connect([gnd_pf, n1_pf])\n", - "r1_pf.connect([n1_pf, gnd_pf])\n", - "r2_pf.connect([n1_pf, gnd_pf])\n", - "\n", - "system_pf = dpsimpy.SystemTopology(50, [gnd_pf, n1_pf], [cs_pf, r1_pf, r2_pf])\n", - "\n", - "logger_pf = dpsimpy.Logger(model_name_pf)\n", - "logger_pf.log_attribute('n1.v', 'v', n1_pf)\n", - "logger_pf.log_attribute('i_r1', 'i_intf', r1_pf)\n", - "logger_pf.log_attribute('i_r2', 'i_intf', r2_pf)\n", - "\n", - "sim_pf = dpsimpy.Simulation(model_name_pf, dpsimpy.LogLevel.debug)\n", - "sim_pf.set_system(system_pf)\n", - "sim_pf.set_domain(dpsimpy.Domain.SP)\n", - "sim_pf.set_solver_component_behaviour(dpsimpy.SolverBehaviour.Initialization)\n", - "sim_pf.set_time_step(time_step)\n", - "sim_pf.set_final_time(final_time)\n", - "sim_pf.add_logger(logger_pf)\n", - "sim_pf.run()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Run Simulation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Simulation parameters\n", - "model_name = 'CS_R1R2C1L1'\n", - "npoint = int(np.round(final_time/time_step))\n", - "\n", - "# Nodes\n", - "gnd = dpsimpy.emt.SimNode.gnd\n", - "n1 = dpsimpy.emt.SimNode('n1')\n", - "n1.set_initial_voltage(complex(5,0), 0)\n", - "n2 = dpsimpy.emt.SimNode('n2')\n", - "n2.set_initial_voltage(complex(5,0), 0)\n", - "\n", - "# Components\n", - "r1 = dpsimpy.emt.ph1.Resistor('r1', dpsimpy.LogLevel.debug)\n", - "r1.R = 1\n", - "r2 = dpsimpy.emt.ph1.Resistor('r2', dpsimpy.LogLevel.debug)\n", - "r2.R = 1\n", - "\n", - "c1 = dpsimpy.emt.ph1.Capacitor('c1', dpsimpy.LogLevel.debug)\n", - "c1.C = 1e-3\n", - "l1 = dpsimpy.emt.ph1.Inductor('l1', dpsimpy.LogLevel.debug)\n", - "l1.L = 1e-3\n", - "cs = dpsimpy.emt.ph1.CurrentSource('cs', dpsimpy.LogLevel.debug)\n", - "cs.I_ref = complex(10,0)\n", - "cs.f_src = 0\n", - "\n", - "cs.connect([gnd, n1])\n", - "r1.connect([n1, gnd])\n", - "c1.connect([n1, n2])\n", - "l1.connect([n2, gnd])\n", - "r2.connect([n2, gnd])\n", - "\n", - "\n", - "system = dpsimpy.SystemTopology(50, [gnd, n1, n2], [cs, r1, r2, c1, l1])\n", - "\n", - "logger = dpsimpy.Logger(model_name)\n", - "logger.log_attribute('n1.v', 'v', n1)\n", - "logger.log_attribute('n2.v', 'v', n2)\n", - "logger.log_attribute('3_i_r1', 'i_intf', r1)\n", - "logger.log_attribute('4_v_c1', 'v_intf', c1)\n", - "logger.log_attribute('5_i_l1', 'i_intf', l1)\n", - "logger.log_attribute('6_i_r2', 'i_intf', r2)\n", - "\n", - "# sim = dpsimpy.Simulation(model_name, system, timestep=time_step, duration=final_time, pbar=True, sim_type=1, log_level=1)\n", - "sim = dpsimpy.Simulation(model_name)\n", - "sim.set_system(system)\n", - "sim.set_domain(dpsimpy.Domain.EMT)\n", - "sim.add_logger(logger)\n", - "sim.set_time_step(time_step)\n", - "sim.set_final_time(final_time)\n", - "sim.do_init_from_nodes_and_terminals(False)\n", - "\n", - "# initialize currents and voltages\n", - "print(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0])\n", - "r1.set_intf_current([[complex(5,0)]])\n", - "r1.set_intf_voltage([[5]])\n", - "r2.set_intf_current([[5]])\n", - "r2.set_intf_voltage([[5]])\n", - "c1.set_intf_current([[5]])\n", - "c1.set_intf_voltage([[0]])\n", - "l1.set_intf_current([[0]])\n", - "l1.set_intf_voltage([[5]])\n", - "\n", - "sim.run()" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Read log" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from villas.dataprocessing.readtools import *\n", - "from villas.dataprocessing.timeseries import *\n", - "import re\n", - "\n", - "work_dir = 'logs/'\n", - "log_path = work_dir + model_name + '.csv'\n", - "# log_lines, log_sections = read_dpsim_log(log_path)\n" - ] - }, - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Read solution log" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "log_path = work_dir + model_name + '.csv'\n", - "ts_dpsim_emt = read_timeseries_dpsim(log_path, print_status=False)\n", - "\n", - "# for key, val in ts_dpsim_emt.items():\n", - " # print(key + ': ' + str(val.values))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## Plot results" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import matplotlib.pyplot as plt\n", - "\n", - "#Extract plot data\n", - "plot_data_1=ts_dpsim_emt[\"n1.v\"]\n", - "y_values_1= np.asarray(plot_data_1.values)\n", - "\n", - "plot_data_2=ts_dpsim_emt[\"n2.v\"]\n", - "y_values_2= np.asarray(plot_data_2.values)\n", - "\n", - "t = np.arange(npoint)*time_step\n", - "\n", - "plt.figure(figsize=(10,8))\n", - "plt.xlabel('Time [s]')\n", - "plt.ylabel('Voltage [V]')\n", - "plt.axis([0, final_time+time_step , -2, 11])\n", - "plt.scatter(t,y_values_1, label='$e_{1}$(t)')\n", - "plt.scatter(t,y_values_2, label='$e_{2}$(t)')\n", - "\n", - "#show corresponding values on the plot\n", - "for i in np.arange(3):\n", - " plt.annotate(' ' + str(np.round(y_values_1[i], 2)), (t[i], y_values_1[i]))\n", - " plt.annotate(' ' + str(np.round(y_values_2[i], 2)), (t[i], y_values_2[i]))\n", - "plt.grid()\n", - "plt.legend(loc='upper right')\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "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" - }, - "orig_nbformat": 4, - "vscode": { - "interpreter": { - "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a" - } - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb b/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb deleted file mode 100644 index c0dd345980..0000000000 --- a/examples/Notebooks/dpsim-villas-weakly-coupled-cosim.ipynb +++ /dev/null @@ -1,227 +0,0 @@ -{ - "cells": [ - { - "attachments": {}, - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Weakly coupled Co-simulation\n", - "================\n", - "\n", - "This guides shows how to implement a simplified weakly-coupled co-simulation in DPsim\n", - "\n", - "Test circuit\n", - "--------------------\n", - "\n", - "As a first simple, test we will simulate a small static network. The network consists of 4 nodes and 4 elements:\n", - "\n", - "| Component | Type | Python Class | Node A | Node B | Paramter |\n", - "| :---------| :---- | :---------------------------------------- | :----- | :----- | :------- |\n", - "| r_1 | Source resistance | `dpsimpy.dp.ph1.Resistor` | 0 | GND | 0.1 Ohm |\n", - "| c_1 | Line capacitance | `dpsimpy.dp.ph1.Capacitor` | 0 | GND | 1 Farad |\n", - "| c_2 | Line capacitance | `dpsimpy.dp.ph1.Capacitor` | 1 | GND | 1 Farad |\n", - "| r_line | Line resistance | `dpsimpy.dp.ph1.Resistor` | 1 | 0 | 0.1 Ohm |\n", - "| r_load | Load | `dpsimpy.dp.ph1.Resistor` | 1 | GND | 1 Ohm |" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Before we can start, we must import the DPsim Python module.\n", - "We also add `dp` as an alias for the dynamic phasor components." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import dpsimpy" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we can define the model by creating a couple of components.\n", - "Each component is identified by a name which is passed as the first argument.\n", - "Following arguments are used to define the topology by assigning the component to a specific node / bus or to pass parameters." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# Nodes\n", - "gnd = dpsimpy.dp.SimNode.gnd\n", - "n0 = dpsimpy.dp.SimNode(\"n0\")\n", - "n1 = dpsimpy.dp.SimNode(\"n1\")\n", - "\n", - "r_1 = dpsimpy.dp.ph1.Resistor(\"r_1\")\n", - "r_1.R = 0.1\n", - "r_line = dpsimpy.dp.ph1.Resistor(\"r_line\")\n", - "r_line.R = 0.1\n", - "c_1 = dpsimpy.dp.ph1.Capacitor(\"c_1\")\n", - "c_1.C = 1\n", - "c_2 = dpsimpy.dp.ph1.Capacitor(\"c_2\")\n", - "c_2.C = 1\n", - "r_load = dpsimpy.dp.ph1.Resistor(\"r_load\")\n", - "r_load.R = 1\n", - "\n", - "# Initial conditions\n", - "n0.set_initial_voltage(5)\n", - "n1.set_initial_voltage(2)\n", - "\n", - "# Connections \n", - "r_1.connect([n0, gnd])\n", - "r_line.connect([n0, n1])\n", - "c_1.connect([n0, gnd])\n", - "c_2.connect([n1, gnd])\n", - "r_load.connect([n1, gnd])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next, we have to create a simulation object:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sys = dpsimpy.SystemTopology(50, [ n0, n1 ], [ r_1, r_line, c_1, c_2, r_load ])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "We can also visualize the system topology:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sys" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, we can start the simulation and wait for its completion:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "sim = dpsimpy.Simulation(\"WeaklyCoupledCosim\", loglevel=dpsimpy.LogLevel.debug)\n", - "sim.set_system(sys)\n", - "sim.set_time_step(1e-3)\n", - "sim.set_final_time(1.0)\n", - "\n", - "log = dpsimpy.Logger(\"WeaklyCoupledCosim\")\n", - "for i in range(0, len(sys.nodes)):\n", - " log.log_attribute(\"v\" + str(i), \"v\", sys.nodes[i])\n", - "\n", - "sim.add_logger(log)\n", - " \n", - "sim.run()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Results can be analyzed and plotted by the `villas.dataprocessing` package:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%matplotlib inline\n", - "%config InlineBackend.figure_format = 'svg'\n", - "%config InlineBackend.rc = {'font.size': 10, 'figure.figsize': (6.0, 4.0), 'figure.facecolor': 'white', 'savefig.dpi': 72, 'figure.subplot.bottom': 0.125, 'figure.edgecolor': 'white'}\n", - "\n", - "import matplotlib.pyplot as plt\n", - "import villas.dataprocessing.plottools as pt\n", - "import villas.dataprocessing.readtools as rt\n", - "import villas.dataprocessing.timeseries as ts\n", - "\n", - "results = rt.read_timeseries_dpsim('logs/WeaklyCoupledCosim.csv')\n", - "\n", - "results_emt = []\n", - "for series in results:\n", - " results_emt.append(results[series].frequency_shift(freq=50))\n", - "\n", - "results_emt = [ results[series].frequency_shift(freq=50) for series in results ]\n", - "\n", - "results_strongly_coupled0 = rt.read_timeseries_dpsim('../../logs/WeaklyCoupledCosim0/WeaklyCoupledCosim0.csv')\n", - "results_strongly_coupled0_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", - "\n", - "for series in results_strongly_coupled0_emt:\n", - " pt.plot_timeseries('Results EMT', series, '--')\n", - "\n", - "plt.grid()\n", - "plt.show()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "!cat logs/Example1_Solver.log" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [] - } - ], - "metadata": { - "interpreter": { - "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a" - }, - "kernelspec": { - "display_name": "Python 3.9.7 64-bit", - "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.10.11" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/villas/dpsim-villas-cosim-base.py b/examples/villas/dpsim-villas-cosim-base.py deleted file mode 100644 index 980eb08fb7..0000000000 --- a/examples/villas/dpsim-villas-cosim-base.py +++ /dev/null @@ -1,49 +0,0 @@ -import sys -import os.path -import logging - -import dpsimpy - -sim_name = "DistributedVILLAS_base" -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]) - -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.set_parameters(1) - -r02 = dpsimpy.dp.ph1.Resistor('r_02', dpsimpy.LogLevel.debug) -r02.set_parameters(1) - -vs1.connect([dpsimpy.dp.SimNode.gnd, n1]) -r12.connect([n1, n2]) -r02.connect([dpsimpy.dp.SimNode.gnd, n2]) - -sys = dpsimpy.SystemTopology(50, [n1, n2], [vs1, r12, r02]) - -sim = dpsimpy.Simulation(sim_name) -sim.set_system(sys) -sim.set_time_step(time_step) -sim.set_final_time(final_time) - -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', 'v_intf', r02) - -sim.add_logger(logger) - -sim.start() - -k_i = sim.next() - -while(k_i <= final_time): - k_i = sim.next() diff --git a/examples/villas/dpsim-villas-cosim.py b/examples/villas/dpsim-villas-cosim.py deleted file mode 100644 index 66b6a4ad1b..0000000000 --- a/examples/villas/dpsim-villas-cosim.py +++ /dev/null @@ -1,172 +0,0 @@ -import sys -import os.path -import logging -import json -import time - -from datetime import datetime -from villas.node.node import Node as VILLASnode - -from multiprocessing import Process - -import dpsimpy -import dpsimpyvillas - -base = os.path.splitext(os.path.basename(sys.argv[0]))[0] -log = logging.getLogger(base) - -def dpsim0(): - sim_name = "DistributedVILLAS0" - time_step = 0.01 - final_time = 1.0 - - 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.set_parameters(complex(5, 0)) - - 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.set_parameters(1) - - evs.connect([dpsimpy.dp.SimNode.gnd, n2]) - vs1.connect([dpsimpy.dp.SimNode.gnd, n1]) - r12.connect([n2, n1]) - - sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, vs1, r12]) - - sim = dpsimpy.Simulation(sim_name) - sim.set_system(sys) - sim.set_time_step(time_step) - sim.set_final_time(final_time) - - intf_config = { - "type": "socket", - "layer": "udp", - "format": "json", - "hooks": [ - {"type": "print"} - ], - "in": { - "address": "127.0.0.1:12008", - "signals": [ - { - "name": "v_intf", - "type": "complex" - } - ] - }, - "out": { - "address": "127.0.0.1:12009", - "signals": [ - { - "name": "i_intf", - "type": "complex" - } - ] - } - } - - dpsimpy.Logger.set_log_dir('logs/' + sim_name) - - logger = dpsimpy.Logger(sim_name) - logger.log_attribute('1_v_1', 'v', n1) - logger.log_attribute('2_v_2', 'v', n2) - logger.log_attribute('3_i_r12', 'i_intf', r12) - logger.log_attribute('4_i_evs', 'i_intf', evs) - logger.log_attribute('5_v_evs', 'v_intf', evs) - - intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-dpsim1", config=intf_config) - - sim.add_interface(intf) - sim.add_logger(logger) - - evs.set_intf_current([[complex(5, 0)]]) - - intf.import_attribute(evs.attr('V_ref'), 0, block_on_read=True, sync_on_start=True) - intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, wait_for_on_write=False) - - sim.run() - -def dpsim1(): - sim_name = "DistributedVILLAS1" - time_step = 0.01 - final_time = 1.0 - - n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [5]) - - 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.set_parameters(1) - - ecs.connect([dpsimpy.dp.SimNode.gnd, n2]) - r02.connect([dpsimpy.dp.SimNode.gnd, n2]) - - sys = dpsimpy.SystemTopology(50, [n2], [ecs, r02]) - - sim = dpsimpy.Simulation(sim_name) - sim.set_system(sys) - sim.set_time_step(time_step) - sim.set_final_time(final_time) - - intf_config = { - "type": "socket", - "layer": "udp", - "format": "json", - "hooks": [ - {"type": "print"} - ], - "in": { - "address": "127.0.0.1:12009", - "signals": [ - { - "name": "i_intf", - "type": "complex" - } - ] - }, - "out": { - "address": "127.0.0.1:12008", - "signals": [ - { - "name": "v_intf", - "type": "complex" - } - ] - } - } - - dpsimpy.Logger.set_log_dir('logs/' + sim_name) - - logger = dpsimpy.Logger(sim_name) - logger.log_attribute('1_v_2', 'v', n2) - logger.log_attribute('2_i_r02', 'i_intf', r02) - logger.log_attribute('3_v_ecs', 'v_intf', ecs) - logger.log_attribute('4_i_ecs', 'i_intf', ecs) - - intf = dpsimpyvillas.InterfaceVillas(name="dpsim1-dpsim0", config=intf_config) - - sim.add_interface(intf) - sim.add_logger(logger) - intf.import_attribute(ecs.attr('I_ref'), 0, block_on_read=True, sync_on_start=True) - intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, wait_for_on_write=False) - - sim.run() - -if __name__ == '__main__': - logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) - - p_sim0 = Process(target=dpsim0) - p_sim1 = Process(target=dpsim1) - - p_sim0.start() - p_sim1.start() - - p_sim0.join() - p_sim1.join() - - print('Both simulations have ended!') diff --git a/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py b/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py deleted file mode 100644 index a623135f8f..0000000000 --- a/examples/villas/dpsim-villas-weakly-coupled-cosim-ext-control.py +++ /dev/null @@ -1,199 +0,0 @@ -import sys -import os.path -import logging - -import dpsimpy -import villas.dataprocessing.timeseries as ts -import numpy as np - -base = os.path.splitext(os.path.basename(sys.argv[0]))[0] -log = logging.getLogger(base) - -def set_dpsim1(t_s, t_f, u_1_0): - r_1_r = 0.1 - c_1_c = 1 - r_line_r = 0.1 - - sim_name = "WeaklyCoupledCosim0" - - gnd = dpsimpy.emt.SimNode.gnd - n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.Single, [5]) - n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.Single, [u_1_0]) - - evs = dpsimpy.emt.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.debug) - evs.set_parameters(u_1_0) - - r_1 = dpsimpy.emt.ph1.Resistor("r_1") - r_1.set_parameters(r_1_r) - c_1 = dpsimpy.emt.ph1.Capacitor("c_1") - c_1.set_parameters(c_1_c) - r_line = dpsimpy.emt.ph1.Resistor('r_line', dpsimpy.LogLevel.debug) - r_line.set_parameters(r_line_r) - - r_1.connect([n1, gnd]) - r_line.connect([n1, n2]) - c_1.connect([n1, gnd]) - evs.connect([gnd, n2]) - - sys = dpsimpy.SystemTopology(50, [gnd, n1, n2], [evs, r_1, c_1, r_line]) - - sim = dpsimpy.Simulation(sim_name) - sim.set_domain(dpsimpy.Domain.EMT) - sim.set_system(sys) - sim.set_time_step(t_s) - sim.set_final_time(t_f) - # sim.do_steady_state_init(True) - - dpsimpy.Logger.set_log_dir('logs/' + sim_name) - - logger = dpsimpy.Logger(sim_name) - logger.log_attribute('1_v_1', 'v', n1) - logger.log_attribute('2_v_2', 'v', n2) - logger.log_attribute('3_i_rline', 'i_intf', r_line) - logger.log_attribute('4_i_evs', 'i_intf', evs) - logger.log_attribute('5_v_evs', 'v_intf', evs) - - sim.add_logger(logger) - - # Initialize currents and voltages - # r = np.array([[1/r_1_r, 0.0], [0.0, 1/r_line_r]]) - # n_v_0 = np.array([5.0, 5.0 - u_1_0]).T - - # i_0 = np.matmul(r, n_v_0) - - - n1_v0 = np.array([5.0]) - n2_v0 = np.array([u_1_0]) - - ir_1_0 = n1_v0 / r_1_r - i_r_line_0 = (n1_v0 - n2_v0) / r_line_r - - # r_1.set_intf_voltage([n_v_0[0]]) - # r_1.set_intf_current([i_0[0]]) - # c_1.set_intf_voltage([n_v_0[0]]) - # c_1.set_intf_current([i_0[0] - i_0[1]]) - # r_line.set_intf_voltage([n_v_0[1]]) - # r_line.set_intf_current([i_0[1]]) - - # evs.set_intf_voltage([n_v_0[0] - n_v_0[1]]) - # evs.set_intf_current([i_0[1]]) - - r_1.set_intf_voltage(n1_v0) - r_1.set_intf_current(ir_1_0) - c_1.set_intf_voltage(n1_v0) - c_1.set_intf_current(ir_1_0 - i_r_line_0) - r_line.set_intf_voltage(n1_v0 - n2_v0) - r_line.set_intf_current(i_r_line_0) - - evs.set_intf_voltage(n2_v0) - evs.set_intf_current(i_r_line_0) - - return sim - - -def set_dpsim2(t_s, t_f, u_2_0): - r_load_r = 1.0 - c_2_c = 1.0 - - sim_name = "WeaklyCoupledCosim1" - - gnd = dpsimpy.emt.SimNode.gnd - n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.Single, [2]) - - ecs = dpsimpy.emt.ph1.CurrentSource('i_intf', dpsimpy.LogLevel.debug) - ecs.set_parameters(u_2_0) - c_2 = dpsimpy.emt.ph1.Capacitor("c_2") - c_2.set_parameters(c_2_c) - r_load = dpsimpy.emt.ph1.Resistor('r_load', dpsimpy.LogLevel.debug) - r_load.set_parameters(r_load_r) - - ecs.connect([gnd, n2]) - c_2.connect([gnd, n2]) - r_load.connect([gnd, n2]) - - sys = dpsimpy.SystemTopology(50, [gnd, n2], [ecs, c_2, r_load]) - - sim = dpsimpy.Simulation(sim_name) - sim.set_domain(dpsimpy.Domain.EMT) - sim.set_system(sys) - sim.set_time_step(t_s) - sim.set_final_time(t_f) - - dpsimpy.Logger.set_log_dir('logs/' + sim_name) - - logger = dpsimpy.Logger(sim_name) - logger.log_attribute('1_v_2', 'v', n2) - logger.log_attribute('2_i_rload', 'i_intf', r_load) - logger.log_attribute('3_v_ecs', 'v_intf', ecs) - logger.log_attribute('4_i_ecs', 'i_intf', ecs) - - sim.add_logger(logger) - - # Initialize currents and voltages - n2_v0 = [2.0] - i_r_line_0 = [u_2_0] - i_r_load_0 = [n2_v0[0] / r_load_r] - - r_load.set_intf_voltage(n2_v0) - r_load.set_intf_current(i_r_load_0) - c_2.set_intf_voltage([n2_v0]) - c_2.set_intf_current([i_r_line_0[0] - i_r_load_0[0]]) - - ecs.set_intf_voltage(n2_v0) - ecs.set_intf_current(i_r_line_0) - - return sim - -if __name__ == '__main__': - logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) - - time_step = 0.01 - final_time = 1.0 - t_k = 0.0 - - # Communication y_2_0 -> S_1 and initialization of S_1 - y_2_0 = 2.0 - sim1 = set_dpsim1(time_step, final_time, y_2_0) - sim1.start() - y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() - print("Output value from S1: {:f}".format(y_1_0)) - - # Communication y_1_0 -> S_2 and initialization of S_2 - sim2 = set_dpsim2(time_step, final_time, y_1_0) - sim2.start() - y_2_0 = sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() - print("Output value from S2: {:f}".format(y_2_0)) - - - - - - - - - - - k1_i = sim1.next() - y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() - print("Output value from S1: {:f}".format(y_1_0)) - # y_1_0_ts = ts.TimeSeries("v2", t_k, y_1_0_dp) - # y_1_0_emt = y_1_0_ts.frequency_shift(freq=50) - - # Switch to S_2 and get initial output - # y_2_0_dp = sim2.get_idobj_attr("n2", "v").derive_coeff(0,0).get() - # y_2_0_ts = ts.TimeSeries("v2", t_k, y_2_0_dp) - # y_2_0 = y_2_0_ts.frequency_shift(freq=50) - - # Communication y_1_0 -> S_2 - # u_1_0 = y_2_0 - # sim1. - - # Switch to S_2 - # y_1_0 = sim2.get_idobj_attr("n2", "v").derive_coeff(0,0).get() - - # k1_i = sim1.next() - # k2_i = sim2.next() - - # while(k1_i <= final_time and k2_i <= final_time): - # k1_i = sim1.next() - # k2_i = sim2.next() diff --git a/examples/villas/dpsim-villas-weakly-coupled-cosim.py b/examples/villas/emt-cosim-villas.py similarity index 65% rename from examples/villas/dpsim-villas-weakly-coupled-cosim.py rename to examples/villas/emt-cosim-villas.py index a299b9a332..4446497292 100644 --- a/examples/villas/dpsim-villas-weakly-coupled-cosim.py +++ b/examples/villas/emt-cosim-villas.py @@ -16,32 +16,38 @@ log = logging.getLogger(base) def dpsim0(): - sim_name = "WeaklyCoupledCosim0" + sim_name = "EMTCosimVILLAS1" time_step = 1e-3 final_time = 1.0 - gnd = dpsimpy.dp.SimNode.gnd - n1 = dpsimpy.dp.SimNode('n1', dpsimpy.PhaseType.Single, [5]) - n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [2]) + gnd = dpsimpy.emt.SimNode.gnd + n1 = dpsimpy.emt.SimNode("n1") + n2 = dpsimpy.emt.SimNode("n2") - evs = dpsimpy.dp.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.debug) - evs.set_parameters(complex(2, 0)) + evs = dpsimpy.emt.ph1.VoltageSource('v_intf') + evs.set_parameters(2) - r_1 = dpsimpy.dp.ph1.Resistor("r_1") + r_1 = dpsimpy.emt.ph1.Resistor("r_1") r_1.set_parameters(0.1) - c_1 = dpsimpy.dp.ph1.Capacitor("c_1") + c_1 = dpsimpy.emt.ph1.Capacitor("c_1") c_1.set_parameters(1) - r_line = dpsimpy.dp.ph1.Resistor('r_line', dpsimpy.LogLevel.debug) + r_line = dpsimpy.emt.ph1.Resistor('r_line') r_line.set_parameters(0.1) + + # Initial conditions + n1.set_initial_voltage(5) + n2.set_initial_voltage(2) + # Connections r_1.connect([n1, gnd]) r_line.connect([n1, n2]) c_1.connect([n1, gnd]) evs.connect([gnd, n2]) - sys = dpsimpy.SystemTopology(50, [n1, n2], [evs, r_1, c_1, r_line]) + sys = dpsimpy.SystemTopology(50, [gnd, n1, n2], [evs, r_1, c_1, r_line]) - sim = dpsimpy.Simulation(sim_name) + sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim.set_domain(dpsimpy.Domain.EMT) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) @@ -76,18 +82,18 @@ def dpsim0(): dpsimpy.Logger.set_log_dir('logs/' + sim_name) logger = dpsimpy.Logger(sim_name) - logger.log_attribute('1_v_1', 'v', n1) - logger.log_attribute('2_v_2', 'v', n2) - logger.log_attribute('3_i_rline', 'i_intf', r_line) - logger.log_attribute('4_i_evs', 'i_intf', evs) - logger.log_attribute('5_v_evs', 'v_intf', evs) + logger.log_attribute('v1', 'v', n1) + logger.log_attribute('v2', 'v', n2) + # logger.log_attribute('i_rline', 'i_intf', r_line) + # logger.log_attribute('i_evs', 'i_intf', evs) + # logger.log_attribute('v_evs', 'v_intf', evs) intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-dpsim1", config=intf_config) sim.add_interface(intf) sim.add_logger(logger) - evs.set_intf_current([[complex(3, 0)]]) + evs.set_intf_current([[30]]) intf.import_attribute(evs.attr('V_ref'), 0, block_on_read=False, sync_on_start=False) intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, wait_for_on_write=True) @@ -95,27 +101,32 @@ def dpsim0(): sim.run() def dpsim1(): - sim_name = "WeaklyCoupledCosim1" + sim_name = "EMTCosimVILLAS2" time_step = 1e-3 final_time = 1.0 - gnd = dpsimpy.dp.SimNode.gnd - n2 = dpsimpy.dp.SimNode('n2', dpsimpy.PhaseType.Single, [2]) + gnd = dpsimpy.emt.SimNode.gnd + n2 = dpsimpy.emt.SimNode("n2") - ecs = dpsimpy.dp.ph1.CurrentSource('i_intf', dpsimpy.LogLevel.debug) - ecs.set_parameters(complex(3, 0)) - c_2 = dpsimpy.dp.ph1.Capacitor("c_2") + ecs = dpsimpy.emt.ph1.CurrentSource("i_intf") + ecs.set_parameters(3) + c_2 = dpsimpy.emt.ph1.Capacitor("c_2") c_2.set_parameters(1) - r_load = dpsimpy.dp.ph1.Resistor('r_load', dpsimpy.LogLevel.debug) + r_load = dpsimpy.emt.ph1.Resistor('r_load') r_load.set_parameters(1) + + # Initial conditions + n2.set_initial_voltage(2) + # Connections ecs.connect([gnd, n2]) c_2.connect([gnd, n2]) r_load.connect([gnd, n2]) - sys = dpsimpy.SystemTopology(50, [n2], [ecs, c_2, r_load]) + sys = dpsimpy.SystemTopology(50, [gnd, n2], [ecs, c_2, r_load]) - sim = dpsimpy.Simulation(sim_name) + sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim.set_domain(dpsimpy.Domain.EMT) sim.set_system(sys) sim.set_time_step(time_step) sim.set_final_time(final_time) @@ -150,17 +161,17 @@ def dpsim1(): dpsimpy.Logger.set_log_dir('logs/' + sim_name) logger = dpsimpy.Logger(sim_name) - logger.log_attribute('1_v_2', 'v', n2) - logger.log_attribute('2_i_rload', 'i_intf', r_load) - logger.log_attribute('3_v_ecs', 'v_intf', ecs) - logger.log_attribute('4_i_ecs', 'i_intf', ecs) + logger.log_attribute('v2', 'v', n2) + # logger.log_attribute('2_i_rload', 'i_intf', r_load) + # logger.log_attribute('3_v_ecs', 'v_intf', ecs) + # logger.log_attribute('4_i_ecs', 'i_intf', ecs) intf = dpsimpyvillas.InterfaceVillas(name="dpsim1-dpsim0", config=intf_config) sim.add_interface(intf) sim.add_logger(logger) intf.import_attribute(ecs.attr('I_ref'), 0, block_on_read=False, sync_on_start=False) - intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_scaled(complex(-1,0)), 0, wait_for_on_write=True) + intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0), 0, wait_for_on_write=True) sim.run() From 413c4064b5d25a2bd07a038374c1f0bc268f2473 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Thu, 30 Nov 2023 10:50:03 +0000 Subject: [PATCH 29/39] First working version of co-simulation using attributes Signed-off-by: pipeacosta Co-authored-by: martinmoraga --- examples/Notebooks/cosim-villas-socket.ipynb | 1981 +++++++++++++++++ .../Python/Attributes/emt-cosim-attributes.py | 206 ++ 2 files changed, 2187 insertions(+) create mode 100644 examples/Notebooks/cosim-villas-socket.ipynb create mode 100644 examples/Python/Attributes/emt-cosim-attributes.py diff --git a/examples/Notebooks/cosim-villas-socket.ipynb b/examples/Notebooks/cosim-villas-socket.ipynb new file mode 100644 index 0000000000..e6bcdc221d --- /dev/null +++ b/examples/Notebooks/cosim-villas-socket.ipynb @@ -0,0 +1,1981 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Weakly coupled Co-simulation\n", + "================\n", + "\n", + "This guides shows how to implement a simplified weakly-coupled co-simulation in emtsim\n", + "\n", + "Test circuit\n", + "--------------------\n", + "\n", + "As a first simple, test we will simulate a small static network. The network consists of 4 nodes and 4 elements:\n", + "\n", + "| Component | Type | Python Class | Node A | Node B | Paramter |\n", + "| :---------| :---- | :---------------------------------------- | :----- | :----- | :------- |\n", + "| r_1 | Source resistance | `dpsimpy.emt.ph1.Resistor` | 0 | GND | 0.1 Ohm |\n", + "| c_1 | Line capacitance | `dpsimpy.emt.ph1.Capacitor` | 0 | GND | 1 Farad |\n", + "| c_2 | Line capacitance | `dpsimpy.emt.ph1.Capacitor` | 1 | GND | 1 Farad |\n", + "| r_line | Line resistance | `dpsimpy.emt.ph1.Resistor` | 1 | 0 | 0.1 Ohm |\n", + "| r_load | Load | `dpsimpy.emt.ph1.Resistor` | 1 | GND | 1 Ohm |" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before we can start, we must import the DPsim Python module.\n", + "We also add `emt` as an alias for the dynamic phasor components." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import dpsimpy" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we can define the model by creating a couple of components.\n", + "Each component is identified by a name which is passed as the first argument.\n", + "Following arguments are used to define the topology by assigning the component to a specific node / bus or to pass parameters." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# Nodes\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode(\"n1\")\n", + "n2 = dpsimpy.emt.SimNode(\"n2\")\n", + "\n", + "r_1 = dpsimpy.emt.ph1.Resistor(\"r_1\")\n", + "r_1.R = 0.1\n", + "r_line = dpsimpy.emt.ph1.Resistor(\"r_line\")\n", + "r_line.R = 0.1\n", + "c_1 = dpsimpy.emt.ph1.Capacitor(\"c_1\")\n", + "c_1.C = 1\n", + "c_2 = dpsimpy.emt.ph1.Capacitor(\"c_2\")\n", + "c_2.C = 1\n", + "r_load = dpsimpy.emt.ph1.Resistor(\"r_load\")\n", + "r_load.R = 1\n", + "\n", + "# Initial conditions\n", + "n1.set_initial_voltage(5)\n", + "n2.set_initial_voltage(2)\n", + "\n", + "# Connections \n", + "r_1.connect([n1, gnd])\n", + "r_line.connect([n1, n2])\n", + "c_1.connect([n1, gnd])\n", + "c_2.connect([n2, gnd])\n", + "r_load.connect([n2, gnd])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we have to create a simulation object:" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "sys = dpsimpy.SystemTopology(50, [ gnd, n1, n2 ], [ r_1, r_line, c_1, c_2, r_load ])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also visualize the system topology:" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Warning: some nodes with margin (3.20,3.20) touch - falling back to straight line edges\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "topology\n", + "\n", + "\n", + "\n", + "gnd\n", + "\n", + "\n", + "\n", + "\n", + "gnd\n", + "\n", + "\n", + "\n", + "n1\n", + "\n", + "\n", + "\n", + "\n", + "n1\n", + "(5.00 V > 0.00°)\n", + "\n", + "\n", + "\n", + "n2\n", + "\n", + "\n", + "\n", + "\n", + "n2\n", + "(2.00 V > 0.00°)\n", + "\n", + "\n", + "\n", + "r_1\n", + "\n", + "\n", + "r_1\n", + "EMT::Ph1::Resistor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "r_1--gnd\n", + "\n", + "\n", + "\n", + "\n", + "r_1--n1\n", + "\n", + "\n", + "\n", + "\n", + "r_line\n", + "\n", + "\n", + "r_line\n", + "EMT::Ph1::Resistor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "r_line--n1\n", + "\n", + "\n", + "\n", + "\n", + "r_line--n2\n", + "\n", + "\n", + "\n", + "\n", + "c_1\n", + "\n", + "\n", + "c_1\n", + "EMT::Ph1::Capacitor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "c_1--gnd\n", + "\n", + "\n", + "\n", + "\n", + "c_1--n1\n", + "\n", + "\n", + "\n", + "\n", + "c_2\n", + "\n", + "\n", + "c_2\n", + "EMT::Ph1::Capacitor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "c_2--gnd\n", + "\n", + "\n", + "\n", + "\n", + "c_2--n2\n", + "\n", + "\n", + "\n", + "\n", + "r_load\n", + "\n", + "\n", + "r_load\n", + "EMT::Ph1::Resistor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "r_load--gnd\n", + "\n", + "\n", + "\n", + "\n", + "r_load--n2\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "sys" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Finally, we can start the simulation and wait for its completion:" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[09:55:34.084247 EMTCosim info] Initialize simulation: EMTCosim\n", + "[09:55:34.084457 MnaSolverFactory info] creating KLUAdapter solver implementation\n", + "[09:55:34.085258 EMTCosim info] Scheduling tasks.\n", + "[09:55:34.085642 EMTCosim info] Scheduling done.\n", + "[09:55:34.085645 EMTCosim info] Opening interfaces.\n", + "[09:55:34.085647 EMTCosim info] Start synchronization with remotes on interfaces\n", + "[09:55:34.085650 EMTCosim info] Synchronized simulation start with remotes\n", + "[09:55:34.085653 EMTCosim info] Start simulation: EMTCosim\n", + "[09:55:34.085659 EMTCosim info] Time step: 1.000000e-02\n", + "[09:55:34.085663 EMTCosim info] Final time: 1.000000e+00\n", + "[09:55:34.086935 EMTCosim info] Simulation calculation time: 0.001261\n", + "[09:55:34.087048 EMTCosim info] Simulation finished.\n" + ] + } + ], + "source": [ + "sim = dpsimpy.Simulation(\"EMTCosim\", loglevel=dpsimpy.LogLevel.debug)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.set_system(sys)\n", + "sim.set_time_step(0.01)\n", + "sim.set_final_time(1.0)\n", + "\n", + "log = dpsimpy.Logger(\"EMTCosim\")\n", + "for i in range(1, len(sys.nodes)):\n", + " log.log_attribute(\"v\" + str(i), \"v\", sys.nodes[i])\n", + "\n", + "sim.add_logger(log)\n", + " \n", + "sim.run()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, we run the co-simulation" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[09:55:34.281079 EMTCosimAttributes2 info] Initialize simulation: EMTCosimAttributes2\n", + "[09:55:34.281387 MnaSolverFactory info] creating KLUAdapter solver implementation\n", + "[09:55:34.282505 EMTCosimAttributes2 info] Scheduling tasks.\n", + "[09:55:34.283001 EMTCosimAttributes2 info] Scheduling done.\n", + "[09:55:34.283011 EMTCosimAttributes2 info] Opening interfaces.\n", + "[09:55:34.283013 EMTCosimAttributes2 info] Start synchronization with remotes on interfaces\n", + "[09:55:34.283016 EMTCosimAttributes2 info] Synchronized simulation start with remotes\n", + "[09:55:34.283019 EMTCosimAttributes2 info] Start simulation: EMTCosimAttributes2\n", + "[09:55:34.283027 EMTCosimAttributes2 info] Time step: 1.000000e-02\n", + "[09:55:34.283031 EMTCosimAttributes2 info] Final time: 1.000000e+00\n", + "[09:55:34.285915 EMTCosimAttributes1 info] Initialize simulation: EMTCosimAttributes1\n", + "[09:55:34.286177 MnaSolverFactory info] creating KLUAdapter solver implementation\n", + "[09:55:34.287332 EMTCosimAttributes1 info] Scheduling tasks.\n", + "[09:55:34.287846 EMTCosimAttributes1 info] Scheduling done.\n", + "[09:55:34.287859 EMTCosimAttributes1 info] Opening interfaces.\n", + "[09:55:34.287862 EMTCosimAttributes1 info] Start synchronization with remotes on interfaces\n", + "[09:55:34.287864 EMTCosimAttributes1 info] Synchronized simulation start with remotes\n", + "[09:55:34.287868 EMTCosimAttributes1 info] Start simulation: EMTCosimAttributes1\n", + "[09:55:34.287875 EMTCosimAttributes1 info] Time step: 1.000000e-02\n", + "[09:55:34.287878 EMTCosimAttributes1 info] Final time: 1.000000e+00\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Output value from S2: 2.000000\n", + "Output value from S1: 30.000000\n", + "Input value in S2 before set: 0.000000\n", + "Input value in S2 after set: 30.000000+0.000000j\n", + "Output value from S2: 2.139303\n", + "Output value from S1: 25.033921\n", + "Time t=0.010000\n", + "Input value in S2 before set: 30.000000\n", + "Input value in S2 after set: 25.033921+0.000000j\n", + "Output value from S2: 2.391817\n", + "Output value from S1: 16.127117\n", + "Time t=0.020000\n", + "Input value in S2 before set: 25.033921\n", + "Input value in S2 after set: 16.127117+0.000000j\n", + "Output value from S2: 2.572800\n", + "Output value from S1: 9.292978\n", + "Time t=0.030000\n", + "Input value in S2 before set: 16.127117\n", + "Input value in S2 after set: 9.292978+0.000000j\n", + "Output value from S2: 2.673668\n", + "Output value from S1: 4.301605\n", + "Time t=0.040000\n", + "Input value in S2 before set: 9.292978\n", + "Input value in S2 after set: 4.301605+0.000000j\n", + "Output value from S2: 2.714699\n", + "Output value from S1: 0.697227\n", + "Time t=0.050000\n", + "Input value in S2 before set: 4.301605\n", + "Input value in S2 after set: 0.697227+0.000000j\n", + "Output value from S2: 2.712557\n", + "Output value from S1: -1.877002\n", + "Time t=0.060000\n", + "Input value in S2 before set: 0.697227\n", + "Input value in S2 after set: -1.877002+0.000000j\n", + "Output value from S2: 2.679697\n", + "Output value from S1: -3.688024\n", + "Time t=0.070000\n", + "Input value in S2 before set: -1.877002\n", + "Input value in S2 after set: -3.688024+0.000000j\n", + "Output value from S2: 2.625346\n", + "Output value from S1: -4.934764\n", + "Time t=0.080000\n", + "Input value in S2 before set: -3.688024\n", + "Input value in S2 after set: -4.934764+0.000000j\n", + "Output value from S2: 2.556324\n", + "Output value from S1: -5.765363\n", + "Time t=0.090000\n", + "Input value in S2 before set: -4.934764\n", + "Input value in S2 after set: -5.765363+0.000000j\n", + "Output value from S2: 2.477653\n", + "Output value from S1: -6.290100\n", + "Time t=0.100000\n", + "Input value in S2 before set: -5.765363\n", + "Input value in S2 after set: -6.290100+0.000000j\n", + "Output value from S2: 2.393023\n", + "Output value from S1: -6.591019\n", + "Time t=0.110000\n", + "Input value in S2 before set: -6.290100\n", + "Input value in S2 after set: -6.591019+0.000000j\n", + "Output value from S2: 2.305126\n", + "Output value from S1: -6.729117\n", + "Time t=0.120000\n", + "Input value in S2 before set: -6.591019\n", + "Input value in S2 after set: -6.729117+0.000000j\n", + "Output value from S2: 2.215920\n", + "Output value from S1: -6.749699\n", + "Time t=0.130000\n", + "Input value in S2 before set: -6.729117\n", + "Input value in S2 after set: -6.749699+0.000000j\n", + "Output value from S2: 2.126813\n", + "Output value from S1: -6.686381\n", + "Time t=0.140000\n", + "Input value in S2 before set: -6.749699\n", + "Input value in S2 after set: -6.686381+0.000000j\n", + "Output value from S2: 2.038804\n", + "Output value from S1: -6.564060\n", + "Time t=0.150000\n", + "Input value in S2 before set: -6.686381\n", + "Input value in S2 after set: -6.564060+0.000000j\n", + "Output value from S2: 1.952595\n", + "Output value from S1: -6.401147\n", + "Time t=0.160000\n", + "Input value in S2 before set: -6.564060\n", + "Input value in S2 after set: -6.401147+0.000000j\n", + "Output value from S2: 1.868663\n", + "Output value from S1: -6.211216\n", + "Time t=0.170000\n", + "Input value in S2 before set: -6.401147\n", + "Input value in S2 after set: -6.211216+0.000000j\n", + "Output value from S2: 1.787321\n", + "Output value from S1: -6.004245\n", + "Time t=0.180000\n", + "Input value in S2 before set: -6.211216\n", + "Input value in S2 after set: -6.004245+0.000000j\n", + "Output value from S2: 1.708763\n", + "Output value from S1: -5.787532\n", + "Time t=0.190000\n", + "Input value in S2 before set: -6.004245\n", + "Input value in S2 after set: -5.787532+0.000000j\n", + "Output value from S2: 1.633095\n", + "Output value from S1: -5.566387\n", + "Time t=0.200000\n", + "Input value in S2 before set: -5.787532\n", + "Input value in S2 after set: -5.566387+0.000000j\n", + "Output value from S2: 1.560358\n", + "Output value from S1: -5.344642\n", + "Time t=0.210000\n", + "Input value in S2 before set: -5.566387\n", + "Input value in S2 after set: -5.344642+0.000000j\n", + "Output value from S2: 1.490549\n", + "Output value from S1: -5.125032\n", + "Time t=0.220000\n", + "Input value in S2 before set: -5.344642\n", + "Input value in S2 after set: -5.125032+0.000000j\n", + "Output value from S2: 1.423629\n", + "Output value from S1: -4.909477\n", + "Time t=0.230000\n", + "Input value in S2 before set: -5.125032\n", + "Input value in S2 after set: -4.909477+0.000000j\n", + "Output value from S2: 1.359541\n", + "Output value from S1: -4.699300\n", + "Time t=0.240000\n", + "Input value in S2 before set: -4.909477\n", + "Input value in S2 after set: -4.699300+0.000000j\n", + "Output value from S2: 1.298208\n", + "Output value from S1: -4.495380\n", + "Time t=0.250000\n", + "Input value in S2 before set: -4.699300\n", + "Input value in S2 after set: -4.495380+0.000000j\n", + "Output value from S2: 1.239546\n", + "Output value from S1: -4.298271\n", + "Time t=0.260000\n", + "Input value in S2 before set: -4.495380\n", + "Input value in S2 after set: -4.298271+0.000000j\n", + "Output value from S2: 1.183463\n", + "Output value from S1: -4.108286\n", + "Time t=0.270000\n", + "Input value in S2 before set: -4.298271\n", + "Input value in S2 after set: -4.108286+0.000000j\n", + "Output value from S2: 1.129863\n", + "Output value from S1: -3.925570\n", + "Time t=0.280000\n", + "Input value in S2 before set: -4.108286\n", + "Input value in S2 after set: -3.925570+0.000000j\n", + "Output value from S2: 1.078651\n", + "Output value from S1: -3.750138\n", + "Time t=0.290000\n", + "Input value in S2 before set: -3.925570\n", + "Input value in S2 after set: -3.750138+0.000000j\n", + "Output value from S2: 1.029731\n", + "Output value from S1: -3.581919\n", + "Time t=0.300000\n", + "Input value in S2 before set: -3.750138\n", + "Input value in S2 after set: -3.581919+0.000000j\n", + "Output value from S2: 0.983007\n", + "Output value from S1: -3.420778\n", + "Time t=0.310000\n", + "Input value in S2 before set: -3.581919\n", + "Input value in S2 after set: -3.420778+0.000000j\n", + "Output value from S2: 0.938387\n", + "Output value from S1: -3.266539\n", + "Time t=0.320000\n", + "Input value in S2 before set: -3.420778\n", + "Input value in S2 after set: -3.266539+0.000000j\n", + "Output value from S2: 0.895779\n", + "Output value from S1: -3.118994\n", + "Time t=0.330000\n", + "Input value in S2 before set: -3.266539\n", + "Input value in S2 after set: -3.118994+0.000000j\n", + "Output value from S2: 0.855097\n", + "Output value from S1: -2.977921\n", + "Time t=0.340000\n", + "Input value in S2 before set: -3.118994\n", + "Input value in S2 after set: -2.977921+0.000000j\n", + "Output value from S2: 0.816256\n", + "Output value from S1: -2.843083\n", + "Time t=0.350000\n", + "Input value in S2 before set: -2.977921\n", + "Input value in S2 after set: -2.843083+0.000000j\n", + "Output value from S2: 0.779174\n", + "Output value from S1: -2.714244\n", + "Time t=0.360000\n", + "Input value in S2 before set: -2.843083\n", + "Input value in S2 after set: -2.714244+0.000000j\n", + "Output value from S2: 0.743772\n", + "Output value from S1: -2.591162\n", + "Time t=0.370000\n", + "Input value in S2 before set: -2.714244\n", + "Input value in S2 after set: -2.591162+0.000000j\n", + "Output value from S2: 0.709976\n", + "Output value from S1: -2.473602\n", + "Time t=0.380000\n", + "Input value in S2 before set: -2.591162\n", + "Input value in S2 after set: -2.473602+0.000000j\n", + "Output value from S2: 0.677714\n", + "Output value from S1: -2.361332\n", + "Time t=0.390000\n", + "Input value in S2 before set: -2.473602\n", + "Input value in S2 after set: -2.361332+0.000000j\n", + "Output value from S2: 0.646916\n", + "Output value from S1: -2.254123\n", + "Time t=0.400000\n", + "Input value in S2 before set: -2.361332\n", + "Input value in S2 after set: -2.254123+0.000000j\n", + "Output value from S2: 0.617517\n", + "Output value from S1: -2.151757\n", + "Time t=0.410000\n", + "Input value in S2 before set: -2.254123\n", + "Input value in S2 after set: -2.151757+0.000000j\n", + "Output value from S2: 0.589453\n", + "Output value from S1: -2.054022\n", + "Time t=0.420000\n", + "Input value in S2 before set: -2.151757\n", + "Input value in S2 after set: -2.054022+0.000000j\n", + "Output value from S2: 0.562663\n", + "Output value from S1: -1.960712\n", + "Time t=0.430000\n", + "Input value in S2 before set: -2.054022\n", + "Input value in S2 after set: -1.960712+0.000000j\n", + "Output value from S2: 0.537091\n", + "Output value from S1: -1.871630\n", + "Time t=0.440000\n", + "Input value in S2 before set: -1.960712\n", + "Input value in S2 after set: -1.871630+0.000000j\n", + "Output value from S2: 0.512680\n", + "Output value from S1: -1.786588\n", + "Time t=0.450000\n", + "Input value in S2 before set: -1.871630\n", + "Input value in S2 after set: -1.786588+0.000000j\n", + "Output value from S2: 0.489379\n", + "Output value from S1: -1.705405\n", + "Time t=0.460000\n", + "Input value in S2 before set: -1.786588\n", + "Input value in S2 after set: -1.705405+0.000000j\n", + "Output value from S2: 0.467136\n", + "Output value from S1: -1.627906\n", + "Time t=0.470000\n", + "Input value in S2 before set: -1.705405\n", + "Input value in S2 after set: -1.627906+0.000000j\n", + "Output value from S2: 0.445905\n", + "Output value from S1: -1.553925\n", + "Time t=0.480000\n", + "Input value in S2 before set: -1.627906\n", + "Input value in S2 after set: -1.553925+0.000000j\n", + "Output value from S2: 0.425638\n", + "Output value from S1: -1.483305\n", + "Time t=0.490000\n", + "Input value in S2 before set: -1.553925\n", + "Input value in S2 after set: -1.483305+0.000000j\n", + "Output value from S2: 0.406292\n", + "Output value from S1: -1.415892\n", + "Time t=0.500000\n", + "Input value in S2 before set: -1.483305\n", + "Input value in S2 after set: -1.415892+0.000000j\n", + "Output value from S2: 0.387825\n", + "Output value from S1: -1.351542\n", + "Time t=0.510000\n", + "Input value in S2 before set: -1.415892\n", + "Input value in S2 after set: -1.351542+0.000000j\n", + "Output value from S2: 0.370198\n", + "Output value from S1: -1.290115\n", + "Time t=0.520000\n", + "Input value in S2 before set: -1.351542\n", + "Input value in S2 after set: -1.290115+0.000000j\n", + "Output value from S2: 0.353372\n", + "Output value from S1: -1.231479\n", + "Time t=0.530000\n", + "Input value in S2 before set: -1.290115\n", + "Input value in S2 after set: -1.231479+0.000000j\n", + "Output value from S2: 0.337311\n", + "Output value from S1: -1.175508\n", + "Time t=0.540000\n", + "Input value in S2 before set: -1.231479\n", + "Input value in S2 after set: -1.175508+0.000000j\n", + "Output value from S2: 0.321979\n", + "Output value from S1: -1.122080\n", + "Time t=0.550000\n", + "Input value in S2 before set: -1.175508\n", + "Input value in S2 after set: -1.122080+0.000000j\n", + "Output value from S2: 0.307345\n", + "Output value from S1: -1.071080\n", + "Time t=0.560000\n", + "Input value in S2 before set: -1.122080\n", + "Input value in S2 after set: -1.071080+0.000000j\n", + "Output value from S2: 0.293375\n", + "Output value from S1: -1.022398\n", + "Time t=0.570000\n", + "Input value in S2 before set: -1.071080\n", + "Input value in S2 after set: -1.022398+0.000000j\n", + "Output value from S2: 0.280041\n", + "Output value from S1: -0.975929\n", + "Time t=0.580000\n", + "Input value in S2 before set: -1.022398\n", + "Input value in S2 after set: -0.975929+0.000000j\n", + "Output value from S2: 0.267312\n", + "Output value from S1: -0.931571\n", + "Time t=0.590000\n", + "Input value in S2 before set: -0.975929\n", + "Input value in S2 after set: -0.931571+0.000000j\n", + "Output value from S2: 0.255162\n", + "Output value from S1: -0.889230\n", + "Time t=0.600000\n", + "Input value in S2 before set: -0.931571\n", + "Input value in S2 after set: -0.889230+0.000000j\n", + "Output value from S2: 0.243565\n", + "Output value from S1: -0.848813\n", + "Time t=0.610000\n", + "Input value in S2 before set: -0.889230\n", + "Input value in S2 after set: -0.848813+0.000000j\n", + "Output value from S2: 0.232494\n", + "Output value from S1: -0.810233\n", + "Time t=0.620000\n", + "Input value in S2 before set: -0.848813\n", + "Input value in S2 after set: -0.810233+0.000000j\n", + "Output value from S2: 0.221927\n", + "Output value from S1: -0.773406\n", + "Time t=0.630000\n", + "Input value in S2 before set: -0.810233\n", + "Input value in S2 after set: -0.773406+0.000000j\n", + "Output value from S2: 0.211840\n", + "Output value from S1: -0.738253\n", + "Time t=0.640000\n", + "Input value in S2 before set: -0.773406\n", + "Input value in S2 after set: -0.738253+0.000000j\n", + "Output value from S2: 0.202211\n", + "Output value from S1: -0.704698\n", + "Time t=0.650000\n", + "Input value in S2 before set: -0.738253\n", + "Input value in S2 after set: -0.704698+0.000000j\n", + "Output value from S2: 0.193020\n", + "Output value from S1: -0.672668\n", + "Time t=0.660000\n", + "Input value in S2 before set: -0.704698\n", + "Input value in S2 after set: -0.672668+0.000000j\n", + "Output value from S2: 0.184247\n", + "Output value from S1: -0.642094\n", + "Time t=0.670000\n", + "Input value in S2 before set: -0.672668\n", + "Input value in S2 after set: -0.642094+0.000000j\n", + "Output value from S2: 0.175873\n", + "Output value from S1: -0.612910\n", + "Time t=0.680000\n", + "Input value in S2 before set: -0.642094\n", + "Input value in S2 after set: -0.612910+0.000000j\n", + "Output value from S2: 0.167879\n", + "Output value from S1: -0.585052\n", + "Time t=0.690000\n", + "Input value in S2 before set: -0.612910\n", + "Input value in S2 after set: -0.585052+0.000000j\n", + "Output value from S2: 0.160249\n", + "Output value from S1: -0.558460\n", + "Time t=0.700000\n", + "Input value in S2 before set: -0.585052\n", + "Input value in S2 after set: -0.558460+0.000000j\n", + "Output value from S2: 0.152965\n", + "Output value from S1: -0.533077\n", + "Time t=0.710000\n", + "Input value in S2 before set: -0.558460\n", + "Input value in S2 after set: -0.533077+0.000000j\n", + "Output value from S2: 0.146012\n", + "Output value from S1: -0.508847\n", + "Time t=0.720000\n", + "Input value in S2 before set: -0.533077\n", + "Input value in S2 after set: -0.508847+0.000000j\n", + "Output value from S2: 0.139376\n", + "Output value from S1: -0.485719\n", + "Time t=0.730000\n", + "Input value in S2 before set: -0.508847\n", + "Input value in S2 after set: -0.485719+0.000000j\n", + "Output value from S2: 0.133041\n", + "Output value from S1: -0.463642\n", + "Time t=0.740000\n", + "Input value in S2 before set: -0.485719\n", + "Input value in S2 after set: -0.463642+0.000000j\n", + "Output value from S2: 0.126994\n", + "Output value from S1: -0.442569\n", + "Time t=0.750000\n", + "Input value in S2 before set: -0.463642\n", + "Input value in S2 after set: -0.442569+0.000000j\n", + "Output value from S2: 0.121222\n", + "Output value from S1: -0.422453\n", + "Time t=0.760000\n", + "Input value in S2 before set: -0.442569\n", + "Input value in S2 after set: -0.422453+0.000000j\n", + "Output value from S2: 0.115712\n", + "Output value from S1: -0.403252\n", + "Time t=0.770000\n", + "Input value in S2 before set: -0.422453\n", + "Input value in S2 after set: -0.403252+0.000000j\n", + "Output value from S2: 0.110453\n", + "Output value from S1: -0.384923\n", + "Time t=0.780000\n", + "Input value in S2 before set: -0.403252\n", + "Input value in S2 after set: -0.384923+0.000000j\n", + "Output value from S2: 0.105432\n", + "Output value from S1: -0.367428\n", + "Time t=0.790000\n", + "Input value in S2 before set: -0.384923\n", + "Input value in S2 after set: -0.367428+0.000000j\n", + "Output value from S2: 0.100640\n", + "Output value from S1: -0.350727\n", + "Time t=0.800000\n", + "Input value in S2 before set: -0.367428\n", + "Input value in S2 after set: -0.350727+0.000000j\n", + "Output value from S2: 0.096066\n", + "Output value from S1: -0.334786\n", + "Time t=0.810000\n", + "Input value in S2 before set: -0.350727\n", + "Input value in S2 after set: -0.334786+0.000000j\n", + "Output value from S2: 0.091700\n", + "Output value from S1: -0.319569\n", + "Time t=0.820000\n", + "Input value in S2 before set: -0.334786\n", + "Input value in S2 after set: -0.319569+0.000000j\n", + "Output value from S2: 0.087532\n", + "Output value from S1: -0.305044\n", + "Time t=0.830000\n", + "Input value in S2 before set: -0.319569\n", + "Input value in S2 after set: -0.305044+0.000000j\n", + "Output value from S2: 0.083553\n", + "Output value from S1: -0.291179\n", + "Time t=0.840000\n", + "Input value in S2 before set: -0.305044\n", + "Input value in S2 after set: -0.291179+0.000000j\n", + "Output value from S2: 0.079756\n", + "Output value from S1: -0.277945\n", + "Time t=0.850000\n", + "Input value in S2 before set: -0.291179\n", + "Input value in S2 after set: -0.277945+0.000000j\n", + "Output value from S2: 0.076130\n", + "Output value from S1: -0.265312\n", + "Time t=0.860000\n", + "Input value in S2 before set: -0.277945\n", + "Input value in S2 after set: -0.265312+0.000000j\n", + "Output value from S2: 0.072670\n", + "Output value from S1: -0.253253\n", + "Time t=0.870000\n", + "Input value in S2 before set: -0.265312\n", + "Input value in S2 after set: -0.253253+0.000000j\n", + "Output value from S2: 0.069367\n", + "Output value from S1: -0.241742\n", + "Time t=0.880000\n", + "Input value in S2 before set: -0.253253\n", + "Input value in S2 after set: -0.241742+0.000000j\n", + "Output value from S2: 0.066214\n", + "Output value from S1: -0.230754\n", + "Time t=0.890000\n", + "Input value in S2 before set: -0.241742\n", + "Input value in S2 after set: -0.230754+0.000000j\n", + "Output value from S2: 0.063205\n", + "Output value from S1: -0.220266\n", + "Time t=0.900000\n", + "Input value in S2 before set: -0.230754\n", + "Input value in S2 after set: -0.220266+0.000000j\n", + "Output value from S2: 0.060332\n", + "Output value from S1: -0.210254\n", + "Time t=0.910000\n", + "Input value in S2 before set: -0.220266\n", + "Input value in S2 after set: -0.210254+0.000000j\n", + "Output value from S2: 0.057590\n", + "Output value from S1: -0.200698\n", + "Time t=0.920000\n", + "Input value in S2 before set: -0.210254\n", + "Input value in S2 after set: -0.200698+0.000000j\n", + "Output value from S2: 0.054972\n", + "Output value from S1: -0.191576\n", + "Time t=0.930000\n", + "Input value in S2 before set: -0.200698\n", + "Input value in S2 after set: -0.191576+0.000000j\n", + "Output value from S2: 0.052474\n", + "Output value from S1: -0.182868\n", + "Time t=0.940000\n", + "Input value in S2 before set: -0.191576\n", + "Input value in S2 after set: -0.182868+0.000000j\n", + "Output value from S2: 0.050089\n", + "Output value from S1: -0.174556\n", + "Time t=0.950000\n", + "Input value in S2 before set: -0.182868\n", + "Input value in S2 after set: -0.174556+0.000000j\n", + "Output value from S2: 0.047812\n", + "Output value from S1: -0.166623\n", + "Time t=0.960000\n", + "Input value in S2 before set: -0.174556\n", + "Input value in S2 after set: -0.166623+0.000000j\n", + "Output value from S2: 0.045639\n", + "Output value from S1: -0.159049\n", + "Time t=0.970000\n", + "Input value in S2 before set: -0.166623\n", + "Input value in S2 after set: -0.159049+0.000000j\n", + "Output value from S2: 0.043564\n", + "Output value from S1: -0.151820\n", + "Time t=0.980000\n", + "Input value in S2 before set: -0.159049\n", + "Input value in S2 after set: -0.151820+0.000000j\n", + "Output value from S2: 0.041584\n", + "Output value from S1: -0.144920\n", + "Time t=0.990000\n", + "Input value in S2 before set: -0.151820\n", + "Input value in S2 after set: -0.144920+0.000000j\n", + "Output value from S2: 0.039694\n", + "Output value from S1: -0.138333\n", + "Time t=1.000000\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[09:55:34.343457 EMTCosimAttributes2 info] Simulation calculation time: 0.060391\n", + "[09:55:34.343757 EMTCosimAttributes2 info] Simulation finished.\n", + "[09:55:34.343937 EMTCosimAttributes1 info] Simulation calculation time: 0.056048\n", + "[09:55:34.344116 EMTCosimAttributes1 info] Simulation finished.\n" + ] + } + ], + "source": [ + "import subprocess\n", + "\n", + "subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes.py\"])\n", + "process = subprocess.Popen([\"python3\", \"../villas/emt-cosim-villas.py\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Results can be analyzed and plotted by the `villas.dataprocessing` package:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "column number: 2\n", + "results length: 100\n", + "real column names: ['v1', 'v2']\n", + "complex column names: []\n", + "column number: 4\n", + "results length: 100\n", + "real column names: ['i', 'ir', 'v1', 'v2']\n", + "complex column names: []\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2023-11-30T09:55:35.140979\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.8.0, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "%config InlineBackend.figure_format = 'svg'\n", + "%config InlineBackend.rc = {'font.size': 10, 'figure.figsize': (6.0, 4.0), 'figure.facecolor': 'white', 'savefig.dpi': 72, 'figure.subplot.bottom': 0.125, 'figure.edgecolor': 'white'}\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import villas.dataprocessing.plottools as pt\n", + "import villas.dataprocessing.readtools as rt\n", + "import villas.dataprocessing.timeseries as ts\n", + "\n", + "results = rt.read_timeseries_dpsim('logs/EMTCosim.csv')\n", + "\n", + "results_emt = []\n", + "for series in results:\n", + " results_emt.append(results[series])\n", + "\n", + "results_attributes0 = rt.read_timeseries_dpsim('logs/EMTCosimAttributes1/EMTCosimAttributes1.csv')\n", + "# results_villas0 = rt.read_timeseries_dpsim('logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", + "\n", + "results_emt_attributes_0 = []\n", + "for series in results_attributes0:\n", + " results_emt_attributes_0.append(results_attributes0[series])\n", + " \n", + "# results_emt_villas_0 = []\n", + "# for series in results_villas0:\n", + "# results_emt_villas_0.append(results_villas0[series])\n", + "\n", + "for series in results_emt:\n", + " pt.plot_timeseries('Results EMT', series)\n", + "\n", + "# for series in results_emt_attributes_0:\n", + "# pt.plot_timeseries('Results EMT', series, '--')\n", + "\n", + "pt.plot_timeseries('Results EMT', results_emt_attributes_0[2], '--')\n", + "pt.plot_timeseries('Results EMT', results_emt_attributes_0[3], '--')\n", + " \n", + "# for series in results_emt_villas_0:\n", + "# pt.plot_timeseries('Results EMT', series, '--')\n", + "\n", + "plt.grid()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "cat: logs/Example1_Solver.log: No such file or directory\n" + ] + } + ], + "source": [ + "!cat logs/Example1_Solver.log" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [] + } + ], + "metadata": { + "interpreter": { + "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a" + }, + "kernelspec": { + "display_name": "Python 3.9.7 64-bit", + "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.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/Python/Attributes/emt-cosim-attributes.py b/examples/Python/Attributes/emt-cosim-attributes.py new file mode 100644 index 0000000000..1591698895 --- /dev/null +++ b/examples/Python/Attributes/emt-cosim-attributes.py @@ -0,0 +1,206 @@ +import sys +import os.path +import logging + +import dpsimpy +import villas.dataprocessing.timeseries as ts +import numpy as np + +base = os.path.splitext(os.path.basename(sys.argv[0]))[0] +log = logging.getLogger(base) + +def set_dpsim1(t_s, t_f, u_1_0): + r_1_r = 0.1 + c_1_c = 1 + r_line_r = 0.1 + + sim_name = "EMTCosimAttributes1" + + gnd = dpsimpy.emt.SimNode.gnd + n1 = dpsimpy.emt.SimNode("n1") + n2 = dpsimpy.emt.SimNode("n2") + + evs = dpsimpy.emt.ph1.VoltageSource("v_intf", dpsimpy.LogLevel.info) + evs.set_parameters(u_1_0) + + r_1 = dpsimpy.emt.ph1.Resistor("r_1", dpsimpy.LogLevel.info) + r_1.set_parameters(r_1_r) + c_1 = dpsimpy.emt.ph1.Capacitor("c_1", dpsimpy.LogLevel.info) + c_1.set_parameters(c_1_c) + r_line = dpsimpy.emt.ph1.Resistor("r_line", dpsimpy.LogLevel.info) + r_line.set_parameters(r_line_r) + + # Initial conditions + n1.set_initial_voltage(5) + n2.set_initial_voltage(u_1_0) + + # Connections + r_1.connect([gnd, n1]) + r_line.connect([n2, n1]) + c_1.connect([gnd, n1]) + evs.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [gnd, n1, n2], [evs, r_1, c_1, r_line]) + + sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim.set_domain(dpsimpy.Domain.EMT) + sim.set_system(sys) + sim.set_time_step(t_s) + sim.set_final_time(t_f) + # sim.do_steady_state_init(True) + + 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('i', 'i_intf', evs) + logger.log_attribute('ir', 'i_intf', r_line) + # logger.log_attribute('4_i_evs', 'i_intf', evs) + # logger.log_attribute('5_v_evs', 'v_intf', evs) + + sim.add_logger(logger) + + # Initialize currents and voltages + # r = np.array([[1/r_1_r, 0.0], [0.0, 1/r_line_r]]) + # n_v_0 = np.array([5.0, 5.0 - u_1_0]).T + + # i_0 = np.matmul(r, n_v_0) + + + n1_v0 = np.array([5.0]) + n2_v0 = np.array([u_1_0]) + + ir_1_0 = n1_v0 / r_1_r + i_r_line_0 = (n1_v0 - n2_v0) / r_line_r + + # r_1.set_intf_voltage([n_v_0[0]]) + # r_1.set_intf_current([i_0[0]]) + # c_1.set_intf_voltage([n_v_0[0]]) + # c_1.set_intf_current([i_0[0] - i_0[1]]) + # r_line.set_intf_voltage([n_v_0[1]]) + # r_line.set_intf_current([i_0[1]]) + + # evs.set_intf_voltage([n_v_0[0] - n_v_0[1]]) + # evs.set_intf_current([i_0[1]]) + + r_1.set_intf_voltage(n1_v0) + r_1.set_intf_current(ir_1_0) + c_1.set_intf_voltage(n1_v0) + c_1.set_intf_current(ir_1_0 - i_r_line_0) + r_line.set_intf_voltage(n1_v0 - n2_v0) + r_line.set_intf_current(i_r_line_0) + + evs.set_intf_voltage(n2_v0) + evs.set_intf_current(i_r_line_0) + + return sim + + +def set_dpsim2(t_s, t_f): + r_load_r = 1.0 + c_2_c = 1.0 + + sim_name = "EMTCosimAttributes2" + + gnd = dpsimpy.emt.SimNode.gnd + n2 = dpsimpy.emt.SimNode("n2") + + ecs = dpsimpy.emt.ph1.CurrentSource("i_intf", dpsimpy.LogLevel.info) + # ecs.set_parameters(u_2_0) + c_2 = dpsimpy.emt.ph1.Capacitor("c_2", dpsimpy.LogLevel.info) + c_2.set_parameters(c_2_c) + r_load = dpsimpy.emt.ph1.Resistor("r_load", dpsimpy.LogLevel.info) + r_load.set_parameters(r_load_r) + + # Initial conditions + n2.set_initial_voltage(2.0) + + # Connections + ecs.connect([gnd, n2]) + c_2.connect([gnd, n2]) + r_load.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [gnd, n2], [ecs, c_2, r_load]) + + sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim.set_domain(dpsimpy.Domain.EMT) + sim.set_system(sys) + sim.set_time_step(t_s) + sim.set_final_time(t_f) + + dpsimpy.Logger.set_log_dir('logs/' + sim_name) + + logger = dpsimpy.Logger(sim_name) + logger.log_attribute('v2', 'v', n2) + logger.log_attribute('i', 'i_intf', ecs) + logger.log_attribute('v', 'v_intf', ecs) + # logger.log_attribute('2_i_rload', 'i_intf', r_load) + # logger.log_attribute('3_v_ecs', 'v_intf', ecs) + # logger.log_attribute('4_i_ecs', 'i_intf', ecs) + + sim.add_logger(logger) + + # Initialize currents and voltages + n2_v0 = [2.0] + # i_r_line_0 = [u_2_0] + i_r_load_0 = [n2_v0[0] / r_load_r] + + r_load.set_intf_voltage(n2_v0) + r_load.set_intf_current(i_r_load_0) + c_2.set_intf_voltage([n2_v0]) + # c_2.set_intf_current([i_r_line_0[0] - i_r_load_0[0]]) + + ecs.set_intf_voltage(n2_v0) + # ecs.set_intf_current(i_r_line_0) + + return sim + +if __name__ == '__main__': + logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) + + time_step = 0.01 + final_time = 1 + t_k = 0.0 + + # Initialization of S_2 and communication y_2_0 -> S_1 + sim2 = set_dpsim2(time_step, final_time) + sim2.start() + y_2_0 = sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() + print("Output value from S2: {:f}".format(y_2_0)) + + # Communication y_2_0 -> S_1 and initialization of S_1 + u_1_0 = y_2_0 + sim1 = set_dpsim1(time_step, final_time, u_1_0) + sim1.start() + y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() + print("Output value from S1: {:f}".format(y_1_0)) + + y_1 = y_1_0 + u_1 = y_1_0 + + while t_k < final_time: + # Switch to S_2 + u_2_prev = sim2.get_idobj_attr("i_intf", "i_intf").derive_coeff(0,0).get() + print("Input value in S2 before set: {:f}".format(u_2_prev)) + + u_2 = y_1 + sim2.get_idobj_attr("i_intf", "I_ref").set(complex(u_2,0)) + u_2_test = sim2.get_idobj_attr("i_intf", "I_ref").get() + print("Input value in S2 after set: {:f}".format(u_2_test)) + + sim2.next() + y_2 = -sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() + print("Output value from S2: {:f}".format(y_2)) + + u_1 = y_2 + + sim1.get_idobj_attr("v_intf", "V_ref").set(complex(u_1,0)) + t_k = sim1.next() + y_1 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() + print("Output value from S1: {:f}".format(y_1)) + print("Time t={:f}".format(t_k)) + + sim2.stop() + sim1.stop() + \ No newline at end of file From 514b0ed1ad9a82dd966971b181b802f6de46cdf7 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 8 Dec 2023 08:47:57 +0100 Subject: [PATCH 30/39] Fixed interface voltage update in EMT_Ph1_CurrentSource Signed-off-by: pipeacosta --- dpsim-models/src/EMT/EMT_Ph1_CurrentSource.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dpsim-models/src/EMT/EMT_Ph1_CurrentSource.cpp b/dpsim-models/src/EMT/EMT_Ph1_CurrentSource.cpp index a025f61782..b872188323 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_CurrentSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_CurrentSource.cpp @@ -76,8 +76,8 @@ void EMT::Ph1::CurrentSource::mnaCompPostStep(Real time, Int timeStepCount, Attr void EMT::Ph1::CurrentSource::mnaCompUpdateVoltage(const Matrix& leftVector) { (**mIntfVoltage)(0,0) = 0; - if (terminalNotGrounded(0)) - (**mIntfVoltage)(0,0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(0)); if (terminalNotGrounded(1)) - (**mIntfVoltage)(0,0) = (**mIntfVoltage)(0,0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(1)); + (**mIntfVoltage)(0,0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(0)); + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0,0) = (**mIntfVoltage)(0,0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0)); } From f7a02e9d4289d108b65fa282133007cf2faa29d6 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 8 Dec 2023 08:50:11 +0100 Subject: [PATCH 31/39] Improve and clean emt-cosim-attributes.py example Signed-off-by: pipeacosta --- .../Python/Attributes/emt-cosim-attributes.py | 71 +++++++++---------- 1 file changed, 32 insertions(+), 39 deletions(-) diff --git a/examples/Python/Attributes/emt-cosim-attributes.py b/examples/Python/Attributes/emt-cosim-attributes.py index 1591698895..a7fe079225 100644 --- a/examples/Python/Attributes/emt-cosim-attributes.py +++ b/examples/Python/Attributes/emt-cosim-attributes.py @@ -3,8 +3,8 @@ import logging import dpsimpy -import villas.dataprocessing.timeseries as ts import numpy as np +import argparse base = os.path.splitext(os.path.basename(sys.argv[0]))[0] log = logging.getLogger(base) @@ -56,34 +56,15 @@ def set_dpsim1(t_s, t_f, u_1_0): logger.log_attribute('v2', 'v', n2) logger.log_attribute('i', 'i_intf', evs) logger.log_attribute('ir', 'i_intf', r_line) - # logger.log_attribute('4_i_evs', 'i_intf', evs) - # logger.log_attribute('5_v_evs', 'v_intf', evs) sim.add_logger(logger) - # Initialize currents and voltages - # r = np.array([[1/r_1_r, 0.0], [0.0, 1/r_line_r]]) - # n_v_0 = np.array([5.0, 5.0 - u_1_0]).T - - # i_0 = np.matmul(r, n_v_0) - - n1_v0 = np.array([5.0]) n2_v0 = np.array([u_1_0]) ir_1_0 = n1_v0 / r_1_r i_r_line_0 = (n1_v0 - n2_v0) / r_line_r - # r_1.set_intf_voltage([n_v_0[0]]) - # r_1.set_intf_current([i_0[0]]) - # c_1.set_intf_voltage([n_v_0[0]]) - # c_1.set_intf_current([i_0[0] - i_0[1]]) - # r_line.set_intf_voltage([n_v_0[1]]) - # r_line.set_intf_current([i_0[1]]) - - # evs.set_intf_voltage([n_v_0[0] - n_v_0[1]]) - # evs.set_intf_current([i_0[1]]) - r_1.set_intf_voltage(n1_v0) r_1.set_intf_current(ir_1_0) c_1.set_intf_voltage(n1_v0) @@ -107,7 +88,6 @@ def set_dpsim2(t_s, t_f): n2 = dpsimpy.emt.SimNode("n2") ecs = dpsimpy.emt.ph1.CurrentSource("i_intf", dpsimpy.LogLevel.info) - # ecs.set_parameters(u_2_0) c_2 = dpsimpy.emt.ph1.Capacitor("c_2", dpsimpy.LogLevel.info) c_2.set_parameters(c_2_c) r_load = dpsimpy.emt.ph1.Resistor("r_load", dpsimpy.LogLevel.info) @@ -135,31 +115,33 @@ def set_dpsim2(t_s, t_f): logger.log_attribute('v2', 'v', n2) logger.log_attribute('i', 'i_intf', ecs) logger.log_attribute('v', 'v_intf', ecs) - # logger.log_attribute('2_i_rload', 'i_intf', r_load) - # logger.log_attribute('3_v_ecs', 'v_intf', ecs) - # logger.log_attribute('4_i_ecs', 'i_intf', ecs) sim.add_logger(logger) # Initialize currents and voltages n2_v0 = [2.0] - # i_r_line_0 = [u_2_0] i_r_load_0 = [n2_v0[0] / r_load_r] r_load.set_intf_voltage(n2_v0) r_load.set_intf_current(i_r_load_0) c_2.set_intf_voltage([n2_v0]) - # c_2.set_intf_current([i_r_line_0[0] - i_r_load_0[0]]) ecs.set_intf_voltage(n2_v0) - # ecs.set_intf_current(i_r_line_0) return sim if __name__ == '__main__': + # parser = argparse.ArgumentParser() + # parser.add_argument('-t', '--timestep') + # parser.add_argument('-e', '--end') + + # args = parser.parse_args() + + debug = True + logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) - time_step = 0.01 + time_step = 0.001 final_time = 1 t_k = 0.0 @@ -167,39 +149,50 @@ def set_dpsim2(t_s, t_f): sim2 = set_dpsim2(time_step, final_time) sim2.start() y_2_0 = sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() - print("Output value from S2: {:f}".format(y_2_0)) + + if debug: + print("Output value from S2: {:f}".format(y_2_0)) # Communication y_2_0 -> S_1 and initialization of S_1 u_1_0 = y_2_0 sim1 = set_dpsim1(time_step, final_time, u_1_0) sim1.start() y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() - print("Output value from S1: {:f}".format(y_1_0)) + + if debug: + print("Output value from S1: {:f}".format(y_1_0)) y_1 = y_1_0 u_1 = y_1_0 while t_k < final_time: - # Switch to S_2 - u_2_prev = sim2.get_idobj_attr("i_intf", "i_intf").derive_coeff(0,0).get() - print("Input value in S2 before set: {:f}".format(u_2_prev)) + # Switch to S_2 + if debug: + u_2_prev = sim2.get_idobj_attr("i_intf", "i_intf").derive_coeff(0,0).get() + print("Input value in S2 before set: {:f}".format(u_2_prev)) u_2 = y_1 sim2.get_idobj_attr("i_intf", "I_ref").set(complex(u_2,0)) - u_2_test = sim2.get_idobj_attr("i_intf", "I_ref").get() - print("Input value in S2 after set: {:f}".format(u_2_test)) + + if debug: + u_2_test = sim2.get_idobj_attr("i_intf", "I_ref").get() + print("Input value in S2 after set: {:f}".format(u_2_test)) sim2.next() - y_2 = -sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() - print("Output value from S2: {:f}".format(y_2)) + y_2 = sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() + + if debug: + print("Output value from S2: {:f}".format(y_2)) u_1 = y_2 sim1.get_idobj_attr("v_intf", "V_ref").set(complex(u_1,0)) t_k = sim1.next() y_1 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() - print("Output value from S1: {:f}".format(y_1)) - print("Time t={:f}".format(t_k)) + + if debug: + print("Output value from S1: {:f}".format(y_1)) + print("Time t={:f}".format(t_k)) sim2.stop() sim1.stop() From 6a28fccfc405e24f52766b0d93443e0058fc1b63 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 8 Dec 2023 08:53:21 +0100 Subject: [PATCH 32/39] Implemented new attribute method deriveComplex Signed-off-by: pipeacosta --- dpsim-models/include/dpsim-models/Attribute.h | 17 +++++++++++++++++ dpsim/src/pybind/Attributes.cpp | 3 ++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/dpsim-models/include/dpsim-models/Attribute.h b/dpsim-models/include/dpsim-models/Attribute.h index 07210a0551..a41fd12564 100644 --- a/dpsim-models/include/dpsim-models/Attribute.h +++ b/dpsim-models/include/dpsim-models/Attribute.h @@ -506,6 +506,23 @@ namespace CPS { return derive(getter, setter); } + /** + * Convenience method for building a complex attribute from a real attribute + * @return a new complex attribute whose real part always equal value of `this` + * */ + template , bool> = true> + AttributePointer> deriveComplex() + // requires std::same_as //CPP20 + { + AttributeUpdateTask::Actor getter = [](std::shared_ptr &dependent, Attribute::Ptr dependency) { + *dependent = CPS::Complex(dependency->get(), 0); + }; + AttributeUpdateTask::Actor setter = [](std::shared_ptr &dependent, Attribute::Ptr dependency) { + dependency->set(dependent->real()); + }; + return derive(getter, setter); + } + }; /** diff --git a/dpsim/src/pybind/Attributes.cpp b/dpsim/src/pybind/Attributes.cpp index 22c7f9cccc..251bd9ea95 100644 --- a/dpsim/src/pybind/Attributes.cpp +++ b/dpsim/src/pybind/Attributes.cpp @@ -30,7 +30,8 @@ void addAttributes(py::module_ m) { py::class_, CPS::AttributePointer>, CPS::AttributeBase>(m, "AttributeReal") .def("get", &CPS::Attribute::get) .def("set", &CPS::Attribute::set) - .def("derive_scaled", &CPS::Attribute::deriveScaled); + .def("derive_scaled", &CPS::Attribute::deriveScaled) + .def("derive_complex", &CPS::Attribute::deriveComplex); py::class_, CPS::AttributePointer>, CPS::Attribute>(m, "AttributeRealStat"); py::class_, CPS::AttributePointer>, CPS::Attribute>(m, "AttributeRealDyn") From 3ff388a6bbb07c545fef8ca9f0a28e3ae467f2f5 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Fri, 8 Dec 2023 09:01:04 +0100 Subject: [PATCH 33/39] Improvements to the co-simulation using the VILLASnode interace Signed-off-by: pipeacosta --- examples/Notebooks/cosim-villas-socket.ipynb | 1799 +----------------- examples/villas/emt-cosim-villas.py | 155 +- 2 files changed, 143 insertions(+), 1811 deletions(-) diff --git a/examples/Notebooks/cosim-villas-socket.ipynb b/examples/Notebooks/cosim-villas-socket.ipynb index e6bcdc221d..64b2b8815e 100644 --- a/examples/Notebooks/cosim-villas-socket.ipynb +++ b/examples/Notebooks/cosim-villas-socket.ipynb @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -93,7 +93,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -109,171 +109,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Warning: some nodes with margin (3.20,3.20) touch - falling back to straight line edges\n" - ] - }, - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "topology\n", - "\n", - "\n", - "\n", - "gnd\n", - "\n", - "\n", - "\n", - "\n", - "gnd\n", - "\n", - "\n", - "\n", - "n1\n", - "\n", - "\n", - "\n", - "\n", - "n1\n", - "(5.00 V > 0.00°)\n", - "\n", - "\n", - "\n", - "n2\n", - "\n", - "\n", - "\n", - "\n", - "n2\n", - "(2.00 V > 0.00°)\n", - "\n", - "\n", - "\n", - "r_1\n", - "\n", - "\n", - "r_1\n", - "EMT::Ph1::Resistor\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "r_1--gnd\n", - "\n", - "\n", - "\n", - "\n", - "r_1--n1\n", - "\n", - "\n", - "\n", - "\n", - "r_line\n", - "\n", - "\n", - "r_line\n", - "EMT::Ph1::Resistor\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "r_line--n1\n", - "\n", - "\n", - "\n", - "\n", - "r_line--n2\n", - "\n", - "\n", - "\n", - "\n", - "c_1\n", - "\n", - "\n", - "c_1\n", - "EMT::Ph1::Capacitor\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "c_1--gnd\n", - "\n", - "\n", - "\n", - "\n", - "c_1--n1\n", - "\n", - "\n", - "\n", - "\n", - "c_2\n", - "\n", - "\n", - "c_2\n", - "EMT::Ph1::Capacitor\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "c_2--gnd\n", - "\n", - "\n", - "\n", - "\n", - "c_2--n2\n", - "\n", - "\n", - "\n", - "\n", - "r_load\n", - "\n", - "\n", - "r_load\n", - "EMT::Ph1::Resistor\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "r_load--gnd\n", - "\n", - "\n", - "\n", - "\n", - "r_load--n2\n", - "\n", - "\n", - "\n", - "\n" - ], - "text/plain": [ - "" - ] - }, - "execution_count": 4, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "sys" ] @@ -287,29 +125,13 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[09:55:34.084247 EMTCosim info] Initialize simulation: EMTCosim\n", - "[09:55:34.084457 MnaSolverFactory info] creating KLUAdapter solver implementation\n", - "[09:55:34.085258 EMTCosim info] Scheduling tasks.\n", - "[09:55:34.085642 EMTCosim info] Scheduling done.\n", - "[09:55:34.085645 EMTCosim info] Opening interfaces.\n", - "[09:55:34.085647 EMTCosim info] Start synchronization with remotes on interfaces\n", - "[09:55:34.085650 EMTCosim info] Synchronized simulation start with remotes\n", - "[09:55:34.085653 EMTCosim info] Start simulation: EMTCosim\n", - "[09:55:34.085659 EMTCosim info] Time step: 1.000000e-02\n", - "[09:55:34.085663 EMTCosim info] Final time: 1.000000e+00\n", - "[09:55:34.086935 EMTCosim info] Simulation calculation time: 0.001261\n", - "[09:55:34.087048 EMTCosim info] Simulation finished.\n" - ] - } - ], + "outputs": [], "source": [ + "time_step = 0.01\n", + "final_time = 1.0\n", + "\n", "sim = dpsimpy.Simulation(\"EMTCosim\", loglevel=dpsimpy.LogLevel.debug)\n", "sim.set_domain(dpsimpy.Domain.EMT)\n", "sim.set_system(sys)\n", @@ -334,559 +156,16 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[09:55:34.281079 EMTCosimAttributes2 info] Initialize simulation: EMTCosimAttributes2\n", - "[09:55:34.281387 MnaSolverFactory info] creating KLUAdapter solver implementation\n", - "[09:55:34.282505 EMTCosimAttributes2 info] Scheduling tasks.\n", - "[09:55:34.283001 EMTCosimAttributes2 info] Scheduling done.\n", - "[09:55:34.283011 EMTCosimAttributes2 info] Opening interfaces.\n", - "[09:55:34.283013 EMTCosimAttributes2 info] Start synchronization with remotes on interfaces\n", - "[09:55:34.283016 EMTCosimAttributes2 info] Synchronized simulation start with remotes\n", - "[09:55:34.283019 EMTCosimAttributes2 info] Start simulation: EMTCosimAttributes2\n", - "[09:55:34.283027 EMTCosimAttributes2 info] Time step: 1.000000e-02\n", - "[09:55:34.283031 EMTCosimAttributes2 info] Final time: 1.000000e+00\n", - "[09:55:34.285915 EMTCosimAttributes1 info] Initialize simulation: EMTCosimAttributes1\n", - "[09:55:34.286177 MnaSolverFactory info] creating KLUAdapter solver implementation\n", - "[09:55:34.287332 EMTCosimAttributes1 info] Scheduling tasks.\n", - "[09:55:34.287846 EMTCosimAttributes1 info] Scheduling done.\n", - "[09:55:34.287859 EMTCosimAttributes1 info] Opening interfaces.\n", - "[09:55:34.287862 EMTCosimAttributes1 info] Start synchronization with remotes on interfaces\n", - "[09:55:34.287864 EMTCosimAttributes1 info] Synchronized simulation start with remotes\n", - "[09:55:34.287868 EMTCosimAttributes1 info] Start simulation: EMTCosimAttributes1\n", - "[09:55:34.287875 EMTCosimAttributes1 info] Time step: 1.000000e-02\n", - "[09:55:34.287878 EMTCosimAttributes1 info] Final time: 1.000000e+00\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Output value from S2: 2.000000\n", - "Output value from S1: 30.000000\n", - "Input value in S2 before set: 0.000000\n", - "Input value in S2 after set: 30.000000+0.000000j\n", - "Output value from S2: 2.139303\n", - "Output value from S1: 25.033921\n", - "Time t=0.010000\n", - "Input value in S2 before set: 30.000000\n", - "Input value in S2 after set: 25.033921+0.000000j\n", - "Output value from S2: 2.391817\n", - "Output value from S1: 16.127117\n", - "Time t=0.020000\n", - "Input value in S2 before set: 25.033921\n", - "Input value in S2 after set: 16.127117+0.000000j\n", - "Output value from S2: 2.572800\n", - "Output value from S1: 9.292978\n", - "Time t=0.030000\n", - "Input value in S2 before set: 16.127117\n", - "Input value in S2 after set: 9.292978+0.000000j\n", - "Output value from S2: 2.673668\n", - "Output value from S1: 4.301605\n", - "Time t=0.040000\n", - "Input value in S2 before set: 9.292978\n", - "Input value in S2 after set: 4.301605+0.000000j\n", - "Output value from S2: 2.714699\n", - "Output value from S1: 0.697227\n", - "Time t=0.050000\n", - "Input value in S2 before set: 4.301605\n", - "Input value in S2 after set: 0.697227+0.000000j\n", - "Output value from S2: 2.712557\n", - "Output value from S1: -1.877002\n", - "Time t=0.060000\n", - "Input value in S2 before set: 0.697227\n", - "Input value in S2 after set: -1.877002+0.000000j\n", - "Output value from S2: 2.679697\n", - "Output value from S1: -3.688024\n", - "Time t=0.070000\n", - "Input value in S2 before set: -1.877002\n", - "Input value in S2 after set: -3.688024+0.000000j\n", - "Output value from S2: 2.625346\n", - "Output value from S1: -4.934764\n", - "Time t=0.080000\n", - "Input value in S2 before set: -3.688024\n", - "Input value in S2 after set: -4.934764+0.000000j\n", - "Output value from S2: 2.556324\n", - "Output value from S1: -5.765363\n", - "Time t=0.090000\n", - "Input value in S2 before set: -4.934764\n", - "Input value in S2 after set: -5.765363+0.000000j\n", - "Output value from S2: 2.477653\n", - "Output value from S1: -6.290100\n", - "Time t=0.100000\n", - "Input value in S2 before set: -5.765363\n", - "Input value in S2 after set: -6.290100+0.000000j\n", - "Output value from S2: 2.393023\n", - "Output value from S1: -6.591019\n", - "Time t=0.110000\n", - "Input value in S2 before set: -6.290100\n", - "Input value in S2 after set: -6.591019+0.000000j\n", - "Output value from S2: 2.305126\n", - "Output value from S1: -6.729117\n", - "Time t=0.120000\n", - "Input value in S2 before set: -6.591019\n", - "Input value in S2 after set: -6.729117+0.000000j\n", - "Output value from S2: 2.215920\n", - "Output value from S1: -6.749699\n", - "Time t=0.130000\n", - "Input value in S2 before set: -6.729117\n", - "Input value in S2 after set: -6.749699+0.000000j\n", - "Output value from S2: 2.126813\n", - "Output value from S1: -6.686381\n", - "Time t=0.140000\n", - "Input value in S2 before set: -6.749699\n", - "Input value in S2 after set: -6.686381+0.000000j\n", - "Output value from S2: 2.038804\n", - "Output value from S1: -6.564060\n", - "Time t=0.150000\n", - "Input value in S2 before set: -6.686381\n", - "Input value in S2 after set: -6.564060+0.000000j\n", - "Output value from S2: 1.952595\n", - "Output value from S1: -6.401147\n", - "Time t=0.160000\n", - "Input value in S2 before set: -6.564060\n", - "Input value in S2 after set: -6.401147+0.000000j\n", - "Output value from S2: 1.868663\n", - "Output value from S1: -6.211216\n", - "Time t=0.170000\n", - "Input value in S2 before set: -6.401147\n", - "Input value in S2 after set: -6.211216+0.000000j\n", - "Output value from S2: 1.787321\n", - "Output value from S1: -6.004245\n", - "Time t=0.180000\n", - "Input value in S2 before set: -6.211216\n", - "Input value in S2 after set: -6.004245+0.000000j\n", - "Output value from S2: 1.708763\n", - "Output value from S1: -5.787532\n", - "Time t=0.190000\n", - "Input value in S2 before set: -6.004245\n", - "Input value in S2 after set: -5.787532+0.000000j\n", - "Output value from S2: 1.633095\n", - "Output value from S1: -5.566387\n", - "Time t=0.200000\n", - "Input value in S2 before set: -5.787532\n", - "Input value in S2 after set: -5.566387+0.000000j\n", - "Output value from S2: 1.560358\n", - "Output value from S1: -5.344642\n", - "Time t=0.210000\n", - "Input value in S2 before set: -5.566387\n", - "Input value in S2 after set: -5.344642+0.000000j\n", - "Output value from S2: 1.490549\n", - "Output value from S1: -5.125032\n", - "Time t=0.220000\n", - "Input value in S2 before set: -5.344642\n", - "Input value in S2 after set: -5.125032+0.000000j\n", - "Output value from S2: 1.423629\n", - "Output value from S1: -4.909477\n", - "Time t=0.230000\n", - "Input value in S2 before set: -5.125032\n", - "Input value in S2 after set: -4.909477+0.000000j\n", - "Output value from S2: 1.359541\n", - "Output value from S1: -4.699300\n", - "Time t=0.240000\n", - "Input value in S2 before set: -4.909477\n", - "Input value in S2 after set: -4.699300+0.000000j\n", - "Output value from S2: 1.298208\n", - "Output value from S1: -4.495380\n", - "Time t=0.250000\n", - "Input value in S2 before set: -4.699300\n", - "Input value in S2 after set: -4.495380+0.000000j\n", - "Output value from S2: 1.239546\n", - "Output value from S1: -4.298271\n", - "Time t=0.260000\n", - "Input value in S2 before set: -4.495380\n", - "Input value in S2 after set: -4.298271+0.000000j\n", - "Output value from S2: 1.183463\n", - "Output value from S1: -4.108286\n", - "Time t=0.270000\n", - "Input value in S2 before set: -4.298271\n", - "Input value in S2 after set: -4.108286+0.000000j\n", - "Output value from S2: 1.129863\n", - "Output value from S1: -3.925570\n", - "Time t=0.280000\n", - "Input value in S2 before set: -4.108286\n", - "Input value in S2 after set: -3.925570+0.000000j\n", - "Output value from S2: 1.078651\n", - "Output value from S1: -3.750138\n", - "Time t=0.290000\n", - "Input value in S2 before set: -3.925570\n", - "Input value in S2 after set: -3.750138+0.000000j\n", - "Output value from S2: 1.029731\n", - "Output value from S1: -3.581919\n", - "Time t=0.300000\n", - "Input value in S2 before set: -3.750138\n", - "Input value in S2 after set: -3.581919+0.000000j\n", - "Output value from S2: 0.983007\n", - "Output value from S1: -3.420778\n", - "Time t=0.310000\n", - "Input value in S2 before set: -3.581919\n", - "Input value in S2 after set: -3.420778+0.000000j\n", - "Output value from S2: 0.938387\n", - "Output value from S1: -3.266539\n", - "Time t=0.320000\n", - "Input value in S2 before set: -3.420778\n", - "Input value in S2 after set: -3.266539+0.000000j\n", - "Output value from S2: 0.895779\n", - "Output value from S1: -3.118994\n", - "Time t=0.330000\n", - "Input value in S2 before set: -3.266539\n", - "Input value in S2 after set: -3.118994+0.000000j\n", - "Output value from S2: 0.855097\n", - "Output value from S1: -2.977921\n", - "Time t=0.340000\n", - "Input value in S2 before set: -3.118994\n", - "Input value in S2 after set: -2.977921+0.000000j\n", - "Output value from S2: 0.816256\n", - "Output value from S1: -2.843083\n", - "Time t=0.350000\n", - "Input value in S2 before set: -2.977921\n", - "Input value in S2 after set: -2.843083+0.000000j\n", - "Output value from S2: 0.779174\n", - "Output value from S1: -2.714244\n", - "Time t=0.360000\n", - "Input value in S2 before set: -2.843083\n", - "Input value in S2 after set: -2.714244+0.000000j\n", - "Output value from S2: 0.743772\n", - "Output value from S1: -2.591162\n", - "Time t=0.370000\n", - "Input value in S2 before set: -2.714244\n", - "Input value in S2 after set: -2.591162+0.000000j\n", - "Output value from S2: 0.709976\n", - "Output value from S1: -2.473602\n", - "Time t=0.380000\n", - "Input value in S2 before set: -2.591162\n", - "Input value in S2 after set: -2.473602+0.000000j\n", - "Output value from S2: 0.677714\n", - "Output value from S1: -2.361332\n", - "Time t=0.390000\n", - "Input value in S2 before set: -2.473602\n", - "Input value in S2 after set: -2.361332+0.000000j\n", - "Output value from S2: 0.646916\n", - "Output value from S1: -2.254123\n", - "Time t=0.400000\n", - "Input value in S2 before set: -2.361332\n", - "Input value in S2 after set: -2.254123+0.000000j\n", - "Output value from S2: 0.617517\n", - "Output value from S1: -2.151757\n", - "Time t=0.410000\n", - "Input value in S2 before set: -2.254123\n", - "Input value in S2 after set: -2.151757+0.000000j\n", - "Output value from S2: 0.589453\n", - "Output value from S1: -2.054022\n", - "Time t=0.420000\n", - "Input value in S2 before set: -2.151757\n", - "Input value in S2 after set: -2.054022+0.000000j\n", - "Output value from S2: 0.562663\n", - "Output value from S1: -1.960712\n", - "Time t=0.430000\n", - "Input value in S2 before set: -2.054022\n", - "Input value in S2 after set: -1.960712+0.000000j\n", - "Output value from S2: 0.537091\n", - "Output value from S1: -1.871630\n", - "Time t=0.440000\n", - "Input value in S2 before set: -1.960712\n", - "Input value in S2 after set: -1.871630+0.000000j\n", - "Output value from S2: 0.512680\n", - "Output value from S1: -1.786588\n", - "Time t=0.450000\n", - "Input value in S2 before set: -1.871630\n", - "Input value in S2 after set: -1.786588+0.000000j\n", - "Output value from S2: 0.489379\n", - "Output value from S1: -1.705405\n", - "Time t=0.460000\n", - "Input value in S2 before set: -1.786588\n", - "Input value in S2 after set: -1.705405+0.000000j\n", - "Output value from S2: 0.467136\n", - "Output value from S1: -1.627906\n", - "Time t=0.470000\n", - "Input value in S2 before set: -1.705405\n", - "Input value in S2 after set: -1.627906+0.000000j\n", - "Output value from S2: 0.445905\n", - "Output value from S1: -1.553925\n", - "Time t=0.480000\n", - "Input value in S2 before set: -1.627906\n", - "Input value in S2 after set: -1.553925+0.000000j\n", - "Output value from S2: 0.425638\n", - "Output value from S1: -1.483305\n", - "Time t=0.490000\n", - "Input value in S2 before set: -1.553925\n", - "Input value in S2 after set: -1.483305+0.000000j\n", - "Output value from S2: 0.406292\n", - "Output value from S1: -1.415892\n", - "Time t=0.500000\n", - "Input value in S2 before set: -1.483305\n", - "Input value in S2 after set: -1.415892+0.000000j\n", - "Output value from S2: 0.387825\n", - "Output value from S1: -1.351542\n", - "Time t=0.510000\n", - "Input value in S2 before set: -1.415892\n", - "Input value in S2 after set: -1.351542+0.000000j\n", - "Output value from S2: 0.370198\n", - "Output value from S1: -1.290115\n", - "Time t=0.520000\n", - "Input value in S2 before set: -1.351542\n", - "Input value in S2 after set: -1.290115+0.000000j\n", - "Output value from S2: 0.353372\n", - "Output value from S1: -1.231479\n", - "Time t=0.530000\n", - "Input value in S2 before set: -1.290115\n", - "Input value in S2 after set: -1.231479+0.000000j\n", - "Output value from S2: 0.337311\n", - "Output value from S1: -1.175508\n", - "Time t=0.540000\n", - "Input value in S2 before set: -1.231479\n", - "Input value in S2 after set: -1.175508+0.000000j\n", - "Output value from S2: 0.321979\n", - "Output value from S1: -1.122080\n", - "Time t=0.550000\n", - "Input value in S2 before set: -1.175508\n", - "Input value in S2 after set: -1.122080+0.000000j\n", - "Output value from S2: 0.307345\n", - "Output value from S1: -1.071080\n", - "Time t=0.560000\n", - "Input value in S2 before set: -1.122080\n", - "Input value in S2 after set: -1.071080+0.000000j\n", - "Output value from S2: 0.293375\n", - "Output value from S1: -1.022398\n", - "Time t=0.570000\n", - "Input value in S2 before set: -1.071080\n", - "Input value in S2 after set: -1.022398+0.000000j\n", - "Output value from S2: 0.280041\n", - "Output value from S1: -0.975929\n", - "Time t=0.580000\n", - "Input value in S2 before set: -1.022398\n", - "Input value in S2 after set: -0.975929+0.000000j\n", - "Output value from S2: 0.267312\n", - "Output value from S1: -0.931571\n", - "Time t=0.590000\n", - "Input value in S2 before set: -0.975929\n", - "Input value in S2 after set: -0.931571+0.000000j\n", - "Output value from S2: 0.255162\n", - "Output value from S1: -0.889230\n", - "Time t=0.600000\n", - "Input value in S2 before set: -0.931571\n", - "Input value in S2 after set: -0.889230+0.000000j\n", - "Output value from S2: 0.243565\n", - "Output value from S1: -0.848813\n", - "Time t=0.610000\n", - "Input value in S2 before set: -0.889230\n", - "Input value in S2 after set: -0.848813+0.000000j\n", - "Output value from S2: 0.232494\n", - "Output value from S1: -0.810233\n", - "Time t=0.620000\n", - "Input value in S2 before set: -0.848813\n", - "Input value in S2 after set: -0.810233+0.000000j\n", - "Output value from S2: 0.221927\n", - "Output value from S1: -0.773406\n", - "Time t=0.630000\n", - "Input value in S2 before set: -0.810233\n", - "Input value in S2 after set: -0.773406+0.000000j\n", - "Output value from S2: 0.211840\n", - "Output value from S1: -0.738253\n", - "Time t=0.640000\n", - "Input value in S2 before set: -0.773406\n", - "Input value in S2 after set: -0.738253+0.000000j\n", - "Output value from S2: 0.202211\n", - "Output value from S1: -0.704698\n", - "Time t=0.650000\n", - "Input value in S2 before set: -0.738253\n", - "Input value in S2 after set: -0.704698+0.000000j\n", - "Output value from S2: 0.193020\n", - "Output value from S1: -0.672668\n", - "Time t=0.660000\n", - "Input value in S2 before set: -0.704698\n", - "Input value in S2 after set: -0.672668+0.000000j\n", - "Output value from S2: 0.184247\n", - "Output value from S1: -0.642094\n", - "Time t=0.670000\n", - "Input value in S2 before set: -0.672668\n", - "Input value in S2 after set: -0.642094+0.000000j\n", - "Output value from S2: 0.175873\n", - "Output value from S1: -0.612910\n", - "Time t=0.680000\n", - "Input value in S2 before set: -0.642094\n", - "Input value in S2 after set: -0.612910+0.000000j\n", - "Output value from S2: 0.167879\n", - "Output value from S1: -0.585052\n", - "Time t=0.690000\n", - "Input value in S2 before set: -0.612910\n", - "Input value in S2 after set: -0.585052+0.000000j\n", - "Output value from S2: 0.160249\n", - "Output value from S1: -0.558460\n", - "Time t=0.700000\n", - "Input value in S2 before set: -0.585052\n", - "Input value in S2 after set: -0.558460+0.000000j\n", - "Output value from S2: 0.152965\n", - "Output value from S1: -0.533077\n", - "Time t=0.710000\n", - "Input value in S2 before set: -0.558460\n", - "Input value in S2 after set: -0.533077+0.000000j\n", - "Output value from S2: 0.146012\n", - "Output value from S1: -0.508847\n", - "Time t=0.720000\n", - "Input value in S2 before set: -0.533077\n", - "Input value in S2 after set: -0.508847+0.000000j\n", - "Output value from S2: 0.139376\n", - "Output value from S1: -0.485719\n", - "Time t=0.730000\n", - "Input value in S2 before set: -0.508847\n", - "Input value in S2 after set: -0.485719+0.000000j\n", - "Output value from S2: 0.133041\n", - "Output value from S1: -0.463642\n", - "Time t=0.740000\n", - "Input value in S2 before set: -0.485719\n", - "Input value in S2 after set: -0.463642+0.000000j\n", - "Output value from S2: 0.126994\n", - "Output value from S1: -0.442569\n", - "Time t=0.750000\n", - "Input value in S2 before set: -0.463642\n", - "Input value in S2 after set: -0.442569+0.000000j\n", - "Output value from S2: 0.121222\n", - "Output value from S1: -0.422453\n", - "Time t=0.760000\n", - "Input value in S2 before set: -0.442569\n", - "Input value in S2 after set: -0.422453+0.000000j\n", - "Output value from S2: 0.115712\n", - "Output value from S1: -0.403252\n", - "Time t=0.770000\n", - "Input value in S2 before set: -0.422453\n", - "Input value in S2 after set: -0.403252+0.000000j\n", - "Output value from S2: 0.110453\n", - "Output value from S1: -0.384923\n", - "Time t=0.780000\n", - "Input value in S2 before set: -0.403252\n", - "Input value in S2 after set: -0.384923+0.000000j\n", - "Output value from S2: 0.105432\n", - "Output value from S1: -0.367428\n", - "Time t=0.790000\n", - "Input value in S2 before set: -0.384923\n", - "Input value in S2 after set: -0.367428+0.000000j\n", - "Output value from S2: 0.100640\n", - "Output value from S1: -0.350727\n", - "Time t=0.800000\n", - "Input value in S2 before set: -0.367428\n", - "Input value in S2 after set: -0.350727+0.000000j\n", - "Output value from S2: 0.096066\n", - "Output value from S1: -0.334786\n", - "Time t=0.810000\n", - "Input value in S2 before set: -0.350727\n", - "Input value in S2 after set: -0.334786+0.000000j\n", - "Output value from S2: 0.091700\n", - "Output value from S1: -0.319569\n", - "Time t=0.820000\n", - "Input value in S2 before set: -0.334786\n", - "Input value in S2 after set: -0.319569+0.000000j\n", - "Output value from S2: 0.087532\n", - "Output value from S1: -0.305044\n", - "Time t=0.830000\n", - "Input value in S2 before set: -0.319569\n", - "Input value in S2 after set: -0.305044+0.000000j\n", - "Output value from S2: 0.083553\n", - "Output value from S1: -0.291179\n", - "Time t=0.840000\n", - "Input value in S2 before set: -0.305044\n", - "Input value in S2 after set: -0.291179+0.000000j\n", - "Output value from S2: 0.079756\n", - "Output value from S1: -0.277945\n", - "Time t=0.850000\n", - "Input value in S2 before set: -0.291179\n", - "Input value in S2 after set: -0.277945+0.000000j\n", - "Output value from S2: 0.076130\n", - "Output value from S1: -0.265312\n", - "Time t=0.860000\n", - "Input value in S2 before set: -0.277945\n", - "Input value in S2 after set: -0.265312+0.000000j\n", - "Output value from S2: 0.072670\n", - "Output value from S1: -0.253253\n", - "Time t=0.870000\n", - "Input value in S2 before set: -0.265312\n", - "Input value in S2 after set: -0.253253+0.000000j\n", - "Output value from S2: 0.069367\n", - "Output value from S1: -0.241742\n", - "Time t=0.880000\n", - "Input value in S2 before set: -0.253253\n", - "Input value in S2 after set: -0.241742+0.000000j\n", - "Output value from S2: 0.066214\n", - "Output value from S1: -0.230754\n", - "Time t=0.890000\n", - "Input value in S2 before set: -0.241742\n", - "Input value in S2 after set: -0.230754+0.000000j\n", - "Output value from S2: 0.063205\n", - "Output value from S1: -0.220266\n", - "Time t=0.900000\n", - "Input value in S2 before set: -0.230754\n", - "Input value in S2 after set: -0.220266+0.000000j\n", - "Output value from S2: 0.060332\n", - "Output value from S1: -0.210254\n", - "Time t=0.910000\n", - "Input value in S2 before set: -0.220266\n", - "Input value in S2 after set: -0.210254+0.000000j\n", - "Output value from S2: 0.057590\n", - "Output value from S1: -0.200698\n", - "Time t=0.920000\n", - "Input value in S2 before set: -0.210254\n", - "Input value in S2 after set: -0.200698+0.000000j\n", - "Output value from S2: 0.054972\n", - "Output value from S1: -0.191576\n", - "Time t=0.930000\n", - "Input value in S2 before set: -0.200698\n", - "Input value in S2 after set: -0.191576+0.000000j\n", - "Output value from S2: 0.052474\n", - "Output value from S1: -0.182868\n", - "Time t=0.940000\n", - "Input value in S2 before set: -0.191576\n", - "Input value in S2 after set: -0.182868+0.000000j\n", - "Output value from S2: 0.050089\n", - "Output value from S1: -0.174556\n", - "Time t=0.950000\n", - "Input value in S2 before set: -0.182868\n", - "Input value in S2 after set: -0.174556+0.000000j\n", - "Output value from S2: 0.047812\n", - "Output value from S1: -0.166623\n", - "Time t=0.960000\n", - "Input value in S2 before set: -0.174556\n", - "Input value in S2 after set: -0.166623+0.000000j\n", - "Output value from S2: 0.045639\n", - "Output value from S1: -0.159049\n", - "Time t=0.970000\n", - "Input value in S2 before set: -0.166623\n", - "Input value in S2 after set: -0.159049+0.000000j\n", - "Output value from S2: 0.043564\n", - "Output value from S1: -0.151820\n", - "Time t=0.980000\n", - "Input value in S2 before set: -0.159049\n", - "Input value in S2 after set: -0.151820+0.000000j\n", - "Output value from S2: 0.041584\n", - "Output value from S1: -0.144920\n", - "Time t=0.990000\n", - "Input value in S2 before set: -0.151820\n", - "Input value in S2 after set: -0.144920+0.000000j\n", - "Output value from S2: 0.039694\n", - "Output value from S1: -0.138333\n", - "Time t=1.000000\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "[09:55:34.343457 EMTCosimAttributes2 info] Simulation calculation time: 0.060391\n", - "[09:55:34.343757 EMTCosimAttributes2 info] Simulation finished.\n", - "[09:55:34.343937 EMTCosimAttributes1 info] Simulation calculation time: 0.056048\n", - "[09:55:34.344116 EMTCosimAttributes1 info] Simulation finished.\n" - ] - } - ], + "outputs": [], "source": [ "import subprocess\n", "\n", "subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes.py\"])\n", - "process = subprocess.Popen([\"python3\", \"../villas/emt-cosim-villas.py\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)" + "\n", + "# TODO: Verify why the villas co-simulation does not log outputs correctly using Popen\n", + "# process = subprocess.Popen([\"python3\", \"../villas/emt-cosim-villas.py\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)" ] }, { @@ -898,997 +177,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "column number: 2\n", - "results length: 100\n", - "real column names: ['v1', 'v2']\n", - "complex column names: []\n", - "column number: 4\n", - "results length: 100\n", - "real column names: ['i', 'ir', 'v1', 'v2']\n", - "complex column names: []\n" - ] - }, - { - "data": { - "image/svg+xml": [ - "\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " 2023-11-30T09:55:35.140979\n", - " image/svg+xml\n", - " \n", - " \n", - " Matplotlib v3.8.0, https://matplotlib.org/\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "\n" - ], - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "%matplotlib inline\n", "%config InlineBackend.figure_format = 'svg'\n", @@ -1905,28 +196,38 @@ "for series in results:\n", " results_emt.append(results[series])\n", "\n", - "results_attributes0 = rt.read_timeseries_dpsim('logs/EMTCosimAttributes1/EMTCosimAttributes1.csv')\n", - "# results_villas0 = rt.read_timeseries_dpsim('logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", + "results_attributes1 = rt.read_timeseries_dpsim('logs/EMTCosimAttributes1/EMTCosimAttributes1.csv')\n", + "\n", + "# Get logs, if the co-simulation was executed from this script\n", + "# results_villas1 = rt.read_timeseries_dpsim('logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", + "# results_villas2 = rt.read_timeseries_dpsim('logs/EMTCosimVILLAS2/EMTCosimVILLAS2.csv')\n", + "\n", + "# If the villas co-simulation was not executed from this script, read the logs as follows\n", + "# This assumes that you executed the script examples/villas/emt-cosim-villas.py previously\n", + "results_villas1 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", + "results_villas2 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS2/EMTCosimVILLAS2.csv')\n", "\n", "results_emt_attributes_0 = []\n", - "for series in results_attributes0:\n", - " results_emt_attributes_0.append(results_attributes0[series])\n", + "for series in results_attributes1:\n", + " results_emt_attributes_0.append(results_attributes1[series])\n", + " \n", + "results_emt_villas_1 = []\n", + "for series in results_villas1:\n", + " results_emt_villas_1.append(results_villas1[series])\n", " \n", - "# results_emt_villas_0 = []\n", - "# for series in results_villas0:\n", - "# results_emt_villas_0.append(results_villas0[series])\n", + "results_emt_villas_2 = []\n", + "for series in results_villas2:\n", + " results_emt_villas_2.append(results_villas2[series])\n", "\n", "for series in results_emt:\n", - " pt.plot_timeseries('Results EMT', series)\n", + " pt.plot_timeseries('Co-simulation results', series)\n", "\n", - "# for series in results_emt_attributes_0:\n", - "# pt.plot_timeseries('Results EMT', series, '--')\n", - "\n", - "pt.plot_timeseries('Results EMT', results_emt_attributes_0[2], '--')\n", - "pt.plot_timeseries('Results EMT', results_emt_attributes_0[3], '--')\n", + "pt.plot_timeseries('Co-simulation results', results_emt_attributes_0[2], '--')\n", + "pt.plot_timeseries('Co-simulation results', results_emt_attributes_0[3], '--')\n", " \n", - "# for series in results_emt_villas_0:\n", - "# pt.plot_timeseries('Results EMT', series, '--')\n", + "pt.plot_timeseries('Co-simulation results', results_emt_villas_1[3], '--')\n", + "pt.plot_timeseries('Co-simulation results', results_emt_villas_1[4], '--')\n", + "pt.plot_timeseries('Co-simulation results', results_emt_villas_2[2], '--')\n", "\n", "plt.grid()\n", "plt.show()" @@ -1934,19 +235,11 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "cat: logs/Example1_Solver.log: No such file or directory\n" - ] - } - ], + "outputs": [], "source": [ - "!cat logs/Example1_Solver.log" + "!cat logs/EMTCosim.log" ] }, { @@ -1973,7 +266,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.11" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/examples/villas/emt-cosim-villas.py b/examples/villas/emt-cosim-villas.py index 4446497292..d3192cd5cf 100644 --- a/examples/villas/emt-cosim-villas.py +++ b/examples/villas/emt-cosim-villas.py @@ -1,64 +1,62 @@ import sys import os.path import logging -import json -import time - -from datetime import datetime -from villas.node.node import Node as VILLASnode - -from multiprocessing import Process import dpsimpy import dpsimpyvillas +import numpy as np + +from multiprocessing import Process base = os.path.splitext(os.path.basename(sys.argv[0]))[0] log = logging.getLogger(base) -def dpsim0(): +def dpsim1(): + t_s = 0.001 + t_f = 1 + + r_1_r = 0.1 + c_1_c = 1 + r_line_r = 0.1 + sim_name = "EMTCosimVILLAS1" - time_step = 1e-3 - final_time = 1.0 gnd = dpsimpy.emt.SimNode.gnd n1 = dpsimpy.emt.SimNode("n1") n2 = dpsimpy.emt.SimNode("n2") - evs = dpsimpy.emt.ph1.VoltageSource('v_intf') + evs = dpsimpy.emt.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.info) evs.set_parameters(2) - r_1 = dpsimpy.emt.ph1.Resistor("r_1") - r_1.set_parameters(0.1) - c_1 = dpsimpy.emt.ph1.Capacitor("c_1") - c_1.set_parameters(1) - r_line = dpsimpy.emt.ph1.Resistor('r_line') - r_line.set_parameters(0.1) + r_1 = dpsimpy.emt.ph1.Resistor("r_1", dpsimpy.LogLevel.info) + r_1.set_parameters(r_1_r) + c_1 = dpsimpy.emt.ph1.Capacitor("c_1", dpsimpy.LogLevel.info) + c_1.set_parameters(c_1_c) + r_line = dpsimpy.emt.ph1.Resistor('r_line', dpsimpy.LogLevel.info) + r_line.set_parameters(r_line_r) # Initial conditions n1.set_initial_voltage(5) n2.set_initial_voltage(2) # Connections - r_1.connect([n1, gnd]) - r_line.connect([n1, n2]) - c_1.connect([n1, gnd]) + r_1.connect([gnd, n1]) + r_line.connect([n2, n1]) + c_1.connect([gnd, n1]) evs.connect([gnd, n2]) sys = dpsimpy.SystemTopology(50, [gnd, n1, n2], [evs, r_1, c_1, r_line]) - sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim = dpsimpy.RealTimeSimulation(sim_name, loglevel=dpsimpy.LogLevel.debug) sim.set_domain(dpsimpy.Domain.EMT) sim.set_system(sys) - sim.set_time_step(time_step) - sim.set_final_time(final_time) + sim.set_time_step(t_s) + sim.set_final_time(t_f) intf_config = { "type": "socket", "layer": "udp", "format": "json", - "hooks": [ - {"type": "print"} - ], "in": { "address": "127.0.0.1:12008", "signals": [ @@ -66,6 +64,9 @@ def dpsim0(): "name": "v_intf", "type": "complex" } + ], + "hooks": [ + {"type": "print", "enabled": True} ] }, "out": { @@ -75,6 +76,9 @@ def dpsim0(): "name": "i_intf", "type": "complex" } + ], + "hooks": [ + {"type": "print", "enabled": True} ] } } @@ -83,37 +87,57 @@ def dpsim0(): logger = dpsimpy.Logger(sim_name) logger.log_attribute('v1', 'v', n1) - logger.log_attribute('v2', 'v', n2) - # logger.log_attribute('i_rline', 'i_intf', r_line) - # logger.log_attribute('i_evs', 'i_intf', evs) - # logger.log_attribute('v_evs', 'v_intf', evs) + logger.log_attribute('v2_S1', 'v', n2) + logger.log_attribute('i', 'i_intf', evs) + logger.log_attribute('ir', 'i_intf', r_line) + logger.log_attribute('V_ref', 'V_ref', evs) intf = dpsimpyvillas.InterfaceVillas(name="dpsim0-dpsim1", config=intf_config) sim.add_interface(intf) sim.add_logger(logger) - evs.set_intf_current([[30]]) + n1_v0 = np.array([5.0]) + n2_v0 = np.array([2.0]) + + ir_1_0 = n1_v0 / r_1_r + i_r_line_0 = (n1_v0 - n2_v0) / r_line_r + + r_1.set_intf_voltage(n1_v0) + r_1.set_intf_current(ir_1_0) + c_1.set_intf_voltage(n1_v0) + c_1.set_intf_current(ir_1_0 - i_r_line_0) + r_line.set_intf_voltage(n1_v0 - n2_v0) + r_line.set_intf_current(i_r_line_0) + + evs.set_intf_voltage(n2_v0) + evs.set_intf_current(i_r_line_0) - intf.import_attribute(evs.attr('V_ref'), 0, block_on_read=False, sync_on_start=False) - intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0), 0, wait_for_on_write=True) + # This expects to import a complex value + intf.import_attribute(evs.attr('V_ref'), 0, block_on_read=False, sync_on_start=True) + + intf.export_attribute(evs.attr('i_intf').derive_coeff(0,0).derive_complex(), 0, wait_for_on_write=False) - sim.run() + sim.run(1) -def dpsim1(): +def dpsim2(): + t_s = 0.001 + t_f = 1 + + r_load_r = 1.0 + c_2_c = 1.0 + sim_name = "EMTCosimVILLAS2" - time_step = 1e-3 - final_time = 1.0 gnd = dpsimpy.emt.SimNode.gnd n2 = dpsimpy.emt.SimNode("n2") - ecs = dpsimpy.emt.ph1.CurrentSource("i_intf") - ecs.set_parameters(3) - c_2 = dpsimpy.emt.ph1.Capacitor("c_2") - c_2.set_parameters(1) - r_load = dpsimpy.emt.ph1.Resistor('r_load') - r_load.set_parameters(1) + ecs = dpsimpy.emt.ph1.CurrentSource("i_intf", dpsimpy.LogLevel.info) + ecs.set_parameters(30) + c_2 = dpsimpy.emt.ph1.Capacitor("c_2", dpsimpy.LogLevel.info) + c_2.set_parameters(c_2_c) + r_load = dpsimpy.emt.ph1.Resistor('r_load', dpsimpy.LogLevel.info) + r_load.set_parameters(r_load_r) # Initial conditions n2.set_initial_voltage(2) @@ -125,19 +149,16 @@ def dpsim1(): sys = dpsimpy.SystemTopology(50, [gnd, n2], [ecs, c_2, r_load]) - sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim = dpsimpy.RealTimeSimulation(sim_name, loglevel=dpsimpy.LogLevel.debug) sim.set_domain(dpsimpy.Domain.EMT) sim.set_system(sys) - sim.set_time_step(time_step) - sim.set_final_time(final_time) + sim.set_time_step(t_s) + sim.set_final_time(t_f) intf_config = { "type": "socket", "layer": "udp", "format": "json", - "hooks": [ - {"type": "print"} - ], "in": { "address": "127.0.0.1:12009", "signals": [ @@ -145,6 +166,9 @@ def dpsim1(): "name": "i_intf", "type": "complex" } + ], + "hooks": [ + {"type": "print", "enabled": False} ] }, "out": { @@ -154,6 +178,9 @@ def dpsim1(): "name": "v_intf", "type": "complex" } + ], + "hooks": [ + {"type": "print", "enabled": True} ] } } @@ -161,30 +188,42 @@ def dpsim1(): dpsimpy.Logger.set_log_dir('logs/' + sim_name) logger = dpsimpy.Logger(sim_name) - logger.log_attribute('v2', 'v', n2) - # logger.log_attribute('2_i_rload', 'i_intf', r_load) - # logger.log_attribute('3_v_ecs', 'v_intf', ecs) - # logger.log_attribute('4_i_ecs', 'i_intf', ecs) + logger.log_attribute('v2_S2', 'v', n2) + logger.log_attribute('I_ref', 'I_ref', ecs) + logger.log_attribute('v', 'v_intf', ecs) intf = dpsimpyvillas.InterfaceVillas(name="dpsim1-dpsim0", config=intf_config) sim.add_interface(intf) sim.add_logger(logger) + + # Initialize currents and voltages + n2_v0 = [2.0] + i_r_load_0 = [n2_v0[0] / r_load_r] + + r_load.set_intf_voltage(n2_v0) + r_load.set_intf_current(i_r_load_0) + c_2.set_intf_voltage([n2_v0]) + + ecs.set_intf_voltage(n2_v0) + + # This expects to import a complex value intf.import_attribute(ecs.attr('I_ref'), 0, block_on_read=False, sync_on_start=False) - intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0), 0, wait_for_on_write=True) + + intf.export_attribute(ecs.attr('v_intf').derive_coeff(0,0).derive_complex(), 0, wait_for_on_write=False) - sim.run() + sim.run(1) if __name__ == '__main__': logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) - p_sim0 = Process(target=dpsim0) p_sim1 = Process(target=dpsim1) + p_sim2 = Process(target=dpsim2) - p_sim0.start() p_sim1.start() + p_sim2.start() - p_sim0.join() p_sim1.join() + p_sim2.join() print('Both simulations have ended!') From 35fcec428b35bf6928eeec72612b4333bb1fd23a Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Mon, 19 Feb 2024 19:56:53 +0000 Subject: [PATCH 34/39] First version of attributes co-simulation using ZOH extrapolation Signed-off-by: pipeacosta --- examples/Notebooks/cosim-villas-socket.ipynb | 105 ++++++-- .../emt-cosim-attributes_polynomial.py | 241 ++++++++++++++++++ 2 files changed, 324 insertions(+), 22 deletions(-) create mode 100644 examples/Python/Attributes/emt-cosim-attributes_polynomial.py diff --git a/examples/Notebooks/cosim-villas-socket.ipynb b/examples/Notebooks/cosim-villas-socket.ipynb index 64b2b8815e..723ec936ff 100644 --- a/examples/Notebooks/cosim-villas-socket.ipynb +++ b/examples/Notebooks/cosim-villas-socket.ipynb @@ -129,14 +129,14 @@ "metadata": {}, "outputs": [], "source": [ - "time_step = 0.01\n", + "time_step = 1e-6\n", "final_time = 1.0\n", "\n", "sim = dpsimpy.Simulation(\"EMTCosim\", loglevel=dpsimpy.LogLevel.debug)\n", "sim.set_domain(dpsimpy.Domain.EMT)\n", "sim.set_system(sys)\n", - "sim.set_time_step(0.01)\n", - "sim.set_final_time(1.0)\n", + "sim.set_time_step(time_step)\n", + "sim.set_final_time(final_time)\n", "\n", "log = dpsimpy.Logger(\"EMTCosim\")\n", "for i in range(1, len(sys.nodes)):\n", @@ -161,8 +161,15 @@ "outputs": [], "source": [ "import subprocess\n", + "import numpy as np\n", "\n", - "subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes.py\"])\n", + "H_v = np.array([1e-4, 0.001, 0.01])\n", + "H_v_legends = ['1e-4', '1e-3', '1e-2']\n", + "\n", + "i=0\n", + "for H in H_v:\n", + " subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-p\", \"EMTCosimAttributes_\" + H_v_legends[i]])\n", + " i+=1\n", "\n", "# TODO: Verify why the villas co-simulation does not log outputs correctly using Popen\n", "# process = subprocess.Popen([\"python3\", \"../villas/emt-cosim-villas.py\"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)" @@ -196,7 +203,9 @@ "for series in results:\n", " results_emt.append(results[series])\n", "\n", - "results_attributes1 = rt.read_timeseries_dpsim('logs/EMTCosimAttributes1/EMTCosimAttributes1.csv')\n", + "results_attributes = {}\n", + "for H_v_leg in H_v_legends:\n", + " results_attributes[H_v_leg] = rt.read_timeseries_dpsim('logs/EMTCosimAttributes_' + H_v_leg + '_S1/S1.csv')\n", "\n", "# Get logs, if the co-simulation was executed from this script\n", "# results_villas1 = rt.read_timeseries_dpsim('logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", @@ -204,35 +213,87 @@ "\n", "# If the villas co-simulation was not executed from this script, read the logs as follows\n", "# This assumes that you executed the script examples/villas/emt-cosim-villas.py previously\n", - "results_villas1 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", - "results_villas2 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS2/EMTCosimVILLAS2.csv')\n", + "# results_villas1 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", + "# results_villas2 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS2/EMTCosimVILLAS2.csv')\n", + "\n", + "results_emt_attributes = {}\n", "\n", - "results_emt_attributes_0 = []\n", - "for series in results_attributes1:\n", - " results_emt_attributes_0.append(results_attributes1[series])\n", + "for k, results_att_list in results_attributes.items():\n", + " results_emt_attributes[k] = []\n", + " for series in results_att_list:\n", + " results_emt_attributes[k].append(results_att_list[series])\n", " \n", - "results_emt_villas_1 = []\n", - "for series in results_villas1:\n", - " results_emt_villas_1.append(results_villas1[series])\n", + "# results_emt_villas_1 = []\n", + "# for series in results_villas1:\n", + "# results_emt_villas_1.append(results_villas1[series])\n", " \n", - "results_emt_villas_2 = []\n", - "for series in results_villas2:\n", - " results_emt_villas_2.append(results_villas2[series])\n", + "# results_emt_villas_2 = []\n", + "# for series in results_villas2:\n", + "# results_emt_villas_2.append(results_villas2[series])\n", "\n", "for series in results_emt:\n", " pt.plot_timeseries('Co-simulation results', series)\n", "\n", - "pt.plot_timeseries('Co-simulation results', results_emt_attributes_0[2], '--')\n", - "pt.plot_timeseries('Co-simulation results', results_emt_attributes_0[3], '--')\n", + "for k, results_att_list in results_emt_attributes.items():\n", + " pt.plot_timeseries('Co-simulation results', results_att_list[2], '--')\n", + " pt.plot_timeseries('Co-simulation results', results_att_list[3], '--')\n", " \n", - "pt.plot_timeseries('Co-simulation results', results_emt_villas_1[3], '--')\n", - "pt.plot_timeseries('Co-simulation results', results_emt_villas_1[4], '--')\n", - "pt.plot_timeseries('Co-simulation results', results_emt_villas_2[2], '--')\n", + "# pt.plot_timeseries('Co-simulation results', results_emt_villas_1[3], '--')\n", + "# pt.plot_timeseries('Co-simulation results', results_emt_villas_1[4], '--')\n", + "# pt.plot_timeseries('Co-simulation results', results_emt_villas_2[2], '--')\n", "\n", "plt.grid()\n", "plt.show()" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Obtain the co-simulation errors" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "global_error_v = []\n", + "\n", + "for i in range(0, len(H_v_legends)): \n", + " H = H_v[i]\n", + " \n", + " m = int(H/time_step)\n", + " \n", + " ts_1_m = results_emt[0]\n", + " ts_2_m = results_emt[1]\n", + " \n", + " ts_1 = results_emt_attributes[H_v_legends[i]][2]\n", + " ts_2 = results_emt_attributes[H_v_legends[i]][3]\n", + " \n", + " v_a = np.array([ts_1_m.values[::m], ts_2_m.values[::m]])\n", + " v_zoh = np.array([ts_1.values[::m], ts_2.values[::m]])\n", + " \n", + " global_error_v.append(np.max(np.linalg.norm(v_a - v_zoh, axis=0)))\n", + " \n", + "plt.figure()\n", + "plt.plot(np.log10(H_v), np.log10(global_error_v), 'b', label='ZOH')\n", + "plt.plot(np.log10(H_v), np.log10(global_error_v), 'bo')\n", + "plt.plot(np.log10(H_v), np.log10(np.multiply(H_v, 10**1)), 'k', label=r'$\\mathcal{O}(H)$')\n", + "plt.xlabel('')\n", + "# TODO: Fix log scale\n", + "# plt.xscale(\"log\")\n", + "# plt.yscale(\"log\")\n", + "plt.grid()\n", + "plt.legend()\n", + "\n", + "plt.tight_layout()\n", + "plt.show()\n", + " \n", + " " + ] + }, { "cell_type": "code", "execution_count": null, @@ -266,7 +327,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.11" } }, "nbformat": 4, diff --git a/examples/Python/Attributes/emt-cosim-attributes_polynomial.py b/examples/Python/Attributes/emt-cosim-attributes_polynomial.py new file mode 100644 index 0000000000..f748de92bc --- /dev/null +++ b/examples/Python/Attributes/emt-cosim-attributes_polynomial.py @@ -0,0 +1,241 @@ +import sys +import os.path +import logging + +import dpsimpy +import numpy as np +import argparse + +base = os.path.splitext(os.path.basename(sys.argv[0]))[0] +log = logging.getLogger(base) + +def set_dpsim1(t_s, t_f, u_1_0, logger_prefix): + r_1_r = 0.1 + c_1_c = 1 + r_line_r = 0.1 + + # sim_name = "EMTCosimAttributes1" + sim_name = "S1" + + gnd = dpsimpy.emt.SimNode.gnd + n1 = dpsimpy.emt.SimNode("n1") + n2 = dpsimpy.emt.SimNode("n2") + + evs = dpsimpy.emt.ph1.VoltageSource("v_intf", dpsimpy.LogLevel.info) + evs.set_parameters(u_1_0) + + r_1 = dpsimpy.emt.ph1.Resistor("r_1", dpsimpy.LogLevel.info) + r_1.set_parameters(r_1_r) + c_1 = dpsimpy.emt.ph1.Capacitor("c_1", dpsimpy.LogLevel.info) + c_1.set_parameters(c_1_c) + r_line = dpsimpy.emt.ph1.Resistor("r_line", dpsimpy.LogLevel.info) + r_line.set_parameters(r_line_r) + + # Initial conditions + n1.set_initial_voltage(5) + n2.set_initial_voltage(u_1_0) + + # Connections + r_1.connect([gnd, n1]) + r_line.connect([n2, n1]) + c_1.connect([gnd, n1]) + evs.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [gnd, n1, n2], [evs, r_1, c_1, r_line]) + + sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim.set_domain(dpsimpy.Domain.EMT) + sim.set_system(sys) + sim.set_time_step(t_s) + sim.set_final_time(t_f) + # sim.do_steady_state_init(True) + + dpsimpy.Logger.set_log_dir('logs/' + logger_prefix + '_' + sim_name) + + logger = dpsimpy.Logger(sim_name) + logger.log_attribute('v1', 'v', n1) + logger.log_attribute('v2', 'v', n2) + logger.log_attribute('i', 'i_intf', evs) + logger.log_attribute('ir', 'i_intf', r_line) + + sim.add_logger(logger) + + n1_v0 = np.array([5.0]) + n2_v0 = np.array([u_1_0]) + + ir_1_0 = n1_v0 / r_1_r + i_r_line_0 = (n1_v0 - n2_v0) / r_line_r + + r_1.set_intf_voltage(n1_v0) + r_1.set_intf_current(ir_1_0) + c_1.set_intf_voltage(n1_v0) + c_1.set_intf_current(ir_1_0 - i_r_line_0) + r_line.set_intf_voltage(n1_v0 - n2_v0) + r_line.set_intf_current(i_r_line_0) + + evs.set_intf_voltage(n2_v0) + evs.set_intf_current(i_r_line_0) + + return sim + + +def set_dpsim2(t_s, t_f, logger_prefix): + r_load_r = 1.0 + c_2_c = 1.0 + + # sim_name = "EMTCosimAttributes2" + sim_name = "S2" + + gnd = dpsimpy.emt.SimNode.gnd + n2 = dpsimpy.emt.SimNode("n2") + + ecs = dpsimpy.emt.ph1.CurrentSource("i_intf", dpsimpy.LogLevel.info) + c_2 = dpsimpy.emt.ph1.Capacitor("c_2", dpsimpy.LogLevel.info) + c_2.set_parameters(c_2_c) + r_load = dpsimpy.emt.ph1.Resistor("r_load", dpsimpy.LogLevel.info) + r_load.set_parameters(r_load_r) + + # Initial conditions + n2.set_initial_voltage(2.0) + + # Connections + ecs.connect([gnd, n2]) + c_2.connect([gnd, n2]) + r_load.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [gnd, n2], [ecs, c_2, r_load]) + + sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim.set_domain(dpsimpy.Domain.EMT) + sim.set_system(sys) + sim.set_time_step(t_s) + sim.set_final_time(t_f) + + dpsimpy.Logger.set_log_dir('logs/' + logger_prefix + '_' + sim_name) + + logger = dpsimpy.Logger(sim_name) + logger.log_attribute('v2', 'v', n2) + logger.log_attribute('i', 'i_intf', ecs) + logger.log_attribute('v', 'v_intf', ecs) + + sim.add_logger(logger) + + # Initialize currents and voltages + n2_v0 = [2.0] + i_r_load_0 = [n2_v0[0] / r_load_r] + + r_load.set_intf_voltage(n2_v0) + r_load.set_intf_current(i_r_load_0) + c_2.set_intf_voltage([n2_v0]) + + ecs.set_intf_voltage(n2_v0) + + return sim + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-t', '--timestep', type=float, required=True) + parser.add_argument('-e', '--end', type=float, required=True) + parser.add_argument('-H', '--macro-step', type=float, required=True) + parser.add_argument('-i', '--interp', default='zoh') + parser.add_argument('-p', '--prefix', default='') + parser.add_argument('-d', '--debug', type=bool, default=False) + + args = parser.parse_args() + + time_step = args.timestep + t_f = args.end + H = args.macro_step + interp = args.interp + prefix = args.prefix + debug = args.debug + + logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) + + # time_step = 0.001 + t_0 = 0.0 + # t_f = 1 + t_k = 0.0 + + # H = 0.01 + + N = int(round((t_f - t_0) / H)) + + t_m = np.around(np.linspace(t_0, t_f, N + 1), 16) + + m = int(H/time_step) + print(m) + + # Initialization of S_2 and communication y_2_0 -> S_1 + sim2 = set_dpsim2(time_step, t_f, prefix) + sim2.start() + y_2_0 = sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() + + if debug: + print("Output value from S2: {:f}".format(y_2_0)) + + # Communication y_2_0 -> S_1 and initialization of S_1 + u_1_0 = y_2_0 + sim1 = set_dpsim1(time_step, t_f, u_1_0, prefix) + sim1.start() + y_1_0 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() + + if debug: + print("Output value from S1: {:f}".format(y_1_0)) + + y_1 = y_1_0 + + # We have to assume the trajectory of y_2 extending its initial value, since we have no prior information + y_1_m_prev = np.tile(y_1_0, m) + + + for i in range(0, N+1): + y_1_prev = y_1_m_prev[-1] + + # Extrapolation: Zero order hold + if interp == 'zoh': + u_2_m = np.tile(y_1_prev, m) + + # j = 0 + y_1_m = np.zeros(m) + + for j in range(0, m): + # Switch to S_2 + if debug: + u_2_prev = sim2.get_idobj_attr("i_intf", "i_intf").derive_coeff(0,0).get() + print("Input value in S2 before set: {:f}".format(u_2_prev)) + + u_2 = u_2_m[j] + sim2.get_idobj_attr("i_intf", "I_ref").set(complex(u_2,0)) + + if debug: + u_2_test = sim2.get_idobj_attr("i_intf", "I_ref").get() + print("Input value in S2 after set: {:f}".format(u_2_test)) + + sim2.next() + y_2 = sim2.get_idobj_attr("i_intf", "v_intf").derive_coeff(0,0).get() + + if debug: + print("Output value from S2: {:f}".format(y_2)) + + u_1 = y_2 + + sim1.get_idobj_attr("v_intf", "V_ref").set(complex(u_1,0)) + t_k = sim1.next() + y_1 = sim1.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() + + y_1_m[j] = y_1 + # j += 1 + + if debug: + print("Output value from S1: {:f}".format(y_1)) + print("Time t={:f}".format(t_k)) + print("DPsim iteration: {}".format(j)) + + y_1_m_prev = y_1_m + if debug: + print(y_1_m_prev) + + sim2.stop() + sim1.stop() + \ No newline at end of file From 7401a2320c0fd62e145fc37bda7665bbe3aecab9 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Tue, 20 Feb 2024 18:14:10 +0000 Subject: [PATCH 35/39] First version of attributes co-simulation using linear extrapolation Signed-off-by: pipeacosta --- examples/Notebooks/cosim-villas-socket.ipynb | 53 +++++++++++++------ .../emt-cosim-attributes_polynomial.py | 21 +++++--- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/examples/Notebooks/cosim-villas-socket.ipynb b/examples/Notebooks/cosim-villas-socket.ipynb index 723ec936ff..0a77176170 100644 --- a/examples/Notebooks/cosim-villas-socket.ipynb +++ b/examples/Notebooks/cosim-villas-socket.ipynb @@ -168,7 +168,8 @@ "\n", "i=0\n", "for H in H_v:\n", - " subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-p\", \"EMTCosimAttributes_\" + H_v_legends[i]])\n", + " subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-p\", \"EMTCosimAttributes_zoh_\" + H_v_legends[i]])\n", + " subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-i\", \"linear\", \"-p\", \"EMTCosimAttributes_linear_\" + H_v_legends[i]])\n", " i+=1\n", "\n", "# TODO: Verify why the villas co-simulation does not log outputs correctly using Popen\n", @@ -203,9 +204,13 @@ "for series in results:\n", " results_emt.append(results[series])\n", "\n", - "results_attributes = {}\n", + "results_attributes_zoh = {}\n", "for H_v_leg in H_v_legends:\n", - " results_attributes[H_v_leg] = rt.read_timeseries_dpsim('logs/EMTCosimAttributes_' + H_v_leg + '_S1/S1.csv')\n", + " results_attributes_zoh[H_v_leg] = rt.read_timeseries_dpsim('logs/EMTCosimAttributes_zoh_' + H_v_leg + '_S1/S1.csv')\n", + " \n", + "results_attributes_linear = {}\n", + "for H_v_leg in H_v_legends:\n", + " results_attributes_linear[H_v_leg] = rt.read_timeseries_dpsim('logs/EMTCosimAttributes_linear_' + H_v_leg + '_S1/S1.csv')\n", "\n", "# Get logs, if the co-simulation was executed from this script\n", "# results_villas1 = rt.read_timeseries_dpsim('logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", @@ -216,12 +221,19 @@ "# results_villas1 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", "# results_villas2 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS2/EMTCosimVILLAS2.csv')\n", "\n", - "results_emt_attributes = {}\n", + "results_emt_attributes_zoh = {}\n", "\n", - "for k, results_att_list in results_attributes.items():\n", - " results_emt_attributes[k] = []\n", + "for k, results_att_list in results_attributes_zoh.items():\n", + " results_emt_attributes_zoh[k] = []\n", " for series in results_att_list:\n", - " results_emt_attributes[k].append(results_att_list[series])\n", + " results_emt_attributes_zoh[k].append(results_att_list[series])\n", + " \n", + "results_emt_attributes_linear = {}\n", + "\n", + "for k, results_att_list in results_attributes_linear.items():\n", + " results_emt_attributes_linear[k] = []\n", + " for series in results_att_list:\n", + " results_emt_attributes_linear[k].append(results_att_list[series])\n", " \n", "# results_emt_villas_1 = []\n", "# for series in results_villas1:\n", @@ -234,7 +246,7 @@ "for series in results_emt:\n", " pt.plot_timeseries('Co-simulation results', series)\n", "\n", - "for k, results_att_list in results_emt_attributes.items():\n", + "for k, results_att_list in results_emt_attributes_zoh.items():\n", " pt.plot_timeseries('Co-simulation results', results_att_list[2], '--')\n", " pt.plot_timeseries('Co-simulation results', results_att_list[3], '--')\n", " \n", @@ -259,7 +271,8 @@ "metadata": {}, "outputs": [], "source": [ - "global_error_v = []\n", + "global_error_zoh = []\n", + "global_error_linear = []\n", "\n", "for i in range(0, len(H_v_legends)): \n", " H = H_v[i]\n", @@ -269,18 +282,26 @@ " ts_1_m = results_emt[0]\n", " ts_2_m = results_emt[1]\n", " \n", - " ts_1 = results_emt_attributes[H_v_legends[i]][2]\n", - " ts_2 = results_emt_attributes[H_v_legends[i]][3]\n", + " ts_1_zoh = results_emt_attributes_zoh[H_v_legends[i]][2]\n", + " ts_2_zoh = results_emt_attributes_zoh[H_v_legends[i]][3]\n", + " \n", + " ts_1_linear = results_emt_attributes_linear[H_v_legends[i]][2]\n", + " ts_2_linear = results_emt_attributes_linear[H_v_legends[i]][3]\n", " \n", " v_a = np.array([ts_1_m.values[::m], ts_2_m.values[::m]])\n", - " v_zoh = np.array([ts_1.values[::m], ts_2.values[::m]])\n", + " v_zoh = np.array([ts_1_zoh.values[::m], ts_2_zoh.values[::m]])\n", + " v_linear = np.array([ts_1_linear.values[::m], ts_2_linear.values[::m]])\n", " \n", - " global_error_v.append(np.max(np.linalg.norm(v_a - v_zoh, axis=0)))\n", + " global_error_zoh.append(np.max(np.linalg.norm(v_a - v_zoh, axis=0)))\n", + " global_error_linear.append(np.max(np.linalg.norm(v_a - v_linear, axis=0)))\n", " \n", "plt.figure()\n", - "plt.plot(np.log10(H_v), np.log10(global_error_v), 'b', label='ZOH')\n", - "plt.plot(np.log10(H_v), np.log10(global_error_v), 'bo')\n", + "plt.plot(np.log10(H_v), np.log10(global_error_zoh), 'b', label='ZOH')\n", + "plt.plot(np.log10(H_v), np.log10(global_error_zoh), 'bo')\n", "plt.plot(np.log10(H_v), np.log10(np.multiply(H_v, 10**1)), 'k', label=r'$\\mathcal{O}(H)$')\n", + "plt.plot(np.log10(H_v), np.log10(global_error_linear), 'r', label='Linear')\n", + "plt.plot(np.log10(H_v), np.log10(global_error_linear), 'ro')\n", + "plt.plot(np.log10(H_v), np.log10(np.multiply(H_v**2, 10**2.6)), '--k', label=r'$\\mathcal{O}(H^2)$')\n", "plt.xlabel('')\n", "# TODO: Fix log scale\n", "# plt.xscale(\"log\")\n", @@ -327,7 +348,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.11" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/examples/Python/Attributes/emt-cosim-attributes_polynomial.py b/examples/Python/Attributes/emt-cosim-attributes_polynomial.py index f748de92bc..8a318eadef 100644 --- a/examples/Python/Attributes/emt-cosim-attributes_polynomial.py +++ b/examples/Python/Attributes/emt-cosim-attributes_polynomial.py @@ -157,10 +157,10 @@ def set_dpsim2(t_s, t_f, logger_prefix): # t_f = 1 t_k = 0.0 - # H = 0.01 + n = int(round((t_f - t_0) / time_step)) + t = np.around(np.linspace(t_0, t_f, n + 1), 16) N = int(round((t_f - t_0) / H)) - t_m = np.around(np.linspace(t_0, t_f, N + 1), 16) m = int(H/time_step) @@ -188,18 +188,21 @@ def set_dpsim2(t_s, t_f, logger_prefix): # We have to assume the trajectory of y_2 extending its initial value, since we have no prior information y_1_m_prev = np.tile(y_1_0, m) - - for i in range(0, N+1): + for i in range(0, N): y_1_prev = y_1_m_prev[-1] + t_m_i = t[m*i : m*(i+1) + 1] # Extrapolation: Zero order hold if interp == 'zoh': - u_2_m = np.tile(y_1_prev, m) + u_2_m = np.tile(y_1_prev, m+1) + elif interp == 'linear': + f_u_2 = np.poly1d(np.polyfit([i*H-H, i*H], y_1_m_prev[-2:], 1)) + u_2_m = f_u_2(t_m_i) # j = 0 - y_1_m = np.zeros(m) + y_1_m = np.zeros(m+1) - for j in range(0, m): + for j in range(0, m+1): # Switch to S_2 if debug: u_2_prev = sim2.get_idobj_attr("i_intf", "i_intf").derive_coeff(0,0).get() @@ -232,7 +235,9 @@ def set_dpsim2(t_s, t_f, logger_prefix): print("Time t={:f}".format(t_k)) print("DPsim iteration: {}".format(j)) - y_1_m_prev = y_1_m + # y_1_m_prev = y_1_m + y_1_m_prev = np.append(y_1_m_prev, y_1_m[-1]) + if debug: print(y_1_m_prev) From b48062ccac7aa5279c8b0552559af9e2d293e940 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Tue, 20 Feb 2024 20:33:08 +0000 Subject: [PATCH 36/39] Adapt paths to make the CI happy Signed-off-by: pipeacosta --- examples/Notebooks/cosim-villas-socket.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/Notebooks/cosim-villas-socket.ipynb b/examples/Notebooks/cosim-villas-socket.ipynb index 0a77176170..7a46ee30dd 100644 --- a/examples/Notebooks/cosim-villas-socket.ipynb +++ b/examples/Notebooks/cosim-villas-socket.ipynb @@ -168,8 +168,8 @@ "\n", "i=0\n", "for H in H_v:\n", - " subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-p\", \"EMTCosimAttributes_zoh_\" + H_v_legends[i]])\n", - " subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-i\", \"linear\", \"-p\", \"EMTCosimAttributes_linear_\" + H_v_legends[i]])\n", + " subprocess.run([\"python3\", \"examples/Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-p\", \"EMTCosimAttributes_zoh_\" + H_v_legends[i]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + " subprocess.run([\"python3\", \"examples/Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-i\", \"linear\", \"-p\", \"EMTCosimAttributes_linear_\" + H_v_legends[i]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", " i+=1\n", "\n", "# TODO: Verify why the villas co-simulation does not log outputs correctly using Popen\n", @@ -348,7 +348,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.10.11" } }, "nbformat": 4, From 7e7543263126daf955e210bbc2859c8935f66bf3 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Wed, 21 Feb 2024 17:41:51 +0000 Subject: [PATCH 37/39] Add deriveComplex function to Attributes.cpp example Signed-off-by: pipeacosta --- dpsim/examples/cxx/Attributes/Attributes.cpp | 4 ++++ dpsim/examples/cxx/CMakeLists.txt | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/dpsim/examples/cxx/Attributes/Attributes.cpp b/dpsim/examples/cxx/Attributes/Attributes.cpp index 819d2b99f4..c8b5e081ca 100644 --- a/dpsim/examples/cxx/Attributes/Attributes.cpp +++ b/dpsim/examples/cxx/Attributes/Attributes.cpp @@ -24,5 +24,9 @@ int main(int argc, char* argv[]) { Real read3 = **attr; //read3 = 0.003 cout << "attr value: " << read3 << endl; + Attribute::Ptr attrComplex = attr->deriveComplex(); + Complex read4 = **attrComplex; + cout << "derived complex attr value: " << read4 << endl; + return 0; } diff --git a/dpsim/examples/cxx/CMakeLists.txt b/dpsim/examples/cxx/CMakeLists.txt index d10d856309..8d321ded8e 100644 --- a/dpsim/examples/cxx/CMakeLists.txt +++ b/dpsim/examples/cxx/CMakeLists.txt @@ -111,6 +111,10 @@ set(INVERTER_SOURCES Components/DP_Inverter_Grid_Sequential_FreqSplit.cpp ) +set(ATTRIBUTES_SOURCES + Attributes/Attributes.cpp +) + # Targets required for tests in the Jupyter Notebooks. This list is only for grouping the (already configured) targets, so every entry # also has to appear in another list in this file. list(APPEND TEST_SOURCES From ab26dd9be9715456fdeb0504b304b91f72340341 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sun, 17 Mar 2024 10:43:42 +0100 Subject: [PATCH 38/39] First working version of co-simulation between DPsim and Matlab Signed-off-by: pipeacosta --- .../emt-cosim-udp-matlab-dpsim.py | 141 ++++++++++++++++++ .../emt-cosim-udp-matlab-matlab.m | 94 ++++++++++++ 2 files changed, 235 insertions(+) create mode 100644 examples/villas/emt-cosim-udp-matlab/emt-cosim-udp-matlab-dpsim.py create mode 100644 examples/villas/emt-cosim-udp-matlab/emt-cosim-udp-matlab-matlab.m diff --git a/examples/villas/emt-cosim-udp-matlab/emt-cosim-udp-matlab-dpsim.py b/examples/villas/emt-cosim-udp-matlab/emt-cosim-udp-matlab-dpsim.py new file mode 100644 index 0000000000..fbb625b434 --- /dev/null +++ b/examples/villas/emt-cosim-udp-matlab/emt-cosim-udp-matlab-dpsim.py @@ -0,0 +1,141 @@ +import sys +import os.path +import logging + +import dpsimpy +import dpsimpyvillas +import numpy as np +import time, socket, errno, signal, struct + +from multiprocessing import Process + +base = os.path.splitext(os.path.basename(sys.argv[0]))[0] +log = logging.getLogger(base) + +if __name__ == '__main__': + local = ("0.0.0.0", 12008) + remote = (os.environ.get('MATLAB_HOST'), 12009) + + logging.basicConfig(format='[%(asctime)s %(name)s %(levelname)s] %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) + t_0 = 0.0 + t_s = 0.001 + t_f = 1 + + r_1_r = 0.1 + c_1_c = 1 + r_line_r = 0.1 + + sim_name = "EMTCosimUDP1" + + gnd = dpsimpy.emt.SimNode.gnd + n1 = dpsimpy.emt.SimNode("n1") + n2 = dpsimpy.emt.SimNode("n2") + + evs = dpsimpy.emt.ph1.VoltageSource('v_intf', dpsimpy.LogLevel.info) + evs.set_parameters(2) + + r_1 = dpsimpy.emt.ph1.Resistor("r_1", dpsimpy.LogLevel.info) + r_1.set_parameters(r_1_r) + c_1 = dpsimpy.emt.ph1.Capacitor("c_1", dpsimpy.LogLevel.info) + c_1.set_parameters(c_1_c) + r_line = dpsimpy.emt.ph1.Resistor('r_line', dpsimpy.LogLevel.info) + r_line.set_parameters(r_line_r) + + # Initial conditions + n1.set_initial_voltage(5) + n2.set_initial_voltage(2) + + # Connections + r_1.connect([gnd, n1]) + r_line.connect([n2, n1]) + c_1.connect([gnd, n1]) + evs.connect([gnd, n2]) + + sys = dpsimpy.SystemTopology(50, [gnd, n1, n2], [evs, r_1, c_1, r_line]) + + sim = dpsimpy.Simulation(sim_name, loglevel=dpsimpy.LogLevel.debug) + sim.set_domain(dpsimpy.Domain.EMT) + sim.set_system(sys) + sim.set_time_step(t_s) + sim.set_final_time(t_f) + + dpsimpy.Logger.set_log_dir('logs/' + sim_name) + + logger = dpsimpy.Logger(sim_name) + logger.log_attribute('v1', 'v', n1) + logger.log_attribute('v2_S1', 'v', n2) + logger.log_attribute('i', 'i_intf', evs) + logger.log_attribute('ir', 'i_intf', r_line) + logger.log_attribute('V_ref', 'V_ref', evs) + + sim.add_logger(logger) + + n1_v0 = np.array([5.0]) + n2_v0 = np.array([2.0]) + + ir_1_0 = n1_v0 / r_1_r + i_r_line_0 = (n1_v0 - n2_v0) / r_line_r + + r_1.set_intf_voltage(n1_v0) + r_1.set_intf_current(ir_1_0) + c_1.set_intf_voltage(n1_v0) + c_1.set_intf_current(ir_1_0 - i_r_line_0) + r_line.set_intf_voltage(n1_v0 - n2_v0) + r_line.set_intf_current(i_r_line_0) + + evs.set_intf_voltage(n2_v0) + evs.set_intf_current(i_r_line_0) + + sim.start() + + skt = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + # This client must be started first + print("Start client...") + + skt.bind(local) + + # Try to connect in case Unix domain socket does not exist yet.. + connected = False + while not connected: + try: + skt.connect(remote) + except socket.error as serr: + if serr.errno not in [errno.ECONNREFUSED, errno.ENOENT]: + raise serr + + print("Not connected. Retrying in 1 sec") + time.sleep(1) + else: + connected = True + + print("Ready. Ctrl-C to quit.") + + + # Gracefully shutdown + def sighandler(signum, frame): + running = False + + + signal.signal(signal.SIGINT, sighandler) + signal.signal(signal.SIGTERM, sighandler) + + running = True + t_k = 0.0 + + while t_k < t_f: + dgram, addr = skt.recvfrom(1024) + if not dgram: + break + else: + u_1 = struct.unpack('f', dgram) + print(u_1) + + sim.get_idobj_attr("v_intf", "V_ref").set(complex(u_1[0],0)) + t_k = sim.next() + y_1 = sim.get_idobj_attr("v_intf", "i_intf").derive_coeff(0,0).get() + skt.send(struct.pack('f', y_1)) + + skt.close() + + print("Bye.") \ No newline at end of file diff --git a/examples/villas/emt-cosim-udp-matlab/emt-cosim-udp-matlab-matlab.m b/examples/villas/emt-cosim-udp-matlab/emt-cosim-udp-matlab-matlab.m new file mode 100644 index 0000000000..9401950fc3 --- /dev/null +++ b/examples/villas/emt-cosim-udp-matlab/emt-cosim-udp-matlab-matlab.m @@ -0,0 +1,94 @@ +% Author: Andres Acosta +% SPDX-FileCopyrightText: 2014-2024 Institute for Automation of Complex Power Systems, RWTH Aachen University +% SPDX-License-Identifier: Apache-2.0 +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +close all; +clc; + +warning('off','Control:analysis:LsimStartTime') +set(0, 'DefaultLineLineWidth', 1.5); + +n_x2 = 1; +n_u2 = 1; +n_y2 = 1; + +R_3 = 1; +C_2 = 1; + +A_2 = -1/(R_3*C_2); +B_2 = 1/C_2; +C_2 = 1; +D_2 = 0; + +x_2_0 = 2; +y_2_0 = C_2*x_2_0; + +fprintf('Output value from S_2: %f\n', y_2_0); + +% Configuration and connection +u = udp(DPSIM_HOST, ... + 'LocalPort', 12009, ... + 'RemotePort', 12008, ... + 'Timeout', 10, ... + 'DatagramTerminateMode', 'on', ... + 'ByteOrder', 'littleEndian' ... +); +disp('UDP Receiver started'); + +fopen(u); +disp('UDP Socket bound'); + +num_values = 1; +t_s = 0.001; +t_f = 1; + +t = 0:t_s:t_f; + +ss_2 = ss(A_2, B_2, C_2, D_2); + +u_2_v = zeros(1, length(t)); +u_2_v(1) = 30; % This should be sent from the other subsystem +y_2_v = zeros(1, length(t)); +y_2_v(1) = y_2_0; + +% Send initial output +fwrite(u, y_2_0, 'float'); + +i = 2; + +while i <= length(t) + % Receive input from S_1 + [ u_2, c_u_2 ] = fread(u, num_values, 'float'); + + fprintf('Received output value from S_1: %f\n', u_2(1)); + + if ~isempty(u_2) + u_2_v(i) = double(u_2(1)); + end + + [y_2,~,x_2] = lsim(ss_2, u_2_v(i-1)*ones(1,2), t(i-1:i), x_2_0); + fprintf('Output value from S_2: %f\n', y_2(end)); + +% fwrite(u, [0, single(y_2(end))], 'float'); + fwrite(u, y_2(end), 'float'); + + x_2_0 = x_2(end); + y_2_v(i) = y_2(end); + i = i + 1; +end + +figure(); +plot(t, u_2_v); +grid on +xlabel('t [s]') +ylabel('$i_2$ [A]', 'Interpreter', 'Latex') + +figure(); +plot(t, y_2_v); +grid on +xlabel('t [s]') +ylabel('$v_2$ [V]', 'Interpreter', 'Latex') + +fclose(u); +delete(u); From 5c96c00810d5ae4911ea87067a8ed5363b9ab0e0 Mon Sep 17 00:00:00 2001 From: pipeacosta Date: Sun, 24 Mar 2024 17:47:50 +0100 Subject: [PATCH 39/39] Add results of DPsim-Matlab co-simulation to the Notebook Signed-off-by: pipeacosta --- examples/Notebooks/cosim-villas-socket.ipynb | 3205 +++++++++++++++++- 1 file changed, 3188 insertions(+), 17 deletions(-) diff --git a/examples/Notebooks/cosim-villas-socket.ipynb b/examples/Notebooks/cosim-villas-socket.ipynb index 7a46ee30dd..e84150b4d0 100644 --- a/examples/Notebooks/cosim-villas-socket.ipynb +++ b/examples/Notebooks/cosim-villas-socket.ipynb @@ -34,7 +34,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -52,7 +52,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -93,7 +93,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -109,9 +109,171 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Warning: some nodes with margin (3.20,3.20) touch - falling back to straight line edges\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "topology\n", + "\n", + "\n", + "\n", + "gnd\n", + "\n", + "\n", + "\n", + "\n", + "gnd\n", + "\n", + "\n", + "\n", + "n1\n", + "\n", + "\n", + "\n", + "\n", + "n1\n", + "(5.00 V > 0.00°)\n", + "\n", + "\n", + "\n", + "n2\n", + "\n", + "\n", + "\n", + "\n", + "n2\n", + "(2.00 V > 0.00°)\n", + "\n", + "\n", + "\n", + "r_1\n", + "\n", + "\n", + "r_1\n", + "EMT::Ph1::Resistor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "r_1--gnd\n", + "\n", + "\n", + "\n", + "\n", + "r_1--n1\n", + "\n", + "\n", + "\n", + "\n", + "r_line\n", + "\n", + "\n", + "r_line\n", + "EMT::Ph1::Resistor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "r_line--n1\n", + "\n", + "\n", + "\n", + "\n", + "r_line--n2\n", + "\n", + "\n", + "\n", + "\n", + "c_1\n", + "\n", + "\n", + "c_1\n", + "EMT::Ph1::Capacitor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "c_1--gnd\n", + "\n", + "\n", + "\n", + "\n", + "c_1--n1\n", + "\n", + "\n", + "\n", + "\n", + "c_2\n", + "\n", + "\n", + "c_2\n", + "EMT::Ph1::Capacitor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "c_2--gnd\n", + "\n", + "\n", + "\n", + "\n", + "c_2--n2\n", + "\n", + "\n", + "\n", + "\n", + "r_load\n", + "\n", + "\n", + "r_load\n", + "EMT::Ph1::Resistor\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "r_load--gnd\n", + "\n", + "\n", + "\n", + "\n", + "r_load--n2\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "sys" ] @@ -125,9 +287,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "[07:52:58.353939 EMTCosim info] Initialize simulation: EMTCosim\n", + "[07:52:58.354170 MnaSolverFactory info] creating KLUAdapter solver implementation\n", + "[07:52:58.354817 EMTCosim info] Scheduling tasks.\n", + "[07:52:58.355182 EMTCosim info] Scheduling done.\n", + "[07:52:58.355185 EMTCosim info] Opening interfaces.\n", + "[07:52:58.355188 EMTCosim info] Start synchronization with remotes on interfaces\n", + "[07:52:58.355190 EMTCosim info] Synchronized simulation start with remotes\n", + "[07:52:58.355193 EMTCosim info] Start simulation: EMTCosim\n", + "[07:52:58.355200 EMTCosim info] Time step: 1.000000e-06\n", + "[07:52:58.355204 EMTCosim info] Final time: 1.000000e+00\n", + "[07:53:08.913325 EMTCosim info] Simulation calculation time: 10.558085\n", + "[07:53:08.980948 EMTCosim info] Simulation finished.\n" + ] + } + ], "source": [ "time_step = 1e-6\n", "final_time = 1.0\n", @@ -156,7 +337,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -168,8 +349,8 @@ "\n", "i=0\n", "for H in H_v:\n", - " subprocess.run([\"python3\", \"examples/Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-p\", \"EMTCosimAttributes_zoh_\" + H_v_legends[i]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", - " subprocess.run([\"python3\", \"examples/Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-i\", \"linear\", \"-p\", \"EMTCosimAttributes_linear_\" + H_v_legends[i]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + " subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-p\", \"EMTCosimAttributes_zoh_\" + H_v_legends[i]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", + " subprocess.run([\"python3\", \"../Python/Attributes/emt-cosim-attributes_polynomial.py\", \"-t\", str(time_step), \"-e\", \"1\", \"-H\", str(H), \"-i\", \"linear\", \"-p\", \"EMTCosimAttributes_linear_\" + H_v_legends[i]], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n", " i+=1\n", "\n", "# TODO: Verify why the villas co-simulation does not log outputs correctly using Popen\n", @@ -185,9 +366,2028 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "column number: 2\n", + "results length: 1000000\n", + "real column names: ['v1', 'v2']\n", + "complex column names: []\n", + "column number: 4\n", + "results length: 1000000\n", + "real column names: ['i', 'ir', 'v1', 'v2']\n", + "complex column names: []\n", + "column number: 4\n", + "results length: 1000000\n", + "real column names: ['i', 'ir', 'v1', 'v2']\n", + "complex column names: []\n", + "column number: 4\n", + "results length: 1000000\n", + "real column names: ['i', 'ir', 'v1', 'v2']\n", + "complex column names: []\n", + "column number: 4\n", + "results length: 1000000\n", + "real column names: ['i', 'ir', 'v1', 'v2']\n", + "complex column names: []\n", + "column number: 4\n", + "results length: 1000000\n", + "real column names: ['i', 'ir', 'v1', 'v2']\n", + "complex column names: []\n", + "column number: 4\n", + "results length: 1000000\n", + "real column names: ['i', 'ir', 'v1', 'v2']\n", + "complex column names: []\n", + "column number: 5\n", + "results length: 1000\n", + "real column names: ['i', 'ir', 'v1', 'v2_S1']\n", + "complex column names: ['V_ref']\n" + ] + }, + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2024-03-19T07:53:14.334819\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.8.0, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "%matplotlib inline\n", "%config InlineBackend.figure_format = 'svg'\n", @@ -221,6 +2421,13 @@ "# results_villas1 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS1/EMTCosimVILLAS1.csv')\n", "# results_villas2 = rt.read_timeseries_dpsim('../../logs/EMTCosimVILLAS2/EMTCosimVILLAS2.csv')\n", "\n", + "# Get logs from the co-simulation with Matlab\n", + "results_matlab = rt.read_timeseries_dpsim('logs/EMTCosimUDP1/EMTCosimUDP1.csv')\n", + "\n", + "results_emt_matlab = []\n", + "for series in results_matlab:\n", + " results_emt_matlab.append(results_matlab[series])\n", + "\n", "results_emt_attributes_zoh = {}\n", "\n", "for k, results_att_list in results_attributes_zoh.items():\n", @@ -254,6 +2461,9 @@ "# pt.plot_timeseries('Co-simulation results', results_emt_villas_1[4], '--')\n", "# pt.plot_timeseries('Co-simulation results', results_emt_villas_2[2], '--')\n", "\n", + "pt.plot_timeseries('Co-simulation results', results_emt_matlab[3], '-.')\n", + "pt.plot_timeseries('Co-simulation results', results_emt_matlab[4], '-.')\n", + "\n", "plt.grid()\n", "plt.show()" ] @@ -267,9 +2477,951 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " 2024-03-19T07:53:14.804341\n", + " image/svg+xml\n", + " \n", + " \n", + " Matplotlib v3.8.0, https://matplotlib.org/\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "\n" + ], + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "global_error_zoh = []\n", "global_error_linear = []\n", @@ -317,9 +3469,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[I] Initialize simulation: EMTCosim\n", + "[I] Scheduling tasks.\n", + "[I] Scheduling done.\n", + "[I] Opening interfaces.\n", + "[I] Start synchronization with remotes on interfaces\n", + "[I] Synchronized simulation start with remotes\n", + "[I] Start simulation: EMTCosim\n", + "[I] Time step: 1.000000e-06\n", + "[I] Final time: 1.000000e+00\n", + "[I] Simulation calculation time: 10.558085\n", + "[I] Simulation finished.\n" + ] + } + ], "source": [ "!cat logs/EMTCosim.log" ] @@ -335,7 +3505,8 @@ "hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a" }, "kernelspec": { - "display_name": "Python 3.9.7 64-bit", + "display_name": "Python 3 (ipykernel)", + "language": "python", "name": "python3" }, "language_info": {