Commit 69c26264 authored by Jan Dinkelbach's avatar Jan Dinkelbach Committed by Markus Mirz
Browse files

refactor dp1ph network injection using vs subcomp and add validation example

parent c585237a
......@@ -8,7 +8,7 @@ endif()
# targets
set(CIRCUIT_SOURCES
# Dynamic phasor examples
# DP examples
Circuits/DP_VS_RL1.cpp
Circuits/DP_Circuits.cpp
Circuits/DP_Basics_DP_Sims.cpp
......@@ -16,10 +16,12 @@ set(CIRCUIT_SOURCES
Circuits/DP_DecouplingLine.cpp
Circuits/DP_Diakoptics.cpp
Circuits/DP_VSI.cpp
# DP examples with PF initialization
Circuits/DP_Slack_PiLine_PQLoad_with_PF_Init.cpp
Circuits/DP_Slack_PiLine_VSI_with_PF_Init.cpp
Circuits/EMT_Slack_PiLine_PQLoad_with_PF_Init.cpp
Circuits/EMT_Slack_PiLine_VSI_with_PF_Init.cpp
# Combined EMT and DP examples
Circuits/EMT_DP_Slack.cpp
Circuits/EMT_DP_VS_RLC_Circuits.cpp
# Powerflow examples
......
/* Copyright 2017-2020 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
* DPsim
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <DPsim.h>
using namespace DPsim;
using namespace CPS::DP;
void simElements() {
Real timeStep = 0.00005;
Real finalTime = 1;
String simName = "DP_Slack_Elements";
Logger::setLogDir("logs/"+simName);
// Nodes
auto n1 = SimNode::make("n1");
// Components
auto vs = Ph1::VoltageSource::make("v_1");
vs->setParameters(CPS::Math::polar(100000, 0));
auto load = Ph1::Resistor::make("R_load");
load->setParameters(10000);
// Topology
vs->connect({ SimNode::GND, n1 });
load->connect({ n1, SimNode::GND });
auto sys = SystemTopology(50,
SystemNodeList{n1},
SystemComponentList{vs, load});
// Logging
auto logger = DataLogger::make(simName);
logger->addAttribute("v1", n1->attribute("v"));
logger->addAttribute("i1", vs->attribute("i_intf"));
Simulation sim(simName);
sim.setSystem(sys);
sim.setTimeStep(timeStep);
sim.setFinalTime(finalTime);
sim.addLogger(logger);
sim.run();
}
void simComponent() {
Real timeStep = 0.00005;
Real finalTime = 1;
String simName = "DP_Slack_Component";
Logger::setLogDir("logs/"+simName);
// Nodes
auto n1 = SimNode::make("n1");
// Components
auto sl = Ph1::NetworkInjection::make("v_1");
sl->setParameters(CPS::Math::polar(100000, 0));
auto load = Ph1::Resistor::make("R_load");
load->setParameters(10000);
// Topology
sl->connect({ n1 });
load->connect({ n1, SimNode::GND });
auto sys = SystemTopology(50,
SystemNodeList{n1},
SystemComponentList{sl, load});
// Logging
auto logger = DataLogger::make(simName);
logger->addAttribute("v1", n1->attribute("v"));
logger->addAttribute("i1", sl->attribute("i_intf"));
Simulation sim(simName);
sim.setSystem(sys);
sim.setTimeStep(timeStep);
sim.setFinalTime(finalTime);
sim.addLogger(logger);
sim.run();
}
int main(int argc, char* argv[]) {
simElements();
simComponent();
}
\ No newline at end of file
%% Cell type:markdown id: tags:
# Slack Tests
%% Cell type:code id: tags:
``` python
import villas.dataprocessing.readtools as rt
from villas.dataprocessing.timeseries import TimeSeries as ts
import matplotlib.pyplot as plt
import numpy as np
#%matplotlib widget
```
%% Cell type:markdown id: tags:
## DP Slack with voltage source element
%% Cell type:code id: tags:
``` python
%%bash
TOP=${TOP:-$(git rev-parse --show-toplevel)}
PATH=${TOP}/build/Examples/Cxx
EMT_DP_Slack
```
%% Cell type:code id: tags:
``` python
work_dir = 'logs/DP_Slack_Elements/'
log_name = 'DP_Slack_Elements'
print(work_dir + log_name + '.csv')
slack_elements = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')
slack_elements_dp_shifted = ts.frequency_shift_list(slack_elements, 50)
```
%% Cell type:code id: tags:
``` python
plt.figure()
plt.plot(slack_elements_dp_shifted['v1_shift'].time, slack_elements_dp_shifted['v1_shift'].values, label='v1_shift')
plt.legend()
```
%% Cell type:code id: tags:
``` python
plt.figure()
plt.plot(slack_elements_dp_shifted['i1_shift'].time, slack_elements_dp_shifted['i1_shift'].values, label='i1_shift')
plt.legend()
```
%% Cell type:markdown id: tags:
## DP Slack composite model
%% Cell type:code id: tags:
``` python
work_dir = 'logs/DP_Slack_Component/'
log_name = 'DP_Slack_Component'
print(work_dir + log_name + '.csv')
slack_component = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')
slack_component_dp_shifted = ts.frequency_shift_list(slack_component, 50)
```
%% Cell type:code id: tags:
``` python
plt.figure()
plt.plot(slack_component_dp_shifted['v1_shift'].time, slack_component_dp_shifted['v1_shift'].values, label='v1_shift')
plt.legend()
```
%% Cell type:code id: tags:
``` python
plt.figure()
plt.plot(slack_component_dp_shifted['i1_shift'].time, slack_component_dp_shifted['i1_shift'].values, label='i1_shift')
plt.legend()
```
%% Cell type:markdown id: tags:
## Error for DP Slack
%% Cell type:code id: tags:
``` python
plt.figure()
plt.plot(slack_elements_dp_shifted['v1_shift'].time, slack_elements_dp_shifted['v1_shift'].values - slack_component_dp_shifted['v1_shift'].values, label='v1_shift_error')
plt.legend()
```
%% Cell type:code id: tags:
``` python
plt.figure()
plt.plot(slack_elements_dp_shifted['i1_shift'].time, slack_elements_dp_shifted['i1_shift'].values - slack_component_dp_shifted['i1_shift'].values, label='i1_shift_error')
plt.legend()
```
%% Cell type:markdown id: tags:
## Assertion for DP Slack
%% Cell type:code id: tags:
``` python
errors_dp_shifted = []
for name in ['v1_shift', 'i1_shift']:
errors_dp_shifted.append(np.absolute(slack_elements_dp_shifted[name].values - slack_component_dp_shifted[name].values).max())
print(name + ': ' + str(errors_dp_shifted[-1]))
assert np.max(errors_dp_shifted) < 1e-3
```
......@@ -249,6 +249,9 @@ void MnaSolver<VarType>::initializeSystemWithPrecomputedMatrices() {
}
// Initialize source vector for debugging
// CAUTION: this does not always deliver proper source vector initialization
// as not full pre-step is executed (not involving necessary electrical or signal
// subcomp updates before right vector calculation)
for (auto comp : mMNAComponents) {
comp->mnaApplyRightSideVectorStamp(mRightSideVector);
auto idObj = std::dynamic_pointer_cast<IdentifiedObject>(comp);
......
......@@ -11,30 +11,28 @@
#include <cps/SimPowerComp.h>
#include <cps/Solver/MNAInterface.h>
#include <cps/Solver/DAEInterface.h>
#include <cps/DP/DP_Ph1_VoltageSource.h>
namespace CPS {
namespace DP {
namespace Ph1 {
/// \brief Ideal Voltage source model
/// \brief Network injection model
///
/// This model uses modified nodal analysis to represent an ideal voltage source.
/// For a voltage source between nodes j and k, a new variable
/// (current across the voltage source) is added to the left side vector
/// as unkown and it is taken into account for the equation of node j as
/// positve and for the equation of node k as negative. Moreover
/// a new equation ej - ek = V is added to the problem.
/// This model represents network injections by an ideal voltage source.
class NetworkInjection :
public SimPowerComp<Complex>,
public MNAInterface,
public DAEInterface,
public SharedFactory<NetworkInjection> {
private:
///
void updateVoltage(Real time);
///
Attribute<Complex>::Ptr mVoltageRef;
///
Attribute<Real>::Ptr mSrcFreq;
// ### Electrical Subcomponents ###
/// Voltage source
std::shared_ptr<DP::Ph1::VoltageSource> mSubVoltageSource;
// #### solver ####
/// Vector to collect subcomponent right vector stamps
std::vector<const Matrix*> mRightVectorStamps;
public:
/// Defines UID, name, component parameters and logging level
NetworkInjection(String uid, String name, Logger::Level loglevel = Logger::Level::off);
......@@ -50,78 +48,52 @@ namespace Ph1 {
// #### General ####
/// Initializes component from power flow data
void initializeFromNodesAndTerminals(Real frequency);
///
void setSourceValue(Complex voltage);
///
/// Setter for reference voltage parameters
void setParameters(Complex voltageRef, Real srcFreq = -1);
// #### MNA Section ####
/// Initializes internal variables of the component
void mnaInitialize(Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector);
void mnaInitializeHarm(Real omega, Real timeStep, std::vector<Attribute<Matrix>::Ptr> leftVectors);
/// Stamps system matrix
void mnaApplySystemMatrixStamp(Matrix& systemMatrix);
void mnaApplySystemMatrixStampHarm(Matrix& systemMatrix, Int freqIdx);
/// Stamps right side (source) vector
void mnaApplyRightSideVectorStamp(Matrix& rightVector);
void mnaApplyRightSideVectorStampHarm(Matrix& rightVector);
/// Returns current through the component
void mnaUpdateCurrent(const Matrix& leftVector);
/// Updates voltage across component
void mnaUpdateVoltage(const Matrix& leftVector);
/// MNA pre step operations
void mnaPreStep(Real time, Int timeStepCount);
/// MNA post step operations
void mnaPostStep(Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector);
/// Add MNA pre step dependencies
void mnaAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes);
/// Add MNA post step dependencies
void mnaAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute<Matrix>::Ptr &leftVector);
class MnaPreStep : public Task {
class MnaPreStep : public CPS::Task {
public:
MnaPreStep(NetworkInjection& NetworkInjection) :
Task(NetworkInjection.mName + ".MnaPreStep"), mNetworkInjection(NetworkInjection) {
mAttributeDependencies.push_back(NetworkInjection.attribute("V_ref"));
mModifiedAttributes.push_back(mNetworkInjection.attribute("right_vector"));
mModifiedAttributes.push_back(mNetworkInjection.attribute("v_intf"));
MnaPreStep(NetworkInjection& networkInjection) :
Task(networkInjection.mName + ".MnaPreStep"), mNetworkInjection(networkInjection) {
mNetworkInjection.mnaAddPreStepDependencies(mPrevStepDependencies, mAttributeDependencies, mModifiedAttributes);
}
void execute(Real time, Int timeStepCount);
private:
NetworkInjection& mNetworkInjection;
};
void execute(Real time, Int timeStepCount) { mNetworkInjection.mnaPreStep(time, timeStepCount); };
class MnaPostStep : public Task {
public:
MnaPostStep(NetworkInjection& NetworkInjection, Attribute<Matrix>::Ptr leftVector) :
Task(NetworkInjection.mName + ".MnaPostStep"),
mNetworkInjection(NetworkInjection), mLeftVector(leftVector) {
mAttributeDependencies.push_back(mLeftVector);
mModifiedAttributes.push_back(mNetworkInjection.attribute("i_intf"));
}
void execute(Real time, Int timeStepCount);
private:
NetworkInjection& mNetworkInjection;
Attribute<Matrix>::Ptr mLeftVector;
};
class MnaPreStepHarm : public CPS::Task {
class MnaPostStep : public CPS::Task {
public:
MnaPreStepHarm(NetworkInjection& NetworkInjection) :
Task(NetworkInjection.mName + ".MnaPreStepHarm"),
mNetworkInjection(NetworkInjection) {
mAttributeDependencies.push_back(NetworkInjection.attribute("V_ref"));
mModifiedAttributes.push_back(mNetworkInjection.attribute("right_vector"));
mModifiedAttributes.push_back(mNetworkInjection.attribute("v_intf"));
MnaPostStep(NetworkInjection& networkInjection, Attribute<Matrix>::Ptr leftVector) :
Task(networkInjection.mName + ".MnaPostStep"), mNetworkInjection(networkInjection), mLeftVector(leftVector) {
mNetworkInjection.mnaAddPostStepDependencies(mPrevStepDependencies, mAttributeDependencies, mModifiedAttributes, mLeftVector);
}
void execute(Real time, Int timeStepCount);
private:
NetworkInjection& mNetworkInjection;
};
void execute(Real time, Int timeStepCount) { mNetworkInjection.mnaPostStep(time, timeStepCount, mLeftVector); };
class MnaPostStepHarm : public CPS::Task {
public:
MnaPostStepHarm(NetworkInjection& NetworkInjection, std::vector<Attribute<Matrix>::Ptr> leftVectors) :
Task(NetworkInjection.mName + ".MnaPostStepHarm"),
mNetworkInjection(NetworkInjection), mLeftVectors(leftVectors) {
for (UInt i = 0; i < mLeftVectors.size(); i++)
mAttributeDependencies.push_back(mLeftVectors[i]);
mModifiedAttributes.push_back(mNetworkInjection.attribute("i_intf"));
}
void execute(Real time, Int timeStepCount);
private:
NetworkInjection& mNetworkInjection;
std::vector< Attribute<Matrix>::Ptr > mLeftVectors;
Attribute<Matrix>::Ptr mLeftVector;
};
// #### DAE Section ####
......
......@@ -12,13 +12,22 @@ using namespace CPS;
DP::Ph1::NetworkInjection::NetworkInjection(String uid, String name, Logger::Level logLevel)
: SimPowerComp<Complex>(uid, name, logLevel) {
setVirtualNodeNumber(1);
setVirtualNodeNumber(0);
setTerminalNumber(1);
mSLog->info("Create {} {}", this->type(), name);
mIntfVoltage = MatrixComp::Zero(1,1);
mIntfCurrent = MatrixComp::Zero(1,1);
addAttribute<Complex>("V_ref", Flags::read | Flags::write);
addAttribute<Real>("f_src", Flags::read | Flags::write);
// Create electrical sub components
mSubVoltageSource = std::make_shared<DP::Ph1::VoltageSource>(mName + "_vs", mLogLevel);
mSubComponents.push_back(mSubVoltageSource);
mSLog->info("Electrical subcomponents: ");
for (auto subcomp: mSubComponents)
mSLog->info("- {}", subcomp->name());
addAttributeRef<Complex>("V_ref", mSubVoltageSource->attribute<Complex>("V_ref"), Flags::read | Flags::write);
addAttributeRef<Real>("f_src", mSubVoltageSource->attribute<Real>("f_src"), Flags::read | Flags::write);
}
SimPowerComp<Complex>::Ptr DP::Ph1::NetworkInjection::clone(String name) {
......@@ -28,25 +37,26 @@ SimPowerComp<Complex>::Ptr DP::Ph1::NetworkInjection::clone(String name) {
}
void DP::Ph1::NetworkInjection::setParameters(Complex voltageRef, Real srcFreq) {
attribute<Complex>("V_ref")->set(voltageRef);
attribute<Real>("f_src")->set(srcFreq);
mParametersSet = true;
mSubVoltageSource->attribute<Complex>("V_ref")->set(voltageRef);
mSubVoltageSource->attribute<Real>("f_src")->set(srcFreq);
mSLog->info("\nVoltage Ref={:s} [V]"
"\nFrequency={:s} [Hz]",
Logger::phasorToString(voltageRef),
Logger::realToString(srcFreq));
}
void DP::Ph1::NetworkInjection::initializeFromNodesAndTerminals(Real frequency) {
mVoltageRef = attribute<Complex>("V_ref");
mSrcFreq = attribute<Real>("f_src");
if (mVoltageRef->get() == Complex(0, 0))
//mVoltageRef->set(Complex(std::abs(initialSingleVoltage(0).real()), std::abs(initialSingleVoltage(0).imag())));
mVoltageRef->set(initialSingleVoltage(0));
mSLog->info(
"\n--- Initialization from node voltages ---"
"\nVoltage across: {:e}<{:e}"
"\nTerminal 0 voltage: {:e}<{:e}"
"\n--- Initialization from node voltages ---",
std::abs(mVoltageRef->get()), std::arg(mVoltageRef->get()),
std::abs(initialSingleVoltage(0)), std::arg(initialSingleVoltage(0)));
// Connect electrical subcomponents
mSubVoltageSource->connect({ SimNode::GND, node(0) });
// Initialize electrical subcomponents
for (auto subcomp: mSubComponents) {
subcomp->initialize(mFrequencies);
subcomp->initializeFromNodesAndTerminals(frequency);
}
}
// #### MNA functions ####
......@@ -55,90 +65,83 @@ void DP::Ph1::NetworkInjection::mnaInitialize(Real omega, Real timeStep, Attribu
MNAInterface::mnaInitialize(omega, timeStep);
updateMatrixNodeIndices();
mIntfVoltage(0,0) = mVoltageRef->get();
mMnaTasks.push_back(std::make_shared<MnaPreStep>(*this));
mMnaTasks.push_back(std::make_shared<MnaPostStep>(*this, leftVector));
mRightVector = Matrix::Zero(leftVector->get().rows(), 1);
}
// initialize electrical subcomponents
for (auto subcomp: mSubComponents)
if (auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
mnasubcomp->mnaInitialize(omega, timeStep, leftVector);
void DP::Ph1::NetworkInjection::mnaInitializeHarm(Real omega, Real timeStep, std::vector<Attribute<Matrix>::Ptr> leftVectors) {
MNAInterface::mnaInitialize(omega, timeStep);
updateMatrixNodeIndices();
// collect right side vectors of subcomponents
mRightVectorStamps.push_back(&mSubVoltageSource->attribute<Matrix>("right_vector")->get());
mIntfVoltage(0,0) = mVoltageRef->get();
// collect tasks
mMnaTasks.push_back(std::make_shared<MnaPreStep>(*this));
mMnaTasks.push_back(std::make_shared<MnaPostStep>(*this, leftVector));
mMnaTasks.push_back(std::make_shared<MnaPreStepHarm>(*this));
mMnaTasks.push_back(std::make_shared<MnaPostStepHarm>(*this, leftVectors));
mRightVector = Matrix::Zero(leftVectors[0]->get().rows(), mNumFreqs);
mRightVector = Matrix::Zero(leftVector->get().rows(), 1);
}
void DP::Ph1::NetworkInjection::mnaApplySystemMatrixStamp(Matrix& systemMatrix) {
for (UInt freq = 0; freq < mNumFreqs; freq++) {
Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0), Complex(1, 0), mNumFreqs, freq);
Math::setMatrixElement(systemMatrix, matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex(), Complex(1, 0), mNumFreqs, freq);
mSLog->info("-- Stamp frequency {:d} ---", freq);
mSLog->info("Add {:f} to system at ({:d},{:d})", 1., matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex());
mSLog->info("Add {:f} to system at ({:d},{:d})", 1., mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0));
}
}
void DP::Ph1::NetworkInjection::mnaApplySystemMatrixStampHarm(Matrix& systemMatrix, Int freqIdx) {
Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0), Complex(1, 0));
Math::setMatrixElement(systemMatrix, matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex(), Complex(1, 0));
mSLog->info("-- Stamp frequency {:d} ---", freqIdx);
mSLog->info("Add {:f} to system at ({:d},{:d})", 1., matrixNodeIndex(0), mVirtualNodes[0]->matrixNodeIndex());
mSLog->info("Add {:f} to system at ({:d},{:d})", 1., mVirtualNodes[0]->matrixNodeIndex(), matrixNodeIndex(0));
for (auto subcomp: mSubComponents)
if (auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix);
}
void DP::Ph1::NetworkInjection::mnaApplyRightSideVectorStamp(Matrix& rightVector) {
// TODO: Is this correct with two nodes not gnd?
Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(), mIntfVoltage(0,0), mNumFreqs);
SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}",
Logger::complexToString(mIntfVoltage(0,0)), mVirtualNodes[0]->matrixNodeIndex());
}
rightVector.setZero();
for (auto stamp : mRightVectorStamps)
rightVector += *stamp;
void DP::Ph1::NetworkInjection::mnaApplyRightSideVectorStampHarm(Matrix& rightVector) {
for (UInt freq = 0; freq < mNumFreqs; freq++) {
// TODO: Is this correct with two nodes not gnd?
Math::setVectorElement(rightVector, mVirtualNodes[0]->matrixNodeIndex(), mIntfVoltage(0,freq), 1, 0, freq);
SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}",
Logger::complexToString(mIntfVoltage(0,freq)), mVirtualNodes[0]->matrixNodeIndex());
}
mSLog->info("Right Side Vector: {:s}",
Logger::matrixToString(rightVector));
}
void DP::Ph1::NetworkInjection::updateVoltage(Real time) {
if (mSrcFreq->get() < 0) {
mIntfVoltage(0,0) = mVoltageRef->get();
}
else {
mIntfVoltage(0,0) = Complex(
Math::abs(mVoltageRef->get()) * cos(time * 2.*PI*mSrcFreq->get() + Math::phase(mVoltageRef->get())),
Math::abs(mVoltageRef->get()) * sin(time * 2.*PI*mSrcFreq->get() + Math::phase(mVoltageRef->get())));
}
void DP::Ph1::NetworkInjection::mnaAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) {
// add pre-step dependencies of subcomponents
for (auto subcomp: mSubComponents)
if (auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
mnasubcomp->mnaAddPreStepDependencies(prevStepDependencies, attributeDependencies, modifiedAttributes);
// add pre-step dependencies of component itself
prevStepDependencies.push_back(attribute("i_intf"));
prevStepDependencies.push_back(attribute("v_intf"));
modifiedAttributes.push_back(attribute("right_vector"));
}
void DP::Ph1::NetworkInjection::MnaPreStep::execute(Real time, Int timeStepCount) {
mNetworkInjection.updateVoltage(time);
mNetworkInjection.mnaApplyRightSideVectorStamp(mNetworkInjection.mRightVector);
void DP::Ph1::NetworkInjection::mnaPreStep(Real time, Int timeStepCount) {
// pre-step of subcomponents
for (auto subcomp: mSubComponents)
if (auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
mnasubcomp->mnaPreStep(time, timeStepCount);
// pre-step of component itself
mnaApplyRightSideVectorStamp(mRightVector);
}
void DP::Ph1::NetworkInjection::MnaPreStepHarm::execute(Real time, Int timeStepCount) {
mNetworkInjection.updateVoltage(time);
mNetworkInjection.mnaApplyRightSideVectorStampHarm(mNetworkInjection.mRightVector);
void DP::Ph1::NetworkInjection::mnaAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute<Matrix>::Ptr &leftVector) {
// add post-step dependencies of subcomponents
for (auto subcomp: mSubComponents)
if (auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
mnasubcomp->mnaAddPostStepDependencies(prevStepDependencies, attributeDependencies, modifiedAttributes, leftVector);
// add post-step dependencies of component itself
attributeDependencies.push_back(leftVector);
modifiedAttributes.push_back(attribute("v_intf"));
modifiedAttributes.push_back(attribute("i_intf"));