Skip to content

Commit

Permalink
Linear SSN (#175)
Browse files Browse the repository at this point in the history
This branch focusses on the implementation of a State Space Nodal (SSN)
simulation approach for real time analysis within the EMT domain limited
to linear components. The approach is based on the paper “A Combined
State-Space Nodal Method for the Simulation of Power System Transients”
,doi:
[10.1109/TPWRD.2010.2090364](https://doi.org/10.1109/TPWRD.2010.2090364)
of Dufour et al. .

Linear State Space Nodal models of basic components and linear circuits
like an RLC circuit are implemented as single SSN components. To achieve
this a state space representation for the electrical element or circuit
is derived. Those equations are discretized using the trapezoidal rule
of integration. The system of linear equations is manipulated such that
current states in the output equations of the state space model can be
replaced with known terms, i.e. state values of the previous simulation
step and input quantities. Previous states are additionally stored
within the SSN component and updated when the system has been solved for
the current time step. Now the output equations (nodal equations for
V-Type SSN-Groups, mesh equations for I-Type SSN-Groups) can be used in
the Modified Nodal Analysis approach by the already implemented stamping
and task systems.

Because of that the simulation sequence and structure does not have to
be changed for these components, only the used methods itself differ in
the executed calculations and the quantity updates for the internally
stored states.

Regarding general changes not limited to the SSN approach, a setter
method (setParameters) has been added for the EMT::Ph3::CurrentSource.
The EMT::Ph3::CurrentSource class and the new
EMT::Ph3::SSN::Full_Serial_RLC class were made usable within the pybind
python module.
  • Loading branch information
m-mirz authored Oct 10, 2024
2 parents ee448db + dbbc8d0 commit d66f826
Show file tree
Hide file tree
Showing 15 changed files with 1,650 additions and 24 deletions.
3 changes: 3 additions & 0 deletions dpsim-models/include/dpsim-models/Components.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@
#include <dpsim-models/EMT/EMT_Ph3_SynchronGeneratorDQTrapez.h>
#include <dpsim-models/EMT/EMT_Ph3_VoltageSource.h>
#include <dpsim-models/EMT/EMT_Ph3_VoltageSourceNorton.h>
#include <dpsim-models/EMT/EMT_Ph3_SSN_Capacitor.h>
#include <dpsim-models/EMT/EMT_Ph3_SSN_Inductor.h>
#include <dpsim-models/EMT/EMT_Ph3_SSN_Full_Serial_RLC.h>
#ifdef WITH_SUNDIALS
#include <dpsim-models/EMT/EMT_Ph3_SynchronGeneratorDQODE.h>
#endif
Expand Down
8 changes: 4 additions & 4 deletions dpsim-models/include/dpsim-models/EMT/EMT_Ph3_CurrentSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ class CurrentSource : public MNASimPowerComp<Real>,
// #### General ####
/// Initializes component from power flow data
void initializeFromNodesAndTerminals(Real frequency) override;
/// Setter for reference voltage
void setParameters(MatrixComp voltageRef, Real srcFreq = 50.0);
/// Setter for reference current
void setParameters(MatrixComp currentRef, Real srcFreq = 50.0);
/// Setter for reference signal of type frequency ramp
void setParameters(MatrixComp voltageRef, Real freqStart, Real rocof,
void setParameters(MatrixComp currentRef, Real freqStart, Real rocof,
Real timeStart, Real duration, bool smoothRamp = true);
/// Setter for reference signal of type cosine frequency modulation
void setParameters(MatrixComp voltageRef, Real modulationFrequency,
void setParameters(MatrixComp currentRef, Real modulationFrequency,
Real modulationAmplitude, Real baseFrequency = 50.0,
bool zigzag = false);

Expand Down
86 changes: 86 additions & 0 deletions dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Capacitor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*********************************************************************************/

#pragma once

#include <dpsim-models/Base/Base_Ph3_Capacitor.h>
#include <dpsim-models/MNASimPowerComp.h>
#include <dpsim-models/Solver/MNAInterface.h>

namespace CPS {
namespace EMT {
namespace Ph3 {
namespace SSN {
/// \brief Capacitor model
///
/// The SSN-capacitor is represented by a DC equivalent circuit which
/// corresponds to one iteration of the trapezoidal integration method.
/// The equivalent DC circuit is a resistance in series with a voltage
/// source (real voltage source). The resistance is constant for a defined
/// time step and system frequency and the voltage source changes for each
/// iteration. This component is meant to show an I-type SSN model
/// implementation based on a simple example element. The RC model should be
/// used over this if focussing on SSN model implementation is not the
/// circuit's goal since this model increases the system matrix dimensions
/// by 1x1 (added virtual node, real voltage source MNA scheme).
class Capacitor final : public MNASimPowerComp<Real>,
public Base::Ph3::Capacitor,
public SharedFactory<Capacitor> {
public:
/// Defines UID, name and logging level
Capacitor(String uid, String name,
Logger::Level logLevel = Logger::Level::off);
/// Defines name and logging level
Capacitor(String name, Logger::Level logLevel = Logger::Level::off)
: Capacitor(name, name, logLevel) {}

SimPowerComp<Real>::Ptr clone(String name) override;

// #### General ####
/// Initializes component from power flow data
void initializeFromNodesAndTerminals(Real frequency) override;

// #### MNA section ####
/// Initializes internal variables of the component
void mnaCompInitialize(Real omega, Real timeStep,
Attribute<Matrix>::Ptr leftVector) override;
/// Stamps system matrix
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override;
/// Stamps right side (source) vector
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override;
/// Update interface voltage from MNA system result
void mnaCompUpdateVoltage(const Matrix &leftVector) override;
/// Update interface current from MNA system result
void mnaCompUpdateCurrent(const Matrix &leftVector) override;
/// MNA pre step operations
void mnaCompPreStep(Real time, Int timeStepCount) override;
/// MNA post step operations
void mnaCompPostStep(Real time, Int timeStepCount,
Attribute<Matrix>::Ptr &leftVector) override;
/// Add MNA pre step dependencies
void mnaCompAddPreStepDependencies(
AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies,
AttributeBase::List &modifiedAttributes) override;
/// Add MNA post step dependencies
void
mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies,
AttributeBase::List &modifiedAttributes,
Attribute<Matrix>::Ptr &leftVector) override;

private:
Matrix mDufourBKHat = Matrix::Zero(3, 3);
Matrix mDufourWKN = Matrix::Zero(3, 3);
//rightsideVector history term
Matrix mHistoricVoltage = Matrix::Zero(3, 1);
};
} // namespace SSN
} // namespace Ph3
} // namespace EMT
} // namespace CPS
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*********************************************************************************/

#pragma once

#include <dpsim-models/Base/Base_Ph3_Capacitor.h>
#include <dpsim-models/Base/Base_Ph3_Inductor.h>
#include <dpsim-models/Base/Base_Ph3_Resistor.h>
#include <dpsim-models/MNASimPowerComp.h>
#include <dpsim-models/Solver/MNAInterface.h>

namespace CPS {
namespace EMT {
namespace Ph3 {
namespace SSN {
/// \brief Full_Serial_RLC
///
/// This element represents an one port circuit consisting of a resistor,
/// an inductor and a capacitor connected in series. The terminals are at
/// the beginning and the end of the component chain.
/// The states are the capacitor voltage and the inductor current, the output
/// is the latter of those states (inductor current). The input is the voltage
/// across the whole circuit. States and past inputs are updated after each
/// time step and are used to calculate the current (input) voltage,
/// represented as MNA node voltages.
class Full_Serial_RLC final : public MNASimPowerComp<Real>,
public SharedFactory<Full_Serial_RLC>,
public Base::Ph3::Resistor,
public Base::Ph3::Inductor,
public Base::Ph3::Capacitor {
public:
/// Defines UID, name, component parameters and logging level
Full_Serial_RLC(String uid, String name,
Logger::Level logLevel = Logger::Level::off);
/// Defines name and logging level
Full_Serial_RLC(String name, Logger::Level logLevel = Logger::Level::off)
: Full_Serial_RLC(name, name, logLevel) {}

SimPowerComp<Real>::Ptr clone(String name) override;
void setParameters(Matrix resistance, Matrix inductance, Matrix capacitance);

// #### General ####
/// Initializes component from power flow data
void initializeFromNodesAndTerminals(Real frequency) override;

// #### MNA section ####
/// Initializes internal variables of the component
void mnaCompInitialize(Real omega, Real timeStep,
Attribute<Matrix>::Ptr leftVector) override;
/// Stamps system matrix
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override;
/// Stamps right side (source) vector
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override;
/// Update interface voltage from MNA system result
void mnaCompUpdateVoltage(const Matrix &leftVector) override;
/// Update interface current from MNA system result
void mnaCompUpdateCurrent(const Matrix &leftVector) override;
/// MNA pre step operations
void mnaCompPreStep(Real time, Int timeStepCount) override;
/// MNA post step operations
void mnaCompPostStep(Real time, Int timeStepCount,
Attribute<Matrix>::Ptr &leftVector) override;
/// Add MNA pre step dependencies
void mnaCompAddPreStepDependencies(
AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies,
AttributeBase::List &modifiedAttributes) override;
/// Add MNA post step dependencies
void
mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies,
AttributeBase::List &modifiedAttributes,
Attribute<Matrix>::Ptr &leftVector) override;

private:
Matrix mState = Matrix::Zero(6, 1);
Matrix mYHistory = Matrix::Zero(3, 1);

Matrix mDufourUNT = Matrix::Zero(3, 1);

Matrix mDufourAKHat = Matrix::Zero(6, 6);
Matrix mDufourBKHat = Matrix::Zero(6, 3);
Matrix mDufourBKNHat = Matrix::Zero(6, 3);
Matrix mDufourWKN = Matrix::Zero(3, 3);
Matrix mDufourCKN = Matrix::Zero(3, 6);

void ssnUpdateState();
};
} // namespace SSN
} // namespace Ph3
} // namespace EMT
} // namespace CPS
86 changes: 86 additions & 0 deletions dpsim-models/include/dpsim-models/EMT/EMT_Ph3_SSN_Inductor.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*********************************************************************************/
#pragma once

#include <dpsim-models/Base/Base_Ph3_Inductor.h>
#include <dpsim-models/MNASimPowerComp.h>
#include <dpsim-models/Solver/MNAInterface.h>

namespace CPS {
namespace EMT {
namespace Ph3 {
namespace SSN {
/// \brief Inductor
///
/// The SSN-inductor is represented by a DC equivalent circuit which
/// corresponds to one iteration of the trapezoidal integration method.
/// The equivalent DC circuit is a resistance in parallel with a current
/// source. The resistance is constant for a defined time step and system
/// frequency and the current source changes for each iteration.
/// This means that for the inductor the SSN and Resistive Companion models
/// are conceptionally the same and only variable names, structures and
/// state update timings differ. This component is meant to show a V-type SSN
/// model implementation based on a simple example element. Due to additional
/// calculation steps, the RC model should be used over this otherwise.
class Inductor final : public MNASimPowerComp<Real>,
public Base::Ph3::Inductor,
public SharedFactory<Inductor> {
public:
/// Defines UID, name, component parameters and logging level
Inductor(String uid, String name,
Logger::Level logLevel = Logger::Level::off);
/// Defines name and logging level
Inductor(String name, Logger::Level logLevel = Logger::Level::off)
: Inductor(name, name, logLevel) {}

SimPowerComp<Real>::Ptr clone(String name) override;

// #### General ####
/// Initializes component from power flow data
void initializeFromNodesAndTerminals(Real frequency) override;

// #### MNA section ####
/// Initializes internal variables of the component
void mnaCompInitialize(Real omega, Real timeStep,
Attribute<Matrix>::Ptr leftVector) override;
/// Stamps system matrix
void mnaCompApplySystemMatrixStamp(SparseMatrixRow &systemMatrix) override;
/// Stamps right side (source) vector
void mnaCompApplyRightSideVectorStamp(Matrix &rightVector) override;
/// Update interface voltage from MNA system result
void mnaCompUpdateVoltage(const Matrix &leftVector) override;
/// Update interface current from MNA system result
void mnaCompUpdateCurrent(const Matrix &leftVector) override;
/// MNA pre step operations
void mnaCompPreStep(Real time, Int timeStepCount) override;
/// MNA post step operations
void mnaCompPostStep(Real time, Int timeStepCount,
Attribute<Matrix>::Ptr &leftVector) override;
/// Add MNA pre step dependencies
void mnaCompAddPreStepDependencies(
AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies,
AttributeBase::List &modifiedAttributes) override;
/// Add MNA post step dependencies
void
mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies,
AttributeBase::List &modifiedAttributes,
Attribute<Matrix>::Ptr &leftVector) override;

private:
//rightsideVector history term
Matrix mHistoricCurrent = Matrix::Zero(3, 1);
//dependency on latest Voltage, represented by Conductance in system matrix
Matrix mDufourBKHat = Matrix::Zero(3, 3);
Matrix mDufourWKN = Matrix::Zero(3, 3);
};
} // namespace SSN
} // namespace Ph3
} // namespace EMT
} // namespace CPS
3 changes: 3 additions & 0 deletions dpsim-models/src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ list(APPEND MODELS_SOURCES
EMT/EMT_Ph3_SynchronGeneratorIdeal.cpp
# EMT/EMT_Ph3_SynchronGeneratorVBRStandalone.cpp
EMT/EMT_Ph3_SynchronGeneratorTrStab.cpp
EMT/EMT_Ph3_SSN_Capacitor.cpp
EMT/EMT_Ph3_SSN_Inductor.cpp
EMT/EMT_Ph3_SSN_Full_Serial_RLC.cpp

SP/SP_Ph1_VoltageSource.cpp
SP/SP_Ph1_Capacitor.cpp
Expand Down
33 changes: 25 additions & 8 deletions dpsim-models/src/EMT/EMT_Ph3_CurrentSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ EMT::Ph3::CurrentSource::CurrentSource(String uid, String name,
**mIntfVoltage = Matrix::Zero(3, 1);
**mIntfCurrent = Matrix::Zero(3, 1);
}
SimPowerComp<Real>::Ptr EMT::Ph3::CurrentSource::clone(String name) {
auto copy = CurrentSource::make(name, mLogLevel);
copy->setParameters(attributeTyped<MatrixComp>("I_ref")->get(),
attributeTyped<Real>("f_src")->get());
return copy;
}

void EMT::Ph3::CurrentSource::setParameters(MatrixComp currentRef,
Real srcFreq) {
auto srcSigSine = Signal::SineWaveGenerator::make(**mName + "_sw");
// Complex(1,0) is used as initialPhasor for signal generator as only phase is used
srcSigSine->setParameters(Complex(1, 0), srcFreq);
mSrcSig = srcSigSine;

**mCurrentRef = currentRef;
mSrcFreq->setReference(mSrcSig->mFreq);

mSLog->info("\nCurrent reference phasor [I]: {:s}"
"\nFrequency [Hz]: {:s}",
Logger::matrixCompToString(currentRef),
Logger::realToString(srcFreq));

mParametersSet = true;
}

void EMT::Ph3::CurrentSource::initializeFromNodesAndTerminals(Real frequency) {
SPDLOG_LOGGER_INFO(
Expand Down Expand Up @@ -70,13 +94,6 @@ void EMT::Ph3::CurrentSource::initializeFromNodesAndTerminals(Real frequency) {
mSLog->flush();
}

SimPowerComp<Real>::Ptr EMT::Ph3::CurrentSource::clone(String name) {
auto copy = CurrentSource::make(name, mLogLevel);
// TODO: implement setParameters
// copy->setParameters(attributeTyped<MatrixComp>("I_ref")->get(), attributeTyped<Real>("f_src")->get());
return copy;
}

void EMT::Ph3::CurrentSource::mnaCompInitialize(
Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector) {
updateMatrixNodeIndices();
Expand Down Expand Up @@ -167,4 +184,4 @@ void EMT::Ph3::CurrentSource::mnaCompUpdateVoltage(const Matrix &leftVector) {
(**mIntfVoltage)(2, 0) -
Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2));
}
}
}
Loading

0 comments on commit d66f826

Please sign in to comment.