diff --git a/docs/hugo/content/en/docs/Models/RLC-Elements/index.md b/docs/hugo/content/en/docs/Models/RLC-Elements/index.md index e9bfbc8ea8..3d0ca55644 100644 --- a/docs/hugo/content/en/docs/Models/RLC-Elements/index.md +++ b/docs/hugo/content/en/docs/Models/RLC-Elements/index.md @@ -169,5 +169,5 @@ $$ a = \frac{\Delta t}{2L}, \qquad b = \frac{\Delta t \omega}{2} $$ $$ - \langle i_{equiv} \rangle(k-1) = \frac{1 - b^2 - j2b + 2Ra + (Ra)^2 - j2Rab}{(1+Ra^2) + b^2} \langle i \rangle(k-1) + \frac{a + Ra^2 - jab}{(1+Ra)^2 + b^2} \langle v \rangle(k-1) + \langle i_{equiv} \rangle(k-1) = \frac{1 - b^2 - j2b - (Ra)^2}{(1+Ra)^2 + b^2} \langle i \rangle(k-1) + \frac{a + Ra^2 - jab}{(1+Ra)^2 + b^2} \langle v \rangle(k-1) $$ \ No newline at end of file diff --git a/docs/hugo/content/en/docs/Models/Transformer/RL-Element.svg b/docs/hugo/content/en/docs/Models/Transformer/RL-Element.svg new file mode 100644 index 0000000000..bb15256a8d --- /dev/null +++ b/docs/hugo/content/en/docs/Models/Transformer/RL-Element.svg @@ -0,0 +1,4 @@ + + + +
i(t)
i(t)
v(t)
v(t)
L
L
R
R
Text is not SVG - cannot display
\ No newline at end of file diff --git a/docs/hugo/content/en/docs/Models/Transformer/Transformer.svg b/docs/hugo/content/en/docs/Models/Transformer/Transformer.svg new file mode 100644 index 0000000000..1f7b6ee8de --- /dev/null +++ b/docs/hugo/content/en/docs/Models/Transformer/Transformer.svg @@ -0,0 +1,4 @@ + + + +
i(t)
i(t)
v(t)
v(t)
n0
n0
n1' 
n1' 
n1
n1
R
R
L
L
isec(t)
isec(t)
n:1
n:1
Text is not SVG - cannot display
\ No newline at end of file diff --git a/docs/hugo/content/en/docs/Models/Transformer/electrical_transformer.svg b/docs/hugo/content/en/docs/Models/Transformer/electrical_transformer.svg deleted file mode 100644 index 981d502c88..0000000000 --- a/docs/hugo/content/en/docs/Models/Transformer/electrical_transformer.svg +++ /dev/null @@ -1,3 +0,0 @@ - - -
R
R
L
L
Ideal
transformer
Ideal...
n2
n2
n1
n1
virtual
node
virtua...
virtual
node
virtua...
Viewer does not support full SVG 1.1
\ No newline at end of file diff --git a/docs/hugo/content/en/docs/Models/Transformer/index.md b/docs/hugo/content/en/docs/Models/Transformer/index.md index 4414883c63..190e4c41af 100644 --- a/docs/hugo/content/en/docs/Models/Transformer/index.md +++ b/docs/hugo/content/en/docs/Models/Transformer/index.md @@ -1,42 +1,176 @@ --- title: "Transformer" linkTitle: "Transformer" -date: 2021-07-22 +date: 2023-06-09 --- -## 2-Winding Transformer -The transformer model is composed of an RL-segment and an ideal transformer. -The single line diagram is depicted in the figure below. +## 2-Winding Power Transformer +The power transformer in DPsim based on the RL-element which is depicted in the Fig. 1. -![Transformer](electrical_transformer.svg) +

+ RL Element +

Fig.1 - RL Element
+

-If node reduction is not applied, two virtual nodes are created to stamp this model into the system matrix. +An RL-element in the time domain is described by -Furthermore, the ideal transformer has an additional equation, which requires an extension of the system matrix. -The complete matrix stamp for the ideal transformer is +```math +v = L \frac{\mathrm{d} i(t)}{dt} + Ri(t) +``` + +```math +i(t) = i(t-\Delta t) + \frac{1}{L} \int_{t - \Delta t}^{t} v(\tau) - R i(\tau)\ \mathrm{d} \tau +``` + +Applying the trapezoidal rule leads to the following algebraic equation: + +```math +i(k) = G_{eq} v(k) + i_{eq}(k) +``` + +with + +```math +a = \frac{\Delta t R}{2L}, \quad b=\frac{\Delta t}{2L} \quad \textrm{and} \quad G_{eq} = \frac{b}{1+a} +``` + +and + +```math +i_{eq}(k) = \frac{1-a}{1+a} i(k-1) + \frac{b}{1+a} v (k-1) +``` + +

+ Power Transformer +

Fig.2 - Equivalent circuit Power transformer
+

+ +To apply this to the power transformer depicted in Fig. 2, the equations of the ideal transformer have to be considered: + +```math +v(t) = v_{n0}(t) - v_{n1}^{'}(t) = v_{n0}(t) - nv_{n1}(t) +``` + +```math +i(t) = \frac{i_{sec}(t)}{n} +``` + +so that the discretized equation for the RL-element becomes: + +```math +i(k) = G_{eq} v_{n0}(k) - n G_{eq} v_{n1}(k) + i_{eq}(k) +``` + +with + +```math +i_{eq}(k) = \frac{1-a}{1+a} i(k-1) + \frac{b}{1+a} (v_{n0}(k-1) - n v_{n1}(k-1)) +``` + +Extending to 3 phase with the following assumptions: +1. Symmetrical components +2. No mutual impedances between the phases + +the equation system of the power transformer becomes: ```math -\begin{array}{c|c c c} - ~ & j & k & l \cr - \hline - j & & & -1 \cr - k & & & T \cr - l & 1 & -T & 0 -\end{array} \begin{pmatrix} -v_j \cr -v_k \cr -i_{l} \cr +i_{a} (k) \cr +i_{b} (k) \cr +i_{c} (k) \cr +i_{a, sec} (k) \cr +i_{b, sec} (k) \cr +i_{c, sec} (k) \cr \end{pmatrix} = \begin{pmatrix} - \cr - \cr - 0\cr + G_{eq} & 0 & 0 & -n G_{eq} & 0 & 0 \cr + 0 & G_{eq} & 0 & 0 & -n G_{eq} & 0 \cr + 0 & 0 & G_{eq} & 0 & 0 & -n G_{eq} \cr + n G_{eq} & 0 & 0 & -n^{2} G_{eq} & 0 & 0 \cr + 0 & n G_{eq} & 0 & 0 & -n^{2} G_{eq} & 0 \cr + 0 & 0 & n G_{eq} & 0 & 0 & -n^{2} G_{eq} \cr \end{pmatrix} +* +\begin{pmatrix} +v_{n0a} (k) \cr +v_{n0b} (k) \cr +v_{n0c} (k) \cr +v_{n1a} (k) \cr +v_{n1b} (k) \cr +v_{n1c} (k) \cr +\end{pmatrix} + +\begin{pmatrix} +i_{eq,a} (k) \cr +i_{eq,b} (k) \cr +i_{eq,c} (k) \cr +n i_{eq,a} (k) \cr +n i_{eq,b} (k) \cr +n i_{eq,c} (k) \cr +\end{pmatrix} +``` + + +## Extension with Dynamic Phasors +The RL-element in the DP domain is described by + +$$ + \frac{\mathrm{d} \langle i \rangle (t)}{\mathrm{d}t} + j\omega \cdot \langle i \rangle (t) = \frac{\langle v \rangle (t) - R \cdot \langle i \rangle (t)}{L} +$$ + +Applying the trapezoidal method leads to the following algebraic equations +```math +\langle i \rangle (k)= \frac{(1-b^2 - (a*R)^2 -j*2b) }{(1+a*R)^2+b^2} \cdot \langle i \rangle(k-1) + \frac{a+a^2*R - j *ab}{(1+aR)^2 + b^2} \cdot ( \langle v \rangle (k) + \langle v \rangle(k-1)) +``` +with +```math +a = \frac{\Delta t}{2L}, \qquad b = \frac{\Delta t \omega}{2} +``` + +Analog to the EMT model to apply this to the power transformer depicted in Fig. 2, the equations of the ideal transformer have to be considered: + +```math +\langle v \rangle (k) = \langle v_{n0} \rangle (k) - \langle v_{n1}^{'} \rangle (k), \qquad \langle v_{n1}^{'} \rangle (k) = n \langle v_{n1} \rangle (k) +``` + +```math +\langle i \rangle (k) = n \langle i_{sec} \rangle (k) +``` +so that the discretized equation for the RL-element becomes: +```math +\langle i \rangle (k) = Y_{eq} (\langle v_{n0} \rangle (k) - n \langle v_{n1} \rangle (k)) + \langle i_{eq} \rangle (k) ``` -The variable $j$ denotes the high voltage node while $k$ is the low voltage node. -$l$ indicates the inserted row and column to accommodate the relation between the two voltages at the ends of the transformer. -The transformer ratio is defined as $T = V_{j} / V_{k}$. -A phase shift can be introduced if $T$ is considered as a complex number. \ No newline at end of file +where: + +```math +Y_{eq} = \frac{a+a^{2}R - jab}{(1+aR)^{2} + b^{2}} +``` +and + +```math +\langle i_{eq} \rangle (k) = \frac{(1-b^{2} - (aR)^{2} -j2b) }{(1+aR)^{2}+b^{2}} \langle i \rangle(k-1) + \frac{a+a^{2}R - jab}{(1+aR)^{2} + b^{2}} \langle v \rangle(k-1) +``` + +Finally, the equation systems for the power transformer in the DP model is given by: + +```math +\begin{pmatrix} +\langle i \rangle (k) \cr +\langle i_{sec} \rangle (k) \cr +\end{pmatrix} += +\begin{pmatrix} + Y_{eq} & -nY_{eq}\cr + nY_{eq} & -n^{2} Y_{eq} \cr +\end{pmatrix} +* +\begin{pmatrix} +\langle v_{n0} \rangle (k) \cr +\langle v_{n1} \rangle (k) \cr +\end{pmatrix} + +\begin{pmatrix} +\langle i_{eq} \rangle (k) \cr +\langle n i_{eq} \rangle (k) \cr +\end{pmatrix} +``` diff --git a/dpsim-models/include/dpsim-models/Base/Base_Ph3_Transformer.h b/dpsim-models/include/dpsim-models/Base/Base_Ph3_Transformer.h index b072d2b0e9..b5271dbd2f 100644 --- a/dpsim-models/include/dpsim-models/Base/Base_Ph3_Transformer.h +++ b/dpsim-models/include/dpsim-models/Base/Base_Ph3_Transformer.h @@ -20,8 +20,6 @@ namespace Ph3 { Real mNominalVoltageEnd1; /// Nominal voltage of secondary side Real mNominalVoltageEnd2; - /// Rated Apparent Power [VA] - Real mRatedPower; /// Resistance [Ohm] Matrix mResistance; /// Inductance [H] @@ -35,10 +33,9 @@ namespace Ph3 { mRatio(attributeList->create("ratio")) { }; /// - void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, Real ratioPhase, Matrix resistance, Matrix inductance) { + void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Matrix resistance, Matrix inductance) { mNominalVoltageEnd1 = nomVoltageEnd1; mNominalVoltageEnd2 = nomVoltageEnd2; - mRatedPower = ratedPower; **mRatio = std::polar(ratioAbs, ratioPhase); mResistance = resistance; mInductance = inductance; diff --git a/dpsim-models/include/dpsim-models/Components.h b/dpsim-models/include/dpsim-models/Components.h index fe843efde9..4d9ede773c 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 @@ -48,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -94,6 +96,7 @@ #include #include #include +#include #include #include #include diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Capacitor.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Capacitor.h index 88b7ac578f..988af3f506 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Capacitor.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Capacitor.h @@ -57,10 +57,10 @@ namespace Ph1 { /// Stamps right side (source) vector void mnaCompApplyRightSideVectorStamp(Matrix& rightVector) override; void mnaCompApplyRightSideVectorStampHarm(Matrix& rightVector) override; + void mnaCompApplyRightSideVectorStampHarm(Matrix& sourceVector, Int freqIdx) override; /// Update interface voltage from MNA system result void mnaCompUpdateVoltage(const Matrix& leftVector) override; void mnaCompUpdateVoltageHarm(const Matrix& leftVector, Int freqIdx); - void mnaCompApplyRightSideVectorStampHarm(Matrix& sourceVector, Int freqIdx) override; /// Update interface current from MNA system result void mnaCompUpdateCurrent(const Matrix& leftVector) override; void mnaCompUpdateCurrentHarm(); diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine.h index 5a24a7a086..68bfc25393 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine.h @@ -11,8 +11,8 @@ #include #include #include +#include #include -#include #include namespace CPS { @@ -28,10 +28,8 @@ namespace Ph1 { public Base::Ph1::PiLine, public SharedFactory { protected: - /// Series Inductance submodel - std::shared_ptr mSubSeriesInductor; - /// Series Resistor submodel - std::shared_ptr mSubSeriesResistor; + /// Series Resistor-Inductance submodel + std::shared_ptr mSubSeriesElement; /// Parallel Resistor submodel at Terminal 0 std::shared_ptr mSubParallelResistor0; // Parallel Capacitor submodel at Terminal 0 @@ -49,8 +47,6 @@ namespace Ph1 { PiLine(String name, Logger::Level logLevel = Logger::Level::off) : PiLine(name, name, logLevel) { } - SimPowerComp::Ptr clone(String copySuffix); - // #### General #### /// Initializes component from power flow data void initializeFromNodesAndTerminals(Real frequency); diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine_deprecated.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine_deprecated.h new file mode 100644 index 0000000000..5a24a7a086 --- /dev/null +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_PiLine_deprecated.h @@ -0,0 +1,79 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace CPS { +namespace DP { +namespace Ph1 { + /// \brief PI-line dynamic phasor model + /// + /// This model consists sub components to represent the + /// RLC elements of a PI-line. + class PiLine : + public CompositePowerComp, + public MNATearInterface, + public Base::Ph1::PiLine, + public SharedFactory { + protected: + /// Series Inductance submodel + std::shared_ptr mSubSeriesInductor; + /// Series Resistor submodel + std::shared_ptr mSubSeriesResistor; + /// Parallel Resistor submodel at Terminal 0 + std::shared_ptr mSubParallelResistor0; + // Parallel Capacitor submodel at Terminal 0 + std::shared_ptr mSubParallelCapacitor0; + /// Parallel resistor submodel at Terminal 1 + std::shared_ptr mSubParallelResistor1; + /// Parallel capacitor submodel at Terminal 1 + std::shared_ptr mSubParallelCapacitor1; + /// Right side vectors of subcomponents + std::vector mRightVectorStamps; + public: + /// Defines UID, name and logging level + PiLine(String uid, String name, Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + PiLine(String name, Logger::Level logLevel = Logger::Level::off) + : PiLine(name, name, logLevel) { } + + SimPowerComp::Ptr clone(String copySuffix); + + // #### General #### + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency); + + // #### MNA section #### + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix& leftVector); + /// Updates internal voltage variable of the component + void mnaCompUpdateVoltage(const Matrix& leftVector); + /// MNA pre and post step operations + void mnaParentPreStep(Real time, Int timeStepCount) override; + void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// add MNA pre and post step dependencies + void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + MNAInterface::List mnaTearGroundComponents(); + void mnaTearInitialize(Real omega, Real timeStep); + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix); + void mnaTearApplyVoltageStamp(Matrix& voltageVector); + void mnaTearPostStep(Complex voltage, Complex current); + + }; +} +} +} diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_ResIndSeries.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_ResIndSeries.h index f72c7a28c5..b48f27d6a1 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_ResIndSeries.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_ResIndSeries.h @@ -9,17 +9,19 @@ #pragma once #include -#include +#include namespace CPS { namespace DP { namespace Ph1 { /// \brief resistor inductor series element - class ResIndSeries : - public MNATearInterface, + class ResIndSeries: public MNASimPowerComp, + public MNATearInterface, public SharedFactory { - protected: + private: + /// Impedance + Complex mImpedance; /// DC equivalent current source for harmonics [A] MatrixComp mEquivCurrent; /// Equivalent conductance for harmonics [S] @@ -35,7 +37,7 @@ namespace Ph1 { ResIndSeries(String uid, String name, Logger::Level logLevel = Logger::Level::off); /// Defines name and log level ResIndSeries(String name, Logger::Level logLevel = Logger::Level::off) - : Inductor(name, name, logLevel) { } + : ResIndSeries(name, name, logLevel) { } // #### General #### /// Sets model specific parameters @@ -45,28 +47,73 @@ namespace Ph1 { /// Initializes state variables considering the number of frequencies void initialize(Matrix frequencies); /// Initializes states from power flow data - void initializeFromNodesAndTerminals(Real frequency); + void initializeFromNodesAndTerminals(Real frequency) override; + /// Initializes auxiliar variables + void initVars(Real timeStep); // #### MNA section #### /// Initializes MNA specific variables - void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector); + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + void mnaCompInitializeHarm(Real omega, Real timeStep, std::vector::Ptr> leftVectors) override; /// Stamps system matrix - void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix); + void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; + void mnaCompApplySystemMatrixStampHarm(SparseMatrixRow& systemMatrix, Int freqIdx) override; /// Stamps right side (source) vector - void mnaCompApplyRightSideVectorStamp(Matrix& rightVector); + void mnaCompApplyRightSideVectorStamp(Matrix& rightVector) override; + void mnaCompApplyRightSideVectorStampHarm(Matrix& rightVector) override; /// Update interface voltage from MNA system results - void mnaCompUpdateVoltage(const Matrix& leftVector); + void mnaCompUpdateVoltage(const Matrix& leftVector) override; + void mnaCompUpdateVoltageHarm(const Matrix& leftVector, Int freqIdx); + void mnaCompApplyRightSideVectorStampHarm(Matrix& sourceVector, Int freqIdx) override; /// Update interface current from MNA system results - void mnaCompUpdateCurrent(); - + void mnaCompUpdateCurrent(const Matrix& leftVector) override; + void mnaCompUpdateCurrentHarm(); + /// Add MNA pre step dependencies void mnaCompPreStep(Real time, Int timeStepCount) override; + /// Add MNA post step dependencies void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; - /// Add MNA pre step dependencies void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; - /// Add MNA post step dependencies void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + class MnaPreStepHarm : public CPS::Task { + public: + MnaPreStepHarm(ResIndSeries& ResIndSeries) + : Task(**ResIndSeries.mName + ".MnaPreStepHarm"), + mResIndSeries(ResIndSeries) { + // actually depends on C, but then we'd have to modify the system matrix anyway + mModifiedAttributes.push_back(mResIndSeries.attribute("right_vector")); + mPrevStepDependencies.push_back(mResIndSeries.attribute("i_intf")); + mPrevStepDependencies.push_back(mResIndSeries.attribute("v_intf")); + } + void execute(Real time, Int timeStepCount); + private: + ResIndSeries& mResIndSeries; + }; + + class MnaPostStepHarm : public CPS::Task { + public: + MnaPostStepHarm(ResIndSeries& ResIndSeries, const std::vector::Ptr> &leftVectors) + : Task(**ResIndSeries.mName + ".MnaPostStepHarm"), + mResIndSeries(ResIndSeries), mLeftVectors(leftVectors) { + for (UInt i = 0; i < mLeftVectors.size(); i++) + mAttributeDependencies.push_back(mLeftVectors[i]); + mModifiedAttributes.push_back(mResIndSeries.attribute("v_intf")); + mModifiedAttributes.push_back(mResIndSeries.attribute("i_intf")); + } + void execute(Real time, Int timeStepCount); + private: + ResIndSeries& mResIndSeries; + std::vector< Attribute::Ptr > mLeftVectors; + }; + + // #### Tearing methods #### + void mnaTearInitialize(Real omega, Real timestep) override; + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) override; + void mnaTearApplyVoltageStamp(Matrix& voltageVector) override; + void mnaTearPostStep(Complex voltage, Complex current) override; + }; } } diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Resistor.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Resistor.h index 127cea1985..ac59f9605d 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Resistor.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Resistor.h @@ -71,7 +71,7 @@ namespace Ph1 { }; // #### MNA Tear Section #### - void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix); + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) override; // #### DAE Section #### ///Residual Function for DAE Solver diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Transformer.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Transformer.h index ebc4ac8d60..0aa61d5521 100644 --- a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Transformer.h +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Transformer.h @@ -8,11 +8,8 @@ #pragma once -#include +#include #include -#include -#include -#include #include namespace CPS { @@ -20,71 +17,103 @@ namespace DP { namespace Ph1 { /// Transformer that includes an inductance and resistance class Transformer : - public CompositePowerComp, + public MNASimPowerComp, public SharedFactory, public Base::Ph1::Transformer { - private: - /// Internal resistor to model losses - std::shared_ptr mSubResistor; - /// Internal inductor to model losses - std::shared_ptr mSubInductor; - /// Internal parallel resistance 1 as snubber - std::shared_ptr mSubSnubResistor1; - /// Internal parallel resistance 2 as snubber - std::shared_ptr mSubSnubResistor2; - /// Internal parallel capacitance 1 as snubber - std::shared_ptr mSubSnubCapacitor1; - /// Internal parallel capacitance 2 as snubber - std::shared_ptr mSubSnubCapacitor2; - - /// Snubber resistance 1 [Ohm] - Real mSnubberResistance1; - /// Snubber resistance 2 [Ohm] - Real mSnubberResistance2; - /// Snubber capacitance 1 [F] - Real mSnubberCapacitance1; - /// Snubber capacitance 2 [F] - Real mSnubberCapacitance2; - - /// Boolean for considering resistive losses with sub resistor - Bool mWithResistiveLosses; public: /// Defines UID, name and logging level Transformer(String uid, String name, - Logger::Level logLevel = Logger::Level::off, Bool withResistiveLosses = false); + Logger::Level logLevel = Logger::Level::off); /// Defines name and logging level Transformer(String name, Logger::Level logLevel = Logger::Level::off) : Transformer(name, name, logLevel) { } - SimPowerComp::Ptr clone(String name); + /// DC equivalent current source for harmonics [A] + MatrixComp mEquivCurrent; + /// Equivalent conductance for harmonics [S] + MatrixComp mEquivCond; + /// Coefficient in front of previous current value for harmonics + MatrixComp mPrevCurrFac; + public: // #### General #### /// Defines component parameters void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance); - /// Set transformer specific parameters - void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance); /// Initializes component from power flow data void initializeFromNodesAndTerminals(Real frequency); + /// Initializes state variables considering the number of frequencies + void initialize(Matrix frequencies); + /// + void initVars(Real timeStep); + // #### MNA section #### /// Initializes internal variables of the component - void mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + /// + void mnaCompInitializeHarm(Real omega, Real timeStep, std::vector::Ptr> leftVectors) override; /// Stamps system matrix void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; + /// Stamps system matrix + void mnaCompApplySystemMatrixStampHarm(SparseMatrixRow& systemMatrix , int freqIdx) override; /// Updates internal current variable of the component void mnaCompUpdateCurrent(const Matrix& leftVector) override; + /// Updates internal current variable of the component + void mnaCompUpdateCurrentHarm(); /// Updates internal voltage variable of the component void mnaCompUpdateVoltage(const Matrix& leftVector) override; + /// Updates internal voltage variable of the component for harmonics + void mnaCompUpdateVoltageHarm(const Matrix& leftVector, int freqIdx); + /// MNA pre step operations + void mnaCompPreStep(Real time, Int timeStepCount) override; /// MNA pre step operations - void mnaParentPreStep(Real time, Int timeStepCount) override; + void mnaCompPreStepHarm(Real time, Int timeStepCount); /// MNA post step operations - void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// MNA post step operations + void mnaPostStepHarm(Real time, Int timeStepCount) ; + /// Stamps right side (source) vector + void mnaCompApplyRightSideVectorStamp(Matrix& rightVector) override; + /// Stamps right side (source) vector + void mnaCompApplyRightSideVectorStampHarm(Matrix& rightVector) override; /// Add MNA pre step dependencies - void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; /// Add MNA post step dependencies - void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + // + class MnaPreStepHarm : public Task { + public: + MnaPreStepHarm(Transformer& transformer) + : Task(**transformer.mName + ".MnaPreStepHarm"), + mTransformer(transformer) { + // actually depends on L, but then we'd have to modify the system matrix anyway + mModifiedAttributes.push_back(mTransformer.attribute("right_vector")); + mPrevStepDependencies.push_back(mTransformer.attribute("v_intf")); + mPrevStepDependencies.push_back(mTransformer.attribute("i_intf")); + } + void execute(Real time, Int timeStepCount); + private: + Transformer& mTransformer; + }; + // + class MnaPostStepHarm : public Task { + public: + MnaPostStepHarm(Transformer& transformer, const std::vector::Ptr> &leftVectors) + : Task(**transformer.mName + ".MnaPostStepHarm"), + mTransformer(transformer), mLeftVectors(leftVectors) { + for (UInt i = 0; i < mLeftVectors.size(); i++) + mAttributeDependencies.push_back(mLeftVectors[i]); + mModifiedAttributes.push_back(mTransformer.attribute("v_intf")); + mModifiedAttributes.push_back(mTransformer.attribute("i_intf")); + } + void execute(Real time, Int timeStepCount); + private: + Transformer& mTransformer; + std::vector< Attribute::Ptr > mLeftVectors; + }; }; } } diff --git a/dpsim-models/include/dpsim-models/DP/DP_Ph1_Transformer_deprecated.h b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Transformer_deprecated.h new file mode 100644 index 0000000000..ebc4ac8d60 --- /dev/null +++ b/dpsim-models/include/dpsim-models/DP/DP_Ph1_Transformer_deprecated.h @@ -0,0 +1,91 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace CPS { +namespace DP { +namespace Ph1 { + /// Transformer that includes an inductance and resistance + class Transformer : + public CompositePowerComp, + public SharedFactory, + public Base::Ph1::Transformer { + private: + /// Internal resistor to model losses + std::shared_ptr mSubResistor; + /// Internal inductor to model losses + std::shared_ptr mSubInductor; + + /// Internal parallel resistance 1 as snubber + std::shared_ptr mSubSnubResistor1; + /// Internal parallel resistance 2 as snubber + std::shared_ptr mSubSnubResistor2; + /// Internal parallel capacitance 1 as snubber + std::shared_ptr mSubSnubCapacitor1; + /// Internal parallel capacitance 2 as snubber + std::shared_ptr mSubSnubCapacitor2; + + /// Snubber resistance 1 [Ohm] + Real mSnubberResistance1; + /// Snubber resistance 2 [Ohm] + Real mSnubberResistance2; + /// Snubber capacitance 1 [F] + Real mSnubberCapacitance1; + /// Snubber capacitance 2 [F] + Real mSnubberCapacitance2; + + /// Boolean for considering resistive losses with sub resistor + Bool mWithResistiveLosses; + public: + /// Defines UID, name and logging level + Transformer(String uid, String name, + Logger::Level logLevel = Logger::Level::off, Bool withResistiveLosses = false); + /// Defines name and logging level + Transformer(String name, Logger::Level logLevel = Logger::Level::off) + : Transformer(name, name, logLevel) { } + + SimPowerComp::Ptr clone(String name); + + // #### General #### + /// Defines component parameters + void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance); + /// Set transformer specific parameters + void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance); + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency); + + // #### MNA section #### + /// Initializes internal variables of the component + void mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + /// Stamps system matrix + void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix& leftVector) override; + /// Updates internal voltage variable of the component + void mnaCompUpdateVoltage(const Matrix& leftVector) override; + /// MNA pre step operations + void mnaParentPreStep(Real time, Int timeStepCount) override; + /// MNA post step operations + void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// Add MNA pre step dependencies + void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + /// Add MNA post step dependencies + void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + }; +} +} +} diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_VoltageSource.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_VoltageSource.h index 0f663c5f40..6e9a990f17 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_VoltageSource.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph1_VoltageSource.h @@ -25,8 +25,6 @@ namespace Ph1 { class VoltageSource : public MNASimPowerComp, public SharedFactory { - private: - Real mTimeStep; protected: void updateVoltage(Real time); public: diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Inductor.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Inductor.h index ae569e2d4f..8ecdf9d3d4 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Inductor.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Inductor.h @@ -42,7 +42,7 @@ namespace CPS { // #### General #### /// Initializes component from power flow data - void initializeFromNodesAndTerminals(Real frequency); + void initializeFromNodesAndTerminals(Real frequency) override; // #### MNA section #### /// Initializes internal variables of the component diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h index 295c676089..6a166cd2ca 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine.h @@ -11,8 +11,8 @@ #include #include #include +#include #include -#include #include namespace CPS { @@ -27,10 +27,8 @@ namespace Ph3 { public Base::Ph3::PiLine, public SharedFactory { protected: - /// Series Inductance submodel - std::shared_ptr mSubSeriesInductor; - /// Series Resistor submodel - std::shared_ptr mSubSeriesResistor; + /// Series Resistor-Inductance submodel + std::shared_ptr mSubSeriesElement; /// Parallel Resistor submodel at Terminal 0 std::shared_ptr mSubParallelResistor0; // Parallel Capacitor submodel at Terminal 0 diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine_deprecated.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine_deprecated.h new file mode 100644 index 0000000000..295c676089 --- /dev/null +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_PiLine_deprecated.h @@ -0,0 +1,80 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace CPS { +namespace EMT { +namespace Ph3 { + /// \brief PI-line dynamic phasor model + /// + /// This model consists sub components to represent the + /// RLC elements of a PI-line. + class PiLine : + public CompositePowerComp, + public Base::Ph3::PiLine, + public SharedFactory { + protected: + /// Series Inductance submodel + std::shared_ptr mSubSeriesInductor; + /// Series Resistor submodel + std::shared_ptr mSubSeriesResistor; + /// Parallel Resistor submodel at Terminal 0 + std::shared_ptr mSubParallelResistor0; + // Parallel Capacitor submodel at Terminal 0 + std::shared_ptr mSubParallelCapacitor0; + /// Parallel resistor submodel at Terminal 1 + std::shared_ptr mSubParallelResistor1; + // Parallel capacitor submodel at Terminal 1 + std::shared_ptr mSubParallelCapacitor1; + /// solver + std::vector mRightVectorStamps; + public: + /// Defines UID, name and logging level + PiLine(String uid, String name, Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + PiLine(String name, Logger::Level logLevel = Logger::Level::off) + : PiLine(name, name, logLevel) { } + + SimPowerComp::Ptr clone(String copySuffix); + + // #### General #### + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency); + + // #### MNA section #### + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix& leftVector) override; + /// Updates internal voltage variable of the component + void mnaCompUpdateVoltage(const Matrix& leftVector) override; + /// MNA pre step operations + void mnaParentPreStep(Real time, Int timeStepCount) override; + /// MNA post step operations + void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// Add MNA pre step dependencies + void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + /// Add MNA post step dependencies + void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + //MNAInterface::List mnaTearGroundComponents(); + /*void mnaTearInitialize(Real omega, Real timeStep); + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix); + void mnaTearApplyVoltageStamp(Matrix& voltageVector); + void mnaTearPostStep(Matrix voltage, Matrix current);*/ + + }; +} +} +} diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ResIndSeries.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ResIndSeries.h new file mode 100644 index 0000000000..84951333bd --- /dev/null +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_ResIndSeries.h @@ -0,0 +1,73 @@ +/* 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 + +namespace CPS { + namespace EMT { + namespace Ph3 { + /// EMT ResIndSeries + /// Assumption: non diagonal terms are equal to zero, Z00=Z11=Z22 + class ResIndSeries : + public MNASimPowerComp, + public SharedFactory { + protected: + /// DC equivalent current source [A] + Matrix mEquivCurrent; + /// Equivalent conductance [S] + Real mEquivCond; + /// Coefficient in front of previous current value + Real mPrevCurrFac; + public: + /// Inductance [H] + const Attribute::Ptr mInductance; + ///Resistance [ohm] + const Attribute::Ptr mResistance; + /// Defines UID, name, component parameters and logging level + ResIndSeries(String uid, String name, Logger::Level logLevel = Logger::Level::off); + /// Defines name, component parameters and logging level + ResIndSeries(String name, Logger::Level logLevel = Logger::Level::off) + : ResIndSeries(name, name, logLevel) { } + /// + SimPowerComp::Ptr clone(String name); + + // #### General #### + /// Sets model specific parameters + void setParameters(Matrix resistanceMatrix, Matrix inductanceMatrix); + + /// Initializes auxiliar variables + void initVars(Real timeStep); + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + // #### MNA section #### + /// Initializes internal variables of the component + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftSideVector) 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 pre and post step operations + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// Add MNA pre step dependencies + void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + /// add MNA pre and post step dependencies + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + }; + } + } +} diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Resistor.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Resistor.h index 800104e3af..607b24fc2c 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Resistor.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Resistor.h @@ -38,19 +38,19 @@ class Resistor : // #### MNA section #### /// Initializes internal variables of the component - void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftSideVector); + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftSideVector) override; /// Stamps system matrix - void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix); + void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; /// Stamps right side (source) vector - void mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { } + void mnaCompApplyRightSideVectorStamp(Matrix& rightVector) override { } /// Update interface voltage from MNA system result - void mnaCompUpdateVoltage(const Matrix& leftVector); + void mnaCompUpdateVoltage(const Matrix& leftVector) override; /// Update interface current from MNA system result - void mnaCompUpdateCurrent(const Matrix& leftVector); + void mnaCompUpdateCurrent(const Matrix& leftVector) override; /// MNA pre and post step operations - void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector); + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; /// add MNA pre and post step dependencies - void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector); + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; }; } } diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Transformer.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Transformer.h index 177be42d61..84e8352f8d 100644 --- a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Transformer.h +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Transformer.h @@ -8,80 +8,63 @@ #pragma once -#include +#include #include -#include -#include -#include #include namespace CPS { namespace EMT { namespace Ph3 { - /// Transformer that includes an inductance and resistance + /// Symmetric Transformer that includes an inductance and resistance class Transformer : - public CompositePowerComp, + public MNASimPowerComp, public SharedFactory, public Base::Ph3::Transformer { - private: - /// Internal resistor to model losses - std::shared_ptr mSubResistor; - /// Internal inductor to model losses - std::shared_ptr mSubInductor; - - /// Internal parallel resistance 1 as snubber - std::shared_ptr mSubSnubResistor1; - /// Internal parallel resistance 2 as snubber - std::shared_ptr mSubSnubResistor2; - /// Internal parallel capacitance 1 as snubber - std::shared_ptr mSubSnubCapacitor1; - /// Internal parallel capacitance 2 as snubber - std::shared_ptr mSubSnubCapacitor2; - - /// Snubber resistance 1 - Matrix mSnubberResistance1; - /// Snubber resistance 2 - Matrix mSnubberResistance2; - /// Snubber capacitance 1 - Matrix mSnubberCapacitance1; - /// Snubber capacitance 2 - Matrix mSnubberCapacitance2; - - /// Boolean for considering resistive losses with sub resistor - Bool mWithResistiveLosses; + public: + /// Defines UID, name and logging level /// Defines UID, name and logging level Transformer(String uid, String name, - Logger::Level logLevel = Logger::Level::off, Bool withResistiveLosses = false); + Logger::Level logLevel = Logger::Level::off); /// Defines name and logging level Transformer(String name, Logger::Level logLevel = Logger::Level::off) : Transformer(name, name, logLevel) { } - SimPowerComp::Ptr clone(String name); - + protected: + /// DC equivalent current source [A] + Matrix mEquivCurrent; + /// Equivalent conductance [S] + Real mEquivCond; + /// Coefficient in front of previous current value + Real mPrevCurrFac ; + public: // #### General #### /// Defines component parameters - void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, Real ratioPhase, Matrix resistance, Matrix inductance); + void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Matrix resistance, Matrix inductance); /// Initializes component from power flow data void initializeFromNodesAndTerminals(Real frequency); + /// Initializes auxiliar variables + void initVars(Real timeStep); // #### MNA section #### /// Initializes internal variables of the component - void mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftSideVector) override; /// Stamps system matrix void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; + /// Stamps right side (source) vector + void mnaCompApplyRightSideVectorStamp(Matrix& rightVector) override; /// Updates internal current variable of the component void mnaCompUpdateCurrent(const Matrix& leftVector) override; /// Updates internal voltage variable of the component void mnaCompUpdateVoltage(const Matrix& leftVector) override; /// MNA pre step operations - void mnaParentPreStep(Real time, Int timeStepCount) override; + void mnaCompPreStep(Real time, Int timeStepCount) override; /// MNA post step operations - void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; /// Add MNA pre step dependencies - void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; /// Add MNA post step dependencies - void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; }; } } diff --git a/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Transformer_deprecated.h b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Transformer_deprecated.h new file mode 100644 index 0000000000..177be42d61 --- /dev/null +++ b/dpsim-models/include/dpsim-models/EMT/EMT_Ph3_Transformer_deprecated.h @@ -0,0 +1,88 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace CPS { + namespace EMT { + namespace Ph3 { + /// Transformer that includes an inductance and resistance + class Transformer : + public CompositePowerComp, + public SharedFactory, + public Base::Ph3::Transformer { + private: + /// Internal resistor to model losses + std::shared_ptr mSubResistor; + /// Internal inductor to model losses + std::shared_ptr mSubInductor; + + /// Internal parallel resistance 1 as snubber + std::shared_ptr mSubSnubResistor1; + /// Internal parallel resistance 2 as snubber + std::shared_ptr mSubSnubResistor2; + /// Internal parallel capacitance 1 as snubber + std::shared_ptr mSubSnubCapacitor1; + /// Internal parallel capacitance 2 as snubber + std::shared_ptr mSubSnubCapacitor2; + + /// Snubber resistance 1 + Matrix mSnubberResistance1; + /// Snubber resistance 2 + Matrix mSnubberResistance2; + /// Snubber capacitance 1 + Matrix mSnubberCapacitance1; + /// Snubber capacitance 2 + Matrix mSnubberCapacitance2; + + /// Boolean for considering resistive losses with sub resistor + Bool mWithResistiveLosses; + public: + /// Defines UID, name and logging level + Transformer(String uid, String name, + Logger::Level logLevel = Logger::Level::off, Bool withResistiveLosses = false); + /// Defines name and logging level + Transformer(String name, Logger::Level logLevel = Logger::Level::off) + : Transformer(name, name, logLevel) { } + + SimPowerComp::Ptr clone(String name); + + // #### General #### + /// Defines component parameters + void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, Real ratioPhase, Matrix resistance, Matrix inductance); + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency); + + // #### MNA section #### + /// Initializes internal variables of the component + void mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + /// Stamps system matrix + void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix& leftVector) override; + /// Updates internal voltage variable of the component + void mnaCompUpdateVoltage(const Matrix& leftVector) override; + /// MNA pre step operations + void mnaParentPreStep(Real time, Int timeStepCount) override; + /// MNA post step operations + void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// Add MNA pre step dependencies + void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + /// Add MNA post step dependencies + void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + }; + } + } +} diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Inductor.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Inductor.h index 14e81501a3..52eedbed75 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Inductor.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Inductor.h @@ -9,7 +9,6 @@ #pragma once #include - #include #include @@ -50,8 +49,11 @@ namespace Ph1 { /// MNA post step operations void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector); /// Add MNA post step dependencies - void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector); - void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix); + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector); + // + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) override; }; } } diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine.h index b75ab78d0c..0d3f57d1e4 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine.h @@ -12,8 +12,8 @@ #include #include #include +#include #include -#include #include namespace CPS { @@ -71,10 +71,8 @@ namespace Ph1 { // #### Admittance matrix stamp #### MatrixComp mY_element; - /// Series Inductance submodel - std::shared_ptr mSubSeriesInductor; - /// Series Resistor submodel - std::shared_ptr mSubSeriesResistor; + /// Series Resistor-Inductance submodel + std::shared_ptr mSubSeriesElement; /// Parallel Resistor submodel at Terminal 0 std::shared_ptr mSubParallelResistor0; // Parallel Capacitor submodel at Terminal 0 @@ -97,10 +95,7 @@ namespace Ph1 { /// Defines name and logging level PiLine(String name, Logger::Level logLevel = Logger::Level::off) : PiLine(name, name, logLevel) { } - /// - SimPowerComp::Ptr clone(String copySuffix) override; - /// - void setParameters(Real resistance, Real inductance, Real capacitance = -1, Real conductance = -1); + /// Initializes component from power flow data void initializeFromNodesAndTerminals(Real frequency) override; diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine_deprecated.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine_deprecated.h new file mode 100644 index 0000000000..b75ab78d0c --- /dev/null +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_PiLine_deprecated.h @@ -0,0 +1,141 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace CPS { +namespace SP { +namespace Ph1 { + /// \brief PI-line static phasor model + /// + /// For MNA this model consists sub components to represent the + /// RLC elements of a PI-line. + class PiLine : + public CompositePowerComp, + public Base::Ph1::PiLine, + public MNATearInterface, + public SharedFactory, + public PFSolverInterfaceBranch { + public: + ///base voltage [V] + const Attribute::Ptr mBaseVoltage; + + // #### Power flow results #### + /// branch Current flow [A], coef(0) has data from node 0, coef(1) from node 1. + const Attribute::Ptr mCurrent; + + /// branch active powerflow [W], coef(0) has data from node 0, coef(1) from node 1. + const Attribute::Ptr mActivePowerBranch; + + /// branch reactive powerflow [Var], coef(0) has data from node 0, coef(1) from node 1. + const Attribute::Ptr mReactivePowerBranch; + + protected: + /// CHECK: Which of these really need to be member variables? + ///base current [A] + Real mBaseCurrent; + ///base apparent power [VA] + Real mBaseApparentPower; + ///base omega [1/s] + Real mBaseOmega; + ///base impedance [Ohm] + Real mBaseImpedance; + ///base admittance [S] + Real mBaseAdmittance; + ///base inductance [H] + Real mBaseInductance; + ///base capacitance [F] + Real mBaseCapacitance; + + ///resistance in [pu] + Real mSeriesResPerUnit; + ///Capacitance of the line in [pu] + Real mParallelCapPerUnit; + ///Inductance of the line in [pu] + Real mSeriesIndPerUnit; + ///Conductance of the line in [pu] + Real mParallelCondPerUnit; + + // #### Admittance matrix stamp #### + MatrixComp mY_element; + /// Series Inductance submodel + std::shared_ptr mSubSeriesInductor; + /// Series Resistor submodel + std::shared_ptr mSubSeriesResistor; + /// Parallel Resistor submodel at Terminal 0 + std::shared_ptr mSubParallelResistor0; + // Parallel Capacitor submodel at Terminal 0 + std::shared_ptr mSubParallelCapacitor0; + /// Parallel resistor submodel at Terminal 1 + std::shared_ptr mSubParallelResistor1; + /// Parallel capacitor submodel at Terminal 1 + std::shared_ptr mSubParallelCapacitor1; + /// Right side vectors of subcomponents + std::vector mRightVectorStamps; + public: + /// nodal active power injection + const Attribute::Ptr mActivePowerInjection; + /// nodal reactive power injection + const Attribute::Ptr mReactivePowerInjection; + + // #### General #### + /// Defines UID, name and logging level + PiLine(String uid, String name, Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + PiLine(String name, Logger::Level logLevel = Logger::Level::off) + : PiLine(name, name, logLevel) { } + /// + SimPowerComp::Ptr clone(String copySuffix) override; + /// + void setParameters(Real resistance, Real inductance, Real capacitance = -1, Real conductance = -1); + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + // #### Powerflow section #### + /// Set base voltage + void setBaseVoltage(Real baseVoltage); + /// Calculates component's parameters in specified per-unit system + void calculatePerUnitParameters(Real baseApparentPower, Real baseOmega); + /// Stamps admittance matrix + void pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) override; + /// updates branch current and power flow, input pu value, update with real value + void updateBranchFlow(VectorComp& current, VectorComp& powerflow); + /// stores nodal injection power in this line object + void storeNodalInjection(Complex powerInjection); + + // #### Getter #### + /// get admittance matrix + MatrixComp Y_element(); + + // #### MNA section #### + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix& leftVector) override; + /// Updates internal voltage variable of the component + void mnaCompUpdateVoltage(const Matrix& leftVector) override; + /// MNA post-step operations + void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// add MNA post-step dependencies + void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + MNAInterface::List mnaTearGroundComponents() override; + void mnaTearInitialize(Real omega, Real timeStep) override; + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) override; + void mnaTearApplyVoltageStamp(Matrix& voltageVector) override; + void mnaTearPostStep(Complex voltage, Complex current) override; + }; +} +} +} diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_ResIndSeries.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_ResIndSeries.h new file mode 100644 index 0000000000..26093af8ee --- /dev/null +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_ResIndSeries.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 + +namespace CPS { +namespace SP { +namespace Ph1 { + /// Static phasor ResIndSeries model (only implemented for dynamic simulations!) + class ResIndSeries : + public MNASimPowerComp, + public MNATearInterface, + public SharedFactory { + private: + /// Impedance + Complex mImpedance; + public: + /// Inductance [H] + const Attribute::Ptr mInductance; + ///Resistance [ohm] + const Attribute::Ptr mResistance; + /// Defines UID, name and logging level + ResIndSeries(String uid, String name, Logger::Level logLevel = Logger::Level::off); + /// Defines name and logging level + ResIndSeries(String name, Logger::Level logLevel = Logger::Level::off) + : ResIndSeries(name, name, logLevel) { } + + SimPowerComp::Ptr clone(String name); + + // #### General #### + /// Sets model specific parameters + void setParameters(Real resistance, Real inductance); + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + + // #### MNA section #### + /// Initializes MNA specific variables + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + /// Stamps system matrix + void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) 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 and post step operations + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// add MNA pre and post step dependencies + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + // #### MNA Tear Section #### + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) override; + }; +} +} +} diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Resistor.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Resistor.h index 97a532b947..8ccea3bf06 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Resistor.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Resistor.h @@ -55,7 +55,7 @@ namespace Ph1 { // #### General #### /// Initializes component from power flow data - void initializeFromNodesAndTerminals(Real frequency); + void initializeFromNodesAndTerminals(Real frequency) override; // #### Powerflow section #### /// Set base voltage @@ -67,20 +67,20 @@ namespace Ph1 { // #### MNA section #### /// - void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector); + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; /// Stamps system matrix - void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix); + void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; /// Update interface voltage from MNA system result - void mnaCompUpdateVoltage(const Matrix& leftVector); + void mnaCompUpdateVoltage(const Matrix& leftVector) override; /// Update interface current from MNA system result - void mnaCompUpdateCurrent(const Matrix& leftVector); + void mnaCompUpdateCurrent(const Matrix& leftVector) override; /// MNA pre and post step operations - void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector); + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; /// add MNA pre and post step dependencies - void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector); + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; // #### MNA Tear Section #### - void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix); + void mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) override; }; } diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer.h index 99927effc0..d9087babd8 100644 --- a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer.h +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer.h @@ -8,12 +8,9 @@ #pragma once -#include +#include #include #include -#include -#include -#include #include namespace CPS { @@ -21,35 +18,12 @@ namespace SP { namespace Ph1 { /// Transformer that includes an inductance and resistance class Transformer : - public CompositePowerComp, + public MNASimPowerComp, public Base::Ph1::Transformer, public SharedFactory, public PFSolverInterfaceBranch { private: - /// Internal resistor to model losses - std::shared_ptr mSubResistor; - /// Internal inductor to model losses - std::shared_ptr mSubInductor; - - /// Internal parallel resistance 1 as snubber - std::shared_ptr mSubSnubResistor1; - /// Internal parallel resistance 2 as snubber - std::shared_ptr mSubSnubResistor2; - /// Internal parallel capacitance 1 as snubber - std::shared_ptr mSubSnubCapacitor1; - /// Internal parallel capacitance 2 as snubber - std::shared_ptr mSubSnubCapacitor2; - - /// Snubber resistance 1 [Ohm] - Real mSnubberResistance1; - /// Snubber resistance 2 [Ohm] - Real mSnubberResistance2; - /// Snubber capacitance 1 [F] - Real mSnubberCapacitance1; - /// Snubber capacitance 2 [F] - Real mSnubberCapacitance2; - /// Transformer ratio magnitude Real mRatioAbs = 1; /// Transformer ratio pase [deg] @@ -59,8 +33,8 @@ namespace Ph1 { /// Reactance [Ohm] Real mReactance; - /// Leakage - Complex mLeakage; + /// Series impedance + Complex mImpedance; /// base apparent power[VA] Real mBaseApparentPower; @@ -84,16 +58,12 @@ namespace Ph1 { Real mInductancePerUnit; /// leakage impedance Complex mLeakagePerUnit; - /// magnetizing impedance - Complex mMagnetizingPerUnit; /// transformer ratio Real mRatioAbsPerUnit; // #### Admittance matrix stamp #### MatrixComp mY_element; - /// Boolean for considering resistive losses with sub resistor - Bool mWithResistiveLosses; public: /// base voltage [V] const Attribute::Ptr mBaseVoltage; @@ -114,13 +84,11 @@ namespace Ph1 { /// Defines UID, name and logging level Transformer(String uid, String name, - Logger::Level logLevel = Logger::Level::off, Bool withResistiveLosses = false); + Logger::Level logLevel = Logger::Level::off); /// Defines name and logging level Transformer(String name, Logger::Level logLevel = Logger::Level::off) : Transformer(name, name, logLevel) { } - SimPowerComp::Ptr clone(String name) override; - // #### General #### /// Set transformer specific parameters (without rated power) void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance); @@ -147,22 +115,19 @@ namespace Ph1 { // #### MNA Section #### /// Initializes internal variables of the component - void mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + void mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; /// Stamps system matrix void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; - /// Updates internal current variable of the component - void mnaCompUpdateCurrent(const Matrix& leftVector) override; + /// + void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) override; + /// MNA post step operations + void mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; /// Updates internal voltage variable of the component void mnaCompUpdateVoltage(const Matrix& leftVector) override; - /// MNA pre step operations - void mnaParentPreStep(Real time, Int timeStepCount) override; - /// MNA post step operations - void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; - /// Add MNA pre step dependencies - void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; - /// Add MNA post step dependencies - void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; - + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix& leftVector) override; }; } } diff --git a/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer_deprecated.h b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer_deprecated.h new file mode 100644 index 0000000000..99927effc0 --- /dev/null +++ b/dpsim-models/include/dpsim-models/SP/SP_Ph1_Transformer_deprecated.h @@ -0,0 +1,169 @@ +/* Copyright 2017-2021 Institute for Automation of Complex Power Systems, + * EONERC, RWTH Aachen University + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + *********************************************************************************/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace CPS { +namespace SP { +namespace Ph1 { + /// Transformer that includes an inductance and resistance + class Transformer : + public CompositePowerComp, + public Base::Ph1::Transformer, + public SharedFactory, + public PFSolverInterfaceBranch { + + private: + /// Internal resistor to model losses + std::shared_ptr mSubResistor; + /// Internal inductor to model losses + std::shared_ptr mSubInductor; + + /// Internal parallel resistance 1 as snubber + std::shared_ptr mSubSnubResistor1; + /// Internal parallel resistance 2 as snubber + std::shared_ptr mSubSnubResistor2; + /// Internal parallel capacitance 1 as snubber + std::shared_ptr mSubSnubCapacitor1; + /// Internal parallel capacitance 2 as snubber + std::shared_ptr mSubSnubCapacitor2; + + /// Snubber resistance 1 [Ohm] + Real mSnubberResistance1; + /// Snubber resistance 2 [Ohm] + Real mSnubberResistance2; + /// Snubber capacitance 1 [F] + Real mSnubberCapacitance1; + /// Snubber capacitance 2 [F] + Real mSnubberCapacitance2; + + /// Transformer ratio magnitude + Real mRatioAbs = 1; + /// Transformer ratio pase [deg] + Real mRatioPhase = 0; + /// Nominal omega + Real mNominalOmega; + /// Reactance [Ohm] + Real mReactance; + + /// Leakage + Complex mLeakage; + + /// base apparent power[VA] + Real mBaseApparentPower; + /// base impedance [ohm] + Real mBaseImpedance; + /// base inductance [H] + Real mBaseInductance; + /// base admittance [S] + Real mBaseAdmittance; + ///base omega [1/s] + Real mBaseOmega; + + ///base current [A] + Real mBaseCurrent; + + /// resistance + Real mResistancePerUnit; + /// reactance + Real mReactancePerUnit; + /// inductance + Real mInductancePerUnit; + /// leakage impedance + Complex mLeakagePerUnit; + /// magnetizing impedance + Complex mMagnetizingPerUnit; + /// transformer ratio + Real mRatioAbsPerUnit; + + // #### Admittance matrix stamp #### + MatrixComp mY_element; + + /// Boolean for considering resistive losses with sub resistor + Bool mWithResistiveLosses; + public: + /// base voltage [V] + const Attribute::Ptr mBaseVoltage; + + // #### Power flow results #### + /// branch Current flow [A], coef(0) has data from node 0, coef(1) from node 1. + const Attribute::Ptr mCurrent; + + /// branch active powerflow [W], coef(0) has data from node 0, coef(1) from node 1. + const Attribute::Ptr mActivePowerBranch; + + /// branch reactive powerflow [Var], coef(0) has data from node 0, coef(1) from node 1. + const Attribute::Ptr mReactivePowerBranch; + /// nodal active power injection + const Attribute::Ptr mActivePowerInjection; + /// nodal reactive power injection + const Attribute::Ptr mReactivePowerInjection; + + /// Defines UID, name and logging level + Transformer(String uid, String name, + Logger::Level logLevel = Logger::Level::off, Bool withResistiveLosses = false); + /// Defines name and logging level + Transformer(String name, Logger::Level logLevel = Logger::Level::off) + : Transformer(name, name, logLevel) { } + + SimPowerComp::Ptr clone(String name) override; + + // #### General #### + /// Set transformer specific parameters (without rated power) + void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance); + /// Set transformer specific parameters + void setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, Real ratioPhase, Real resistance, Real inductance); + /// Initializes component from power flow data + void initializeFromNodesAndTerminals(Real frequency) override; + + // #### Powerflow section #### + /// Set base voltage + void setBaseVoltage(Real baseVoltage); + /// Initializes component from power flow data + void calculatePerUnitParameters(Real baseApparentPower, Real baseOmega); + /// Stamps admittance matrix + void pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) override; + /// updates branch current and power flow, input pu value, update with real value + void updateBranchFlow(VectorComp& current, VectorComp& powerflow); + /// stores nodal injection power in this line object + void storeNodalInjection(Complex powerInjection); + + // #### Getter #### + /// get admittance matrix + MatrixComp Y_element(); + + // #### MNA Section #### + /// Initializes internal variables of the component + void mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) override; + /// Stamps system matrix + void mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) override; + /// Updates internal current variable of the component + void mnaCompUpdateCurrent(const Matrix& leftVector) override; + /// Updates internal voltage variable of the component + void mnaCompUpdateVoltage(const Matrix& leftVector) override; + /// MNA pre step operations + void mnaParentPreStep(Real time, Int timeStepCount) override; + /// MNA post step operations + void mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) override; + /// Add MNA pre step dependencies + void mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) override; + /// Add MNA post step dependencies + void mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) override; + + }; +} +} +} diff --git a/dpsim-models/src/CIM/Reader.cpp b/dpsim-models/src/CIM/Reader.cpp index c093ba0cf1..f17eda13a9 100644 --- a/dpsim-models/src/CIM/Reader.cpp +++ b/dpsim-models/src/CIM/Reader.cpp @@ -351,8 +351,10 @@ TopologicalPowerComp::Ptr Reader::mapACLineSegment(CIMPP::ACLineSegment* line) { // By default there is always a small conductance to ground to // avoid problems with floating nodes. - Real capacitance = mShuntCapacitorValue; - Real conductance = mShuntConductanceValue; + //Real capacitance = mShuntCapacitorValue; + //Real conductance = mShuntConductanceValue; + Real capacitance=0; + Real conductance=0; if(line->bch.value > 1e-9 && !mSetShuntCapacitor) capacitance = Real(line->bch.value / mOmega); @@ -491,8 +493,8 @@ TopologicalPowerComp::Ptr Reader::mapPowerTransformer(CIMPP::PowerTransformer* t Matrix resistance_3ph = CPS::Math::singlePhaseParameterToThreePhase(resistance); Matrix inductance_3ph = CPS::Math::singlePhaseParameterToThreePhase(inductance); Bool withResistiveLosses = resistance > 0; - auto transformer = std::make_shared(trans->mRID, trans->name, mComponentLogLevel, withResistiveLosses); - transformer->setParameters(voltageNode1, voltageNode2, ratedPower, ratioAbs, ratioPhase, resistance_3ph, inductance_3ph); + auto transformer = std::make_shared(trans->mRID, trans->name, mComponentLogLevel); + transformer->setParameters(voltageNode1, voltageNode2, ratioAbs, ratioPhase, resistance_3ph, inductance_3ph); return transformer; } else @@ -509,9 +511,8 @@ TopologicalPowerComp::Ptr Reader::mapPowerTransformer(CIMPP::PowerTransformer* t return transformer; } else { - Bool withResistiveLosses = resistance > 0; - auto transformer = std::make_shared(trans->mRID, trans->name, mComponentLogLevel, withResistiveLosses); - transformer->setParameters(voltageNode1, voltageNode2, ratedPower, ratioAbs, ratioPhase, resistance, inductance); + auto transformer = std::make_shared(trans->mRID, trans->name, mComponentLogLevel); + transformer->setParameters(voltageNode1, voltageNode2, ratioAbs, ratioPhase, resistance, inductance); return transformer; } } diff --git a/dpsim-models/src/CMakeLists.txt b/dpsim-models/src/CMakeLists.txt index 230c6cccc3..61175f60b4 100644 --- a/dpsim-models/src/CMakeLists.txt +++ b/dpsim-models/src/CMakeLists.txt @@ -27,6 +27,7 @@ list(APPEND MODELS_SOURCES DP/DP_Ph1_RXLoadSwitch.cpp DP/DP_Ph1_PQLoadCS.cpp DP/DP_Ph1_Resistor.cpp + DP/DP_Ph1_ResIndSeries.cpp DP/DP_Ph1_Transformer.cpp DP/DP_Ph1_VoltageSource.cpp DP/DP_Ph1_VoltageSourceRamp.cpp @@ -77,6 +78,7 @@ list(APPEND MODELS_SOURCES EMT/EMT_Ph3_AvVoltSourceInverterStateSpace.cpp EMT/EMT_Ph3_Resistor.cpp EMT/EMT_Ph3_SeriesResistor.cpp + EMT/EMT_Ph3_ResIndSeries.cpp EMT/EMT_Ph3_SeriesSwitch.cpp EMT/EMT_Ph3_VoltageSourceNorton.cpp EMT/EMT_Ph3_PiLine.cpp @@ -105,6 +107,7 @@ list(APPEND MODELS_SOURCES SP/SP_Ph1_Capacitor.cpp SP/SP_Ph1_Inductor.cpp SP/SP_Ph1_Resistor.cpp + SP/SP_Ph1_ResIndSeries.cpp SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp SP/SP_Ph1_RXLine.cpp SP/SP_Ph1_VoltageSourceInverter.cpp diff --git a/dpsim-models/src/DP/DP_Ph1_AvVoltageSourceInverterDQ.cpp b/dpsim-models/src/DP/DP_Ph1_AvVoltageSourceInverterDQ.cpp index b780d164f6..3915088639 100644 --- a/dpsim-models/src/DP/DP_Ph1_AvVoltageSourceInverterDQ.cpp +++ b/dpsim-models/src/DP/DP_Ph1_AvVoltageSourceInverterDQ.cpp @@ -29,7 +29,7 @@ DP::Ph1::AvVoltageSourceInverterDQ::AvVoltageSourceInverterDQ(String uid, String if (withTrafo) { setVirtualNodeNumber(4); - mConnectionTransformer = DP::Ph1::Transformer::make(**mName + "_trans", **mName + "_trans", mLogLevel, false); + mConnectionTransformer = DP::Ph1::Transformer::make(**mName + "_trans", **mName + "_trans", mLogLevel); addMNASubComponent(mConnectionTransformer, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); } else { setVirtualNodeNumber(3); @@ -111,7 +111,8 @@ void DP::Ph1::AvVoltageSourceInverterDQ::setTransformerParameters(Real nomVoltag if (mWithConnectionTransformer) // TODO: resistive losses neglected so far (mWithResistiveLosses=false) - mConnectionTransformer->setParameters(mTransformerNominalVoltageEnd1, mTransformerNominalVoltageEnd2, mTransformerRatedPower, mTransformerRatioAbs, mTransformerRatioPhase, mTransformerResistance, mTransformerInductance); + mConnectionTransformer->setParameters(mTransformerNominalVoltageEnd1, mTransformerNominalVoltageEnd2, + mTransformerRatioAbs, mTransformerRatioPhase, mTransformerResistance, mTransformerInductance); } void DP::Ph1::AvVoltageSourceInverterDQ::setControllerParameters(Real Kp_pll, Real Ki_pll, diff --git a/dpsim-models/src/DP/DP_Ph1_Inductor.cpp b/dpsim-models/src/DP/DP_Ph1_Inductor.cpp index 8affd71788..b60fba5b09 100644 --- a/dpsim-models/src/DP/DP_Ph1_Inductor.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Inductor.cpp @@ -54,6 +54,7 @@ void DP::Ph1::Inductor::initializeFromNodesAndTerminals(Real frequency) { Logger::phasorToString((**mIntfCurrent)(0,0)), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } // #### MNA functions #### @@ -89,11 +90,11 @@ void DP::Ph1::Inductor::mnaCompInitialize(Real omega, Real timeStep, Attributeflush(); } void DP::Ph1::Inductor::mnaCompInitializeHarm(Real omega, Real timeStep, std::vector::Ptr> leftVectors) { - updateMatrixNodeIndices(); - + updateMatrixNodeIndices(); initVars(timeStep); mMnaTasks.push_back(std::make_shared(*this)); diff --git a/dpsim-models/src/DP/DP_Ph1_PiLine.cpp b/dpsim-models/src/DP/DP_Ph1_PiLine.cpp index 929d8b3ff5..26e119507d 100644 --- a/dpsim-models/src/DP/DP_Ph1_PiLine.cpp +++ b/dpsim-models/src/DP/DP_Ph1_PiLine.cpp @@ -12,7 +12,6 @@ using namespace CPS; DP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) : Base::Ph1::PiLine(mAttributes), CompositePowerComp(uid, name, true, true, logLevel) { - setVirtualNodeNumber(1); setTerminalNumber(2); SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); @@ -20,13 +19,6 @@ DP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) **mIntfCurrent = MatrixComp::Zero(1,1); } -///DEPRECATED: Remove method -SimPowerComp::Ptr DP::Ph1::PiLine::clone(String name) { - auto copy = PiLine::make(name, mLogLevel); - copy->setParameters(**mSeriesRes, **mSeriesInd, **mParallelCap, **mParallelCond); - return copy; -} - void DP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { // Static calculation @@ -35,46 +27,32 @@ void DP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { (**mIntfVoltage)(0,0) = initialSingleVoltage(1) - initialSingleVoltage(0); (**mIntfCurrent)(0,0) = (**mIntfVoltage)(0,0) / impedance; - // Initialization of virtual node - mVirtualNodes[0]->setInitialVoltage( initialSingleVoltage(0) + (**mIntfCurrent)(0,0) * **mSeriesRes ); - - // Create series sub components - mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); - mSubSeriesResistor->setParameters(**mSeriesRes); - mSubSeriesResistor->connect({ mTerminals[0]->node(), mVirtualNodes[0] }); - mSubSeriesResistor->initialize(mFrequencies); - mSubSeriesResistor->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); - - mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); - mSubSeriesInductor->setParameters(**mSeriesInd); - mSubSeriesInductor->connect({ mVirtualNodes[0], mTerminals[1]->node() }); - mSubSeriesInductor->initialize(mFrequencies); - mSubSeriesInductor->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubSeriesInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - // By default there is always a small conductance to ground to - // avoid problems with floating nodes. - Real defaultParallelCond = 1e-6; - **mParallelCond = (**mParallelCond > 0) ? **mParallelCond : defaultParallelCond; + // Create series rl sub component + mSubSeriesElement = std::make_shared(**mName + "_ResIndSeries", mLogLevel); + mSubSeriesElement->connect({ mTerminals[0]->node(), mTerminals[1]->node() }); + mSubSeriesElement->setParameters(**mSeriesRes, **mSeriesInd); + mSubSeriesElement->initialize(mFrequencies); + mSubSeriesElement->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesElement, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); // Create parallel sub components - mSubParallelResistor0 = std::make_shared(**mName + "_con0", mLogLevel); - mSubParallelResistor0->setParameters(2. / **mParallelCond); - mSubParallelResistor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); - mSubParallelResistor0->initialize(mFrequencies); - mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubParallelResistor0, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); - - mSubParallelResistor1 = std::make_shared(**mName + "_con1", mLogLevel); - mSubParallelResistor1->setParameters(2. / **mParallelCond); - mSubParallelResistor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); - mSubParallelResistor1->initialize(mFrequencies); - mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubParallelResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); - - - if (**mParallelCap >= 0) { + if (**mParallelCond > 0) { + mSubParallelResistor0 = std::make_shared(**mName + "_con0", mLogLevel); + mSubParallelResistor0->setParameters(2. / **mParallelCond); + mSubParallelResistor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); + mSubParallelResistor0->initialize(mFrequencies); + mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor0, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubParallelResistor1 = std::make_shared(**mName + "_con1", mLogLevel); + mSubParallelResistor1->setParameters(2. / **mParallelCond); + mSubParallelResistor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); + mSubParallelResistor1->initialize(mFrequencies); + mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + } + + if (**mParallelCap > 0) { mSubParallelCapacitor0 = std::make_shared(**mName + "_cap0", mLogLevel); mSubParallelCapacitor0->setParameters(**mParallelCap / 2.); mSubParallelCapacitor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); @@ -96,13 +74,11 @@ void DP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { "\nCurrent: {:s}" "\nTerminal 0 voltage: {:s}" "\nTerminal 1 voltage: {:s}" - "\nVirtual Node 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)), - Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); + Logger::phasorToString(initialSingleVoltage(1))); } void DP::Ph1::PiLine::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { @@ -139,16 +115,18 @@ void DP::Ph1::PiLine::mnaCompUpdateVoltage(const Matrix& leftVector) { } void DP::Ph1::PiLine::mnaCompUpdateCurrent(const Matrix& leftVector) { - (**mIntfCurrent)(0,0) = mSubSeriesInductor->intfCurrent()(0, 0); + (**mIntfCurrent)(0,0) = mSubSeriesElement->intfCurrent()(0, 0); } MNAInterface::List DP::Ph1::PiLine::mnaTearGroundComponents() { MNAInterface::List gndComponents; - gndComponents.push_back(mSubParallelResistor0); - gndComponents.push_back(mSubParallelResistor1); + if (**mParallelCond > 0) { + gndComponents.push_back(mSubParallelResistor0); + gndComponents.push_back(mSubParallelResistor1); + } - if (**mParallelCap >= 0) { + if (**mParallelCap > 0) { gndComponents.push_back(mSubParallelCapacitor0); gndComponents.push_back(mSubParallelCapacitor1); } @@ -157,21 +135,18 @@ MNAInterface::List DP::Ph1::PiLine::mnaTearGroundComponents() { } void DP::Ph1::PiLine::mnaTearInitialize(Real omega, Real timeStep) { - mSubSeriesResistor->mnaTearSetIdx(mTearIdx); - mSubSeriesResistor->mnaTearInitialize(omega, timeStep); - mSubSeriesInductor->mnaTearSetIdx(mTearIdx); - mSubSeriesInductor->mnaTearInitialize(omega, timeStep); + mSubSeriesElement->mnaTearSetIdx(mTearIdx); + mSubSeriesElement->mnaTearInitialize(omega, timeStep); } void DP::Ph1::PiLine::mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) { - mSubSeriesResistor->mnaTearApplyMatrixStamp(tearMatrix); - mSubSeriesInductor->mnaTearApplyMatrixStamp(tearMatrix); + mSubSeriesElement->mnaTearApplyMatrixStamp(tearMatrix); } void DP::Ph1::PiLine::mnaTearApplyVoltageStamp(Matrix& voltageVector) { - mSubSeriesInductor->mnaTearApplyVoltageStamp(voltageVector); + mSubSeriesElement->mnaTearApplyVoltageStamp(voltageVector); } void DP::Ph1::PiLine::mnaTearPostStep(Complex voltage, Complex current) { - mSubSeriesInductor->mnaTearPostStep(voltage - current * **mSeriesRes, current); + mSubSeriesElement->mnaTearPostStep(voltage - current * **mSeriesRes, current); } diff --git a/dpsim-models/src/DP/DP_Ph1_PiLine_deprecated.cpp b/dpsim-models/src/DP/DP_Ph1_PiLine_deprecated.cpp new file mode 100644 index 0000000000..929d8b3ff5 --- /dev/null +++ b/dpsim-models/src/DP/DP_Ph1_PiLine_deprecated.cpp @@ -0,0 +1,177 @@ +/* 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; + +DP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) + : Base::Ph1::PiLine(mAttributes), CompositePowerComp(uid, name, true, true, logLevel) { + setVirtualNodeNumber(1); + setTerminalNumber(2); + + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + **mIntfVoltage = MatrixComp::Zero(1,1); + **mIntfCurrent = MatrixComp::Zero(1,1); +} + +///DEPRECATED: Remove method +SimPowerComp::Ptr DP::Ph1::PiLine::clone(String name) { + auto copy = PiLine::make(name, mLogLevel); + copy->setParameters(**mSeriesRes, **mSeriesInd, **mParallelCap, **mParallelCond); + return copy; +} + +void DP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { + + // Static calculation + Real omega = 2.*PI * frequency; + Complex impedance = { **mSeriesRes, omega * **mSeriesInd }; + (**mIntfVoltage)(0,0) = initialSingleVoltage(1) - initialSingleVoltage(0); + (**mIntfCurrent)(0,0) = (**mIntfVoltage)(0,0) / impedance; + + // Initialization of virtual node + mVirtualNodes[0]->setInitialVoltage( initialSingleVoltage(0) + (**mIntfCurrent)(0,0) * **mSeriesRes ); + + // Create series sub components + mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); + mSubSeriesResistor->setParameters(**mSeriesRes); + mSubSeriesResistor->connect({ mTerminals[0]->node(), mVirtualNodes[0] }); + mSubSeriesResistor->initialize(mFrequencies); + mSubSeriesResistor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); + mSubSeriesInductor->setParameters(**mSeriesInd); + mSubSeriesInductor->connect({ mVirtualNodes[0], mTerminals[1]->node() }); + mSubSeriesInductor->initialize(mFrequencies); + mSubSeriesInductor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // By default there is always a small conductance to ground to + // avoid problems with floating nodes. + Real defaultParallelCond = 1e-6; + **mParallelCond = (**mParallelCond > 0) ? **mParallelCond : defaultParallelCond; + + // Create parallel sub components + mSubParallelResistor0 = std::make_shared(**mName + "_con0", mLogLevel); + mSubParallelResistor0->setParameters(2. / **mParallelCond); + mSubParallelResistor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); + mSubParallelResistor0->initialize(mFrequencies); + mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor0, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubParallelResistor1 = std::make_shared(**mName + "_con1", mLogLevel); + mSubParallelResistor1->setParameters(2. / **mParallelCond); + mSubParallelResistor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); + mSubParallelResistor1->initialize(mFrequencies); + mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + + if (**mParallelCap >= 0) { + mSubParallelCapacitor0 = std::make_shared(**mName + "_cap0", mLogLevel); + mSubParallelCapacitor0->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); + mSubParallelCapacitor0->initialize(mFrequencies); + mSubParallelCapacitor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor0, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + mSubParallelCapacitor1 = std::make_shared(**mName + "_cap1", mLogLevel); + mSubParallelCapacitor1->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); + mSubParallelCapacitor1->initialize(mFrequencies); + mSubParallelCapacitor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + } + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\nVirtual Node 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::phasorToString((**mIntfVoltage)(0,0)), + Logger::phasorToString((**mIntfCurrent)(0,0)), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1)), + Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); +} + +void DP::Ph1::PiLine::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { + // add pre-step dependencies of component itself + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); +} + +void DP::Ph1::PiLine::mnaParentPreStep(Real time, Int timeStepCount) { + // pre-step of component itself + this->mnaApplyRightSideVectorStamp(**mRightVector); +} + +void DP::Ph1::PiLine::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + // add post-step dependencies of component itself + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void DP::Ph1::PiLine::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + // post-step of component itself + this->mnaUpdateVoltage(**leftVector); + this->mnaUpdateCurrent(**leftVector); +} + +void DP::Ph1::PiLine::mnaCompUpdateVoltage(const Matrix& leftVector) { + (**mIntfVoltage)(0, 0) = 0; + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0,0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0,0) = (**mIntfVoltage)(0,0) - Math::complexFromVectorElement(leftVector, matrixNodeIndex(0)); +} + +void DP::Ph1::PiLine::mnaCompUpdateCurrent(const Matrix& leftVector) { + (**mIntfCurrent)(0,0) = mSubSeriesInductor->intfCurrent()(0, 0); +} + +MNAInterface::List DP::Ph1::PiLine::mnaTearGroundComponents() { + MNAInterface::List gndComponents; + + gndComponents.push_back(mSubParallelResistor0); + gndComponents.push_back(mSubParallelResistor1); + + if (**mParallelCap >= 0) { + gndComponents.push_back(mSubParallelCapacitor0); + gndComponents.push_back(mSubParallelCapacitor1); + } + + return gndComponents; +} + +void DP::Ph1::PiLine::mnaTearInitialize(Real omega, Real timeStep) { + mSubSeriesResistor->mnaTearSetIdx(mTearIdx); + mSubSeriesResistor->mnaTearInitialize(omega, timeStep); + mSubSeriesInductor->mnaTearSetIdx(mTearIdx); + mSubSeriesInductor->mnaTearInitialize(omega, timeStep); +} + +void DP::Ph1::PiLine::mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) { + mSubSeriesResistor->mnaTearApplyMatrixStamp(tearMatrix); + mSubSeriesInductor->mnaTearApplyMatrixStamp(tearMatrix); +} + +void DP::Ph1::PiLine::mnaTearApplyVoltageStamp(Matrix& voltageVector) { + mSubSeriesInductor->mnaTearApplyVoltageStamp(voltageVector); +} + +void DP::Ph1::PiLine::mnaTearPostStep(Complex voltage, Complex current) { + mSubSeriesInductor->mnaTearPostStep(voltage - current * **mSeriesRes, current); +} diff --git a/dpsim-models/src/DP/DP_Ph1_ResIndSeries.cpp b/dpsim-models/src/DP/DP_Ph1_ResIndSeries.cpp index 2c60752ed3..9de8888c54 100644 --- a/dpsim-models/src/DP/DP_Ph1_ResIndSeries.cpp +++ b/dpsim-models/src/DP/DP_Ph1_ResIndSeries.cpp @@ -7,13 +7,13 @@ *********************************************************************************/ #include +#include using namespace CPS; DP::Ph1::ResIndSeries::ResIndSeries(String uid, String name, Logger::Level logLevel) : MNASimPowerComp(uid, name, true, true, logLevel), mInductance(mAttributes->create("L")), - ///FIXME: The resistance is never used anywhere... mResistance(mAttributes->create("R")) { mEquivCurrent = { 0, 0 }; **mIntfVoltage = MatrixComp::Zero(1,1); @@ -31,6 +31,12 @@ SimPowerComp::Ptr DP::Ph1::ResIndSeries::clone(String name) { void DP::Ph1::ResIndSeries::setParameters(Real resistance, Real inductance) { **mResistance = resistance; **mInductance = inductance; + + //check initial value of inductance + if (**mInductance==0.0) { + std::string err = "Inductance of " + this->name() + " can not be zero!"; + throw std::invalid_argument(err); + } } void DP::Ph1::ResIndSeries::initialize(Matrix frequencies) { @@ -44,7 +50,7 @@ void DP::Ph1::ResIndSeries::initialize(Matrix frequencies) { void DP::Ph1::ResIndSeries::initializeFromNodesAndTerminals(Real frequency) { Real omega = 2. * PI * frequency; - Complex impedance = { 0, omega * **mInductance }; + Complex impedance = { **mResistance, omega * **mInductance }; (**mIntfVoltage)(0,0) = initialSingleVoltage(1) - initialSingleVoltage(0); (**mIntfCurrent)(0,0) = (**mIntfVoltage)(0,0) / impedance; @@ -59,6 +65,7 @@ void DP::Ph1::ResIndSeries::initializeFromNodesAndTerminals(Real frequency) { Logger::phasorToString((**mIntfCurrent)(0,0)), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } // #### MNA functions #### @@ -66,18 +73,17 @@ void DP::Ph1::ResIndSeries::initializeFromNodesAndTerminals(Real frequency) { void DP::Ph1::ResIndSeries::initVars(Real timeStep) { for (Int freq = 0; freq < mNumFreqs; freq++) { Real a = timeStep / (2. * **mInductance); - Real b = timeStep * 2.*PI * mFrequencies(freq,0) / 2.; + Real b = timeStep * 2. *PI * mFrequencies(freq,0) / 2.; - Real equivCondReal = a / (1. + b * b); - Real equivCondImag = -a * b / (1. + b * b); + Real equivCondReal = ( a + **mResistance * std::pow(a, 2) ) / ( std::pow(1. + **mResistance * a, 2) + std::pow(b, 2) ); + Real equivCondImag = -a * b / ( std::pow(1. + **mResistance * a, 2) + std::pow(b, 2) ); mEquivCond(freq,0) = { equivCondReal, equivCondImag }; - Real preCurrFracReal = (1. - b * b) / (1. + b * b); - Real preCurrFracImag = (-2. * b) / (1. + b * b); + + Real preCurrFracReal = ( 1. - std::pow(b,2) + - std::pow(**mResistance * a, 2) ) / ( std::pow(1. + **mResistance * a, 2) + std::pow(b, 2)); + Real preCurrFracImag = ( -2. * b ) / ( std::pow(1. + **mResistance * a, 2) + std::pow(b, 2) ); mPrevCurrFac(freq,0) = { preCurrFracReal, preCurrFracImag }; - // TODO: check if this is correct or if it should be only computed before the step mEquivCurrent(freq,0) = mEquivCond(freq,0) * (**mIntfVoltage)(0,freq) + mPrevCurrFac(freq,0) * (**mIntfCurrent)(0,freq); - (**mIntfCurrent)(0,freq) = mEquivCond(freq,0) * (**mIntfVoltage)(0,freq) + mEquivCurrent(freq,0); } } @@ -94,11 +100,11 @@ void DP::Ph1::ResIndSeries::mnaCompInitialize(Real omega, Real timeStep, Attribu Logger::phasorToString((**mIntfVoltage)(0,0)), Logger::phasorToString((**mIntfCurrent)(0,0)), Logger::complexToString(mEquivCurrent(0,0))); + mSLog->flush(); } void DP::Ph1::ResIndSeries::mnaCompInitializeHarm(Real omega, Real timeStep, std::vector::Ptr> leftVectors) { - updateMatrixNodeIndices(); - + updateMatrixNodeIndices(); initVars(timeStep); mMnaTasks.push_back(std::make_shared(*this)); @@ -194,7 +200,18 @@ void DP::Ph1::ResIndSeries::mnaCompApplyRightSideVectorStampHarm(Matrix& rightVe } } -void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { +void DP::Ph1::ResIndSeries::mnaCompApplyRightSideVectorStampHarm(Matrix& rightVector, Int freqIdx) { + mEquivCurrent(freqIdx,0) = + mEquivCond(freqIdx,0) * (**mIntfVoltage)(0, freqIdx) + + mPrevCurrFac(freqIdx,0) * (**mIntfCurrent)(0, freqIdx); + + if (terminalNotGrounded(0)) + Math::setVectorElement(rightVector, matrixNodeIndex(0), mEquivCurrent(freqIdx,0)); + if (terminalNotGrounded(1)) + Math::setVectorElement(rightVector, matrixNodeIndex(1), -mEquivCurrent(freqIdx,0)); +} + +void DP::Ph1::ResIndSeries::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { // actually depends on L, but then we'd have to modify the system matrix anyway modifiedAttributes.push_back(mRightVector); prevStepDependencies.push_back(mIntfVoltage); @@ -202,14 +219,14 @@ void mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, At } void DP::Ph1::ResIndSeries::mnaCompPreStep(Real time, Int timeStepCount) { - mResIndSeries.mnaCompApplyRightSideVectorStamp(**mRightVector); + this->mnaCompApplyRightSideVectorStamp(**mRightVector); } void DP::Ph1::ResIndSeries::MnaPreStepHarm::execute(Real time, Int timeStepCount) { mResIndSeries.mnaCompApplyRightSideVectorStampHarm(**mResIndSeries.mRightVector); } -void mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { +void DP::Ph1::ResIndSeries::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { attributeDependencies.push_back(leftVector); modifiedAttributes.push_back(mIntfVoltage); modifiedAttributes.push_back(mIntfCurrent); @@ -281,5 +298,4 @@ void DP::Ph1::ResIndSeries::mnaTearApplyVoltageStamp(Matrix& voltageVector) { void DP::Ph1::ResIndSeries::mnaTearPostStep(Complex voltage, Complex current) { (**mIntfVoltage)(0, 0) = voltage; (**mIntfCurrent)(0, 0) = mEquivCond(0,0) * voltage + mEquivCurrent(0,0); - } diff --git a/dpsim-models/src/DP/DP_Ph1_Resistor.cpp b/dpsim-models/src/DP/DP_Ph1_Resistor.cpp index 7bc76214b4..668b288703 100644 --- a/dpsim-models/src/DP/DP_Ph1_Resistor.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Resistor.cpp @@ -43,6 +43,7 @@ void DP::Ph1::Resistor::initializeFromNodesAndTerminals(Real frequency) { Logger::phasorToString((**mIntfCurrent)(0,0)), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } // #### MNA functions #### @@ -58,6 +59,7 @@ void DP::Ph1::Resistor::mnaCompInitialize(Real omega, Real timeStep, Attributeflush(); } void DP::Ph1::Resistor::mnaCompInitializeHarm(Real omega, Real timeStep, std::vector::Ptr> leftVectors) { diff --git a/dpsim-models/src/DP/DP_Ph1_SynchronGenerator6aOrderVBR.cpp b/dpsim-models/src/DP/DP_Ph1_SynchronGenerator6aOrderVBR.cpp index e01fd9b03d..5b338ad6e1 100644 --- a/dpsim-models/src/DP/DP_Ph1_SynchronGenerator6aOrderVBR.cpp +++ b/dpsim-models/src/DP/DP_Ph1_SynchronGenerator6aOrderVBR.cpp @@ -75,6 +75,10 @@ void DP::Ph1::SynchronGenerator6aOrderVBR::stepInPerUnit() { (**mEdq_s)(0,0) = -(**mIdq)(1,0) * mLq_s + (**mVdq)(0,0); (**mEdq_s)(1,0) = (**mIdq)(0,0) * mLd_s + (**mVdq)(1,0); + // calculate Edq_s at t=k + (**mEdq_s)(0,0) = -(**mIdq)(1,0) * mLq_s + (**mVdq)(0,0); + (**mEdq_s)(1,0) = (**mIdq)(0,0) * mLd_s + (**mVdq)(1,0); + // Update time-varying reactance matrix calculateConductanceMatrix(); diff --git a/dpsim-models/src/DP/DP_Ph1_SynchronGenerator6bOrderVBR.cpp b/dpsim-models/src/DP/DP_Ph1_SynchronGenerator6bOrderVBR.cpp index 77d6655990..88c67f5a46 100644 --- a/dpsim-models/src/DP/DP_Ph1_SynchronGenerator6bOrderVBR.cpp +++ b/dpsim-models/src/DP/DP_Ph1_SynchronGenerator6bOrderVBR.cpp @@ -76,6 +76,10 @@ void DP::Ph1::SynchronGenerator6bOrderVBR::stepInPerUnit() { (**mEdq_s)(0,0) = -(**mIdq)(1,0) * mLq_s + (**mVdq)(0,0); (**mEdq_s)(1,0) = (**mIdq)(0,0) * mLd_s + (**mVdq)(1,0); + // calculate Edq_s at t=k + (**mEdq_s)(0,0) = -(**mIdq)(1,0) * mLq_s + (**mVdq)(0,0); + (**mEdq_s)(1,0) = (**mIdq)(0,0) * mLd_s + (**mVdq)(1,0); + // Update time-varying reactance matrix calculateConductanceMatrix(); diff --git a/dpsim-models/src/DP/DP_Ph1_Transformer.cpp b/dpsim-models/src/DP/DP_Ph1_Transformer.cpp index 1bcbe3658d..784afe508d 100644 --- a/dpsim-models/src/DP/DP_Ph1_Transformer.cpp +++ b/dpsim-models/src/DP/DP_Ph1_Transformer.cpp @@ -10,48 +10,39 @@ using namespace CPS; -DP::Ph1::Transformer::Transformer(String uid, String name, - Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph1::Transformer(mAttributes), CompositePowerComp(uid, name, true, true, logLevel) { - if (withResistiveLosses) - setVirtualNodeNumber(3); - else - setVirtualNodeNumber(2); - +DP::Ph1::Transformer::Transformer(String uid, String name, Logger::Level logLevel) + : Base::Ph1::Transformer(mAttributes), + MNASimPowerComp(uid, name, true, true, logLevel) { + + // setTerminalNumber(2); + // SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + + // **mIntfVoltage = MatrixComp::Zero(1,1); **mIntfCurrent = MatrixComp::Zero(1,1); } -/// DEPRECATED: Delete method -SimPowerComp::Ptr DP::Ph1::Transformer::clone(String name) { - auto copy = Transformer::make(name, mLogLevel); - copy->setParameters(**mNominalVoltageEnd1, **mNominalVoltageEnd2, std::abs(**mRatio), std::arg(**mRatio), **mResistance, **mInductance); - return copy; -} - -void DP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, - Real resistance, Real inductance) { +void DP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, + Real ratioPhase, Real resistance, Real inductance) { Base::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs, ratioPhase, resistance, inductance); SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1={} [V] Nominal Voltage End 2={} [V]", **mNominalVoltageEnd1, **mNominalVoltageEnd2); SPDLOG_LOGGER_INFO(mSLog, "Resistance={} [Ohm] Inductance={} [Ohm] (referred to primary side)", **mResistance, **mInductance); SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [ ] Phase Shift={} [deg]", std::abs(**mRatio), std::arg(**mRatio)); - SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower); mParametersSet = true; } -void DP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, - Real ratioPhase, Real resistance, Real inductance) { - - **mRatedPower = ratedPower; - SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower); +void DP::Ph1::Transformer::initialize(Matrix frequencies) { + SimPowerComp::initialize(frequencies); - DP::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs, ratioPhase, resistance, inductance); + mEquivCurrent = MatrixComp::Zero(mNumFreqs, 1); + mEquivCond = MatrixComp::Zero(mNumFreqs, 1); + mPrevCurrFac = MatrixComp::Zero(mNumFreqs, 1); } void DP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { @@ -71,161 +62,221 @@ void DP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]", **mNominalVoltageEnd1, **mNominalVoltageEnd2); SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", std::abs(**mRatio), std::arg(**mRatio)); } - - // Set initial voltage of virtual node in between - mVirtualNodes[0]->setInitialVoltage( initialSingleVoltage(1) * **mRatio ); - + // Static calculations from load flow data - Real omega = 2.*PI* frequency; - Complex impedance = { **mResistance, omega * **mInductance }; - SPDLOG_LOGGER_INFO(mSLog, "Reactance={} [Ohm] (referred to primary side)", omega * **mInductance ); - (**mIntfVoltage)(0,0) = mVirtualNodes[0]->initialSingleVoltage() - initialSingleVoltage(0); - (**mIntfCurrent)(0,0) = (**mIntfVoltage)(0,0) / impedance; - - // Create series sub components - mSubInductor = std::make_shared(**mName + "_ind", mLogLevel); - mSubInductor->setParameters(**mInductance); - addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - if (mNumVirtualNodes == 3) { - mVirtualNodes[2]->setInitialVoltage(initialSingleVoltage(0)); - mSubResistor = std::make_shared(**mName + "_res", mLogLevel); - mSubResistor->setParameters(**mResistance); - mSubResistor->connect({node(0), mVirtualNodes[2]}); - mSubInductor->connect({mVirtualNodes[2], mVirtualNodes[0]}); - addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - } else { - mSubInductor->connect({node(0), mVirtualNodes[0]}); - } - - // Create parallel sub components - Real pSnub = P_SNUB_TRANSFORMER * **mRatedPower; - Real qSnub = Q_SNUB_TRANSFORMER * **mRatedPower; - - // A snubber conductance is added on the higher voltage side - mSnubberResistance1 = std::pow(std::abs(**mNominalVoltageEnd1),2) / pSnub; - mSubSnubResistor1 = std::make_shared(**mName + "_snub_res1", mLogLevel); - mSubSnubResistor1->setParameters(mSnubberResistance1); - mSubSnubResistor1->connect({ node(0), DP::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]", node(0)->name(), Logger::realToString(mSnubberResistance1)); - addMNASubComponent(mSubSnubResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - - // A snubber conductance is added on the lower voltage side - mSnubberResistance2 = std::pow(std::abs(**mNominalVoltageEnd2),2) / pSnub; - mSubSnubResistor2 = std::make_shared(**mName + "_snub_res2", mLogLevel); - mSubSnubResistor2->setParameters(mSnubberResistance2); - mSubSnubResistor2->connect({ node(1), DP::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]", node(1)->name(), Logger::realToString(mSnubberResistance2)); - addMNASubComponent(mSubSnubResistor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - // // A snubber capacitance is added to higher voltage side (not used as capacitor at high voltage side made it worse) - // mSnubberCapacitance1 = qSnub / std::pow(std::abs(mNominalVoltageEnd1),2) / omega; - // mSubSnubCapacitor1 = std::make_shared(**mName + "_snub_cap1", mLogLevel); - // mSubSnubCapacitor1->setParameters(mSnubberCapacitance1); - // mSubSnubCapacitor1->connect({ node(0), DP::SimNode::GND }); - // SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 1 (connected to higher voltage side {}) = \n{} [F] \n ", node(0)->name(), Logger::realToString(mSnubberCapacitance1)); - // mSubComponents.push_back(mSubSnubCapacitor1); - - // A snubber capacitance is added to lower voltage side - mSnubberCapacitance2 = qSnub / std::pow(std::abs(**mNominalVoltageEnd2),2) / omega; - mSubSnubCapacitor2 = std::make_shared(**mName + "_snub_cap2", mLogLevel); - mSubSnubCapacitor2->setParameters(mSnubberCapacitance2); - mSubSnubCapacitor2->connect({ node(1), DP::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]", node(1)->name(), Logger::realToString(mSnubberCapacitance2)); - addMNASubComponent(mSubSnubCapacitor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - // Initialize electrical subcomponents - SPDLOG_LOGGER_INFO(mSLog, "Electrical subcomponents: "); - for (auto subcomp: mSubComponents) { - SPDLOG_LOGGER_INFO(mSLog, "- {}", subcomp->name()); - subcomp->initialize(mFrequencies); - subcomp->initializeFromNodesAndTerminals(frequency); - } + Real omega = 2. * PI * frequency; + Complex mImpedance = Complex(**mResistance, omega * **mInductance); + (**mIntfVoltage)(0,0) = initialSingleVoltage(0) - initialSingleVoltage(1) * **mRatio; + (**mIntfCurrent)(0,0) = -(**mIntfVoltage)(0,0) / mImpedance; SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization from powerflow ---" - "\nVoltage across: {:s}" - "\nCurrent: {:s}" + "\nVoltage across primary side: {:s}" + "\nPrimary side current flowing into node 0: {:s}" "\nTerminal 0 voltage: {:s}" "\nTerminal 1 voltage: {:s}" - "\nVirtual Node 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)), - Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); + Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } -void DP::Ph1::Transformer::mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { +void DP::Ph1::Transformer::initVars(Real timeStep) { + for (Int freq = 0; freq < mNumFreqs; freq++) { + Real a = timeStep / (2. * **mInductance); + Real b = (timeStep * 2.*PI * mFrequencies(freq,0)) / 2.; + Real c = (1 + a * **mResistance) * (1 + a * **mResistance) + b * b; + + Real equivCondReal = ( a + (a * a * **mResistance) ) / c; + Real equivCondImag = -(a * b) / c; + mEquivCond(freq,0) = { equivCondReal, equivCondImag }; + Real preCurrFracReal = (( 1. - b * b ) - pow((a * **mResistance),2)) / c; + Real preCurrFracImag = (-2. * b) / c; + mPrevCurrFac(freq,0) = { preCurrFracReal, preCurrFracImag }; + + // + mEquivCurrent(freq,0) = mEquivCond(freq,0) * (**mIntfVoltage)(0, freq) - mPrevCurrFac(freq,0) * (**mIntfCurrent)(0, freq); + } +} + +void DP::Ph1::Transformer::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); + initVars(timeStep); + SPDLOG_LOGGER_INFO(mSLog, - "\nTerminal 0 connected to {:s} = sim node {:d}" - "\nTerminal 1 connected to {:s} = sim node {:d}", - mTerminals[0]->node()->name(), mTerminals[0]->node()->matrixNodeIndex(), - mTerminals[1]->node()->name(), mTerminals[1]->node()->matrixNodeIndex()); + "\n--- MNA initialization ---" + "\nInitial voltage {:s}" + "\nInitial current {:s}" + "\nEquiv. current {:s}" + "\n--- MNA initialization finished ---", + Logger::phasorToString((**mIntfVoltage)(0,0)), + Logger::phasorToString((**mIntfCurrent)(0,0)), + Logger::complexToString(mEquivCurrent(0,0))); +} + +void DP::Ph1::Transformer::mnaCompInitializeHarm(Real omega, Real timeStep, std::vector::Ptr> leftVectors) { + updateMatrixNodeIndices(); + + initVars(timeStep); + + mMnaTasks.push_back(std::make_shared(*this)); + mMnaTasks.push_back(std::make_shared(*this, leftVectors)); + **mRightVector = Matrix::Zero(leftVectors[0]->get().rows(), mNumFreqs); } void DP::Ph1::Transformer::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { - // Ideal transformer equations - if (terminalNotGrounded(0)) { - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), mVirtualNodes[1]->matrixNodeIndex(), Complex(-1.0, 0)); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(), mVirtualNodes[0]->matrixNodeIndex(), Complex(1.0, 0)); + for (Int freq = 0; freq < mNumFreqs; freq++) { + if (terminalNotGrounded(0)) + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), matrixNodeIndex(0), mEquivCond(freq,0), mNumFreqs, freq); + if (terminalNotGrounded(1)) + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), matrixNodeIndex(1), std::pow(**mRatio,2) * mEquivCond(freq,0), mNumFreqs, freq); + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), matrixNodeIndex(1), -**mRatio * mEquivCond(freq,0), mNumFreqs, freq); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), matrixNodeIndex(0), -**mRatio * mEquivCond(freq,0), mNumFreqs, freq); + } + + SPDLOG_LOGGER_INFO(mSLog, "-- Stamp frequency {:d} ---", freq); + if (terminalNotGrounded(0)) + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", + Logger::complexToString(mEquivCond(freq,0)), matrixNodeIndex(0), matrixNodeIndex(0)); + if (terminalNotGrounded(1)) + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", + Logger::complexToString(std::pow(**mRatio,2) * mEquivCond(freq,0)), matrixNodeIndex(1), matrixNodeIndex(1)); + if ( terminalNotGrounded(0) && terminalNotGrounded(1) ) { + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", + Logger::complexToString(- **mRatio * mEquivCond(freq,0)), matrixNodeIndex(0), matrixNodeIndex(1)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", + Logger::complexToString(- **mRatio * mEquivCond(freq,0)), matrixNodeIndex(1), matrixNodeIndex(0)); + } } - if (terminalNotGrounded(1)) { - Math::setMatrixElement(systemMatrix, matrixNodeIndex(1), mVirtualNodes[1]->matrixNodeIndex(), **mRatio); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1), - **mRatio); +} + +void DP::Ph1::Transformer::mnaCompApplySystemMatrixStampHarm(SparseMatrixRow& systemMatrix, Int freqIdx) { + if (terminalNotGrounded(0)) + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), matrixNodeIndex(0), mEquivCond(freqIdx,0)); + if (terminalNotGrounded(1)) + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), matrixNodeIndex(1), std::pow(**mRatio,2) * mEquivCond(freqIdx,0)); + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), matrixNodeIndex(1), -**mRatio * mEquivCond(freqIdx,0)); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), matrixNodeIndex(0), -**mRatio * mEquivCond(freqIdx,0)); + } + + SPDLOG_LOGGER_INFO(mSLog, "-- Stamp frequency {:d} ---", freqIdx); + if (terminalNotGrounded(0)) + SPDLOG_LOGGER_INFO(mSLog, "Add {:f}+j{:f} to system at ({:d},{:d})", + mEquivCond(freqIdx,0).real(), mEquivCond(freqIdx,0).imag(), matrixNodeIndex(0), matrixNodeIndex(0)); + if (terminalNotGrounded(1)) + SPDLOG_LOGGER_INFO(mSLog, "Add {:f}+j{:f} to system at ({:d},{:d})", + **mRatio * **mRatio * mEquivCond(freqIdx,0).real(), std::pow(**mRatio,2) * mEquivCond(freqIdx,0).imag(), matrixNodeIndex(1), matrixNodeIndex(1)); + if ( terminalNotGrounded(0) && terminalNotGrounded(1) ) { + SPDLOG_LOGGER_INFO(mSLog, "Add {:f}+j{:f} to system at ({:d},{:d})", + - **mRatio * mEquivCond(freqIdx,0).real(), - **mRatio * mEquivCond(freqIdx,0).imag(), matrixNodeIndex(0), matrixNodeIndex(1)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:f}+j{:f} to system at ({:d},{:d})", + - **mRatio * mEquivCond(freqIdx,0).real(), - **mRatio * mEquivCond(freqIdx,0).imag(), matrixNodeIndex(1), matrixNodeIndex(0)); + } +} + +void DP::Ph1::Transformer::mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { + for (Int freq = 0; freq < mNumFreqs; freq++) { + if (terminalNotGrounded(0)) + Math::setVectorElement(rightVector, matrixNodeIndex(0), -mEquivCurrent(freq,0), mNumFreqs, freq); + if (terminalNotGrounded(1)) + Math::setVectorElement(rightVector, matrixNodeIndex(1), **mRatio * mEquivCurrent(freq,0), mNumFreqs, freq); + + SPDLOG_LOGGER_DEBUG(mSLog, "MNA EquivCurrent {:s}", Logger::complexToString(mEquivCurrent(freq,0))); + if (terminalNotGrounded(0)) + SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}", + Logger::complexToString(mEquivCurrent(freq,0)), matrixNodeIndex(0)); + if (terminalNotGrounded(1)) + SPDLOG_LOGGER_DEBUG(mSLog, "Add {:s} to source vector at {:d}", + Logger::complexToString(- **mRatio * mEquivCurrent(freq,0)), matrixNodeIndex(1)); } +} - // Add subcomps to system matrix - for (auto subcomp: mSubComponents) - if (auto mnasubcomp = std::dynamic_pointer_cast(subcomp)) - mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix); + void DP::Ph1::Transformer::mnaCompApplyRightSideVectorStampHarm(Matrix& rightVector) { + for (Int freq = 0; freq < mNumFreqs; freq++) { + // Calculate equivalent current source for next time step + mEquivCurrent(freq,0) = mEquivCond(freq,0) * (**mIntfVoltage)(0, freq) - mPrevCurrFac(freq,0) * (**mIntfCurrent)(0,freq); - if (terminalNotGrounded(0)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), - mVirtualNodes[0]->matrixNodeIndex(), mVirtualNodes[1]->matrixNodeIndex()); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), - mVirtualNodes[1]->matrixNodeIndex(), mVirtualNodes[0]->matrixNodeIndex()); - } - if (terminalNotGrounded(1)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), - matrixNodeIndex(1), mVirtualNodes[1]->matrixNodeIndex()); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), - mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1)); + if (terminalNotGrounded(0)) + Math::setVectorElement(rightVector, matrixNodeIndex(0), mEquivCurrent(freq,0), 1, 0, freq); + if (terminalNotGrounded(1)) + Math::setVectorElement(rightVector, matrixNodeIndex(1), - **mRatio * mEquivCurrent(freq,0), 1, 0, freq); } } -void DP::Ph1::Transformer::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { - prevStepDependencies.push_back(mIntfCurrent); - prevStepDependencies.push_back(mIntfVoltage); +void DP::Ph1::Transformer::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { modifiedAttributes.push_back(mRightVector); + prevStepDependencies.push_back(mIntfVoltage); + prevStepDependencies.push_back(mIntfCurrent); } -void DP::Ph1::Transformer::mnaParentPreStep(Real time, Int timeStepCount) { - this->mnaApplyRightSideVectorStamp(**this->mRightVector); +void DP::Ph1::Transformer::mnaCompPreStep(Real time, Int timeStepCount) { + this->mnaCompApplyRightSideVectorStamp(**mRightVector); } -void DP::Ph1::Transformer::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { +void DP::Ph1::Transformer::MnaPreStepHarm::execute(Real time, Int timeStepCount) { + mTransformer.mnaCompApplyRightSideVectorStampHarm(**mTransformer.mRightVector); +} + +void DP::Ph1::Transformer::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { attributeDependencies.push_back(leftVector); modifiedAttributes.push_back(mIntfVoltage); modifiedAttributes.push_back(mIntfCurrent); } -void DP::Ph1::Transformer::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { - this->mnaUpdateVoltage(**leftVector); - this->mnaUpdateCurrent(**leftVector); +void DP::Ph1::Transformer::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); } -void DP::Ph1::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { - (**mIntfCurrent)(0,0) = mSubInductor->intfCurrent()(0, 0); +void DP::Ph1::Transformer::MnaPostStepHarm::execute(Real time, Int timeStepCount) { + for (Int freq = 0; freq < mTransformer.mNumFreqs; freq++) + mTransformer.mnaCompUpdateVoltageHarm(**mLeftVectors[freq], freq); + mTransformer.mnaCompUpdateCurrentHarm(); } void DP::Ph1::Transformer::mnaCompUpdateVoltage(const Matrix& leftVector) { - // v1 - v0 - (**mIntfVoltage)(0, 0) = 0; - (**mIntfVoltage)(0, 0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); - (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::complexFromVectorElement(leftVector, mVirtualNodes[0]->matrixNodeIndex()); - SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}", Logger::phasorToString((**mIntfVoltage)(0, 0))); + // v0 - v1 + for (Int freq = 0; freq < mNumFreqs; freq++) { + (**mIntfVoltage)(0,freq) = 0; + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0, freq) += Math::complexFromVectorElement(leftVector, matrixNodeIndex(0), mNumFreqs, freq); + if (terminalNotGrounded(1)) + // TODO: add other frequencies + (**mIntfVoltage)(0, freq) -= Math::complexFromVectorElement(leftVector, matrixNodeIndex(1), mNumFreqs, freq) * **mRatio; + + SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}", Logger::phasorToString((**mIntfVoltage)(0,freq))); + } +} + +void DP::Ph1::Transformer::mnaCompUpdateVoltageHarm(const Matrix& leftVector, Int freqIdx) { + // v0 - v1 + (**mIntfVoltage)(0, freqIdx) = 0; + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0, freqIdx) += Math::complexFromVectorElement(leftVector, matrixNodeIndex(0)); + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0, freqIdx) -= Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)) * **mRatio; + + SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}", Logger::phasorToString((**mIntfVoltage)(0,freqIdx))); +} + +void DP::Ph1::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { + for (Int freq = 0; freq < mNumFreqs; freq++) { + (**mIntfCurrent)(0, freq) = -(mEquivCond(freq,0) * (**mIntfVoltage)(0, freq) + mEquivCurrent(freq,0)); + SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}", Logger::phasorToString((**mIntfCurrent)(0,freq))); + + // Calculate equivalent current source for next time step + mEquivCurrent(freq,0) = mEquivCond(freq,0) * (**mIntfVoltage)(0, freq) - mPrevCurrFac(freq,0) * (**mIntfCurrent)(0,freq); + } } +void DP::Ph1::Transformer::mnaCompUpdateCurrentHarm() { + // primary side current flowing into node 0 + for (Int freq = 0; freq < mNumFreqs; freq++) { + (**mIntfCurrent)(0,freq) = -(mEquivCond(freq,0) * (**mIntfVoltage)(0,freq) + mEquivCurrent(freq,0)); + SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}", Logger::phasorToString((**mIntfCurrent)(0,freq))); + } +} \ No newline at end of file diff --git a/dpsim-models/src/DP/DP_Ph1_Transformer_deprecated.cpp b/dpsim-models/src/DP/DP_Ph1_Transformer_deprecated.cpp new file mode 100644 index 0000000000..1bcbe3658d --- /dev/null +++ b/dpsim-models/src/DP/DP_Ph1_Transformer_deprecated.cpp @@ -0,0 +1,231 @@ +/* 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; + +DP::Ph1::Transformer::Transformer(String uid, String name, + Logger::Level logLevel, Bool withResistiveLosses) + : Base::Ph1::Transformer(mAttributes), CompositePowerComp(uid, name, true, true, logLevel) { + if (withResistiveLosses) + setVirtualNodeNumber(3); + else + setVirtualNodeNumber(2); + + setTerminalNumber(2); + + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + **mIntfVoltage = MatrixComp::Zero(1,1); + **mIntfCurrent = MatrixComp::Zero(1,1); +} + +/// DEPRECATED: Delete method +SimPowerComp::Ptr DP::Ph1::Transformer::clone(String name) { + auto copy = Transformer::make(name, mLogLevel); + copy->setParameters(**mNominalVoltageEnd1, **mNominalVoltageEnd2, std::abs(**mRatio), std::arg(**mRatio), **mResistance, **mInductance); + return copy; +} + +void DP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, + Real resistance, Real inductance) { + + Base::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs, ratioPhase, resistance, inductance); + + SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1={} [V] Nominal Voltage End 2={} [V]", **mNominalVoltageEnd1, **mNominalVoltageEnd2); + SPDLOG_LOGGER_INFO(mSLog, "Resistance={} [Ohm] Inductance={} [Ohm] (referred to primary side)", **mResistance, **mInductance); + SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [ ] Phase Shift={} [deg]", std::abs(**mRatio), std::arg(**mRatio)); + SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower); + + mParametersSet = true; +} + +void DP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, + Real ratioPhase, Real resistance, Real inductance) { + + **mRatedPower = ratedPower; + SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower); + + DP::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs, ratioPhase, resistance, inductance); +} + +void DP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { + + // Component parameters are referred to higher voltage side. + // Switch terminals to have terminal 0 at higher voltage side + // if transformer is connected the other way around. + if (Math::abs(**mRatio) < 1.) { + **mRatio = 1. / **mRatio; + std::shared_ptr> tmp = mTerminals[0]; + mTerminals[0] = mTerminals[1]; + mTerminals[1] = tmp; + Real tmpVolt = **mNominalVoltageEnd1; + **mNominalVoltageEnd1 = **mNominalVoltageEnd2; + **mNominalVoltageEnd2 = tmpVolt; + SPDLOG_LOGGER_INFO(mSLog, "Switching terminals to have first terminal at higher voltage side. Updated parameters: "); + SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]", **mNominalVoltageEnd1, **mNominalVoltageEnd2); + SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", std::abs(**mRatio), std::arg(**mRatio)); + } + + // Set initial voltage of virtual node in between + mVirtualNodes[0]->setInitialVoltage( initialSingleVoltage(1) * **mRatio ); + + // Static calculations from load flow data + Real omega = 2.*PI* frequency; + Complex impedance = { **mResistance, omega * **mInductance }; + SPDLOG_LOGGER_INFO(mSLog, "Reactance={} [Ohm] (referred to primary side)", omega * **mInductance ); + (**mIntfVoltage)(0,0) = mVirtualNodes[0]->initialSingleVoltage() - initialSingleVoltage(0); + (**mIntfCurrent)(0,0) = (**mIntfVoltage)(0,0) / impedance; + + // Create series sub components + mSubInductor = std::make_shared(**mName + "_ind", mLogLevel); + mSubInductor->setParameters(**mInductance); + addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + if (mNumVirtualNodes == 3) { + mVirtualNodes[2]->setInitialVoltage(initialSingleVoltage(0)); + mSubResistor = std::make_shared(**mName + "_res", mLogLevel); + mSubResistor->setParameters(**mResistance); + mSubResistor->connect({node(0), mVirtualNodes[2]}); + mSubInductor->connect({mVirtualNodes[2], mVirtualNodes[0]}); + addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + } else { + mSubInductor->connect({node(0), mVirtualNodes[0]}); + } + + // Create parallel sub components + Real pSnub = P_SNUB_TRANSFORMER * **mRatedPower; + Real qSnub = Q_SNUB_TRANSFORMER * **mRatedPower; + + // A snubber conductance is added on the higher voltage side + mSnubberResistance1 = std::pow(std::abs(**mNominalVoltageEnd1),2) / pSnub; + mSubSnubResistor1 = std::make_shared(**mName + "_snub_res1", mLogLevel); + mSubSnubResistor1->setParameters(mSnubberResistance1); + mSubSnubResistor1->connect({ node(0), DP::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]", node(0)->name(), Logger::realToString(mSnubberResistance1)); + addMNASubComponent(mSubSnubResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + + // A snubber conductance is added on the lower voltage side + mSnubberResistance2 = std::pow(std::abs(**mNominalVoltageEnd2),2) / pSnub; + mSubSnubResistor2 = std::make_shared(**mName + "_snub_res2", mLogLevel); + mSubSnubResistor2->setParameters(mSnubberResistance2); + mSubSnubResistor2->connect({ node(1), DP::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]", node(1)->name(), Logger::realToString(mSnubberResistance2)); + addMNASubComponent(mSubSnubResistor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // // A snubber capacitance is added to higher voltage side (not used as capacitor at high voltage side made it worse) + // mSnubberCapacitance1 = qSnub / std::pow(std::abs(mNominalVoltageEnd1),2) / omega; + // mSubSnubCapacitor1 = std::make_shared(**mName + "_snub_cap1", mLogLevel); + // mSubSnubCapacitor1->setParameters(mSnubberCapacitance1); + // mSubSnubCapacitor1->connect({ node(0), DP::SimNode::GND }); + // SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 1 (connected to higher voltage side {}) = \n{} [F] \n ", node(0)->name(), Logger::realToString(mSnubberCapacitance1)); + // mSubComponents.push_back(mSubSnubCapacitor1); + + // A snubber capacitance is added to lower voltage side + mSnubberCapacitance2 = qSnub / std::pow(std::abs(**mNominalVoltageEnd2),2) / omega; + mSubSnubCapacitor2 = std::make_shared(**mName + "_snub_cap2", mLogLevel); + mSubSnubCapacitor2->setParameters(mSnubberCapacitance2); + mSubSnubCapacitor2->connect({ node(1), DP::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]", node(1)->name(), Logger::realToString(mSnubberCapacitance2)); + addMNASubComponent(mSubSnubCapacitor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // Initialize electrical subcomponents + SPDLOG_LOGGER_INFO(mSLog, "Electrical subcomponents: "); + for (auto subcomp: mSubComponents) { + SPDLOG_LOGGER_INFO(mSLog, "- {}", subcomp->name()); + subcomp->initialize(mFrequencies); + subcomp->initializeFromNodesAndTerminals(frequency); + } + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\nVirtual Node 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::phasorToString((**mIntfVoltage)(0,0)), + Logger::phasorToString((**mIntfCurrent)(0,0)), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1)), + Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); +} + +void DP::Ph1::Transformer::mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + SPDLOG_LOGGER_INFO(mSLog, + "\nTerminal 0 connected to {:s} = sim node {:d}" + "\nTerminal 1 connected to {:s} = sim node {:d}", + mTerminals[0]->node()->name(), mTerminals[0]->node()->matrixNodeIndex(), + mTerminals[1]->node()->name(), mTerminals[1]->node()->matrixNodeIndex()); +} + +void DP::Ph1::Transformer::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { + // Ideal transformer equations + if (terminalNotGrounded(0)) { + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), mVirtualNodes[1]->matrixNodeIndex(), Complex(-1.0, 0)); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(), mVirtualNodes[0]->matrixNodeIndex(), Complex(1.0, 0)); + } + if (terminalNotGrounded(1)) { + Math::setMatrixElement(systemMatrix, matrixNodeIndex(1), mVirtualNodes[1]->matrixNodeIndex(), **mRatio); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1), - **mRatio); + } + + // Add subcomps to system matrix + for (auto subcomp: mSubComponents) + if (auto mnasubcomp = std::dynamic_pointer_cast(subcomp)) + mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix); + + if (terminalNotGrounded(0)) { + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), + mVirtualNodes[0]->matrixNodeIndex(), mVirtualNodes[1]->matrixNodeIndex()); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), + mVirtualNodes[1]->matrixNodeIndex(), mVirtualNodes[0]->matrixNodeIndex()); + } + if (terminalNotGrounded(1)) { + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), + matrixNodeIndex(1), mVirtualNodes[1]->matrixNodeIndex()); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), + mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1)); + } +} + +void DP::Ph1::Transformer::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); +} + +void DP::Ph1::Transformer::mnaParentPreStep(Real time, Int timeStepCount) { + this->mnaApplyRightSideVectorStamp(**this->mRightVector); +} + +void DP::Ph1::Transformer::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void DP::Ph1::Transformer::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + this->mnaUpdateVoltage(**leftVector); + this->mnaUpdateCurrent(**leftVector); +} + +void DP::Ph1::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { + (**mIntfCurrent)(0,0) = mSubInductor->intfCurrent()(0, 0); +} + +void DP::Ph1::Transformer::mnaCompUpdateVoltage(const Matrix& leftVector) { + // v1 - v0 + (**mIntfVoltage)(0, 0) = 0; + (**mIntfVoltage)(0, 0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); + (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::complexFromVectorElement(leftVector, mVirtualNodes[0]->matrixNodeIndex()); + SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}", Logger::phasorToString((**mIntfVoltage)(0, 0))); +} + diff --git a/dpsim-models/src/EMT/EMT_Ph1_VoltageSource.cpp b/dpsim-models/src/EMT/EMT_Ph1_VoltageSource.cpp index cc4afb5cba..8af828066f 100644 --- a/dpsim-models/src/EMT/EMT_Ph1_VoltageSource.cpp +++ b/dpsim-models/src/EMT/EMT_Ph1_VoltageSource.cpp @@ -36,8 +36,6 @@ SimPowerComp::Ptr EMT::Ph1::VoltageSource::clone(String name) { void EMT::Ph1::VoltageSource::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { updateMatrixNodeIndices(); (**mIntfVoltage)(0,0) = Math::abs(**mVoltageRef) * cos(Math::phase(**mVoltageRef)); - - mTimeStep = timeStep; } void EMT::Ph1::VoltageSource::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { @@ -68,7 +66,7 @@ void EMT::Ph1::VoltageSource::updateVoltage(Real time) { Complex voltageRef = mVoltageRef->get(); Real srcFreq = mSrcFreq->get(); if (srcFreq > 0) - (**mIntfVoltage)(0,0) = Math::abs(voltageRef) * cos((time) * 2.*PI*srcFreq + Math::phase(voltageRef)); + (**mIntfVoltage)(0,0) = Math::abs(voltageRef) * cos(time * 2. * PI * srcFreq + Math::phase(voltageRef)); else (**mIntfVoltage)(0,0) = voltageRef.real(); } diff --git a/dpsim-models/src/EMT/EMT_Ph3_AvVoltageSourceInverterDQ.cpp b/dpsim-models/src/EMT/EMT_Ph3_AvVoltageSourceInverterDQ.cpp index 4a964d75ba..f7e995ec51 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_AvVoltageSourceInverterDQ.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_AvVoltageSourceInverterDQ.cpp @@ -29,7 +29,7 @@ EMT::Ph3::AvVoltageSourceInverterDQ::AvVoltageSourceInverterDQ(String uid, Strin mPhaseType = PhaseType::ABC; if (withTrafo) { setVirtualNodeNumber(4); - mConnectionTransformer = EMT::Ph3::Transformer::make(**mName + "_trans", **mName + "_trans", mLogLevel, false); + mConnectionTransformer = EMT::Ph3::Transformer::make(**mName + "_trans", **mName + "_trans", mLogLevel); addMNASubComponent(mConnectionTransformer, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); } else { setVirtualNodeNumber(3); @@ -111,7 +111,7 @@ void EMT::Ph3::AvVoltageSourceInverterDQ::setTransformerParameters(Real nomVolta if (mWithConnectionTransformer) // TODO: resistive losses neglected so far (mWithResistiveLosses=false) - mConnectionTransformer->setParameters(mTransformerNominalVoltageEnd1, mTransformerNominalVoltageEnd2, mTransformerRatedPower, mTransformerRatioAbs, mTransformerRatioPhase, CPS::Math::singlePhaseParameterToThreePhase(mTransformerResistance), CPS::Math::singlePhaseParameterToThreePhase(mTransformerInductance)); + mConnectionTransformer->setParameters(mTransformerNominalVoltageEnd1, mTransformerNominalVoltageEnd2, mTransformerRatioAbs, mTransformerRatioPhase, CPS::Math::singlePhaseParameterToThreePhase(mTransformerResistance), CPS::Math::singlePhaseParameterToThreePhase(mTransformerInductance)); } void EMT::Ph3::AvVoltageSourceInverterDQ::setControllerParameters(Real Kp_pll, Real Ki_pll, diff --git a/dpsim-models/src/EMT/EMT_Ph3_Capacitor.cpp b/dpsim-models/src/EMT/EMT_Ph3_Capacitor.cpp index aaa19c3af8..93934237c0 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Capacitor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Capacitor.cpp @@ -56,6 +56,7 @@ void EMT::Ph3::Capacitor::initializeFromNodesAndTerminals(Real frequency) { Logger::matrixToString(**mIntfCurrent), Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)), Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1))); + mSLog->flush(); } void EMT::Ph3::Capacitor::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { @@ -102,7 +103,6 @@ void EMT::Ph3::Capacitor::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemM Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2), matrixNodeIndex(1, 1), -mEquivCond(2, 1)); Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2), matrixNodeIndex(1, 2), -mEquivCond(2, 2)); - Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 0), -mEquivCond(0, 0)); Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 1), -mEquivCond(0, 1)); Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 2), -mEquivCond(0, 2)); @@ -117,6 +117,8 @@ void EMT::Ph3::Capacitor::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemM SPDLOG_LOGGER_INFO(mSLog, "\nEquivalent Conductance: {:s}", Logger::matrixToString(mEquivCond)); + + mSLog->flush(); } void EMT::Ph3::Capacitor::mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { diff --git a/dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp b/dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp index 19d48f1074..4065ec348d 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Inductor.cpp @@ -177,14 +177,14 @@ void EMT::Ph3::Inductor::mnaCompUpdateVoltage(const Matrix& leftVector) { // v1 - v0 **mIntfVoltage = Matrix::Zero(3, 1); if (terminalNotGrounded(1)) { - (**mIntfVoltage)(0, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); - (**mIntfVoltage)(1, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)); - (**mIntfVoltage)(2, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)); + (**mIntfVoltage)(0, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); + (**mIntfVoltage)(1, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)); + (**mIntfVoltage)(2, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)); } if (terminalNotGrounded(0)) { - (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); - (**mIntfVoltage)(1, 0) = (**mIntfVoltage)(1, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); - (**mIntfVoltage)(2, 0) = (**mIntfVoltage)(2, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); + (**mIntfVoltage)(0, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); + (**mIntfVoltage)(1, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); + (**mIntfVoltage)(2, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); } SPDLOG_LOGGER_DEBUG(mSLog, "\nUpdate Voltage: {:s}", diff --git a/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp b/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp index caac66efb3..b5c833d201 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_PiLine.cpp @@ -13,7 +13,6 @@ using namespace CPS; EMT::Ph3::PiLine::PiLine(String uid, String name, Logger::Level logLevel) : Base::Ph3::PiLine(mAttributes), CompositePowerComp(uid, name, true, true, logLevel) { mPhaseType = PhaseType::ABC; - setVirtualNodeNumber(1); setTerminalNumber(2); SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); @@ -32,15 +31,6 @@ SimPowerComp::Ptr EMT::Ph3::PiLine::clone(String name) { void EMT::Ph3::PiLine::initializeFromNodesAndTerminals(Real frequency) { - // By default there is always a small conductance to ground to - // avoid problems with floating nodes. - Matrix defaultParallelCond = Matrix::Zero(3, 3); - defaultParallelCond << - 1e-6, 0, 0, - 0, 1e-6, 0, - 0, 0, 1e-6; - **mParallelCond = ((**mParallelCond)(0, 0) > 0) ? **mParallelCond : defaultParallelCond; - // Static calculation Real omega = 2. * PI * frequency; MatrixComp impedance = MatrixComp::Zero(3, 3); @@ -57,44 +47,30 @@ void EMT::Ph3::PiLine::initializeFromNodesAndTerminals(Real frequency) { **mIntfCurrent = iInit.real(); **mIntfVoltage = vInitABC.real(); - // Initialization of virtual node - // Initial voltage of phase B,C is set after A - MatrixComp vInitTerm0 = MatrixComp::Zero(3, 1); - vInitTerm0(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(0); - vInitTerm0(1, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_B; - vInitTerm0(2, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_C; - - mVirtualNodes[0]->setInitialVoltage(PEAK1PH_TO_RMS3PH*(vInitTerm0 + **mSeriesRes * iInit)); - - // Create series sub components - mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); - mSubSeriesResistor->setParameters(**mSeriesRes); - mSubSeriesResistor->connect({ mTerminals[0]->node(), mVirtualNodes[0] }); - mSubSeriesResistor->initialize(mFrequencies); - mSubSeriesResistor->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); - - mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); - mSubSeriesInductor->setParameters(**mSeriesInd); - mSubSeriesInductor->connect({ mVirtualNodes[0], mTerminals[1]->node() }); - mSubSeriesInductor->initialize(mFrequencies); - mSubSeriesInductor->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubSeriesInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + // Create series rl sub component + mSubSeriesElement = std::make_shared(**mName + "_ResIndSeries", mLogLevel); + mSubSeriesElement->connect({ mTerminals[0]->node(), mTerminals[1]->node() }); + mSubSeriesElement->setParameters(**mSeriesRes, **mSeriesInd); + mSubSeriesElement->initialize(mFrequencies); + mSubSeriesElement->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesElement, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); // Create parallel sub components - mSubParallelResistor0 = std::make_shared(**mName + "_con0", mLogLevel); - mSubParallelResistor0->setParameters(2. * (**mParallelCond).inverse()); - mSubParallelResistor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); - mSubParallelResistor0->initialize(mFrequencies); - mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubParallelResistor0, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); - - mSubParallelResistor1 = std::make_shared(**mName + "_con1", mLogLevel); - mSubParallelResistor1->setParameters(2. * (**mParallelCond).inverse()); - mSubParallelResistor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); - mSubParallelResistor1->initialize(mFrequencies); - mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubParallelResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + if ((**mParallelCond)(0,0) > 0) { + mSubParallelResistor0 = std::make_shared(**mName + "_con0", mLogLevel); + mSubParallelResistor0->setParameters(2. * (**mParallelCond).inverse()); + mSubParallelResistor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); + mSubParallelResistor0->initialize(mFrequencies); + mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor0, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubParallelResistor1 = std::make_shared(**mName + "_con1", mLogLevel); + mSubParallelResistor1->setParameters(2. * (**mParallelCond).inverse()); + mSubParallelResistor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); + mSubParallelResistor1->initialize(mFrequencies); + mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + } if ((**mParallelCap)(0,0) > 0) { mSubParallelCapacitor0 = std::make_shared(**mName + "_cap0", mLogLevel); @@ -131,13 +107,11 @@ void EMT::Ph3::PiLine::initializeFromNodesAndTerminals(Real frequency) { "\nCurrent: {:s}" "\nTerminal 0 voltage: {:s}" "\nTerminal 1 voltage: {:s}" - "\nVirtual Node 1 voltage: {:s}" "\n--- Initialization from powerflow finished ---", Logger::matrixToString(**mIntfVoltage), Logger::matrixToString(**mIntfCurrent), Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)), - Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)), - Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1))); mSLog->flush(); } @@ -178,5 +152,5 @@ void EMT::Ph3::PiLine::mnaCompUpdateVoltage(const Matrix& leftVector) { } void EMT::Ph3::PiLine::mnaCompUpdateCurrent(const Matrix& leftVector) { - **mIntfCurrent = mSubSeriesInductor->intfCurrent(); + **mIntfCurrent = mSubSeriesElement->intfCurrent(); } diff --git a/dpsim-models/src/EMT/EMT_Ph3_PiLine_deprecated.cpp b/dpsim-models/src/EMT/EMT_Ph3_PiLine_deprecated.cpp new file mode 100644 index 0000000000..caac66efb3 --- /dev/null +++ b/dpsim-models/src/EMT/EMT_Ph3_PiLine_deprecated.cpp @@ -0,0 +1,182 @@ +/* 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; + +EMT::Ph3::PiLine::PiLine(String uid, String name, Logger::Level logLevel) + : Base::Ph3::PiLine(mAttributes), CompositePowerComp(uid, name, true, true, logLevel) { + mPhaseType = PhaseType::ABC; + setVirtualNodeNumber(1); + setTerminalNumber(2); + + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + **mIntfVoltage = Matrix::Zero(3, 1); + **mIntfCurrent = Matrix::Zero(3, 1); + + mSLog->flush(); +} + +/// DEPRECATED: Delete method +SimPowerComp::Ptr EMT::Ph3::PiLine::clone(String name) { + auto copy = PiLine::make(name, mLogLevel); + copy->setParameters(**mSeriesRes, **mSeriesInd, **mParallelCap, **mParallelCond); + return copy; +} + +void EMT::Ph3::PiLine::initializeFromNodesAndTerminals(Real frequency) { + + // By default there is always a small conductance to ground to + // avoid problems with floating nodes. + Matrix defaultParallelCond = Matrix::Zero(3, 3); + defaultParallelCond << + 1e-6, 0, 0, + 0, 1e-6, 0, + 0, 0, 1e-6; + **mParallelCond = ((**mParallelCond)(0, 0) > 0) ? **mParallelCond : defaultParallelCond; + + // Static calculation + Real omega = 2. * PI * frequency; + MatrixComp impedance = MatrixComp::Zero(3, 3); + impedance << + Complex((**mSeriesRes)(0, 0), omega * (**mSeriesInd)(0, 0)), Complex((**mSeriesRes)(0, 1), omega * (**mSeriesInd)(0, 1)), Complex((**mSeriesRes)(0, 2), omega * (**mSeriesInd)(0, 2)), + Complex((**mSeriesRes)(1, 0), omega * (**mSeriesInd)(1, 0)), Complex((**mSeriesRes)(1, 1), omega * (**mSeriesInd)(1, 1)), Complex((**mSeriesRes)(1, 2), omega * (**mSeriesInd)(1, 2)), + Complex((**mSeriesRes)(2, 0), omega * (**mSeriesInd)(2, 0)), Complex((**mSeriesRes)(2, 1), omega * (**mSeriesInd)(2, 1)), Complex((**mSeriesRes)(2, 2), omega * (**mSeriesInd)(2, 2)); + + MatrixComp vInitABC = MatrixComp::Zero(3, 1); + vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(1) - RMS3PH_TO_PEAK1PH * initialSingleVoltage(0); + vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B; + vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C; + MatrixComp iInit = impedance.inverse() * vInitABC; + **mIntfCurrent = iInit.real(); + **mIntfVoltage = vInitABC.real(); + + // Initialization of virtual node + // Initial voltage of phase B,C is set after A + MatrixComp vInitTerm0 = MatrixComp::Zero(3, 1); + vInitTerm0(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(0); + vInitTerm0(1, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_B; + vInitTerm0(2, 0) = vInitTerm0(0, 0) * SHIFT_TO_PHASE_C; + + mVirtualNodes[0]->setInitialVoltage(PEAK1PH_TO_RMS3PH*(vInitTerm0 + **mSeriesRes * iInit)); + + // Create series sub components + mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); + mSubSeriesResistor->setParameters(**mSeriesRes); + mSubSeriesResistor->connect({ mTerminals[0]->node(), mVirtualNodes[0] }); + mSubSeriesResistor->initialize(mFrequencies); + mSubSeriesResistor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); + mSubSeriesInductor->setParameters(**mSeriesInd); + mSubSeriesInductor->connect({ mVirtualNodes[0], mTerminals[1]->node() }); + mSubSeriesInductor->initialize(mFrequencies); + mSubSeriesInductor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // Create parallel sub components + mSubParallelResistor0 = std::make_shared(**mName + "_con0", mLogLevel); + mSubParallelResistor0->setParameters(2. * (**mParallelCond).inverse()); + mSubParallelResistor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); + mSubParallelResistor0->initialize(mFrequencies); + mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor0, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubParallelResistor1 = std::make_shared(**mName + "_con1", mLogLevel); + mSubParallelResistor1->setParameters(2. * (**mParallelCond).inverse()); + mSubParallelResistor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); + mSubParallelResistor1->initialize(mFrequencies); + mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + if ((**mParallelCap)(0,0) > 0) { + mSubParallelCapacitor0 = std::make_shared(**mName + "_cap0", mLogLevel); + mSubParallelCapacitor0->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); + mSubParallelCapacitor0->initialize(mFrequencies); + mSubParallelCapacitor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor0, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + mSubParallelCapacitor1 = std::make_shared(**mName + "_cap1", mLogLevel); + mSubParallelCapacitor1->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); + mSubParallelCapacitor1->initialize(mFrequencies); + mSubParallelCapacitor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + } + + SPDLOG_LOGGER_DEBUG(mSLog, + "\n--debug--" + "\n seriesRes: {:s}" + "\n seriesInd: {:s}" + "\n Impedance: {:s}" + "\n vInit: {:s}" + "\n iInit: {:s}", + Logger::matrixToString(**mSeriesRes), + Logger::matrixToString(**mSeriesInd), + Logger::matrixCompToString(impedance), + Logger::matrixCompToString(vInitABC), + Logger::matrixCompToString(iInit)); + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\nVirtual Node 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::matrixToString(**mIntfVoltage), + Logger::matrixToString(**mIntfCurrent), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)), + Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); + mSLog->flush(); +} + +void EMT::Ph3::PiLine::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes){ + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); +} + +void EMT::Ph3::PiLine::mnaParentPreStep(Real time, Int timeStepCount) { + mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void EMT::Ph3::PiLine::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void EMT::Ph3::PiLine::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); +} + +void EMT::Ph3::PiLine::mnaCompUpdateVoltage(const Matrix& leftVector) { + // v1 - v0 + **mIntfVoltage = Matrix::Zero(3, 1); + if (terminalNotGrounded(1)) { + (**mIntfVoltage)(0, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); + (**mIntfVoltage)(1, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)); + (**mIntfVoltage)(2, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)); + } + if (terminalNotGrounded(0)) { + (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); + (**mIntfVoltage)(1, 0) = (**mIntfVoltage)(1, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); + (**mIntfVoltage)(2, 0) = (**mIntfVoltage)(2, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); + } +} + +void EMT::Ph3::PiLine::mnaCompUpdateCurrent(const Matrix& leftVector) { + **mIntfCurrent = mSubSeriesInductor->intfCurrent(); +} diff --git a/dpsim-models/src/EMT/EMT_Ph3_ResIndSeries.cpp b/dpsim-models/src/EMT/EMT_Ph3_ResIndSeries.cpp new file mode 100644 index 0000000000..1130981808 --- /dev/null +++ b/dpsim-models/src/EMT/EMT_Ph3_ResIndSeries.cpp @@ -0,0 +1,186 @@ +/* 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; + +EMT::Ph3::ResIndSeries::ResIndSeries(String uid, String name, Logger::Level logLevel) + : MNASimPowerComp(uid, name, true, true, logLevel), + mInductance(mAttributes->create("L")), + mResistance(mAttributes->create("R")) { + + mPhaseType = PhaseType::ABC; + setTerminalNumber(2); + **mIntfVoltage = Matrix::Zero(3, 1); + **mIntfCurrent = Matrix::Zero(3, 1); +} + +SimPowerComp::Ptr EMT::Ph3::ResIndSeries::clone(String name) { + auto copy = ResIndSeries::make(name, mLogLevel); + copy->setParameters(**mResistance, **mInductance); + return copy; +} + +void EMT::Ph3::ResIndSeries::setParameters(Matrix resistanceMatrix, Matrix inductanceMatrix) { + **mResistance = resistanceMatrix; + **mInductance = inductanceMatrix; + + //check initial value of inductance + if ((**mInductance)(0,0)==0.0 || (**mInductance)(1,1)==0.0 || (**mInductance)(2,2)==0.0 ) { + std::string err = "Inductance of " + this->name() + " can not be zero!"; + throw std::invalid_argument(err); + } +} + +void EMT::Ph3::ResIndSeries::initializeFromNodesAndTerminals(Real frequency) { + Real omega = 2. * PI * frequency; + MatrixComp impedance = MatrixComp::Zero(3, 3); + impedance << + Complex((**mResistance)(0, 0), omega * (**mInductance)(0, 0)), 0.0, 0.0, + 0.0, Complex((**mResistance)(1, 1), omega * (**mInductance)(1, 1)), 0.0, + 0.0, 0.0, Complex((**mResistance)(2, 2), omega * (**mInductance)(2, 2)); + + // IntfVoltage initialization for each phase + MatrixComp vInitABC = Matrix::Zero(3, 1); + vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * initialSingleVoltage(1) - RMS3PH_TO_PEAK1PH * initialSingleVoltage(0); + vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B; + vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C; + **mIntfVoltage = vInitABC.real(); + **mIntfCurrent = (impedance.inverse() * vInitABC).real(); + + mSLog->info("\nResistance matrix [Ohm]: {:s}" + "\nInductance matrix [H]: {:s}" + "\nImpedance matrix [Ohm]: {:s}", + Logger::matrixToString(**mResistance), + Logger::matrixToString(**mInductance), + Logger::matrixCompToString(impedance)); + mSLog->info( + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::matrixToString(**mIntfVoltage), + Logger::matrixToString(**mIntfCurrent), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1))); + mSLog->flush(); +} + +void EMT::Ph3::ResIndSeries::initVars(Real timeStep) { + // Assumption: symmetric R and L matrix + Real a = timeStep * (**mResistance)(0,0) / (2. * (**mInductance)(0,0)); + Real b = timeStep / (2. * (**mInductance)(0,0)); + + mEquivCond = b / (1. + a); + mPrevCurrFac = (1. - a ) / (1. + a); + + mEquivCurrent = mEquivCond * **mIntfVoltage + mPrevCurrFac * **mIntfCurrent; +} + +void EMT::Ph3::ResIndSeries::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); + initVars(timeStep); + + mSLog->info( + "\n--- MNA initialization ---" + "\nInitial current {:s}" + "\nEquiv. current {:s}" + "\n--- MNA initialization finished ---", + Logger::matrixToString(**mIntfCurrent), + Logger::matrixToString(mEquivCurrent)); + mSLog->flush(); +} + +void EMT::Ph3::ResIndSeries::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { + + // Set diagonal entries + if (terminalNotGrounded(0)) { + // set upper left block, 3x3 entries + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(0, 0), mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 1), matrixNodeIndex(0, 1), mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2), matrixNodeIndex(0, 2), mEquivCond); + } + if (terminalNotGrounded(1)) { + // set buttom right block, 3x3 entries + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(1, 0), mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 1), matrixNodeIndex(1, 1), mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 2), matrixNodeIndex(1, 2), mEquivCond); + } + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + // set buttom right block, 3x3 entries + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(1, 0), -mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 1), matrixNodeIndex(1, 1), -mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2), matrixNodeIndex(1, 2), -mEquivCond); + + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 0), -mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 1), matrixNodeIndex(0, 1), -mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 2), matrixNodeIndex(0, 2), -mEquivCond); + } + + mSLog->info( + "\nEquivalent Conductance: {:}", + mEquivCond); +} + +void EMT::Ph3::ResIndSeries::mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { + // Update internal state + mEquivCurrent = mEquivCond * **mIntfVoltage + mPrevCurrFac * **mIntfCurrent; + if (terminalNotGrounded(0)) { + Math::setVectorElement(rightVector, matrixNodeIndex(0, 0), mEquivCurrent(0, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(0, 1), mEquivCurrent(1, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(0, 2), mEquivCurrent(2, 0)); + } + if (terminalNotGrounded(1)) { + Math::setVectorElement(rightVector, matrixNodeIndex(1, 0), -mEquivCurrent(0, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(1, 1), -mEquivCurrent(1, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(1, 2), -mEquivCurrent(2, 0)); + } +} + +void EMT::Ph3::ResIndSeries::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { + prevStepDependencies.push_back(mIntfVoltage); + prevStepDependencies.push_back(mIntfCurrent); + modifiedAttributes.push_back(mRightVector); +} + +void EMT::Ph3::ResIndSeries::mnaCompPreStep(Real time, Int timeStepCount) { + this->mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void EMT::Ph3::ResIndSeries::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void EMT::Ph3::ResIndSeries::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); +} + +void EMT::Ph3::ResIndSeries::mnaCompUpdateVoltage(const Matrix& leftVector) { + // v1 - v0 + **mIntfVoltage = Matrix::Zero(3,1); + if (terminalNotGrounded(1)) { + (**mIntfVoltage)(0, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); + (**mIntfVoltage)(1, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)); + (**mIntfVoltage)(2, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)); + } + if (terminalNotGrounded(0)) { + (**mIntfVoltage)(0, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); + (**mIntfVoltage)(1, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); + (**mIntfVoltage)(2, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); + } +} + +void EMT::Ph3::ResIndSeries::mnaCompUpdateCurrent(const Matrix& leftVector) { + **mIntfCurrent = mEquivCond * **mIntfVoltage + mEquivCurrent; +} diff --git a/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp b/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp index 077727e9ce..05928f282a 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_RxLine.cpp @@ -94,6 +94,7 @@ void EMT::Ph3::RxLine::initializeFromNodesAndTerminals(Real frequency) { Logger::matrixToString(**mIntfCurrent), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } void EMT::Ph3::RxLine::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { diff --git a/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp b/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp index 686eaedc52..7255ae6608 100644 --- a/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp +++ b/dpsim-models/src/EMT/EMT_Ph3_Transformer.cpp @@ -11,42 +11,34 @@ using namespace CPS; EMT::Ph3::Transformer::Transformer(String uid, String name, - Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph3::Transformer(mAttributes), CompositePowerComp(uid, name, true, true, logLevel) { + Logger::Level logLevel) + : Base::Ph3::Transformer(mAttributes), + MNASimPowerComp(uid, name, true, true, logLevel) { + + // mPhaseType = PhaseType::ABC; - if (withResistiveLosses) - setVirtualNodeNumber(3); - else - setVirtualNodeNumber(2); - setTerminalNumber(2); - SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + // **mIntfVoltage = Matrix::Zero(3, 1); - **mIntfCurrent = Matrix::Zero(1, 1); -} + **mIntfCurrent = Matrix::Zero(3, 1); + mEquivCurrent = Matrix::Zero(3, 1); -/// DEPRECATED: Delete method -SimPowerComp::Ptr EMT::Ph3::Transformer::clone(String name) { - auto copy = Transformer::make(name, mLogLevel); - copy->setParameters(mNominalVoltageEnd1, mNominalVoltageEnd2, mRatedPower, std::abs(**mRatio), std::arg(**mRatio), mResistance, mInductance); - return copy; + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); } -void EMT::Ph3::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, Real ratioPhase, +void EMT::Ph3::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, Real ratioPhase, Matrix resistance, Matrix inductance) { - Base::Ph3::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratedPower, ratioAbs, ratioPhase, resistance, inductance); + Base::Ph3::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs, ratioPhase, resistance, inductance); SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]", mNominalVoltageEnd1, mNominalVoltageEnd2); - SPDLOG_LOGGER_INFO(mSLog, "Rated Apparent Power = {} [VA]", mRatedPower); SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", std::abs(**mRatio), std::arg(**mRatio)); mParametersSet = true; } void EMT::Ph3::Transformer::initializeFromNodesAndTerminals(Real frequency) { - // Component parameters are referred to higher voltage side. // Switch terminals to have terminal 0 at higher voltage side // if transformer is connected the other way around. @@ -63,213 +55,148 @@ void EMT::Ph3::Transformer::initializeFromNodesAndTerminals(Real frequency) { SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", std::abs(**mRatio), std::arg(**mRatio)); } - // Set initial voltage of virtual node in between - mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(1) * **mRatio); - // Static calculations from load flow data Real omega = 2. * PI * frequency; MatrixComp impedance = MatrixComp::Zero(3, 3); impedance << - Complex(mResistance(0, 0), omega * mInductance(0, 0)), Complex(mResistance(0, 1), omega * mInductance(0, 1)), Complex(mResistance(0, 2), omega * mInductance(0, 2)), - Complex(mResistance(1, 0), omega * mInductance(1, 0)), Complex(mResistance(1, 1), omega * mInductance(1, 1)), Complex(mResistance(1, 2), omega * mInductance(1, 2)), - Complex(mResistance(2, 0), omega * mInductance(2, 0)), Complex(mResistance(2, 1), omega * mInductance(2, 1)), Complex(mResistance(2, 2), omega * mInductance(2, 2)); + Complex((mResistance)(0, 0), omega * (mInductance)(0, 0)), 0.0, 0.0, + 0.0, Complex((mResistance)(1, 1), omega * (mInductance)(1, 1)), 0.0, + 0.0, 0.0, Complex((mResistance)(2, 2), omega * (mInductance)(2, 2)); SPDLOG_LOGGER_INFO(mSLog, "Resistance (referred to higher voltage side) = {} [Ohm]", Logger::matrixToString(mResistance)); SPDLOG_LOGGER_INFO(mSLog, "Inductance (referred to higher voltage side) = {} [H]", Logger::matrixToString(mInductance)); - SPDLOG_LOGGER_INFO(mSLog, "Reactance (referred to higher voltage side) = {} [Ohm]", Logger::matrixToString(omega * mInductance)); + //SPDLOG_LOGGER_INFO(mSLog, "Impedance (referred to higher voltage side) = {} [Ohm]", Logger::matrixCompToString(impedance)); MatrixComp vInitABC = MatrixComp::Zero(3, 1); - vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * (mVirtualNodes[0]->initialSingleVoltage() - initialSingleVoltage(0)); + vInitABC(0, 0) = RMS3PH_TO_PEAK1PH * (initialSingleVoltage(0) - initialSingleVoltage(1)* **mRatio); vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B; vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C; MatrixComp iInit = impedance.inverse() * vInitABC; - **mIntfCurrent = iInit.real(); + **mIntfCurrent = -iInit.real(); **mIntfVoltage = vInitABC.real(); - // Create series sub components - mSubInductor = std::make_shared(**mName + "_ind", mLogLevel); - mSubInductor->setParameters(mInductance); - addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - if (mNumVirtualNodes == 3) { - mVirtualNodes[2]->setInitialVoltage(initialSingleVoltage(0)); - mSubResistor = std::make_shared(**mName + "_res", mLogLevel); - addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - mSubResistor->setParameters(mResistance); - mSubResistor->connect({ node(0), mVirtualNodes[2] }); - mSubInductor->connect({ mVirtualNodes[2], mVirtualNodes[0] }); - } - else { - mSubInductor->connect({ node(0), mVirtualNodes[0] }); - } - - // Create parallel sub components (three-phase power) - Real pSnub = P_SNUB_TRANSFORMER*mRatedPower; - Real qSnub = Q_SNUB_TRANSFORMER*mRatedPower; - - // A snubber conductance is added on the higher voltage side - Real snubberResistance1 = std::pow(std::abs(mNominalVoltageEnd1),2) / pSnub; - mSnubberResistance1 = Math::singlePhaseParameterToThreePhase(snubberResistance1); - mSubSnubResistor1 = std::make_shared(**mName + "_snub_res1", mLogLevel); - mSubSnubResistor1->setParameters(mSnubberResistance1); - mSubSnubResistor1->connect({ node(0), EMT::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]", node(0)->name(), Logger::matrixToString(mSnubberResistance1)); - addMNASubComponent(mSubSnubResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - // A snubber conductance is added on the lower voltage side - Real snubberResistance2 = std::pow(std::abs(mNominalVoltageEnd2),2) / pSnub; - mSnubberResistance2 = Math::singlePhaseParameterToThreePhase(snubberResistance2); - mSubSnubResistor2 = std::make_shared(**mName + "_snub_res2", mLogLevel); - mSubSnubResistor2->setParameters(mSnubberResistance2); - mSubSnubResistor2->connect({ node(1), EMT::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]", node(1)->name(), Logger::matrixToString(mSnubberResistance2)); - addMNASubComponent(mSubSnubResistor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - // // A snubber capacitance is added to higher voltage side (not used as capacitor at high voltage side made it worse) - // Real snubberCapacitance1 = qSnub / std::pow(std::abs(mNominalVoltageEnd1),2) / omega; - // mSnubberCapacitance1 = Math::singlePhaseParameterToThreePhase*(snubberCapacitance1); - // mSubSnubCapacitor1 = std::make_shared(**mName + "_snub_cap1", mLogLevel); - // mSubSnubCapacitor1->setParameters(mSnubberCapacitance1); - // mSubSnubCapacitor1->connect({ node(0), EMT::SimNode::GND }); - // SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 1 (connected to higher voltage side {}) = \n{} [F] \n ", node(0)->name(), Logger::matrixToString(mSnubberCapacitance1)); - // mSubComponents.push_back(mSubSnubCapacitor1); - - // A snubber capacitance is added to lower voltage side - Real snubberCapacitance2 = qSnub / std::pow(std::abs(mNominalVoltageEnd2),2) / omega; - mSnubberCapacitance2 = Math::singlePhaseParameterToThreePhase(snubberCapacitance2); - mSubSnubCapacitor2 = std::make_shared(**mName + "_snub_cap2", mLogLevel); - mSubSnubCapacitor2->setParameters(mSnubberCapacitance2); - mSubSnubCapacitor2->connect({ node(1), EMT::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]", node(1)->name(), Logger::matrixToString(mSnubberCapacitance2)); - addMNASubComponent(mSubSnubCapacitor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - // Initialize electrical subcomponents - SPDLOG_LOGGER_INFO(mSLog, "Electrical subcomponents: "); - for (auto subcomp: mSubComponents) { - SPDLOG_LOGGER_INFO(mSLog, "- {}", subcomp->name()); - subcomp->initialize(mFrequencies); - subcomp->initializeFromNodesAndTerminals(frequency); - } - SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization from powerflow ---" - "\nVoltage across: {:s}" - "\nCurrent: {:s}" + "\nVoltage across primary side: {:s}" + "\nPrimary side current flowing into node 0: {:s}" "\nTerminal 0 voltage: {:s}" "\nTerminal 1 voltage: {:s}" - "\nVirtual Node 1 voltage: {:s}" "\n--- Initialization from powerflow finished ---", Logger::matrixToString(**mIntfVoltage), Logger::matrixToString(**mIntfCurrent), Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)), - Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)), - Logger::phasorToString(RMS3PH_TO_PEAK1PH * mVirtualNodes[0]->initialSingleVoltage())); + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1))); + mSLog->flush(); } -void EMT::Ph3::Transformer::mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { +void EMT::Ph3::Transformer::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); + initVars(timeStep); +} + +void EMT::Ph3::Transformer::initVars(Real timeStep) { + // Assumption: symmetric R and L matrix + Real a = timeStep * (mResistance)(0,0) / (2. * (mInductance)(0,0)); + Real b = timeStep / (2. * (mInductance)(0,0)); + + mEquivCond = b / (1. + a); + mPrevCurrFac = (1. - a ) / (1. + a); + + // Update internal state + mEquivCurrent = mEquivCond * **mIntfVoltage - mPrevCurrFac * **mIntfCurrent; + SPDLOG_LOGGER_INFO(mSLog, - "\nTerminal 0 connected to {:s} = sim node {:d}" - "\nTerminal 1 connected to {:s} = sim node {:d}", - mTerminals[0]->node()->name(), mTerminals[0]->node()->matrixNodeIndex(), - mTerminals[1]->node()->name(), mTerminals[1]->node()->matrixNodeIndex()); + "\n--- Initialization internal states ---" + "\nInitial current {:s}" + "\nEquiv. current {:s}" + "\n--- Initialization internal states finished ---", + Logger::matrixToString(**mIntfCurrent), + Logger::matrixToString(mEquivCurrent)); + mSLog->flush(); } void EMT::Ph3::Transformer::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { - // Ideal transformer equations if (terminalNotGrounded(0)) { - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), -1.); - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), -1.); - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), -1.); - - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), 1.); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), 1.); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), 1.); - + // set upper left block, 3x3 entries + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(0, 0), mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 1), matrixNodeIndex(0, 1), mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2), matrixNodeIndex(0, 2), mEquivCond); } if (terminalNotGrounded(1)) { - Math::setMatrixElement(systemMatrix, matrixNodeIndex(1, 0), mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), (**mRatio).real()); - Math::setMatrixElement(systemMatrix, matrixNodeIndex(1, 1), mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), (**mRatio).real()); - Math::setMatrixElement(systemMatrix, matrixNodeIndex(1, 2), mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), (**mRatio).real()); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), matrixNodeIndex(1, 0), -(**mRatio).real()); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), matrixNodeIndex(1, 1), -(**mRatio).real()); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), matrixNodeIndex(1, 2), -(**mRatio).real()); + // set buttom right block, 3x3 entries + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(1, 0), std::pow((**mRatio).real(),2) * mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 1), matrixNodeIndex(1, 1), std::pow((**mRatio).real(),2) * mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 2), matrixNodeIndex(1, 2), std::pow((**mRatio).real(),2) * mEquivCond); + } + // Set off diagonal blocks, 2x3x3 entries + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 0), matrixNodeIndex(1, 0), - (**mRatio).real() * mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 1), matrixNodeIndex(1, 1), - (**mRatio).real() * mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0, 2), matrixNodeIndex(1, 2), - (**mRatio).real() * mEquivCond); + + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 0), matrixNodeIndex(0, 0), - (**mRatio).real() * mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 1), matrixNodeIndex(0, 1), - (**mRatio).real() * mEquivCond); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1, 2), matrixNodeIndex(0, 2), - (**mRatio).real() * mEquivCond); } - // Add subcomps to system matrix - for (auto subcomp: mSubComponents) - if (auto mnasubcomp = std::dynamic_pointer_cast(subcomp)) - mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix); + SPDLOG_LOGGER_DEBUG(mSLog, "\nEquivalent Conductance: {:s}", Logger::matrixToString(mEquivCond)); +} + +void EMT::Ph3::Transformer::mnaCompApplyRightSideVectorStamp(Matrix& rightVector) { + // Update internal state + mEquivCurrent = mEquivCond * **mIntfVoltage - mPrevCurrFac * **mIntfCurrent; if (terminalNotGrounded(0)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), - mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), mVirtualNodes[1]->matrixNodeIndex(PhaseType::A)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), - mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), mVirtualNodes[1]->matrixNodeIndex(PhaseType::B)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), - mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), mVirtualNodes[1]->matrixNodeIndex(PhaseType::C)); - - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), - mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), mVirtualNodes[0]->matrixNodeIndex(PhaseType::A)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), - mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), mVirtualNodes[0]->matrixNodeIndex(PhaseType::B)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), - mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), mVirtualNodes[0]->matrixNodeIndex(PhaseType::C)); + Math::setVectorElement(rightVector, matrixNodeIndex(0, 0), -mEquivCurrent(0, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(0, 1), -mEquivCurrent(1, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(0, 2), -mEquivCurrent(2, 0)); } if (terminalNotGrounded(1)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), - matrixNodeIndex(1, 0), mVirtualNodes[1]->matrixNodeIndex(PhaseType::A)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), - matrixNodeIndex(1, 1), mVirtualNodes[1]->matrixNodeIndex(PhaseType::B)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), - matrixNodeIndex(1, 2), mVirtualNodes[1]->matrixNodeIndex(PhaseType::C)); - - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), - mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), matrixNodeIndex(1, 0)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), - mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), matrixNodeIndex(1, 1)); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), - mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), matrixNodeIndex(1, 2)); + Math::setVectorElement(rightVector, matrixNodeIndex(1, 0), (**mRatio).real() * mEquivCurrent(0, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(1, 1), (**mRatio).real() * mEquivCurrent(1, 0)); + Math::setVectorElement(rightVector, matrixNodeIndex(1, 2), (**mRatio).real() * mEquivCurrent(2, 0)); } } -void EMT::Ph3::Transformer::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { - prevStepDependencies.push_back(mIntfCurrent); +void EMT::Ph3::Transformer::mnaCompAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { prevStepDependencies.push_back(mIntfVoltage); + prevStepDependencies.push_back(mIntfCurrent); modifiedAttributes.push_back(mRightVector); } -void EMT::Ph3::Transformer::mnaParentPreStep(Real time, Int timeStepCount) { - mnaCompApplyRightSideVectorStamp(**mRightVector); +void EMT::Ph3::Transformer::mnaCompPreStep(Real time, Int timeStepCount) { + this->mnaCompApplyRightSideVectorStamp(**mRightVector); } -void EMT::Ph3::Transformer::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { +void EMT::Ph3::Transformer::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { attributeDependencies.push_back(leftVector); modifiedAttributes.push_back(mIntfVoltage); modifiedAttributes.push_back(mIntfCurrent); } -void EMT::Ph3::Transformer::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { +void EMT::Ph3::Transformer::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { mnaCompUpdateVoltage(**leftVector); mnaCompUpdateCurrent(**leftVector); } -void EMT::Ph3::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { - **mIntfCurrent = mSubInductor->intfCurrent(); -} - void EMT::Ph3::Transformer::mnaCompUpdateVoltage(const Matrix& leftVector) { - // v1 - v0 - **mIntfVoltage = Matrix::Zero(3, 1); - if (terminalNotGrounded(1)) { - (**mIntfVoltage)(0, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); - (**mIntfVoltage)(1, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)); - (**mIntfVoltage)(2, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)); - } + // v0 - v1 + **mIntfVoltage = Matrix::Zero(3,1); if (terminalNotGrounded(0)) { - (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); - (**mIntfVoltage)(1, 0) = (**mIntfVoltage)(1, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); - (**mIntfVoltage)(2, 0) = (**mIntfVoltage)(2, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); + (**mIntfVoltage)(0, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); + (**mIntfVoltage)(1, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); + (**mIntfVoltage)(2, 0) += Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); + } + if (terminalNotGrounded(1)) { + (**mIntfVoltage)(0, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)) * (**mRatio).real(); + (**mIntfVoltage)(1, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)) * (**mRatio).real(); + (**mIntfVoltage)(2, 0) -= Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)) * (**mRatio).real(); } } +void EMT::Ph3::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { + // primary side current flowing into node 0 + **mIntfCurrent = -(mEquivCond * **mIntfVoltage + mEquivCurrent); +} + diff --git a/dpsim-models/src/EMT/EMT_Ph3_Transformer_deprecated.cpp b/dpsim-models/src/EMT/EMT_Ph3_Transformer_deprecated.cpp new file mode 100644 index 0000000000..6aa249bd01 --- /dev/null +++ b/dpsim-models/src/EMT/EMT_Ph3_Transformer_deprecated.cpp @@ -0,0 +1,275 @@ +/* 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; + +EMT::Ph3::Transformer::Transformer(String uid, String name, + Logger::Level logLevel, Bool withResistiveLosses) + : Base::Ph3::Transformer(mAttributes), CompositePowerComp(uid, name, true, true, logLevel) { + mPhaseType = PhaseType::ABC; + if (withResistiveLosses) + setVirtualNodeNumber(3); + else + setVirtualNodeNumber(2); + + setTerminalNumber(2); + + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + **mIntfVoltage = Matrix::Zero(3, 1); + **mIntfCurrent = Matrix::Zero(1, 1); +} + +/// DEPRECATED: Delete method +SimPowerComp::Ptr EMT::Ph3::Transformer::clone(String name) { + auto copy = Transformer::make(name, mLogLevel); + copy->setParameters(mNominalVoltageEnd1, mNominalVoltageEnd2, mRatedPower, std::abs(**mRatio), std::arg(**mRatio), mResistance, mInductance); + return copy; +} + +void EMT::Ph3::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, Real ratioPhase, + Matrix resistance, Matrix inductance) { + + Base::Ph3::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratedPower, ratioAbs, ratioPhase, resistance, inductance); + + SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]", mNominalVoltageEnd1, mNominalVoltageEnd2); + SPDLOG_LOGGER_INFO(mSLog, "Rated Apparent Power = {} [VA]", mRatedPower); + SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", std::abs(**mRatio), std::arg(**mRatio)); + + mParametersSet = true; +} + +void EMT::Ph3::Transformer::initializeFromNodesAndTerminals(Real frequency) { + + // Component parameters are referred to higher voltage side. + // Switch terminals to have terminal 0 at higher voltage side + // if transformer is connected the other way around. + if (Math::abs(**mRatio) < 1.) { + **mRatio = 1. / **mRatio; + std::shared_ptr> tmp = mTerminals[0]; + mTerminals[0] = mTerminals[1]; + mTerminals[1] = tmp; + Real tmpVolt = mNominalVoltageEnd1; + mNominalVoltageEnd1 = mNominalVoltageEnd2; + mNominalVoltageEnd2 = tmpVolt; + SPDLOG_LOGGER_INFO(mSLog, "Switching terminals to have first terminal at higher voltage side. Updated parameters: "); + SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]", mNominalVoltageEnd1, mNominalVoltageEnd2); + SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", std::abs(**mRatio), std::arg(**mRatio)); + } + + // Set initial voltage of virtual node in between + mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(1) * **mRatio); + + // Static calculations from load flow data + Real omega = 2. * PI * frequency; + MatrixComp impedance = MatrixComp::Zero(3, 3); + impedance << + Complex(mResistance(0, 0), omega * mInductance(0, 0)), Complex(mResistance(0, 1), omega * mInductance(0, 1)), Complex(mResistance(0, 2), omega * mInductance(0, 2)), + Complex(mResistance(1, 0), omega * mInductance(1, 0)), Complex(mResistance(1, 1), omega * mInductance(1, 1)), Complex(mResistance(1, 2), omega * mInductance(1, 2)), + Complex(mResistance(2, 0), omega * mInductance(2, 0)), Complex(mResistance(2, 1), omega * mInductance(2, 1)), Complex(mResistance(2, 2), omega * mInductance(2, 2)); + + SPDLOG_LOGGER_INFO(mSLog, "Resistance (referred to higher voltage side) = {} [Ohm]", Logger::matrixToString(mResistance)); + SPDLOG_LOGGER_INFO(mSLog, "Inductance (referred to higher voltage side) = {} [H]", Logger::matrixToString(mInductance)); + SPDLOG_LOGGER_INFO(mSLog, "Reactance (referred to higher voltage side) = {} [Ohm]", Logger::matrixToString(omega * mInductance)); + + MatrixComp vInitABC = MatrixComp::Zero(3, 1); + vInitABC(0, 0) = mVirtualNodes[0]->initialSingleVoltage() - RMS3PH_TO_PEAK1PH * initialSingleVoltage(0); + vInitABC(1, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_B; + vInitABC(2, 0) = vInitABC(0, 0) * SHIFT_TO_PHASE_C; + + MatrixComp iInit = impedance.inverse() * vInitABC; + **mIntfCurrent = iInit.real(); + **mIntfVoltage = vInitABC.real(); + + // Create series sub components + mSubInductor = std::make_shared(**mName + "_ind", mLogLevel); + mSubInductor->setParameters(mInductance); + addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + if (mNumVirtualNodes == 3) { + mVirtualNodes[2]->setInitialVoltage(initialSingleVoltage(0)); + mSubResistor = std::make_shared(**mName + "_res", mLogLevel); + addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + mSubResistor->setParameters(mResistance); + mSubResistor->connect({ node(0), mVirtualNodes[2] }); + mSubInductor->connect({ mVirtualNodes[2], mVirtualNodes[0] }); + } + else { + mSubInductor->connect({ node(0), mVirtualNodes[0] }); + } + + // Create parallel sub components (three-phase power) + Real pSnub = P_SNUB_TRANSFORMER*mRatedPower; + Real qSnub = Q_SNUB_TRANSFORMER*mRatedPower; + + // A snubber conductance is added on the higher voltage side + Real snubberResistance1 = std::pow(std::abs(mNominalVoltageEnd1),2) / pSnub; + mSnubberResistance1 = Math::singlePhaseParameterToThreePhase(snubberResistance1); + mSubSnubResistor1 = std::make_shared(**mName + "_snub_res1", mLogLevel); + mSubSnubResistor1->setParameters(mSnubberResistance1); + mSubSnubResistor1->connect({ node(0), EMT::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]", node(0)->name(), Logger::matrixToString(mSnubberResistance1)); + addMNASubComponent(mSubSnubResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // A snubber conductance is added on the lower voltage side + Real snubberResistance2 = std::pow(std::abs(mNominalVoltageEnd2),2) / pSnub; + mSnubberResistance2 = Math::singlePhaseParameterToThreePhase(snubberResistance2); + mSubSnubResistor2 = std::make_shared(**mName + "_snub_res2", mLogLevel); + mSubSnubResistor2->setParameters(mSnubberResistance2); + mSubSnubResistor2->connect({ node(1), EMT::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]", node(1)->name(), Logger::matrixToString(mSnubberResistance2)); + addMNASubComponent(mSubSnubResistor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // // A snubber capacitance is added to higher voltage side (not used as capacitor at high voltage side made it worse) + // Real snubberCapacitance1 = qSnub / std::pow(std::abs(mNominalVoltageEnd1),2) / omega; + // mSnubberCapacitance1 = Math::singlePhaseParameterToThreePhase*(snubberCapacitance1); + // mSubSnubCapacitor1 = std::make_shared(**mName + "_snub_cap1", mLogLevel); + // mSubSnubCapacitor1->setParameters(mSnubberCapacitance1); + // mSubSnubCapacitor1->connect({ node(0), EMT::SimNode::GND }); + // SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 1 (connected to higher voltage side {}) = \n{} [F] \n ", node(0)->name(), Logger::matrixToString(mSnubberCapacitance1)); + // mSubComponents.push_back(mSubSnubCapacitor1); + + // A snubber capacitance is added to lower voltage side + Real snubberCapacitance2 = qSnub / std::pow(std::abs(mNominalVoltageEnd2),2) / omega; + mSnubberCapacitance2 = Math::singlePhaseParameterToThreePhase(snubberCapacitance2); + mSubSnubCapacitor2 = std::make_shared(**mName + "_snub_cap2", mLogLevel); + mSubSnubCapacitor2->setParameters(mSnubberCapacitance2); + mSubSnubCapacitor2->connect({ node(1), EMT::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]", node(1)->name(), Logger::matrixToString(mSnubberCapacitance2)); + addMNASubComponent(mSubSnubCapacitor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // Initialize electrical subcomponents + SPDLOG_LOGGER_INFO(mSLog, "Electrical subcomponents: "); + for (auto subcomp: mSubComponents) { + SPDLOG_LOGGER_INFO(mSLog, "- {}", subcomp->name()); + subcomp->initialize(mFrequencies); + subcomp->initializeFromNodesAndTerminals(frequency); + } + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\nVirtual Node 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::matrixToString(**mIntfVoltage), + Logger::matrixToString(**mIntfCurrent), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(0)), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * initialSingleVoltage(1)), + Logger::phasorToString(RMS3PH_TO_PEAK1PH * mVirtualNodes[0]->initialSingleVoltage())); +} + +void EMT::Ph3::Transformer::mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + SPDLOG_LOGGER_INFO(mSLog, + "\nTerminal 0 connected to {:s} = sim node {:d}" + "\nTerminal 1 connected to {:s} = sim node {:d}", + mTerminals[0]->node()->name(), mTerminals[0]->node()->matrixNodeIndex(), + mTerminals[1]->node()->name(), mTerminals[1]->node()->matrixNodeIndex()); +} + +void EMT::Ph3::Transformer::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { + // Ideal transformer equations + if (terminalNotGrounded(0)) { + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), -1.); + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), -1.); + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), -1.); + + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), 1.); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), 1.); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), 1.); + + } + if (terminalNotGrounded(1)) { + Math::setMatrixElement(systemMatrix, matrixNodeIndex(1, 0), mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), (**mRatio).real()); + Math::setMatrixElement(systemMatrix, matrixNodeIndex(1, 1), mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), (**mRatio).real()); + Math::setMatrixElement(systemMatrix, matrixNodeIndex(1, 2), mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), (**mRatio).real()); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), matrixNodeIndex(1, 0), -(**mRatio).real()); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), matrixNodeIndex(1, 1), -(**mRatio).real()); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), matrixNodeIndex(1, 2), -(**mRatio).real()); + } + + // Add subcomps to system matrix + for (auto subcomp: mSubComponents) + if (auto mnasubcomp = std::dynamic_pointer_cast(subcomp)) + mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix); + + if (terminalNotGrounded(0)) { + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::A), mVirtualNodes[1]->matrixNodeIndex(PhaseType::A)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::B), mVirtualNodes[1]->matrixNodeIndex(PhaseType::B)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), + mVirtualNodes[0]->matrixNodeIndex(PhaseType::C), mVirtualNodes[1]->matrixNodeIndex(PhaseType::C)); + + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), + mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), mVirtualNodes[0]->matrixNodeIndex(PhaseType::A)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), + mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), mVirtualNodes[0]->matrixNodeIndex(PhaseType::B)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), + mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), mVirtualNodes[0]->matrixNodeIndex(PhaseType::C)); + } + if (terminalNotGrounded(1)) { + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), + matrixNodeIndex(1, 0), mVirtualNodes[1]->matrixNodeIndex(PhaseType::A)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), + matrixNodeIndex(1, 1), mVirtualNodes[1]->matrixNodeIndex(PhaseType::B)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), + matrixNodeIndex(1, 2), mVirtualNodes[1]->matrixNodeIndex(PhaseType::C)); + + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), + mVirtualNodes[1]->matrixNodeIndex(PhaseType::A), matrixNodeIndex(1, 0)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), + mVirtualNodes[1]->matrixNodeIndex(PhaseType::B), matrixNodeIndex(1, 1)); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), + mVirtualNodes[1]->matrixNodeIndex(PhaseType::C), matrixNodeIndex(1, 2)); + } +} + +void EMT::Ph3::Transformer::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); +} + +void EMT::Ph3::Transformer::mnaParentPreStep(Real time, Int timeStepCount) { + mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void EMT::Ph3::Transformer::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void EMT::Ph3::Transformer::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + mnaCompUpdateVoltage(**leftVector); + mnaCompUpdateCurrent(**leftVector); +} + +void EMT::Ph3::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { + **mIntfCurrent = mSubInductor->intfCurrent(); +} + +void EMT::Ph3::Transformer::mnaCompUpdateVoltage(const Matrix& leftVector) { + // v1 - v0 + **mIntfVoltage = Matrix::Zero(3, 1); + if (terminalNotGrounded(1)) { + (**mIntfVoltage)(0, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 0)); + (**mIntfVoltage)(1, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 1)); + (**mIntfVoltage)(2, 0) = Math::realFromVectorElement(leftVector, matrixNodeIndex(1, 2)); + } + if (terminalNotGrounded(0)) { + (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 0)); + (**mIntfVoltage)(1, 0) = (**mIntfVoltage)(1, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 1)); + (**mIntfVoltage)(2, 0) = (**mIntfVoltage)(2, 0) - Math::realFromVectorElement(leftVector, matrixNodeIndex(0, 2)); + } +} + diff --git a/dpsim-models/src/SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp b/dpsim-models/src/SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp index 7515d1d037..92c5c242e8 100644 --- a/dpsim-models/src/SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp +++ b/dpsim-models/src/SP/SP_Ph1_AvVoltageSourceInverterDQ.cpp @@ -28,8 +28,8 @@ SP::Ph1::AvVoltageSourceInverterDQ::AvVoltageSourceInverterDQ(String uid, String mPowerctrlStates(mAttributes->createDynamic("powerctrl_states")) { if (withTrafo) { setVirtualNodeNumber(4); - mConnectionTransformer = SP::Ph1::Transformer::make(**mName + "_trans", **mName + "_trans", mLogLevel, false); - addMNASubComponent(mConnectionTransformer, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + mConnectionTransformer = SP::Ph1::Transformer::make(**mName + "_trans", **mName + "_trans", mLogLevel); + addMNASubComponent(mConnectionTransformer, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); } else { setVirtualNodeNumber(3); } @@ -97,7 +97,7 @@ void SP::Ph1::AvVoltageSourceInverterDQ::setParameters(Real sysOmega, Real sysVo } void SP::Ph1::AvVoltageSourceInverterDQ::setTransformerParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, - Real ratioAbs, Real ratioPhase, Real resistance, Real inductance) { + Real ratioAbs, Real ratioPhase, Real resistance, Real inductance) { Base::AvVoltageSourceInverterDQ::setTransformerParameters(nomVoltageEnd1, nomVoltageEnd2, ratedPower, ratioAbs, ratioPhase, resistance, inductance); @@ -109,8 +109,7 @@ void SP::Ph1::AvVoltageSourceInverterDQ::setTransformerParameters(Real nomVoltag SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [ ] Phase Shift={} [deg]", mTransformerRatioAbs, mTransformerRatioPhase); if (mWithConnectionTransformer) - // TODO: resistive losses neglected so far (mWithResistiveLosses=false) - mConnectionTransformer->setParameters(mTransformerNominalVoltageEnd1, mTransformerNominalVoltageEnd2, mTransformerRatedPower, mTransformerRatioAbs, mTransformerRatioPhase, mTransformerResistance, mTransformerInductance); + mConnectionTransformer->setParameters(mTransformerNominalVoltageEnd1, mTransformerNominalVoltageEnd2, mTransformerRatioAbs, mTransformerRatioPhase, mTransformerResistance, mTransformerInductance); } void SP::Ph1::AvVoltageSourceInverterDQ::setControllerParameters(Real Kp_pll, Real Ki_pll, diff --git a/dpsim-models/src/SP/SP_Ph1_Capacitor.cpp b/dpsim-models/src/SP/SP_Ph1_Capacitor.cpp index 877a7fc2fe..ddba32069d 100644 --- a/dpsim-models/src/SP/SP_Ph1_Capacitor.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Capacitor.cpp @@ -49,6 +49,7 @@ void SP::Ph1::Capacitor::initializeFromNodesAndTerminals(Real frequency) { Logger::phasorToString((**mIntfCurrent)(0, 0)), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } // #### MNA section #### @@ -62,6 +63,7 @@ void SP::Ph1::Capacitor::mnaCompInitialize(Real omega, Real timeStep, Attribute< "\n--- MNA initialization finished ---", Logger::phasorToString((**mIntfVoltage)(0, 0)), Logger::phasorToString((**mIntfCurrent)(0, 0))); + mSLog->flush(); } void SP::Ph1::Capacitor::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { @@ -105,7 +107,7 @@ void SP::Ph1::Capacitor::mnaCompPostStep(Real time, Int timeStepCount, Attribute void SP::Ph1::Capacitor::mnaCompUpdateVoltage(const Matrix& leftVector) { // v1 - v0 - **mIntfVoltage = Matrix::Zero(3, 1); + **mIntfVoltage = Matrix::Zero(1, 1); if (terminalNotGrounded(1)) { (**mIntfVoltage)(0, 0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); } diff --git a/dpsim-models/src/SP/SP_Ph1_Inductor.cpp b/dpsim-models/src/SP/SP_Ph1_Inductor.cpp index 3a092bf14b..3aefd28c9f 100644 --- a/dpsim-models/src/SP/SP_Ph1_Inductor.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Inductor.cpp @@ -45,6 +45,7 @@ void SP::Ph1::Inductor::initializeFromNodesAndTerminals(Real frequency) { Logger::phasorToString((**mIntfCurrent)(0, 0)), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } // #### MNA section #### @@ -59,6 +60,7 @@ void SP::Ph1::Inductor::mnaCompInitialize(Real omega, Real timeStep, Attributeflush(); } void SP::Ph1::Inductor::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { @@ -87,9 +89,12 @@ void SP::Ph1::Inductor::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMat SPDLOG_LOGGER_INFO(mSLog, "Add {:e}+j{:e} to system at ({:d},{:d})", -mSusceptance.real(), -mSusceptance.imag(), matrixNodeIndex(1), matrixNodeIndex(0)); } + mSLog->flush(); } -void SP::Ph1::Inductor::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { +void SP::Ph1::Inductor::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { attributeDependencies.push_back(leftVector); modifiedAttributes.push_back(mIntfVoltage); modifiedAttributes.push_back(mIntfCurrent); @@ -102,7 +107,7 @@ void SP::Ph1::Inductor::mnaCompPostStep(Real time, Int timeStepCount, Attribute< void SP::Ph1::Inductor::mnaCompUpdateVoltage(const Matrix& leftVector) { // v1 - v0 - **mIntfVoltage = Matrix::Zero(3, 1); + **mIntfVoltage = Matrix::Zero(1, 1); if (terminalNotGrounded(1)) { (**mIntfVoltage)(0, 0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); } diff --git a/dpsim-models/src/SP/SP_Ph1_PiLine.cpp b/dpsim-models/src/SP/SP_Ph1_PiLine.cpp index 4203874973..4c3d98afc0 100644 --- a/dpsim-models/src/SP/SP_Ph1_PiLine.cpp +++ b/dpsim-models/src/SP/SP_Ph1_PiLine.cpp @@ -22,7 +22,6 @@ SP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); mSLog->flush(); - setVirtualNodeNumber(1); setTerminalNumber(2); **mIntfVoltage = MatrixComp::Zero(1, 1); **mIntfCurrent = MatrixComp::Zero(1, 1); @@ -31,40 +30,6 @@ SP::Ph1::PiLine::PiLine(String uid, String name, Logger::Level logLevel) **mReactivePowerBranch = Matrix::Zero(2,1); } -void SP::Ph1::PiLine::setParameters(Real resistance, Real inductance, Real capacitance, Real conductance) { - - **mSeriesRes = resistance; - **mSeriesInd = inductance; - SPDLOG_LOGGER_INFO(mSLog, "Resistance={} [Ohm] Inductance={} [H]", **mSeriesRes, **mSeriesInd); - - if(capacitance > 0){ - **mParallelCap = capacitance; - }else{ - **mParallelCap = 1e-12; - SPDLOG_LOGGER_WARN(mSLog, "Zero value for Capacitance, setting default value of C={} [F]", **mParallelCap); - } - if(conductance > 0){ - **mParallelCond = conductance; - }else{ - if (mBehaviour == Behaviour::Initialization) - **mParallelCond = (conductance >= 0) ? conductance : 1e-6; // init mode for initFromPowerFlow of mna system components - else - **mParallelCond = (conductance > 0) ? conductance : 1e-6; - SPDLOG_LOGGER_WARN(mSLog, "Zero value for Conductance, setting default value of G={} [S]", **mParallelCond); - } - SPDLOG_LOGGER_INFO(mSLog, "Capacitance={} [F] Conductance={} [S]", **mParallelCap, **mParallelCond); - mSLog->flush(); - mParametersSet = true; - -} - -/// DEPRECATED: Delete method -SimPowerComp::Ptr SP::Ph1::PiLine::clone(String name) { - auto copy = PiLine::make(name, mLogLevel); - copy->setParameters(**mSeriesRes, **mSeriesInd, **mParallelCap, **mParallelCond); - return copy; -} - // #### Powerflow section #### void SP::Ph1::PiLine::setBaseVoltage(Real baseVoltage) { **mBaseVoltage = baseVoltage; @@ -99,7 +64,11 @@ void SP::Ph1::PiLine::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) { //create the element admittance matrix Complex y = Complex(1, 0) / Complex(mSeriesResPerUnit, 1. * mSeriesIndPerUnit); - Complex ys = Complex(mParallelCondPerUnit, 1. * mParallelCapPerUnit) / Complex(2, 0); + Complex ys; + if (mParallelCondPerUnit==0 && mParallelCapPerUnit == 0) + ys = Complex(0,0); + else + ys = Complex(mParallelCondPerUnit, 1. * mParallelCapPerUnit) / Complex(2, 0); //Fill the internal matrix mY_element = MatrixComp(2, 2); @@ -116,7 +85,6 @@ void SP::Ph1::PiLine::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) { std::stringstream ss; ss << "Line>>" << this->name() << ": infinite or nan values in the element Y at: " << i << "," << j; throw std::invalid_argument(ss.str()); - std::cout << "Line>>" << this->name() << ": infinite or nan values in the element Y at: " << i << "," << j << std::endl; } //set the circuit matrix values @@ -147,36 +115,22 @@ MatrixComp SP::Ph1::PiLine::Y_element() { void SP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { - // By default there is always a small conductance to ground to - // avoid problems with floating nodes. - **mParallelCond = (**mParallelCond >= 0) ? **mParallelCond : 1e-6; - // Static calculation Real omega = 2. * PI * frequency; Complex impedance = { **mSeriesRes, omega * **mSeriesInd }; (**mIntfVoltage)(0, 0) = initialSingleVoltage(1) - initialSingleVoltage(0); (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance; - // Initialization of virtual node - mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(0) + (**mIntfCurrent)(0, 0) * **mSeriesRes); - - // Create series sub components - mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); - mSubSeriesResistor->setParameters(**mSeriesRes); - mSubSeriesResistor->connect({ mTerminals[0]->node(), mVirtualNodes[0] }); - mSubSeriesResistor->initialize(mFrequencies); - mSubSeriesResistor->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); - - mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); - mSubSeriesInductor->setParameters(**mSeriesInd); - mSubSeriesInductor->connect({ mVirtualNodes[0], mTerminals[1]->node() }); - mSubSeriesInductor->initialize(mFrequencies); - mSubSeriesInductor->initializeFromNodesAndTerminals(frequency); - addMNASubComponent(mSubSeriesInductor, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + // Create series rl sub component + mSubSeriesElement = std::make_shared(**mName + "_ResIndSeries", mLogLevel); + mSubSeriesElement->connect({ mTerminals[0]->node(), mTerminals[1]->node() }); + mSubSeriesElement->setParameters(**mSeriesRes, **mSeriesInd); + mSubSeriesElement->initialize(mFrequencies); + mSubSeriesElement->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesElement, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); // Create parallel sub components - if (**mParallelCond >= 0) { + if (**mParallelCond > 0) { mSubParallelResistor0 = std::make_shared(**mName + "_con0", mLogLevel); mSubParallelResistor0->setParameters(2. / **mParallelCond); mSubParallelResistor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); @@ -192,7 +146,7 @@ void SP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { addMNASubComponent(mSubParallelResistor1, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); } - if (**mParallelCap >= 0) { + if (**mParallelCap > 0) { mSubParallelCapacitor0 = std::make_shared(**mName + "_cap0", mLogLevel); mSubParallelCapacitor0->setParameters(**mParallelCap / 2.); mSubParallelCapacitor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); @@ -214,13 +168,11 @@ void SP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { "\nCurrent: {:s}" "\nTerminal 0 voltage: {:s}" "\nTerminal 1 voltage: {:s}" - "\nVirtual Node 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)), - Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); + Logger::phasorToString(initialSingleVoltage(1))); } void SP::Ph1::PiLine::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { @@ -243,16 +195,18 @@ void SP::Ph1::PiLine::mnaCompUpdateVoltage(const Matrix& leftVector) { } void SP::Ph1::PiLine::mnaCompUpdateCurrent(const Matrix& leftVector) { - (**mIntfCurrent)(0, 0) = mSubSeriesInductor->intfCurrent()(0, 0); + (**mIntfCurrent)(0, 0) = mSubSeriesElement->intfCurrent()(0, 0); } MNAInterface::List SP::Ph1::PiLine::mnaTearGroundComponents() { MNAInterface::List gndComponents; - gndComponents.push_back(mSubParallelResistor0); - gndComponents.push_back(mSubParallelResistor1); + if (**mParallelCond > 0) { + gndComponents.push_back(mSubParallelResistor0); + gndComponents.push_back(mSubParallelResistor1); + } - if (**mParallelCap >= 0) { + if (**mParallelCap > 0) { gndComponents.push_back(mSubParallelCapacitor0); gndComponents.push_back(mSubParallelCapacitor1); } @@ -261,21 +215,18 @@ MNAInterface::List SP::Ph1::PiLine::mnaTearGroundComponents() { } void SP::Ph1::PiLine::mnaTearInitialize(Real omega, Real timeStep) { - mSubSeriesResistor->mnaTearSetIdx(mTearIdx); - mSubSeriesResistor->mnaTearInitialize(omega, timeStep); - mSubSeriesInductor->mnaTearSetIdx(mTearIdx); - mSubSeriesInductor->mnaTearInitialize(omega, timeStep); + mSubSeriesElement->mnaTearSetIdx(mTearIdx); + mSubSeriesElement->mnaTearInitialize(omega, timeStep); } void SP::Ph1::PiLine::mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) { - mSubSeriesResistor->mnaTearApplyMatrixStamp(tearMatrix); - mSubSeriesInductor->mnaTearApplyMatrixStamp(tearMatrix); + mSubSeriesElement->mnaTearApplyMatrixStamp(tearMatrix); } void SP::Ph1::PiLine::mnaTearApplyVoltageStamp(Matrix& voltageVector) { - mSubSeriesInductor->mnaTearApplyVoltageStamp(voltageVector); + mSubSeriesElement->mnaTearApplyVoltageStamp(voltageVector); } void SP::Ph1::PiLine::mnaTearPostStep(Complex voltage, Complex current) { - mSubSeriesInductor->mnaTearPostStep(voltage - current * **mSeriesRes, current); + mSubSeriesElement->mnaTearPostStep(voltage - current * **mSeriesRes, current); } diff --git a/dpsim-models/src/SP/SP_Ph1_PiLine_deprecated.cpp b/dpsim-models/src/SP/SP_Ph1_PiLine_deprecated.cpp new file mode 100644 index 0000000000..4203874973 --- /dev/null +++ b/dpsim-models/src/SP/SP_Ph1_PiLine_deprecated.cpp @@ -0,0 +1,281 @@ +/* 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::PiLine::PiLine(String uid, String name, Logger::Level logLevel) + : Base::Ph1::PiLine(mAttributes), CompositePowerComp(uid, name, false, true, logLevel), + mBaseVoltage(mAttributes->create("base_Voltage")), + mCurrent(mAttributes->create("current_vector")), + mActivePowerBranch(mAttributes->create("p_branch_vector")), + mReactivePowerBranch(mAttributes->create("q_branch_vector")), + mActivePowerInjection(mAttributes->create("p_inj")), + mReactivePowerInjection(mAttributes->create("q_inj")) { + + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + mSLog->flush(); + + setVirtualNodeNumber(1); + setTerminalNumber(2); + **mIntfVoltage = MatrixComp::Zero(1, 1); + **mIntfCurrent = MatrixComp::Zero(1, 1); + **mCurrent = MatrixComp::Zero(2,1); + **mActivePowerBranch = Matrix::Zero(2,1); + **mReactivePowerBranch = Matrix::Zero(2,1); +} + +void SP::Ph1::PiLine::setParameters(Real resistance, Real inductance, Real capacitance, Real conductance) { + + **mSeriesRes = resistance; + **mSeriesInd = inductance; + SPDLOG_LOGGER_INFO(mSLog, "Resistance={} [Ohm] Inductance={} [H]", **mSeriesRes, **mSeriesInd); + + if(capacitance > 0){ + **mParallelCap = capacitance; + }else{ + **mParallelCap = 1e-12; + SPDLOG_LOGGER_WARN(mSLog, "Zero value for Capacitance, setting default value of C={} [F]", **mParallelCap); + } + if(conductance > 0){ + **mParallelCond = conductance; + }else{ + if (mBehaviour == Behaviour::Initialization) + **mParallelCond = (conductance >= 0) ? conductance : 1e-6; // init mode for initFromPowerFlow of mna system components + else + **mParallelCond = (conductance > 0) ? conductance : 1e-6; + SPDLOG_LOGGER_WARN(mSLog, "Zero value for Conductance, setting default value of G={} [S]", **mParallelCond); + } + SPDLOG_LOGGER_INFO(mSLog, "Capacitance={} [F] Conductance={} [S]", **mParallelCap, **mParallelCond); + mSLog->flush(); + mParametersSet = true; + +} + +/// DEPRECATED: Delete method +SimPowerComp::Ptr SP::Ph1::PiLine::clone(String name) { + auto copy = PiLine::make(name, mLogLevel); + copy->setParameters(**mSeriesRes, **mSeriesInd, **mParallelCap, **mParallelCond); + return copy; +} + +// #### Powerflow section #### +void SP::Ph1::PiLine::setBaseVoltage(Real baseVoltage) { + **mBaseVoltage = baseVoltage; +} + +void SP::Ph1::PiLine::calculatePerUnitParameters(Real baseApparentPower, Real baseOmega) { + SPDLOG_LOGGER_INFO(mSLog, "#### Calculate Per Unit Parameters for {}", **mName); + mBaseApparentPower = baseApparentPower; + mBaseOmega = baseOmega; + SPDLOG_LOGGER_INFO(mSLog, "Base Power={} [VA] Base Omega={} [1/s]", baseApparentPower, baseOmega); + + mBaseImpedance = (**mBaseVoltage * **mBaseVoltage) / mBaseApparentPower; + mBaseAdmittance = 1.0 / mBaseImpedance; + mBaseInductance = mBaseImpedance / mBaseOmega; + mBaseCapacitance = 1.0 / mBaseOmega / mBaseImpedance; + mBaseCurrent = baseApparentPower / (**mBaseVoltage * sqrt(3)); // I_base=(S_threephase/3)/(V_line_to_line/sqrt(3)) + SPDLOG_LOGGER_INFO(mSLog, "Base Voltage={} [V] Base Impedance={} [Ohm]", **mBaseVoltage, mBaseImpedance); + + mSeriesResPerUnit = **mSeriesRes / mBaseImpedance; + mSeriesIndPerUnit = **mSeriesInd / mBaseInductance; + mParallelCapPerUnit = **mParallelCap / mBaseCapacitance; + mParallelCondPerUnit = **mParallelCond / mBaseAdmittance; + + SPDLOG_LOGGER_INFO(mSLog, "Resistance={} [pu] Reactance={} [pu]", mSeriesResPerUnit, 1. * mSeriesIndPerUnit); + SPDLOG_LOGGER_INFO(mSLog, "Susceptance={} [pu] Conductance={} [pu]", 1. * mParallelCapPerUnit, mParallelCondPerUnit); + mSLog->flush(); +} + +void SP::Ph1::PiLine::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) { + int bus1 = this->matrixNodeIndex(0); + int bus2 = this->matrixNodeIndex(1); + + //create the element admittance matrix + Complex y = Complex(1, 0) / Complex(mSeriesResPerUnit, 1. * mSeriesIndPerUnit); + Complex ys = Complex(mParallelCondPerUnit, 1. * mParallelCapPerUnit) / Complex(2, 0); + + //Fill the internal matrix + mY_element = MatrixComp(2, 2); + mY_element(0, 0) = y + ys; + mY_element(0, 1) = -y; + mY_element(1, 0) = -y; + mY_element(1, 1) = y + ys; + + //check for inf or nan + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + if (std::isinf(mY_element.coeff(i, j).real()) || std::isinf(mY_element.coeff(i, j).imag())) { + std::cout << mY_element << std::endl; + std::stringstream ss; + ss << "Line>>" << this->name() << ": infinite or nan values in the element Y at: " << i << "," << j; + throw std::invalid_argument(ss.str()); + std::cout << "Line>>" << this->name() << ": infinite or nan values in the element Y at: " << i << "," << j << std::endl; + } + + //set the circuit matrix values + Y.coeffRef(bus1, bus1) += mY_element.coeff(0, 0); + Y.coeffRef(bus1, bus2) += mY_element.coeff(0, 1); + Y.coeffRef(bus2, bus2) += mY_element.coeff(1, 1); + Y.coeffRef(bus2, bus1) += mY_element.coeff(1, 0); + + SPDLOG_LOGGER_INFO(mSLog, "#### PF Y matrix stamping #### "); + SPDLOG_LOGGER_INFO(mSLog, "{}", mY_element); + mSLog->flush(); +} + +void SP::Ph1::PiLine::updateBranchFlow(VectorComp& current, VectorComp& powerflow) { + **mCurrent = current * mBaseCurrent; + **mActivePowerBranch = powerflow.real()*mBaseApparentPower; + **mReactivePowerBranch = powerflow.imag()*mBaseApparentPower; +} + +void SP::Ph1::PiLine::storeNodalInjection(Complex powerInjection) { + **mActivePowerInjection = std::real(powerInjection)*mBaseApparentPower; + **mReactivePowerInjection = std::imag(powerInjection)*mBaseApparentPower; +} + +MatrixComp SP::Ph1::PiLine::Y_element() { + return mY_element; +} + +void SP::Ph1::PiLine::initializeFromNodesAndTerminals(Real frequency) { + + // By default there is always a small conductance to ground to + // avoid problems with floating nodes. + **mParallelCond = (**mParallelCond >= 0) ? **mParallelCond : 1e-6; + + // Static calculation + Real omega = 2. * PI * frequency; + Complex impedance = { **mSeriesRes, omega * **mSeriesInd }; + (**mIntfVoltage)(0, 0) = initialSingleVoltage(1) - initialSingleVoltage(0); + (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance; + + // Initialization of virtual node + mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(0) + (**mIntfCurrent)(0, 0) * **mSeriesRes); + + // Create series sub components + mSubSeriesResistor = std::make_shared(**mName + "_res", mLogLevel); + mSubSeriesResistor->setParameters(**mSeriesRes); + mSubSeriesResistor->connect({ mTerminals[0]->node(), mVirtualNodes[0] }); + mSubSeriesResistor->initialize(mFrequencies); + mSubSeriesResistor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesResistor, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubSeriesInductor = std::make_shared(**mName + "_ind", mLogLevel); + mSubSeriesInductor->setParameters(**mSeriesInd); + mSubSeriesInductor->connect({ mVirtualNodes[0], mTerminals[1]->node() }); + mSubSeriesInductor->initialize(mFrequencies); + mSubSeriesInductor->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubSeriesInductor, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // Create parallel sub components + if (**mParallelCond >= 0) { + mSubParallelResistor0 = std::make_shared(**mName + "_con0", mLogLevel); + mSubParallelResistor0->setParameters(2. / **mParallelCond); + mSubParallelResistor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); + mSubParallelResistor0->initialize(mFrequencies); + mSubParallelResistor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor0, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + + mSubParallelResistor1 = std::make_shared(**mName + "_con1", mLogLevel); + mSubParallelResistor1->setParameters(2. / **mParallelCond); + mSubParallelResistor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); + mSubParallelResistor1->initialize(mFrequencies); + mSubParallelResistor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelResistor1, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, false); + } + + if (**mParallelCap >= 0) { + mSubParallelCapacitor0 = std::make_shared(**mName + "_cap0", mLogLevel); + mSubParallelCapacitor0->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor0->connect(SimNode::List{ SimNode::GND, mTerminals[0]->node() }); + mSubParallelCapacitor0->initialize(mFrequencies); + mSubParallelCapacitor0->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor0, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + mSubParallelCapacitor1 = std::make_shared(**mName + "_cap1", mLogLevel); + mSubParallelCapacitor1->setParameters(**mParallelCap / 2.); + mSubParallelCapacitor1->connect(SimNode::List{ SimNode::GND, mTerminals[1]->node() }); + mSubParallelCapacitor1->initialize(mFrequencies); + mSubParallelCapacitor1->initializeFromNodesAndTerminals(frequency); + addMNASubComponent(mSubParallelCapacitor1, MNA_SUBCOMP_TASK_ORDER::NO_TASK, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + } + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\nVirtual Node 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::phasorToString((**mIntfVoltage)(0, 0)), + Logger::phasorToString((**mIntfCurrent)(0, 0)), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1)), + Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); +} + +void SP::Ph1::PiLine::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void SP::Ph1::PiLine::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + this->mnaUpdateVoltage(**leftVector); + this->mnaUpdateCurrent(**leftVector); +} + +void SP::Ph1::PiLine::mnaCompUpdateVoltage(const Matrix& leftVector) { + (**mIntfVoltage)(0, 0) = 0; + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0, 0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::complexFromVectorElement(leftVector, matrixNodeIndex(0)); +} + +void SP::Ph1::PiLine::mnaCompUpdateCurrent(const Matrix& leftVector) { + (**mIntfCurrent)(0, 0) = mSubSeriesInductor->intfCurrent()(0, 0); +} + +MNAInterface::List SP::Ph1::PiLine::mnaTearGroundComponents() { + MNAInterface::List gndComponents; + + gndComponents.push_back(mSubParallelResistor0); + gndComponents.push_back(mSubParallelResistor1); + + if (**mParallelCap >= 0) { + gndComponents.push_back(mSubParallelCapacitor0); + gndComponents.push_back(mSubParallelCapacitor1); + } + + return gndComponents; +} + +void SP::Ph1::PiLine::mnaTearInitialize(Real omega, Real timeStep) { + mSubSeriesResistor->mnaTearSetIdx(mTearIdx); + mSubSeriesResistor->mnaTearInitialize(omega, timeStep); + mSubSeriesInductor->mnaTearSetIdx(mTearIdx); + mSubSeriesInductor->mnaTearInitialize(omega, timeStep); +} + +void SP::Ph1::PiLine::mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) { + mSubSeriesResistor->mnaTearApplyMatrixStamp(tearMatrix); + mSubSeriesInductor->mnaTearApplyMatrixStamp(tearMatrix); +} + +void SP::Ph1::PiLine::mnaTearApplyVoltageStamp(Matrix& voltageVector) { + mSubSeriesInductor->mnaTearApplyVoltageStamp(voltageVector); +} + +void SP::Ph1::PiLine::mnaTearPostStep(Complex voltage, Complex current) { + mSubSeriesInductor->mnaTearPostStep(voltage - current * **mSeriesRes, current); +} diff --git a/dpsim-models/src/SP/SP_Ph1_ResIndSeries.cpp b/dpsim-models/src/SP/SP_Ph1_ResIndSeries.cpp new file mode 100644 index 0000000000..32f00ad63d --- /dev/null +++ b/dpsim-models/src/SP/SP_Ph1_ResIndSeries.cpp @@ -0,0 +1,137 @@ +/* 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::ResIndSeries::ResIndSeries(String uid, String name, Logger::Level logLevel) + : MNASimPowerComp(uid, name, false, true, logLevel), + mInductance(mAttributes->create("L")), + mResistance(mAttributes->create("R")) { + setTerminalNumber(2); + **mIntfVoltage = MatrixComp::Zero(1, 1); + **mIntfCurrent = MatrixComp::Zero(1, 1); +} + +SimPowerComp::Ptr SP::Ph1::ResIndSeries::clone(String name) { + auto copy = ResIndSeries::make(name, mLogLevel); + copy->setParameters(**mResistance, **mInductance); + return copy; +} + +void SP::Ph1::ResIndSeries::setParameters(Real resistance, Real inductance) { + **mResistance = resistance; + **mInductance = inductance; + + //check initial value of inductance + if (**mInductance==0.0) { + std::string err = "Inductance of " + this->name() + " can not be zero!"; + throw std::invalid_argument(err); + } +} + +void SP::Ph1::ResIndSeries::initializeFromNodesAndTerminals(Real frequency) { + + Real omega = 2. * PI * frequency; + mImpedance = { **mResistance, omega * **mInductance }; + (**mIntfVoltage)(0,0) = initialSingleVoltage(1) - initialSingleVoltage(0); + (**mIntfCurrent)(0,0) = (**mIntfVoltage)(0,0) / mImpedance; + + mSLog->info( + "\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))); + mSLog->flush(); +} + +// #### MNA section #### + +void SP::Ph1::ResIndSeries::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); + **mRightVector = Matrix::Zero(0, 0); + + mSLog->info( + "\n--- MNA initialization ---" + "\nInitial voltage {:s}" + "\nInitial current {:s}" + "\n--- MNA initialization finished ---", + Logger::phasorToString((**mIntfVoltage)(0, 0)), + Logger::phasorToString((**mIntfCurrent)(0, 0))); +} + +void SP::Ph1::ResIndSeries::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { + Complex conductance = 1. / mImpedance; + + for (UInt freq = 0; freq < mNumFreqs; freq++) { + // Set diagonal entries + if (terminalNotGrounded(0)) + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), matrixNodeIndex(0), conductance, mNumFreqs, freq); + if (terminalNotGrounded(1)) + // Set off diagonal entries + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), matrixNodeIndex(1), conductance, mNumFreqs, freq); + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), matrixNodeIndex(1), -conductance, mNumFreqs, freq); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), matrixNodeIndex(0), -conductance, mNumFreqs, freq); + } + + mSLog->info("-- Stamp frequency {:d} ---", freq); + if (terminalNotGrounded(0)) + mSLog->info("Add {:s} to system at ({:d},{:d})", Logger::complexToString(conductance), matrixNodeIndex(0), matrixNodeIndex(0)); + if (terminalNotGrounded(1)) + mSLog->info("Add {:s} to system at ({:d},{:d})", Logger::complexToString(conductance), matrixNodeIndex(1), matrixNodeIndex(1)); + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + mSLog->info("Add {:s} to system at ({:d},{:d})", Logger::complexToString(-conductance), matrixNodeIndex(0), matrixNodeIndex(1)); + mSLog->info("Add {:s} to system at ({:d},{:d})", Logger::complexToString(-conductance), matrixNodeIndex(1), matrixNodeIndex(0)); + } + } +} + +void SP::Ph1::ResIndSeries::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void SP::Ph1::ResIndSeries::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + this->mnaUpdateVoltage(**leftVector); + this->mnaUpdateCurrent(**leftVector); +} + +void SP::Ph1::ResIndSeries::mnaCompUpdateVoltage(const Matrix& leftVector) { + // v1 - v0 + for (UInt freq = 0; freq < mNumFreqs; freq++) { + (**mIntfVoltage)(0,freq) = 0; + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0,freq) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1), mNumFreqs, freq); + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0,freq) = (**mIntfVoltage)(0,freq) - Math::complexFromVectorElement(leftVector, matrixNodeIndex(0), mNumFreqs, freq); + + SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}", Logger::phasorToString((**mIntfVoltage)(0,freq))); + } +} + +void SP::Ph1::ResIndSeries::mnaCompUpdateCurrent(const Matrix& leftVector) { + for (UInt freq = 0; freq < mNumFreqs; freq++) { + (**mIntfCurrent)(0,freq) = (**mIntfVoltage)(0,freq) / mImpedance; + SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}", Logger::phasorToString((**mIntfCurrent)(0,freq))); + } +} + +// #### Tear Methods #### +void SP::Ph1::ResIndSeries::mnaTearApplyMatrixStamp(SparseMatrixRow& tearMatrix) { + Math::addToMatrixElement(tearMatrix, mTearIdx, mTearIdx, mImpedance); +} diff --git a/dpsim-models/src/SP/SP_Ph1_Resistor.cpp b/dpsim-models/src/SP/SP_Ph1_Resistor.cpp index b44f8feefa..8f917aa4c0 100644 --- a/dpsim-models/src/SP/SP_Ph1_Resistor.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Resistor.cpp @@ -43,6 +43,7 @@ void SP::Ph1::Resistor::initializeFromNodesAndTerminals(Real frequency) { Logger::phasorToString((**mIntfCurrent)(0, 0)), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } // #### Powerflow section #### @@ -95,6 +96,7 @@ void SP::Ph1::Resistor::mnaCompInitialize(Real omega, Real timeStep, Attributeflush(); } void SP::Ph1::Resistor::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { @@ -122,6 +124,7 @@ void SP::Ph1::Resistor::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMat SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(-conductance), matrixNodeIndex(1), matrixNodeIndex(0)); } } + mSLog->flush(); } void SP::Ph1::Resistor::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { diff --git a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp index ef67009d4d..16bdc7e585 100644 --- a/dpsim-models/src/SP/SP_Ph1_Transformer.cpp +++ b/dpsim-models/src/SP/SP_Ph1_Transformer.cpp @@ -11,23 +11,20 @@ using namespace CPS; // #### General #### -SP::Ph1::Transformer::Transformer(String uid, String name, Logger::Level logLevel, Bool withResistiveLosses) - : Base::Ph1::Transformer(mAttributes), CompositePowerComp(uid, name, true, true, logLevel), +SP::Ph1::Transformer::Transformer(String uid, String name, Logger::Level logLevel) + : Base::Ph1::Transformer(mAttributes), MNASimPowerComp(uid, name, false, true, logLevel), mBaseVoltage(mAttributes->create("base_Voltage")), mCurrent(mAttributes->create("current_vector")), mActivePowerBranch(mAttributes->create("p_branch_vector")), mReactivePowerBranch(mAttributes->create("q_branch_vector")), mActivePowerInjection(mAttributes->create("p_inj")), mReactivePowerInjection(mAttributes->create("q_inj")) { - if (withResistiveLosses) - setVirtualNodeNumber(3); - else - setVirtualNodeNumber(2); + + setTerminalNumber(2); SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); **mIntfVoltage = MatrixComp::Zero(1, 1); **mIntfCurrent = MatrixComp::Zero(1, 1); - setTerminalNumber(2); **mCurrent = MatrixComp::Zero(2,1); **mActivePowerBranch = Matrix::Zero(2,1); @@ -44,7 +41,7 @@ void SP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1={} [V] Nominal Voltage End 2={} [V]", **mNominalVoltageEnd1, **mNominalVoltageEnd2); SPDLOG_LOGGER_INFO(mSLog, "Resistance={} [Ohm] Inductance={} [H] (referred to primary side)", **mResistance, **mInductance); SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [/] Phase Shift={} [deg]", std::abs(**mRatio), std::arg(**mRatio)); - SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower); + SPDLOG_LOGGER_INFO(mSLog, "Rated Power={} [W]", **mRatedPower); mRatioAbs = std::abs(**mRatio); mRatioPhase = std::arg(**mRatio); @@ -56,24 +53,17 @@ void SP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd Real ratioPhase, Real resistance, Real inductance) { **mRatedPower = ratedPower; - SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower); + SPDLOG_LOGGER_INFO(mSLog, "Rated Power={} [W]", **mRatedPower); SP::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs, ratioPhase, resistance, inductance); -} - - -/// DEPRECATED: Delete method -SimPowerComp::Ptr SP::Ph1::Transformer::clone(String name) { - auto copy = Transformer::make(name, mLogLevel); - copy->setParameters(**mNominalVoltageEnd1, **mNominalVoltageEnd2, **mRatedPower, - std::abs(**mRatio), std::arg(**mRatio), **mResistance, **mInductance); - return copy; + mSLog->flush(); } void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { mNominalOmega = 2. * PI * frequency; mReactance = mNominalOmega * **mInductance; - SPDLOG_LOGGER_INFO(mSLog, "Reactance={} [Ohm] (referred to primary side)", mReactance); + mImpedance = { **mResistance, mReactance }; + SPDLOG_LOGGER_INFO(mSLog, "Impedance={} [Ohm] (referred to primary side)", mImpedance); // Component parameters are referred to higher voltage side. // Switch terminals to have terminal 0 at higher voltage side @@ -93,94 +83,22 @@ void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", mRatioAbs, mRatioPhase); } - // Set initial voltage of virtual node in between - mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(1) * **mRatio); - // Static calculations from load flow data - Complex impedance = { **mResistance, mReactance }; - (**mIntfVoltage)(0, 0) = mVirtualNodes[0]->initialSingleVoltage() - initialSingleVoltage(0); - (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance; - - // Create series sub components - mSubInductor = std::make_shared(**mUID + "_ind", **mName + "_ind", Logger::Level::off); - mSubInductor->setParameters(**mInductance); - addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - if (mNumVirtualNodes == 3) { - mVirtualNodes[2]->setInitialVoltage(initialSingleVoltage(0)); - mSubResistor = std::make_shared(**mUID + "_res", **mName + "_res", Logger::Level::off); - mSubResistor->setParameters(**mResistance); - mSubResistor->connect({ node(0), mVirtualNodes[2] }); - mSubInductor->connect({ mVirtualNodes[2], mVirtualNodes[0] }); - addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - } else { - mSubInductor->connect({ node(0), mVirtualNodes[0] }); - } - - // Create parallel sub components for init and mna behaviour - if (mBehaviour == TopologicalPowerComp::Behaviour::Initialization || mBehaviour == TopologicalPowerComp::Behaviour::MNASimulation) { - - Real pSnub = P_SNUB_TRANSFORMER * **mRatedPower; - Real qSnub = Q_SNUB_TRANSFORMER * **mRatedPower; - - // A snubber conductance is added on the higher voltage side - mSnubberResistance1 = std::pow(std::abs(**mNominalVoltageEnd1),2) / pSnub; - mSubSnubResistor1 = std::make_shared(**mName + "_snub_res1", mLogLevel); - mSubSnubResistor1->setParameters(mSnubberResistance1); - mSubSnubResistor1->connect({ node(0), SP::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]", node(0)->name(), Logger::realToString(mSnubberResistance1)); - mSubSnubResistor1->setBaseVoltage(**mNominalVoltageEnd1); - addMNASubComponent(mSubSnubResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - // A snubber conductance is added on the lower voltage side - mSnubberResistance2 = std::pow(std::abs(**mNominalVoltageEnd2),2) / pSnub; - mSubSnubResistor2 = std::make_shared(**mName + "_snub_res2", mLogLevel); - mSubSnubResistor2->setParameters(mSnubberResistance2); - mSubSnubResistor2->connect({ node(1), SP::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]", node(1)->name(), Logger::realToString(mSnubberResistance2)); - mSubSnubResistor2->setBaseVoltage(**mNominalVoltageEnd2); - addMNASubComponent(mSubSnubResistor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - - // // A snubber capacitance is added to higher voltage side (not used as capacitor at high voltage side made it worse) - // mSnubberCapacitance1 = qSnub / std::pow(std::abs(mNominalVoltageEnd1),2) / mNominalOmega; - // mSubSnubCapacitor1 = std::make_shared(**mName + "_snub_cap1", mLogLevel); - // mSubSnubCapacitor1->setParameters(mSnubberCapacitance1); - // mSubSnubCapacitor1->connect({ node(0), SP::SimNode::GND }); - // SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 1 (connected to higher voltage side {}) = \n{} [F] \n ", node(0)->name(), Logger::realToString(mSnubberCapacitance1)); - // mSubSnubCapacitor1->setBaseVoltage(mNominalVoltageEnd1); - // mSubComponents.push_back(mSubSnubCapacitor1); - - // A snubber capacitance is added to lower voltage side - mSnubberCapacitance2 = qSnub / std::pow(std::abs(**mNominalVoltageEnd2),2) / mNominalOmega; - mSubSnubCapacitor2 = std::make_shared(**mName + "_snub_cap2", mLogLevel); - mSubSnubCapacitor2->setParameters(mSnubberCapacitance2); - mSubSnubCapacitor2->connect({ node(1), SP::SimNode::GND }); - SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]", node(1)->name(), Logger::realToString(mSnubberCapacitance2)); - mSubSnubCapacitor2->setBaseVoltage(**mNominalVoltageEnd2); - addMNASubComponent(mSubSnubCapacitor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); - } - - // Initialize electrical subcomponents - SPDLOG_LOGGER_INFO(mSLog, "Electrical subcomponents: "); - for (auto subcomp: mSubComponents) { - SPDLOG_LOGGER_INFO(mSLog, "- {}", subcomp->name()); - subcomp->initialize(mFrequencies); - subcomp->initializeFromNodesAndTerminals(frequency); - } + (**mIntfVoltage)(0, 0) = initialSingleVoltage(0) - initialSingleVoltage(1) * **mRatio; + (**mIntfCurrent)(0, 0) = -(initialSingleVoltage(0) - initialSingleVoltage(1) * **mRatio) / mImpedance; SPDLOG_LOGGER_INFO(mSLog, "\n--- Initialization from powerflow ---" - "\nVoltage across: {:s}" - "\nCurrent: {:s}" - "\nTerminal 0 voltage: {:s}" - "\nTerminal 1 voltage: {:s}" - "\nVirtual Node 1 voltage: {:s}" + "\nVoltage across primary side: {:s}" + "\nPrimary side current flowing into node 0: {:s}" + "\nTerminal 0 voltage (HV side voltage): {:s}" + "\nTerminal 1 voltage (LV side 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)), - Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); + Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } @@ -215,16 +133,6 @@ void SP::Ph1::Transformer::calculatePerUnitParameters(Real baseApparentPower, Re mRatioAbsPerUnit = mRatioAbs / **mNominalVoltageEnd1 * **mNominalVoltageEnd2; SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [pu]", mRatioAbsPerUnit); - - // Calculate per unit parameters of subcomps - if (mSubSnubResistor1) - mSubSnubResistor1->calculatePerUnitParameters(mBaseApparentPower); - if (mSubSnubResistor2) - mSubSnubResistor2->calculatePerUnitParameters(mBaseApparentPower); - if (mSubSnubCapacitor1) - mSubSnubCapacitor1->calculatePerUnitParameters(mBaseApparentPower); - if (mSubSnubCapacitor2) - mSubSnubCapacitor2->calculatePerUnitParameters(mBaseApparentPower); } void SP::Ph1::Transformer::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) { @@ -242,7 +150,7 @@ void SP::Ph1::Transformer::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) for (int j = 0; j < 2; j++) if (std::isinf(mY_element.coeff(i, j).real()) || std::isinf(mY_element.coeff(i, j).imag())) { std::cout << mY_element << std::endl; - std::cout << "Zl:" << mLeakage << std::endl; + std::cout << "Zl:" << y << std::endl; std::cout << "tap:" << mRatioAbsPerUnit << std::endl; std::stringstream ss; ss << "Transformer>>" << this->name() << ": infinite or nan values in the element Y at: " << i << "," << j; @@ -256,15 +164,6 @@ void SP::Ph1::Transformer::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) Y.coeffRef(this->matrixNodeIndex(1), this->matrixNodeIndex(0)) += mY_element.coeff(1, 0); SPDLOG_LOGGER_INFO(mSLog, "#### Y matrix stamping: {}", mY_element); - - if (mSubSnubResistor1) - mSubSnubResistor1->pfApplyAdmittanceMatrixStamp(Y); - if (mSubSnubResistor2) - mSubSnubResistor2->pfApplyAdmittanceMatrixStamp(Y); - if (mSubSnubCapacitor1) - mSubSnubCapacitor1->pfApplyAdmittanceMatrixStamp(Y); - if (mSubSnubCapacitor2) - mSubSnubCapacitor2->pfApplyAdmittanceMatrixStamp(Y); } @@ -285,77 +184,58 @@ MatrixComp SP::Ph1::Transformer::Y_element() { } // #### MNA Section #### +void SP::Ph1::Transformer::mnaCompInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + updateMatrixNodeIndices(); -void SP::Ph1::Transformer::mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { - SPDLOG_LOGGER_INFO(mSLog, - "\nTerminal 0 connected to {:s} = sim node {:d}" - "\nTerminal 1 connected to {:s} = sim node {:d}", - mTerminals[0]->node()->name(), mTerminals[0]->node()->matrixNodeIndex(), - mTerminals[1]->node()->name(), mTerminals[1]->node()->matrixNodeIndex()); } - void SP::Ph1::Transformer::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { - // Ideal transformer equations + SPDLOG_LOGGER_INFO(mSLog, "-- Matrix Stamp ---"); if (terminalNotGrounded(0)) { - Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), mVirtualNodes[1]->matrixNodeIndex(), Complex(-1.0, 0)); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(), mVirtualNodes[0]->matrixNodeIndex(), Complex(1.0, 0)); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), matrixNodeIndex(0), 1. / mImpedance); + SPDLOG_LOGGER_INFO(mSLog, "Add {:e}+j{:e} to system at ({:d},{:d})", + (Complex(1, 0) / mImpedance).real(), (Complex(1, 0) / mImpedance).imag(), matrixNodeIndex(0), matrixNodeIndex(0)); } if (terminalNotGrounded(1)) { - Math::setMatrixElement(systemMatrix, matrixNodeIndex(1), mVirtualNodes[1]->matrixNodeIndex(), **mRatio); - Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1), - **mRatio); - } - - // Add subcomps to system matrix - for (auto subcomp: mSubComponents) - if (auto mnasubcomp = std::dynamic_pointer_cast(subcomp)) - mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix); - - if (terminalNotGrounded(0)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), - mVirtualNodes[0]->matrixNodeIndex(), mVirtualNodes[1]->matrixNodeIndex()); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), - mVirtualNodes[1]->matrixNodeIndex(), mVirtualNodes[0]->matrixNodeIndex()); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), matrixNodeIndex(1), std::pow(**mRatio,2) / mImpedance ); + SPDLOG_LOGGER_INFO(mSLog, "Add {:e}+j{:e} to system at ({:d},{:d})", + (std::pow(**mRatio,2) / mImpedance).real(), (std::pow(**mRatio,2) / mImpedance).imag(), matrixNodeIndex(1), matrixNodeIndex(1)); } - if (terminalNotGrounded(1)) { - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), - matrixNodeIndex(1), mVirtualNodes[1]->matrixNodeIndex()); - SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), - mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1)); + if (terminalNotGrounded(0) && terminalNotGrounded(1)) { + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(0), matrixNodeIndex(1), -**mRatio / mImpedance ); + SPDLOG_LOGGER_INFO(mSLog, "Add {:e}+j{:e} to system at ({:d},{:d})", + (-**mRatio / mImpedance).real(), (-**mRatio / mImpedance).imag(), matrixNodeIndex(0), matrixNodeIndex(1)); + Math::addToMatrixElement(systemMatrix, matrixNodeIndex(1), matrixNodeIndex(0), -**mRatio / mImpedance ); + SPDLOG_LOGGER_INFO(mSLog, "Add {:e}+j{:e} to system at ({:d},{:d})", + (-**mRatio / mImpedance).real(), (-**mRatio / mImpedance).imag(), matrixNodeIndex(1), matrixNodeIndex(0)); } -} -void SP::Ph1::Transformer::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { - prevStepDependencies.push_back(mIntfCurrent); - prevStepDependencies.push_back(mIntfVoltage); - modifiedAttributes.push_back(mRightVector); + mSLog->flush(); } -void SP::Ph1::Transformer::mnaParentPreStep(Real time, Int timeStepCount) { - mnaCompApplyRightSideVectorStamp(**mRightVector); -} - -void SP::Ph1::Transformer::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { +void SP::Ph1::Transformer::mnaCompAddPostStepDependencies(AttributeBase::List &prevStepDependencies, + AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, + Attribute::Ptr &leftVector) { attributeDependencies.push_back(leftVector); modifiedAttributes.push_back(mIntfVoltage); modifiedAttributes.push_back(mIntfCurrent); } -void SP::Ph1::Transformer::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { +void SP::Ph1::Transformer::mnaCompPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { this->mnaUpdateVoltage(**leftVector); this->mnaUpdateCurrent(**leftVector); } -void SP::Ph1::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { - (**mIntfCurrent)(0, 0) = mSubInductor->intfCurrent()(0, 0); - SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}", Logger::phasorToString((**mIntfCurrent)(0, 0))); - -} - void SP::Ph1::Transformer::mnaCompUpdateVoltage(const Matrix& leftVector) { - // v1 - v0 - (**mIntfVoltage)(0, 0) = 0; - (**mIntfVoltage)(0, 0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); - (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::complexFromVectorElement(leftVector, mVirtualNodes[0]->matrixNodeIndex()); - SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}", Logger::phasorToString((**mIntfVoltage)(0, 0))); + // v0 - v1 + (**mIntfVoltage)(0, 0) = 0.0; + if (terminalNotGrounded(0)) + (**mIntfVoltage)(0, 0) += Math::complexFromVectorElement(leftVector, matrixNodeIndex(0)); + if (terminalNotGrounded(1)) + (**mIntfVoltage)(0, 0) -= Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)) * **mRatio; } + +void SP::Ph1::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { + // primary side current flowing into node 0 + (**mIntfCurrent)(0, 0) = -(**mIntfVoltage)(0, 0) / mImpedance; +} \ No newline at end of file diff --git a/dpsim-models/src/SP/SP_Ph1_Transformer_deprecated.cpp b/dpsim-models/src/SP/SP_Ph1_Transformer_deprecated.cpp new file mode 100644 index 0000000000..ef67009d4d --- /dev/null +++ b/dpsim-models/src/SP/SP_Ph1_Transformer_deprecated.cpp @@ -0,0 +1,361 @@ +/* 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; + +// #### General #### +SP::Ph1::Transformer::Transformer(String uid, String name, Logger::Level logLevel, Bool withResistiveLosses) + : Base::Ph1::Transformer(mAttributes), CompositePowerComp(uid, name, true, true, logLevel), + mBaseVoltage(mAttributes->create("base_Voltage")), + mCurrent(mAttributes->create("current_vector")), + mActivePowerBranch(mAttributes->create("p_branch_vector")), + mReactivePowerBranch(mAttributes->create("q_branch_vector")), + mActivePowerInjection(mAttributes->create("p_inj")), + mReactivePowerInjection(mAttributes->create("q_inj")) { + if (withResistiveLosses) + setVirtualNodeNumber(3); + else + setVirtualNodeNumber(2); + + SPDLOG_LOGGER_INFO(mSLog, "Create {} {}", this->type(), name); + **mIntfVoltage = MatrixComp::Zero(1, 1); + **mIntfCurrent = MatrixComp::Zero(1, 1); + setTerminalNumber(2); + + **mCurrent = MatrixComp::Zero(2,1); + **mActivePowerBranch = Matrix::Zero(2,1); + **mReactivePowerBranch = Matrix::Zero(2,1); +} + + +void SP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratioAbs, + Real ratioPhase, Real resistance, Real inductance) { + + // Note: to be consistent impedance values must be referred to high voltage side (and base voltage set to higher voltage) + Base::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs, ratioPhase, resistance, inductance); + + SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1={} [V] Nominal Voltage End 2={} [V]", **mNominalVoltageEnd1, **mNominalVoltageEnd2); + SPDLOG_LOGGER_INFO(mSLog, "Resistance={} [Ohm] Inductance={} [H] (referred to primary side)", **mResistance, **mInductance); + SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [/] Phase Shift={} [deg]", std::abs(**mRatio), std::arg(**mRatio)); + SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower); + + mRatioAbs = std::abs(**mRatio); + mRatioPhase = std::arg(**mRatio); + + mParametersSet = true; +} + +void SP::Ph1::Transformer::setParameters(Real nomVoltageEnd1, Real nomVoltageEnd2, Real ratedPower, Real ratioAbs, + Real ratioPhase, Real resistance, Real inductance) { + + **mRatedPower = ratedPower; + SPDLOG_LOGGER_INFO(mSLog, "Rated Power ={} [W]", **mRatedPower); + + SP::Ph1::Transformer::setParameters(nomVoltageEnd1, nomVoltageEnd2, ratioAbs, ratioPhase, resistance, inductance); +} + + +/// DEPRECATED: Delete method +SimPowerComp::Ptr SP::Ph1::Transformer::clone(String name) { + auto copy = Transformer::make(name, mLogLevel); + copy->setParameters(**mNominalVoltageEnd1, **mNominalVoltageEnd2, **mRatedPower, + std::abs(**mRatio), std::arg(**mRatio), **mResistance, **mInductance); + return copy; +} + +void SP::Ph1::Transformer::initializeFromNodesAndTerminals(Real frequency) { + mNominalOmega = 2. * PI * frequency; + mReactance = mNominalOmega * **mInductance; + SPDLOG_LOGGER_INFO(mSLog, "Reactance={} [Ohm] (referred to primary side)", mReactance); + + // Component parameters are referred to higher voltage side. + // Switch terminals to have terminal 0 at higher voltage side + // if transformer is connected the other way around. + if (Math::abs(**mRatio) < 1.) { + **mRatio = 1. / **mRatio; + mRatioAbs = std::abs(**mRatio); + mRatioPhase = std::arg(**mRatio); + std::shared_ptr> tmp = mTerminals[0]; + mTerminals[0] = mTerminals[1]; + mTerminals[1] = tmp; + Real tmpVolt = **mNominalVoltageEnd1; + **mNominalVoltageEnd1 = **mNominalVoltageEnd2; + **mNominalVoltageEnd2 = tmpVolt; + SPDLOG_LOGGER_INFO(mSLog, "Switching terminals to have first terminal at higher voltage side. Updated parameters: "); + SPDLOG_LOGGER_INFO(mSLog, "Nominal Voltage End 1 = {} [V] Nominal Voltage End 2 = {} [V]", **mNominalVoltageEnd1, **mNominalVoltageEnd2); + SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio = {} [ ] Phase Shift = {} [deg]", mRatioAbs, mRatioPhase); + } + + // Set initial voltage of virtual node in between + mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(1) * **mRatio); + + // Static calculations from load flow data + Complex impedance = { **mResistance, mReactance }; + (**mIntfVoltage)(0, 0) = mVirtualNodes[0]->initialSingleVoltage() - initialSingleVoltage(0); + (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance; + + // Create series sub components + mSubInductor = std::make_shared(**mUID + "_ind", **mName + "_ind", Logger::Level::off); + mSubInductor->setParameters(**mInductance); + addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + if (mNumVirtualNodes == 3) { + mVirtualNodes[2]->setInitialVoltage(initialSingleVoltage(0)); + mSubResistor = std::make_shared(**mUID + "_res", **mName + "_res", Logger::Level::off); + mSubResistor->setParameters(**mResistance); + mSubResistor->connect({ node(0), mVirtualNodes[2] }); + mSubInductor->connect({ mVirtualNodes[2], mVirtualNodes[0] }); + addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + } else { + mSubInductor->connect({ node(0), mVirtualNodes[0] }); + } + + // Create parallel sub components for init and mna behaviour + if (mBehaviour == TopologicalPowerComp::Behaviour::Initialization || mBehaviour == TopologicalPowerComp::Behaviour::MNASimulation) { + + Real pSnub = P_SNUB_TRANSFORMER * **mRatedPower; + Real qSnub = Q_SNUB_TRANSFORMER * **mRatedPower; + + // A snubber conductance is added on the higher voltage side + mSnubberResistance1 = std::pow(std::abs(**mNominalVoltageEnd1),2) / pSnub; + mSubSnubResistor1 = std::make_shared(**mName + "_snub_res1", mLogLevel); + mSubSnubResistor1->setParameters(mSnubberResistance1); + mSubSnubResistor1->connect({ node(0), SP::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 1 (connected to higher voltage side {}) = {} [Ohm]", node(0)->name(), Logger::realToString(mSnubberResistance1)); + mSubSnubResistor1->setBaseVoltage(**mNominalVoltageEnd1); + addMNASubComponent(mSubSnubResistor1, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // A snubber conductance is added on the lower voltage side + mSnubberResistance2 = std::pow(std::abs(**mNominalVoltageEnd2),2) / pSnub; + mSubSnubResistor2 = std::make_shared(**mName + "_snub_res2", mLogLevel); + mSubSnubResistor2->setParameters(mSnubberResistance2); + mSubSnubResistor2->connect({ node(1), SP::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Resistance 2 (connected to lower voltage side {}) = {} [Ohm]", node(1)->name(), Logger::realToString(mSnubberResistance2)); + mSubSnubResistor2->setBaseVoltage(**mNominalVoltageEnd2); + addMNASubComponent(mSubSnubResistor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + + // // A snubber capacitance is added to higher voltage side (not used as capacitor at high voltage side made it worse) + // mSnubberCapacitance1 = qSnub / std::pow(std::abs(mNominalVoltageEnd1),2) / mNominalOmega; + // mSubSnubCapacitor1 = std::make_shared(**mName + "_snub_cap1", mLogLevel); + // mSubSnubCapacitor1->setParameters(mSnubberCapacitance1); + // mSubSnubCapacitor1->connect({ node(0), SP::SimNode::GND }); + // SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 1 (connected to higher voltage side {}) = \n{} [F] \n ", node(0)->name(), Logger::realToString(mSnubberCapacitance1)); + // mSubSnubCapacitor1->setBaseVoltage(mNominalVoltageEnd1); + // mSubComponents.push_back(mSubSnubCapacitor1); + + // A snubber capacitance is added to lower voltage side + mSnubberCapacitance2 = qSnub / std::pow(std::abs(**mNominalVoltageEnd2),2) / mNominalOmega; + mSubSnubCapacitor2 = std::make_shared(**mName + "_snub_cap2", mLogLevel); + mSubSnubCapacitor2->setParameters(mSnubberCapacitance2); + mSubSnubCapacitor2->connect({ node(1), SP::SimNode::GND }); + SPDLOG_LOGGER_INFO(mSLog, "Snubber Capacitance 2 (connected to lower voltage side {}) = {} [F]", node(1)->name(), Logger::realToString(mSnubberCapacitance2)); + mSubSnubCapacitor2->setBaseVoltage(**mNominalVoltageEnd2); + addMNASubComponent(mSubSnubCapacitor2, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true); + } + + // Initialize electrical subcomponents + SPDLOG_LOGGER_INFO(mSLog, "Electrical subcomponents: "); + for (auto subcomp: mSubComponents) { + SPDLOG_LOGGER_INFO(mSLog, "- {}", subcomp->name()); + subcomp->initialize(mFrequencies); + subcomp->initializeFromNodesAndTerminals(frequency); + } + + SPDLOG_LOGGER_INFO(mSLog, + "\n--- Initialization from powerflow ---" + "\nVoltage across: {:s}" + "\nCurrent: {:s}" + "\nTerminal 0 voltage: {:s}" + "\nTerminal 1 voltage: {:s}" + "\nVirtual Node 1 voltage: {:s}" + "\n--- Initialization from powerflow finished ---", + Logger::phasorToString((**mIntfVoltage)(0, 0)), + Logger::phasorToString((**mIntfCurrent)(0, 0)), + Logger::phasorToString(initialSingleVoltage(0)), + Logger::phasorToString(initialSingleVoltage(1)), + Logger::phasorToString(mVirtualNodes[0]->initialSingleVoltage())); +} + + +// #### Powerflow section #### + +void SP::Ph1::Transformer::setBaseVoltage(Real baseVoltage) { + // Note: to be consistent set base voltage to higher voltage (and impedance values must be referred to high voltage side) + // TODO: use attribute setter for setting base voltage + **mBaseVoltage = baseVoltage; +} + +void SP::Ph1::Transformer::calculatePerUnitParameters(Real baseApparentPower, Real baseOmega) { + SPDLOG_LOGGER_INFO(mSLog, "#### Calculate Per Unit Parameters for {}", **mName); + mBaseApparentPower = baseApparentPower; + mBaseOmega = baseOmega; + SPDLOG_LOGGER_INFO(mSLog, "Base Power={} [VA] Base Omega={} [1/s]", baseApparentPower, baseOmega); + + mBaseImpedance = **mBaseVoltage * **mBaseVoltage / mBaseApparentPower; + mBaseAdmittance = 1.0 / mBaseImpedance; + mBaseCurrent = baseApparentPower / (**mBaseVoltage * sqrt(3)); // I_base=(S_threephase/3)/(V_line_to_line/sqrt(3)) + SPDLOG_LOGGER_INFO(mSLog, "Base Voltage={} [V] Base Impedance={} [Ohm]", **mBaseVoltage, mBaseImpedance); + + mResistancePerUnit = **mResistance / mBaseImpedance; + mReactancePerUnit = mReactance / mBaseImpedance; + SPDLOG_LOGGER_INFO(mSLog, "Resistance={} [pu] Reactance={} [pu]", mResistancePerUnit, mReactancePerUnit); + + mBaseInductance = mBaseImpedance / mBaseOmega; + mInductancePerUnit = **mInductance / mBaseInductance; + // omega per unit=1, hence 1.0*mInductancePerUnit. + mLeakagePerUnit = Complex(mResistancePerUnit,1.*mInductancePerUnit); + SPDLOG_LOGGER_INFO(mSLog, "Leakage Impedance={} [pu] ", mLeakagePerUnit); + + mRatioAbsPerUnit = mRatioAbs / **mNominalVoltageEnd1 * **mNominalVoltageEnd2; + SPDLOG_LOGGER_INFO(mSLog, "Tap Ratio={} [pu]", mRatioAbsPerUnit); + + // Calculate per unit parameters of subcomps + if (mSubSnubResistor1) + mSubSnubResistor1->calculatePerUnitParameters(mBaseApparentPower); + if (mSubSnubResistor2) + mSubSnubResistor2->calculatePerUnitParameters(mBaseApparentPower); + if (mSubSnubCapacitor1) + mSubSnubCapacitor1->calculatePerUnitParameters(mBaseApparentPower); + if (mSubSnubCapacitor2) + mSubSnubCapacitor2->calculatePerUnitParameters(mBaseApparentPower); +} + +void SP::Ph1::Transformer::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow & Y) { + // calculate matrix stamp + mY_element = MatrixComp(2, 2); + Complex y = Complex(1, 0) / mLeakagePerUnit; + + mY_element(0, 0) = y; + mY_element(0, 1) = -y*mRatioAbsPerUnit; + mY_element(1, 0) = -y*mRatioAbsPerUnit; + mY_element(1, 1) = y*std::pow(mRatioAbsPerUnit, 2); + + //check for inf or nan + for (int i = 0; i < 2; i++) + for (int j = 0; j < 2; j++) + if (std::isinf(mY_element.coeff(i, j).real()) || std::isinf(mY_element.coeff(i, j).imag())) { + std::cout << mY_element << std::endl; + std::cout << "Zl:" << mLeakage << std::endl; + std::cout << "tap:" << mRatioAbsPerUnit << std::endl; + std::stringstream ss; + ss << "Transformer>>" << this->name() << ": infinite or nan values in the element Y at: " << i << "," << j; + throw std::invalid_argument(ss.str()); + } + + //set the circuit matrix values + Y.coeffRef(this->matrixNodeIndex(0), this->matrixNodeIndex(0)) += mY_element.coeff(0, 0); + Y.coeffRef(this->matrixNodeIndex(0), this->matrixNodeIndex(1)) += mY_element.coeff(0, 1); + Y.coeffRef(this->matrixNodeIndex(1), this->matrixNodeIndex(1)) += mY_element.coeff(1, 1); + Y.coeffRef(this->matrixNodeIndex(1), this->matrixNodeIndex(0)) += mY_element.coeff(1, 0); + + SPDLOG_LOGGER_INFO(mSLog, "#### Y matrix stamping: {}", mY_element); + + if (mSubSnubResistor1) + mSubSnubResistor1->pfApplyAdmittanceMatrixStamp(Y); + if (mSubSnubResistor2) + mSubSnubResistor2->pfApplyAdmittanceMatrixStamp(Y); + if (mSubSnubCapacitor1) + mSubSnubCapacitor1->pfApplyAdmittanceMatrixStamp(Y); + if (mSubSnubCapacitor2) + mSubSnubCapacitor2->pfApplyAdmittanceMatrixStamp(Y); +} + + +void SP::Ph1::Transformer::updateBranchFlow(VectorComp& current, VectorComp& powerflow) { + **mCurrent = current * mBaseCurrent; + **mActivePowerBranch = powerflow.real()*mBaseApparentPower; + **mReactivePowerBranch = powerflow.imag()*mBaseApparentPower; +} + + +void SP::Ph1::Transformer::storeNodalInjection(Complex powerInjection) { + **mActivePowerInjection = std::real(powerInjection)*mBaseApparentPower; + **mReactivePowerInjection = std::imag(powerInjection)*mBaseApparentPower; +} + +MatrixComp SP::Ph1::Transformer::Y_element() { + return mY_element; +} + +// #### MNA Section #### + +void SP::Ph1::Transformer::mnaParentInitialize(Real omega, Real timeStep, Attribute::Ptr leftVector) { + SPDLOG_LOGGER_INFO(mSLog, + "\nTerminal 0 connected to {:s} = sim node {:d}" + "\nTerminal 1 connected to {:s} = sim node {:d}", + mTerminals[0]->node()->name(), mTerminals[0]->node()->matrixNodeIndex(), + mTerminals[1]->node()->name(), mTerminals[1]->node()->matrixNodeIndex()); +} + + +void SP::Ph1::Transformer::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { + // Ideal transformer equations + if (terminalNotGrounded(0)) { + Math::setMatrixElement(systemMatrix, mVirtualNodes[0]->matrixNodeIndex(), mVirtualNodes[1]->matrixNodeIndex(), Complex(-1.0, 0)); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(), mVirtualNodes[0]->matrixNodeIndex(), Complex(1.0, 0)); + } + if (terminalNotGrounded(1)) { + Math::setMatrixElement(systemMatrix, matrixNodeIndex(1), mVirtualNodes[1]->matrixNodeIndex(), **mRatio); + Math::setMatrixElement(systemMatrix, mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1), - **mRatio); + } + + // Add subcomps to system matrix + for (auto subcomp: mSubComponents) + if (auto mnasubcomp = std::dynamic_pointer_cast(subcomp)) + mnasubcomp->mnaApplySystemMatrixStamp(systemMatrix); + + if (terminalNotGrounded(0)) { + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(-1.0, 0)), + mVirtualNodes[0]->matrixNodeIndex(), mVirtualNodes[1]->matrixNodeIndex()); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(Complex(1.0, 0)), + mVirtualNodes[1]->matrixNodeIndex(), mVirtualNodes[0]->matrixNodeIndex()); + } + if (terminalNotGrounded(1)) { + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(**mRatio), + matrixNodeIndex(1), mVirtualNodes[1]->matrixNodeIndex()); + SPDLOG_LOGGER_INFO(mSLog, "Add {:s} to system at ({:d},{:d})", Logger::complexToString(- **mRatio), + mVirtualNodes[1]->matrixNodeIndex(), matrixNodeIndex(1)); + } +} + +void SP::Ph1::Transformer::mnaParentAddPreStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes) { + prevStepDependencies.push_back(mIntfCurrent); + prevStepDependencies.push_back(mIntfVoltage); + modifiedAttributes.push_back(mRightVector); +} + +void SP::Ph1::Transformer::mnaParentPreStep(Real time, Int timeStepCount) { + mnaCompApplyRightSideVectorStamp(**mRightVector); +} + +void SP::Ph1::Transformer::mnaParentAddPostStepDependencies(AttributeBase::List &prevStepDependencies, AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes, Attribute::Ptr &leftVector) { + attributeDependencies.push_back(leftVector); + modifiedAttributes.push_back(mIntfVoltage); + modifiedAttributes.push_back(mIntfCurrent); +} + +void SP::Ph1::Transformer::mnaParentPostStep(Real time, Int timeStepCount, Attribute::Ptr &leftVector) { + this->mnaUpdateVoltage(**leftVector); + this->mnaUpdateCurrent(**leftVector); +} + +void SP::Ph1::Transformer::mnaCompUpdateCurrent(const Matrix& leftVector) { + (**mIntfCurrent)(0, 0) = mSubInductor->intfCurrent()(0, 0); + SPDLOG_LOGGER_DEBUG(mSLog, "Current {:s}", Logger::phasorToString((**mIntfCurrent)(0, 0))); + +} + +void SP::Ph1::Transformer::mnaCompUpdateVoltage(const Matrix& leftVector) { + // v1 - v0 + (**mIntfVoltage)(0, 0) = 0; + (**mIntfVoltage)(0, 0) = Math::complexFromVectorElement(leftVector, matrixNodeIndex(1)); + (**mIntfVoltage)(0, 0) = (**mIntfVoltage)(0, 0) - Math::complexFromVectorElement(leftVector, mVirtualNodes[0]->matrixNodeIndex()); + SPDLOG_LOGGER_DEBUG(mSLog, "Voltage {:s}", Logger::phasorToString((**mIntfVoltage)(0, 0))); +} diff --git a/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp b/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp index f3b1fffafd..2ec0554628 100644 --- a/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp +++ b/dpsim-models/src/SP/SP_Ph1_VoltageSource.cpp @@ -78,6 +78,7 @@ void SP::Ph1::VoltageSource::initializeFromNodesAndTerminals(Real frequency) { Logger::phasorToString(mSrcSig->getSignal()), Logger::phasorToString(initialSingleVoltage(0)), Logger::phasorToString(initialSingleVoltage(1))); + mSLog->flush(); } // #### MNA functions #### @@ -105,6 +106,7 @@ void SP::Ph1::VoltageSource::mnaCompInitialize(Real omega, Real timeStep, Attrib "\n--- MNA initialization finished ---", Logger::phasorToString((**mIntfVoltage)(0,0)), Logger::phasorToString((**mIntfCurrent)(0,0))); + mSLog->flush(); } void SP::Ph1::VoltageSource::mnaCompApplySystemMatrixStamp(SparseMatrixRow& systemMatrix) { diff --git a/dpsim/examples/cxx/Circuits/EMT_DP_SP_Trafo.cpp b/dpsim/examples/cxx/Circuits/EMT_DP_SP_Trafo.cpp index 14808c9d38..1c6d1e95d8 100644 --- a/dpsim/examples/cxx/Circuits/EMT_DP_SP_Trafo.cpp +++ b/dpsim/examples/cxx/Circuits/EMT_DP_SP_Trafo.cpp @@ -105,7 +105,7 @@ void simTrafoSP1ph() { // Components auto vs = SP::Ph1::VoltageSource::make("v_1", Logger::Level::debug); - auto trafo = SP::Ph1::Transformer::make("trafo", "trafo", Logger::Level::debug, true); + auto trafo = SP::Ph1::Transformer::make("trafo", "trafo", Logger::Level::debug); auto loadRes = SP::Ph1::Resistor::make("r_1", Logger::Level::debug); // Topology @@ -212,6 +212,7 @@ void simTrafoElementsDP1ph() { void simTrafoDP1ph() { Real timeStep = 0.00005; Real finalTime = 1; + std::cout << timeStep << timeStep << finalTime << std::endl; String simName = "DP_Trafo_Component"; Logger::setLogDir("logs/"+simName); @@ -219,7 +220,6 @@ void simTrafoDP1ph() { Real voltageMVSide = 10000; Real trafoResistance = 1; Real trafoInductance = 0.1; - Real trafoPower = 1e6; Real loadResistanceHVSide = 10000; Real ratio = voltageHVSide/voltageMVSide; Real loadResistanceMVSide = loadResistanceHVSide/(ratio*ratio); @@ -230,7 +230,7 @@ void simTrafoDP1ph() { // Components auto vs = DP::Ph1::VoltageSource::make("v_1", Logger::Level::debug); - auto trafo = DP::Ph1::Transformer::make("trafo", "trafo", Logger::Level::debug, true); + auto trafo = DP::Ph1::Transformer::make("trafo", "trafo", Logger::Level::debug); auto loadRes = DP::Ph1::Resistor::make("r_1", Logger::Level::debug); // Topology @@ -240,12 +240,12 @@ void simTrafoDP1ph() { // Parameters vs->setParameters(CPS::Math::polar(voltageHVSide, 0)); - trafo->setParameters(voltageHVSide, voltageMVSide, trafoPower, ratio, 0, trafoResistance, trafoInductance); + trafo->setParameters(voltageHVSide, voltageMVSide, ratio, 0, trafoResistance, trafoInductance); loadRes->setParameters(loadResistanceMVSide); // Define system topology SystemTopology sys(50, SystemNodeList{n1, n2 }, SystemComponentList{vs, trafo, loadRes}); - +//* // Logging auto logger = DataLogger::make(simName); logger->logAttribute("v1", n1->attribute("v")); @@ -260,6 +260,7 @@ void simTrafoDP1ph() { sim.addLogger(logger); sim.run(); +//*/ } void simTrafoElementsEMT3ph() { @@ -325,11 +326,11 @@ void simTrafoElementsEMT3ph() { logger->logAttribute("itrafo", trafoInd->attribute("i_intf")); Simulation sim(simName); - sim.setSystem(sys); + //sim.setSystem(sys); sim.setTimeStep(timeStep); sim.setFinalTime(finalTime); - sim.setDomain(Domain::EMT); - sim.addLogger(logger); + //sim.setDomain(Domain::EMT); + //sim.addLogger(logger); sim.run(); } @@ -344,7 +345,6 @@ void simTrafoEMT3ph() { Real voltageMVSide = 10000; Real trafoResistance = 1; Real trafoInductance = 0.1; - Real trafoPower = 1e6; Real loadResistanceHVSide = 10000; Real ratio = voltageHVSide/voltageMVSide; Real loadResistanceMVSide = loadResistanceHVSide/(ratio*ratio); @@ -355,7 +355,7 @@ void simTrafoEMT3ph() { // Components auto vs = EMT::Ph3::VoltageSource::make("v_1", Logger::Level::debug); - auto trafo = EMT::Ph3::Transformer::make("trafo", "trafo", Logger::Level::debug, true); + auto trafo = EMT::Ph3::Transformer::make("trafo", "trafo", Logger::Level::debug); auto loadRes = EMT::Ph3::Resistor::make("r_1", Logger::Level::debug); // Topology @@ -365,7 +365,7 @@ void simTrafoEMT3ph() { // Parameters vs->setParameters(CPS::Math::singlePhaseVariableToThreePhase(CPS::Math::polar(100000, 0)), 50); - trafo->setParameters(voltageHVSide, voltageMVSide, trafoPower, ratio, 0, CPS::Math::singlePhaseParameterToThreePhase(trafoResistance), CPS::Math::singlePhaseParameterToThreePhase(trafoInductance)); + trafo->setParameters(voltageHVSide, voltageMVSide, ratio, 0, CPS::Math::singlePhaseParameterToThreePhase(trafoResistance), CPS::Math::singlePhaseParameterToThreePhase(trafoInductance)); loadRes->setParameters(CPS::Math::singlePhaseParameterToThreePhase(loadResistanceMVSide)); // Define system topology diff --git a/dpsim/examples/cxx/Circuits/EMT_VSI.cpp b/dpsim/examples/cxx/Circuits/EMT_VSI.cpp index 0c39ee48a5..da5aabe699 100644 --- a/dpsim/examples/cxx/Circuits/EMT_VSI.cpp +++ b/dpsim/examples/cxx/Circuits/EMT_VSI.cpp @@ -52,10 +52,10 @@ void EMT_Ph3_VSI2_4bus_SampleGrid() { Real cf_param = 789.3e-6; Real rc_param = 0.5; - Real transformerNominalPower = 5e6; + //Real transformerNominalPower = 5e6; - trans_DG1->setParameters(Vnom_pv, Vnom, Vnom_pv / Vnom, transformerNominalPower, 0., Matrix::Identity(3,3)*rc_param, Matrix::Identity(3,3)*lf_param*0.01); - trans_DG2->setParameters(Vnom_pv, Vnom, Vnom_pv / Vnom, transformerNominalPower, 0., Matrix::Identity(3,3)*rc_param, Matrix::Identity(3,3)*lf_param * 0.01); + trans_DG1->setParameters(Vnom_pv, Vnom, Vnom_pv / Vnom, 0., Matrix::Identity(3,3)*rc_param, Matrix::Identity(3,3)*lf_param*0.01); + trans_DG2->setParameters(Vnom_pv, Vnom, Vnom_pv / Vnom, 0., Matrix::Identity(3,3)*rc_param, Matrix::Identity(3,3)*lf_param * 0.01); //trans_inductor->setParameters(lf_param*0.01); auto piline = PiLine::make("piline", Logger::Level::debug); diff --git a/dpsim/examples/cxx/Circuits/SP_SynGenTrStab_SMIB_Fault_KundurExample1.cpp b/dpsim/examples/cxx/Circuits/SP_SynGenTrStab_SMIB_Fault_KundurExample1.cpp index 0e596fc2e8..e143c36056 100644 --- a/dpsim/examples/cxx/Circuits/SP_SynGenTrStab_SMIB_Fault_KundurExample1.cpp +++ b/dpsim/examples/cxx/Circuits/SP_SynGenTrStab_SMIB_Fault_KundurExample1.cpp @@ -78,7 +78,7 @@ void SP_1ph_SynGenTrStab_Fault(String simName, Real timeStep, Real finalTime, Re genPF->modifyPowerFlowBusType(PowerflowBusType::PV); // Transformer - auto trafoPF = CPS::SP::Ph1::Transformer::make("trafo", "trafo", Logger::Level::debug, true); + auto trafoPF = CPS::SP::Ph1::Transformer::make("trafo", "trafo", Logger::Level::debug); trafoPF->setParameters(transformerNomVoltageHV, transformerNomVoltageMV, transformerRatio, 0, transformerResistance, transformerInductance); trafoPF->setBaseVoltage(nomVoltNetwork); @@ -144,7 +144,7 @@ void SP_1ph_SynGenTrStab_Fault(String simName, Real timeStep, Real finalTime, Re genSP->setModelFlags(false); // Transformer - auto trafoSP = CPS::SP::Ph1::Transformer::make("trafo", "trafo", Logger::Level::debug, false); + auto trafoSP = CPS::SP::Ph1::Transformer::make("trafo", "trafo", Logger::Level::debug); trafoSP->setParameters(transformerNomVoltageHV, transformerNomVoltageMV, transformerRatio, 0, transformerResistance, transformerInductance); // Slack diff --git a/dpsim/src/pybind/DPComponents.cpp b/dpsim/src/pybind/DPComponents.cpp index 28ee26808c..4621240767 100644 --- a/dpsim/src/pybind/DPComponents.cpp +++ b/dpsim/src/pybind/DPComponents.cpp @@ -79,6 +79,12 @@ void addDPPh1Components(py::module_ mDPPh1) { .def("connect", &CPS::DP::Ph1::Inductor::connect) .def_property("L", createAttributeGetter("L"), createAttributeSetter("L")); + py::class_, CPS::SimPowerComp>(mDPPh1, "ResInductor", py::multiple_inheritance()) + .def(py::init()) + .def(py::init()) + .def("set_parameters", &CPS::DP::Ph1::ResIndSeries::setParameters, "R"_a, "L"_a) + .def("connect", &CPS::DP::Ph1::ResIndSeries::connect); + py::class_, CPS::SimPowerComp>(mDPPh1, "NetworkInjection", py::multiple_inheritance()) .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) .def("set_parameters", py::overload_cast(&CPS::DP::Ph1::NetworkInjection::setParameters), "V_ref"_a, "f_src"_a = 0) @@ -186,9 +192,8 @@ void addDPPh1Components(py::module_ mDPPh1) { py::class_, CPS::SimPowerComp>(mDPPh1, "Transformer", py::multiple_inheritance()) .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) - .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off, "with_resistive_losses"_a = false) // cppcheck-suppress assignBoolToPointer + .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off) // cppcheck-suppress assignBoolToPointer .def("set_parameters", py::overload_cast(&CPS::DP::Ph1::Transformer::setParameters), "nom_voltage_end_1"_a, "nom_voltage_end_2"_a, "ratio_abs"_a, "ratio_phase"_a, "resistance"_a, "inductance"_a) - .def("set_parameters", py::overload_cast(&CPS::DP::Ph1::Transformer::setParameters), "nom_voltage_end_1"_a, "nom_voltage_end_2"_a, "rated_power"_a, "ratio_abs"_a, "ratio_phase"_a, "resistance"_a, "inductance"_a) .def("connect", &CPS::DP::Ph1::Transformer::connect); } diff --git a/dpsim/src/pybind/EMTComponents.cpp b/dpsim/src/pybind/EMTComponents.cpp index 7582322c2b..d2eef5a3e4 100644 --- a/dpsim/src/pybind/EMTComponents.cpp +++ b/dpsim/src/pybind/EMTComponents.cpp @@ -100,6 +100,12 @@ void addEMTPh3Components(py::module_ mEMTPh3) { .def("set_parameters", &CPS::EMT::Ph3::Inductor::setParameters, "L"_a) .def("connect", &CPS::EMT::Ph3::Inductor::connect); + py::class_, CPS::SimPowerComp>(mEMTPh3, "ResInductor", py::multiple_inheritance()) + .def(py::init()) + .def(py::init()) + .def("set_parameters", &CPS::EMT::Ph3::ResIndSeries::setParameters, "R"_a, "L"_a) + .def("connect", &CPS::EMT::Ph3::ResIndSeries::connect); + py::class_, CPS::SimPowerComp>(mEMTPh3, "NetworkInjection", py::multiple_inheritance()) .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) .def("set_parameters", py::overload_cast(&CPS::EMT::Ph3::NetworkInjection::setParameters), "V_ref"_a, "f_src"_a=50) @@ -201,8 +207,8 @@ void addEMTPh3Components(py::module_ mEMTPh3) { py::class_, CPS::SimPowerComp>(mEMTPh3, "Transformer", py::multiple_inheritance()) .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) - .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off, "with_resistive_losses"_a = false) // cppcheck-suppress assignBoolToPointer - .def("set_parameters", &CPS::EMT::Ph3::Transformer::setParameters, "nom_voltage_end_1"_a, "nom_voltage_end_2"_a, "rated_power"_a, "ratio_abs"_a, "ratio_phase"_a, "resistance"_a, "inductance"_a) + .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off) // cppcheck-suppress assignBoolToPointer + .def("set_parameters", &CPS::EMT::Ph3::Transformer::setParameters, "nom_voltage_end_1"_a, "nom_voltage_end_2"_a, "ratio_abs"_a, "ratio_phase"_a, "resistance"_a, "inductance"_a) .def("connect", &CPS::EMT::Ph3::Transformer::connect); py::class_, CPS::SimPowerComp>(mEMTPh3, "SeriesResistor", py::multiple_inheritance()) diff --git a/dpsim/src/pybind/SPComponents.cpp b/dpsim/src/pybind/SPComponents.cpp index f34e84baa5..9eb1857ec6 100644 --- a/dpsim/src/pybind/SPComponents.cpp +++ b/dpsim/src/pybind/SPComponents.cpp @@ -55,6 +55,12 @@ void addSPPh1Components(py::module_ mSPPh1) { .def("connect", &CPS::SP::Ph1::Inductor::connect) .def_property("L", createAttributeGetter("L"), createAttributeSetter("L")); + py::class_, CPS::SimPowerComp>(mSPPh1, "ResInductor", py::multiple_inheritance()) + .def(py::init()) + .def(py::init()) + .def("set_parameters", &CPS::SP::Ph1::ResIndSeries::setParameters, "R"_a, "L"_a) + .def("connect", &CPS::SP::Ph1::ResIndSeries::connect); + py::class_, CPS::SimPowerComp>(mSPPh1, "NetworkInjection", py::multiple_inheritance()) .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) .def("set_parameters", py::overload_cast(&CPS::SP::Ph1::NetworkInjection::setParameters), "voltage_set_point"_a) @@ -65,7 +71,7 @@ void addSPPh1Components(py::module_ mSPPh1) { py::class_, CPS::SimPowerComp>(mSPPh1, "PiLine", py::multiple_inheritance()) .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) - .def("set_parameters", &CPS::SP::Ph1::PiLine::setParameters, "R"_a, "L"_a, "C"_a=-1, "G"_a=-1) + .def("set_parameters", &CPS::SP::Ph1::PiLine::setParameters, "R"_a, "L"_a, "C"_a=0, "G"_a=0) .def("set_base_voltage", &CPS::SP::Ph1::PiLine::setBaseVoltage, "base_voltage"_a) .def("connect", &CPS::SP::Ph1::PiLine::connect); @@ -160,7 +166,7 @@ void addSPPh1Components(py::module_ mSPPh1) { py::class_, CPS::SimPowerComp>(mSPPh1, "Transformer", py::multiple_inheritance()) .def(py::init(), "name"_a, "loglevel"_a = CPS::Logger::Level::off) - .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off, "with_resistive_losses"_a = false) // cppcheck-suppress assignBoolToPointer + .def(py::init(), "uid"_a, "name"_a, "loglevel"_a = CPS::Logger::Level::off) // cppcheck-suppress assignBoolToPointer .def("set_parameters", py::overload_cast(&CPS::SP::Ph1::Transformer::setParameters), "nom_voltage_end_1"_a, "nom_voltage_end_2"_a, "ratio_abs"_a, "ratio_phase"_a, "resistance"_a, "inductance"_a) .def("set_parameters", py::overload_cast(&CPS::SP::Ph1::Transformer::setParameters), "nom_voltage_end_1"_a, "nom_voltage_end_2"_a, "rated_power"_a, "ratio_abs"_a, "ratio_phase"_a, "resistance"_a, "inductance"_a) .def("set_base_voltage", &CPS::SP::Ph1::Transformer::setBaseVoltage, "base_voltage"_a) diff --git a/examples/Notebooks/Circuits/DP_Slack_PiLine_VSI_Ramp.ipynb b/examples/Notebooks/Circuits/DP_Slack_PiLine_VSI_Ramp.ipynb index d5008ac76e..89f59b81ad 100644 --- a/examples/Notebooks/Circuits/DP_Slack_PiLine_VSI_Ramp.ipynb +++ b/examples/Notebooks/Circuits/DP_Slack_PiLine_VSI_Ramp.ipynb @@ -18,6 +18,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -25,6 +26,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -62,6 +64,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -113,6 +116,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -188,6 +192,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -203,7 +208,7 @@ "if emt_reference_available:\n", " error_abs = np.absolute(np.sqrt(3/2)*ts_dpsim_ref_emt['v2_0'].values - ts_v2_shifted.values[80000:160002]).max()\n", " print('EMT ref v2_0 vs. DP v2_shift (abs): ' + str(error_abs))\n", - " assert error_abs < 9.72" + " assert error_abs < 9.53" ] }, { @@ -215,7 +220,7 @@ "if dp_reference_available:\n", " error_abs = np.absolute(ts_dpsim_ref_dp['v2'].values - ts_v2_interpolated.values[80000:160002]).max()\n", " print('DP ref v2 vs. DP v2 (abs): ' + str(error_abs))\n", - " assert error_abs < 10.26" + " assert error_abs < 9.75" ] }, { diff --git a/examples/Notebooks/Circuits/SP_Slack_PiLine_VSI_with_PF_Init.ipynb b/examples/Notebooks/Circuits/SP_Slack_PiLine_VSI_with_PF_Init.ipynb index abf0935cbc..e637529432 100644 --- a/examples/Notebooks/Circuits/SP_Slack_PiLine_VSI_with_PF_Init.ipynb +++ b/examples/Notebooks/Circuits/SP_Slack_PiLine_VSI_with_PF_Init.ipynb @@ -65,7 +65,7 @@ "outputs": [], "source": [ "time_step_pf = final_time\n", - "final_time_pf = final_time + time_step_pf\n", + "final_time_pf = final_time\n", "sim_name_pf = sim_name + \"_PF\"\n", "dpsimpy.Logger.set_log_dir('logs/' + sim_name_pf)\n", "\n", @@ -284,7 +284,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.7" + "version": "3.9.13" }, "orig_nbformat": 3 }, diff --git a/examples/Notebooks/Circuits/Validation_RL_Element.ipynb b/examples/Notebooks/Circuits/Validation_RL_Element.ipynb new file mode 100644 index 0000000000..b9a24506bd --- /dev/null +++ b/examples/Notebooks/Circuits/Validation_RL_Element.ipynb @@ -0,0 +1,868 @@ +{ + "cells": [ + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Validation RL-Element" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Import dpsimpy " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import dpsimpy" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parameters" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "resistance = 10\n", + "inductance = 1e-3\n", + "capacitance = 5e-6\n", + "frequency = 50\n", + "epsilon = 1e-12" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Powerflow for Initialization" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "sim_name_pf = 'VS_RLC1_PF'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + sim_name_pf)\n", + "\n", + "# Nodes\n", + "gnd_pf = dpsimpy.sp.SimNode.gnd\n", + "n1_pf = dpsimpy.sp.SimNode('n1_pf')\n", + "n2_pf = dpsimpy.sp.SimNode('n2_pf')\n", + "n3_pf = dpsimpy.sp.SimNode('n3_pf')\n", + "\n", + "# Components\n", + "vs_pf = dpsimpy.sp.ph1.VoltageSource('vs_pf', dpsimpy.LogLevel.debug)\n", + "vs_pf.set_parameters(V_ref=complex(10,0))\n", + "r1_pf = dpsimpy.sp.ph1.Resistor('r1_pf', dpsimpy.LogLevel.debug)\n", + "r1_pf.set_parameters(R=resistance)\n", + "c1_pf = dpsimpy.sp.ph1.Capacitor('c1_pf', dpsimpy.LogLevel.debug)\n", + "c1_pf.set_parameters(C=capacitance)\n", + "l1_pf = dpsimpy.sp.ph1.Inductor('l1_pf', dpsimpy.LogLevel.debug)\n", + "l1_pf.set_parameters(L=inductance)\n", + "\n", + "# Connections\n", + "vs_pf.connect([gnd_pf, n1_pf])\n", + "r1_pf.connect([n2_pf, n1_pf])\n", + "l1_pf.connect([n3_pf, n2_pf])\n", + "c1_pf.connect([gnd_pf, n3_pf])\n", + "\n", + "# Define system topology\n", + "system_pf = dpsimpy.SystemTopology(frequency, [n1_pf, n2_pf, n3_pf], [vs_pf, r1_pf, l1_pf, c1_pf])\n", + "\n", + "# Logging\n", + "logger_pf = dpsimpy.Logger(sim_name_pf)\n", + "logger_pf.log_attribute('n1.v', 'v', n1_pf)\n", + "logger_pf.log_attribute('n2.v', 'v', n2_pf)\n", + "logger_pf.log_attribute('n3.v', 'v', n3_pf)\n", + "logger_pf.log_attribute('r1.i_intf', 'i_intf', r1_pf)\n", + "logger_pf.log_attribute('l1.i_intf', 'i_intf', l1_pf)\n", + "\n", + "sim_pf = dpsimpy.Simulation(sim_name_pf, dpsimpy.LogLevel.debug)\n", + "sim_pf.set_system(system_pf)\n", + "sim_pf.set_domain(dpsimpy.Domain.SP)\n", + "sim_pf.set_time_step(0.1)\n", + "sim_pf.set_final_time(0.5)\n", + "sim_pf.add_logger(logger_pf)\n", + "sim_pf.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1. DP Domain" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### RLC circuit (reference)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name = 'DP_VS_RLC'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + name)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.dp.SimNode.gnd\n", + "n1 = dpsimpy.dp.SimNode('n1')\n", + "n1.set_initial_voltage(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0])\n", + "n2 = dpsimpy.dp.SimNode('n2')\n", + "n2.set_initial_voltage(sim_pf.get_idobj_attr(n2_pf.name(), 'v').get()[0])\n", + "n3 = dpsimpy.dp.SimNode('n3')\n", + "n3.set_initial_voltage(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0])\n", + "\n", + "# Components\n", + "vs = dpsimpy.dp.ph1.VoltageSource('vs')\n", + "vs.set_parameters(V_ref=complex(10,0))\n", + "r1 = dpsimpy.dp.ph1.Resistor('r_1', dpsimpy.LogLevel.off)\n", + "r1.R = resistance\n", + "l1 = dpsimpy.dp.ph1.Inductor('l_1', dpsimpy.LogLevel.off)\n", + "l1.L = inductance\n", + "c1 = dpsimpy.dp.ph1.Capacitor('c1', dpsimpy.LogLevel.off)\n", + "c1.set_parameters(C=capacitance)\n", + "\n", + "# Connections\n", + "vs.connect([gnd, n1])\n", + "r1.connect([n2, n1])\n", + "l1.connect([n3, n2])\n", + "c1.connect([gnd, n3])\n", + "\n", + "# Define system topology\n", + "system = dpsimpy.SystemTopology(frequency, [gnd, n1, n2, n3], [vs, r1, l1, c1])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(name)\n", + "logger.log_attribute('n1.v', 'v', n1)\n", + "logger.log_attribute('n2.v', 'v', n2)\n", + "logger.log_attribute('n3.v', 'v', n3)\n", + "logger.log_attribute('l1.i_intf', 'i_intf', l1)\n", + "\n", + "\n", + "sim = dpsimpy.Simulation(name, dpsimpy.LogLevel.off)\n", + "sim.set_system(system)\n", + "sim.set_domain(dpsimpy.Domain.DP)\n", + "sim.set_time_step(0.0001)\n", + "sim.set_final_time(0.02)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read Results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# read Simulink log file\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import villas.dataprocessing.readtools as rt\n", + "from villas.dataprocessing.timeseries import TimeSeries as ts\n", + "import villas.dataprocessing.plottools as pt\n", + "import os\n", + "\n", + "# read EMT results\n", + "file_path = os.getcwd() + \"/logs/\" + name + \"/\" + name + \".csv\"\n", + "ts_dpsim_comps = rt.read_timeseries_dpsim(file_path)\n", + "\n", + "#convert to emt\n", + "ts_dpsim_comps = ts.frequency_shift_list(ts_dpsim_comps, frequency)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Circuit with RL-Element" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name_dp = 'DP_RL-element'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + name_dp)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.dp.SimNode.gnd\n", + "n1 = dpsimpy.dp.SimNode('n1')\n", + "n1.set_initial_voltage(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0])\n", + "n2 = dpsimpy.dp.SimNode('n2')\n", + "n2.set_initial_voltage(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0])\n", + "\n", + "# Components\n", + "vs = dpsimpy.dp.ph1.VoltageSource('vs', dpsimpy.LogLevel.debug)\n", + "vs.set_parameters(V_ref=complex(10,0))\n", + "rl = dpsimpy.dp.ph1.ResInductor('rl', dpsimpy.LogLevel.debug)\n", + "rl.set_parameters(R=resistance, L=inductance)\n", + "c1 = dpsimpy.dp.ph1.Capacitor('c1', dpsimpy.LogLevel.debug)\n", + "c1.set_parameters(C=capacitance)\n", + "\n", + "# Connections\n", + "vs.connect([gnd, n1])\n", + "rl.connect([n2, n1])\n", + "c1.connect([gnd, n2])\n", + "\n", + "# Define system topology\n", + "system = dpsimpy.SystemTopology(frequency, [gnd, n1, n2], [vs, rl, c1])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(name_dp)\n", + "logger.log_attribute('n1.v', 'v', n1)\n", + "logger.log_attribute('n2.v', 'v', n2)\n", + "logger.log_attribute('rl.i_intf', 'i_intf', rl)\n", + "logger.log_attribute('rl.v', 'v_intf', rl)\n", + "\n", + "sim = dpsimpy.Simulation(name_dp)\n", + "sim.set_system(system)\n", + "sim.set_domain(dpsimpy.Domain.DP)\n", + "sim.set_time_step(0.0001)\n", + "sim.set_final_time(0.02)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read Results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# read DP results\n", + "file_path = os.getcwd() + \"/logs/\" + name_dp + \"/\" + name_dp + \".csv\"\n", + "ts_dpsim_dp = rt.read_timeseries_dpsim(file_path)\n", + "\n", + "#convert to emt\n", + "ts_dpsim_dp = ts.frequency_shift_list(ts_dpsim_dp, frequency)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ts_dpsim_comps[\"n3.v_shift\"].label = 'vc - RLC circuit'\n", + "ts_dpsim_comps[\"l1.i_intf_shift\"].label = 'i - RLC circuit'\n", + "\n", + "ts_dpsim_dp[\"n2.v_shift\"].label = 'vc RL Element - DP'\n", + "ts_dpsim_dp[\"rl.i_intf_shift\"].label = 'i RL Element - DP'\n", + "\n", + "pt.plot_timeseries(1, ts_dpsim_comps[\"n3.v_shift\"])\n", + "pt.plot_timeseries(1, ts_dpsim_dp[\"n2.v_shift\"], plt_linestyle='--')\n", + "\n", + "pt.plot_timeseries(2, ts_dpsim_comps[\"l1.i_intf_shift\"])\n", + "pt.plot_timeseries(2, ts_dpsim_dp[\"rl.i_intf_shift\"], plt_linestyle='--')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Assert " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# calculate the RMSE between both models\n", + "err_current = ts.rmse(ts_dpsim_comps[\"l1.i_intf_shift\"], ts_dpsim_dp[\"rl.i_intf_shift\"])\n", + "err_voltage = ts.rmse(ts_dpsim_comps[\"n3.v_shift\"], ts_dpsim_dp[\"n2.v_shift\"])\n", + "\n", + "print(err_current)\n", + "print(err_voltage)\n", + "\n", + "assert err_current < epsilon\n", + "assert err_voltage < epsilon" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. EMT" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### RLC Circuit (reference)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name_emt_ref = 'EMT_RL-ref'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + name_emt_ref)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", + "n1.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0]))\n", + "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "n2.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(sim_pf.get_idobj_attr(n2_pf.name(), 'v').get()[0][0]))\n", + "n3 = dpsimpy.emt.SimNode('n3', dpsimpy.PhaseType.ABC)\n", + "n3.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0][0]))\n", + "\n", + "# Components\n", + "vs = dpsimpy.emt.ph3.VoltageSource('vs', dpsimpy.LogLevel.off)\n", + "vs.set_parameters(V_ref=dpsimpy.Math.single_phase_variable_to_three_phase(complex(10, 0)), f_src=frequency)\n", + "r1 = dpsimpy.emt.ph3.Resistor('r1', dpsimpy.LogLevel.off)\n", + "r1.set_parameters(R=dpsimpy.Math.single_phase_parameter_to_three_phase(resistance))\n", + "l1 = dpsimpy.emt.ph3.Inductor('l1', dpsimpy.LogLevel.off)\n", + "l1.set_parameters(L=dpsimpy.Math.single_phase_parameter_to_three_phase(inductance))\n", + "c1 = dpsimpy.emt.ph3.Capacitor('c1', dpsimpy.LogLevel.off)\n", + "c1.set_parameters(C=dpsimpy.Math.single_phase_parameter_to_three_phase(capacitance))\n", + "\n", + "# Connections\n", + "vs.connect([gnd, n1])\n", + "r1.connect([n2, n1])\n", + "l1.connect([n3, n2])\n", + "c1.connect([gnd, n3])\n", + "\n", + "\n", + "# Define system topology\n", + "system = dpsimpy.SystemTopology(frequency, [gnd, n1, n2, n3], [vs, r1, l1, c1])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(name_emt_ref)\n", + "logger.log_attribute('n1.v', 'v', n1)\n", + "logger.log_attribute('n2.v', 'v', n2)\n", + "logger.log_attribute('n3.v', 'v', n3)\n", + "logger.log_attribute('r1.i_intf', 'i_intf', r1)\n", + "logger.log_attribute('r1.v', 'v_intf', r1)\n", + "logger.log_attribute('l1.i_intf', 'i_intf', l1)\n", + "logger.log_attribute('l1.v', 'v_intf', l1)\n", + "\n", + "sim = dpsimpy.Simulation(name_emt_ref, dpsimpy.LogLevel.off)\n", + "sim.set_system(system)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.set_time_step(0.0001)\n", + "sim.set_final_time(0.02)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# read DP results\n", + "file_path = os.getcwd() + \"/logs/\" + name_emt_ref + \"/\" + name_emt_ref + \".csv\"\n", + "ts_dpsim_emt_ref = rt.read_timeseries_dpsim(file_path)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Circuit with RL-Element" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name_emt = 'EMT_RL-element'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + name_emt)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.emt.SimNode.gnd\n", + "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", + "n1.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0][0]))\n", + "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "n2.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0][0]))\n", + "\n", + "# Components\n", + "vs = dpsimpy.emt.ph3.VoltageSource('vs', dpsimpy.LogLevel.off)\n", + "vs.set_parameters(V_ref=dpsimpy.Math.single_phase_variable_to_three_phase(complex(10, 0)), f_src=frequency)\n", + "rl = dpsimpy.emt.ph3.ResInductor('rl', dpsimpy.LogLevel.debug)\n", + "rl.set_parameters(R=dpsimpy.Math.single_phase_parameter_to_three_phase(resistance), L=dpsimpy.Math.single_phase_parameter_to_three_phase(inductance))\n", + "c1 = dpsimpy.emt.ph3.Capacitor('c1', dpsimpy.LogLevel.debug)\n", + "c1.set_parameters(C=dpsimpy.Math.single_phase_parameter_to_three_phase(capacitance))\n", + "\n", + "# Connections\n", + "vs.connect([gnd, n1])\n", + "rl.connect([n2, n1])\n", + "c1.connect([gnd, n2])\n", + "\n", + "# Define system topology\n", + "system = dpsimpy.SystemTopology(frequency, [gnd, n1, n2], [vs, rl, c1])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(name_emt)\n", + "logger.log_attribute('n1.v', 'v', n1)\n", + "logger.log_attribute('n2.v', 'v', n2)\n", + "logger.log_attribute('rl.i_intf', 'i_intf', rl)\n", + "logger.log_attribute('rl.v', 'v_intf', rl)\n", + "\n", + "sim = dpsimpy.Simulation(name_emt, dpsimpy.LogLevel.off)\n", + "sim.set_system(system)\n", + "sim.set_domain(dpsimpy.Domain.EMT)\n", + "sim.set_time_step(0.0001)\n", + "sim.set_final_time(0.02)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read EMT results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# read DP results\n", + "file_path = os.getcwd() + \"/logs/\" + name_emt + \"/\" + name_emt + \".csv\"\n", + "ts_dpsim_emt = rt.read_timeseries_dpsim(file_path)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot Results phase a" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ts_dpsim_emt_ref[\"l1.i_intf_0\"].label = 'i (phase a) - REF'\n", + "ts_dpsim_emt_ref[\"n3.v_0\"].label = 'vc (phase a) - REF'\n", + "ts_dpsim_emt[\"rl.i_intf_0\"].label = 'i (phase a) RL Element'\n", + "ts_dpsim_emt[\"n2.v_0\"].label = 'vc (phase a) RL Element'\n", + "\n", + "pt.plot_timeseries(3, ts_dpsim_emt_ref[\"n3.v_0\"])\n", + "pt.plot_timeseries(3, ts_dpsim_emt[\"n2.v_0\"], plt_linestyle='--')\n", + "\n", + "pt.plot_timeseries(4, ts_dpsim_emt_ref[\"l1.i_intf_0\"])\n", + "pt.plot_timeseries(4, ts_dpsim_emt[\"rl.i_intf_0\"], plt_linestyle='--')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ts_dpsim_emt_ref[\"l1.i_intf_1\"].label = 'i (phase b) - REF'\n", + "ts_dpsim_emt_ref[\"n3.v_1\"].label = 'vc (phase b) - REF'\n", + "ts_dpsim_emt[\"rl.i_intf_1\"].label = 'i (phase b) RL Element'\n", + "ts_dpsim_emt[\"n2.v_1\"].label = 'vc RL (phase b) Element'\n", + "\n", + "pt.plot_timeseries(3, ts_dpsim_emt_ref[\"n3.v_1\"])\n", + "pt.plot_timeseries(3, ts_dpsim_emt[\"n2.v_1\"], plt_linestyle='--')\n", + "\n", + "pt.plot_timeseries(4, ts_dpsim_emt_ref[\"l1.i_intf_1\"])\n", + "pt.plot_timeseries(4, ts_dpsim_emt[\"rl.i_intf_1\"], plt_linestyle='--')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ts_dpsim_emt_ref[\"l1.i_intf_2\"].label = 'i (phase c) - REF'\n", + "ts_dpsim_emt_ref[\"n3.v_2\"].label = 'vc (phase c) - REF'\n", + "ts_dpsim_emt[\"rl.i_intf_2\"].label = 'i (phase c) RL Element'\n", + "ts_dpsim_emt[\"n2.v_2\"].label = 'vc RL (phase c) Element'\n", + "\n", + "pt.plot_timeseries(3, ts_dpsim_emt_ref[\"n3.v_2\"])\n", + "pt.plot_timeseries(3, ts_dpsim_emt[\"n2.v_2\"], plt_linestyle='--')\n", + "\n", + "pt.plot_timeseries(4, ts_dpsim_emt_ref[\"l1.i_intf_2\"])\n", + "pt.plot_timeseries(4, ts_dpsim_emt[\"rl.i_intf_2\"], plt_linestyle='--')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Assert" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# calculate the RMSE between both models phase a\n", + "err_current = ts.rmse(ts_dpsim_emt_ref[\"l1.i_intf_0\"], ts_dpsim_emt[\"rl.i_intf_0\"])\n", + "err_voltage = ts.rmse(ts_dpsim_emt_ref[\"n3.v_0\"], ts_dpsim_emt[\"n2.v_0\"])\n", + "\n", + "print(err_current)\n", + "print(err_voltage)\n", + "\n", + "assert err_current < epsilon\n", + "assert err_voltage < epsilon\n", + "\n", + "# calculate the RMSE between both models phase b\n", + "err_current = ts.rmse(ts_dpsim_emt_ref[\"l1.i_intf_1\"], ts_dpsim_emt[\"rl.i_intf_1\"])\n", + "err_voltage = ts.rmse(ts_dpsim_emt_ref[\"n3.v_1\"], ts_dpsim_emt[\"n2.v_1\"])\n", + "\n", + "print(err_current)\n", + "print(err_voltage)\n", + "\n", + "assert err_current < epsilon\n", + "assert err_voltage < epsilon\n", + "\n", + "# calculate the RMSE between both models phase a\n", + "err_current = ts.rmse(ts_dpsim_emt_ref[\"l1.i_intf_2\"], ts_dpsim_emt[\"rl.i_intf_2\"])\n", + "err_voltage = ts.rmse(ts_dpsim_emt_ref[\"n3.v_2\"], ts_dpsim_emt[\"n2.v_2\"])\n", + "\n", + "print(err_current)\n", + "print(err_voltage)\n", + "\n", + "assert err_current < epsilon\n", + "assert err_voltage < epsilon" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. SP" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### RLC circuit (reference)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name_sp_ref = 'SP_VS_RLC'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + name_sp_ref)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.sp.SimNode.gnd\n", + "n1 = dpsimpy.sp.SimNode('n1')\n", + "n1.set_initial_voltage(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0])\n", + "n2 = dpsimpy.sp.SimNode('n2')\n", + "n2.set_initial_voltage(sim_pf.get_idobj_attr(n2_pf.name(), 'v').get()[0])\n", + "n3 = dpsimpy.sp.SimNode('n3')\n", + "n3.set_initial_voltage(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0])\n", + "\n", + "# Components\n", + "vs = dpsimpy.sp.ph1.VoltageSource('vs')\n", + "vs.set_parameters(V_ref=complex(10,0))\n", + "r1 = dpsimpy.sp.ph1.Resistor('r_1', dpsimpy.LogLevel.info)\n", + "r1.set_parameters(R=resistance)\n", + "l1 = dpsimpy.sp.ph1.Inductor('l_1', dpsimpy.LogLevel.info)\n", + "l1.set_parameters(L=inductance)\n", + "c1 = dpsimpy.sp.ph1.Capacitor('c1', dpsimpy.LogLevel.info)\n", + "c1.set_parameters(C=capacitance)\n", + "\n", + "# Connections\n", + "vs.connect([gnd, n1])\n", + "r1.connect([n2, n1])\n", + "l1.connect([n3, n2])\n", + "c1.connect([gnd, n3])\n", + "\n", + "# Define system topology\n", + "system = dpsimpy.SystemTopology(frequency, [gnd, n1, n2, n3], [vs, r1, l1, c1])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(name_sp_ref)\n", + "logger.log_attribute('n1.v', 'v', n1)\n", + "logger.log_attribute('n2.v', 'v', n2)\n", + "logger.log_attribute('n3.v', 'v', n3)\n", + "logger.log_attribute('l1.i_intf', 'i_intf', l1)\n", + "\n", + "\n", + "sim = dpsimpy.Simulation(name_sp_ref, dpsimpy.LogLevel.info)\n", + "sim.set_system(system)\n", + "sim.set_domain(dpsimpy.Domain.SP)\n", + "sim.set_time_step(0.0001)\n", + "sim.set_final_time(0.02)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read Results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# read Simulink log file\n", + "\n", + "# read EMT results\n", + "file_path = os.getcwd() + \"/logs/\" + name_sp_ref + \"/\" + name_sp_ref + \".csv\"\n", + "ts_dpsim_sp_ref = rt.read_timeseries_dpsim(file_path)\n", + "\n", + "#convert to emt\n", + "ts_dpsim_sp_ref = ts.frequency_shift_list(ts_dpsim_sp_ref, frequency)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Circuit with RL-Element" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name_sp = 'SP_RL-element'\n", + "dpsimpy.Logger.set_log_dir(\"logs/\" + name_sp)\n", + "\n", + "# Nodes\n", + "gnd = dpsimpy.sp.SimNode.gnd\n", + "n1 = dpsimpy.sp.SimNode('n1')\n", + "n1.set_initial_voltage(sim_pf.get_idobj_attr(n1_pf.name(), 'v').get()[0])\n", + "n2 = dpsimpy.sp.SimNode('n2')\n", + "n2.set_initial_voltage(sim_pf.get_idobj_attr(n3_pf.name(), 'v').get()[0])\n", + "\n", + "# Components\n", + "vs = dpsimpy.sp.ph1.VoltageSource('vs', dpsimpy.LogLevel.debug)\n", + "vs.set_parameters(V_ref=complex(10,0))\n", + "rl = dpsimpy.sp.ph1.ResInductor('rl', dpsimpy.LogLevel.debug)\n", + "rl.set_parameters(R=resistance, L=inductance)\n", + "c1 = dpsimpy.sp.ph1.Capacitor('c1', dpsimpy.LogLevel.debug)\n", + "c1.set_parameters(C=capacitance)\n", + "\n", + "# Connections\n", + "vs.connect([gnd, n1])\n", + "rl.connect([n2, n1])\n", + "c1.connect([gnd, n2])\n", + "\n", + "# Define system topology\n", + "system = dpsimpy.SystemTopology(frequency, [gnd, n1, n2], [vs, rl, c1])\n", + "\n", + "# Logging\n", + "logger = dpsimpy.Logger(name_sp)\n", + "logger.log_attribute('n1.v', 'v', n1)\n", + "logger.log_attribute('n2.v', 'v', n2)\n", + "logger.log_attribute('rl.i_intf', 'i_intf', rl)\n", + "logger.log_attribute('rl.v', 'v_intf', rl)\n", + "\n", + "sim = dpsimpy.Simulation(name_sp)\n", + "sim.set_system(system)\n", + "sim.set_domain(dpsimpy.Domain.SP)\n", + "sim.set_time_step(0.0001)\n", + "sim.set_final_time(0.02)\n", + "sim.add_logger(logger)\n", + "sim.run()" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Read Results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# read Simulink log file\n", + "\n", + "# read EMT results\n", + "file_path = os.getcwd() + \"/logs/\" + name_sp + \"/\" + name_sp + \".csv\"\n", + "ts_dpsim_sp = rt.read_timeseries_dpsim(file_path)\n", + "\n", + "#convert to emt\n", + "ts_dpsim_sp = ts.frequency_shift_list(ts_dpsim_sp, frequency)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot Results" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ts_dpsim_sp_ref[\"l1.i_intf_shift\"].label = 'i - REF'\n", + "ts_dpsim_sp_ref[\"n3.v_shift\"].label = 'vc - REF'\n", + "ts_dpsim_sp[\"rl.i_intf_shift\"].label = 'i RL Element'\n", + "ts_dpsim_sp[\"n2.v_shift\"].label = 'vc RL Element'\n", + "\n", + "pt.plot_timeseries(5, ts_dpsim_sp_ref[\"n3.v_shift\"])\n", + "pt.plot_timeseries(5, ts_dpsim_sp[\"n2.v_shift\"], plt_linestyle='--')\n", + "\n", + "pt.plot_timeseries(6, ts_dpsim_sp_ref[\"l1.i_intf_shift\"])\n", + "pt.plot_timeseries(6, ts_dpsim_sp[\"rl.i_intf_shift\"], plt_linestyle='--')" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Assert" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# calculate the RMSE between both models\n", + "err_current = ts.rmse(ts_dpsim_sp_ref[\"l1.i_intf_shift\"], ts_dpsim_sp[\"rl.i_intf_shift\"])\n", + "err_voltage = ts.rmse(ts_dpsim_sp_ref[\"n3.v_shift\"], ts_dpsim_sp[\"n2.v_shift\"])\n", + "\n", + "print(err_current)\n", + "print(err_voltage)\n", + "\n", + "assert err_current < epsilon\n", + "assert err_voltage < epsilon" + ] + } + ], + "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" + }, + "tests": { + "skip": false + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/Notebooks/Components/Line.ipynb b/examples/Notebooks/Components/Line.ipynb index 1c6a275061..19ae104ae4 100644 --- a/examples/Notebooks/Components/Line.ipynb +++ b/examples/Notebooks/Components/Line.ipynb @@ -21,7 +21,7 @@ "\n", "#%matplotlib widget\n", "\n", - "epsilon = 1e-12" + "epsilon = 2e-6" ] }, { @@ -785,7 +785,7 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in ['v1_0', 'v2_0', 'iline_0']:\n", + "for name in ['v1_0', 'v2_0', 'iline_0', 'v1_1', 'v2_1', 'iline_1', 'v1_2', 'v2_2', 'iline_2']:\n", " plt.plot(piline_elements_emt[name].time, piline_elements_emt[name].values - piline_component_emt[name].values, label=name+'_error')\n", "plt.legend()\n", "plt.show()" @@ -805,7 +805,7 @@ "outputs": [], "source": [ "errors_emt = []\n", - "for name in ['v1_0', 'v2_0', 'iline_0']:\n", + "for name in ['v1_0', 'v2_0', 'iline_0', 'v1_1', 'v2_1', 'iline_1', 'v1_2', 'v2_2', 'iline_2']:\n", " errors_emt.append(np.absolute(piline_elements_emt[name].values - piline_component_emt[name].values).max())\n", " print(name + ': ' + str(errors_emt[-1]))\n", "assert np.max(errors_emt) < epsilon" @@ -1243,7 +1243,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.10" + "version": "3.9.13" } }, "nbformat": 4, diff --git a/examples/Notebooks/Components/Trafo.ipynb b/examples/Notebooks/Components/Trafo.ipynb index e54a49a58c..7861ce4f84 100644 --- a/examples/Notebooks/Components/Trafo.ipynb +++ b/examples/Notebooks/Components/Trafo.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -27,6 +28,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -51,48 +53,38 @@ "trafo_resistance = 1\n", "trafo_inductance = 0.1\n", "trafo_power = 1e6\n", - "p_snub = dpsimpy.P_SNUB_TRANSFORMER * trafo_power\n", - "q_snub = dpsimpy.Q_SNUB_TRANSFORMER * trafo_power\n", "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", - "snubber_resistance_hv_side = np.abs(voltage_hv_side)**2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side)**2 / p_snub\n", - "snubber_capacitance_mv_side_to_hv_side = 1/(omega * ratio**2 * np.abs(voltage_mv_side)**2 / q_snub) \n", "\n", "n1 = dpsimpy.sp.SimNode('n1')\n", + "n1.set_initial_voltage(complex(voltage_hv_side, 0))\n", "n2 = dpsimpy.sp.SimNode('n2')\n", + "n2.set_initial_voltage(complex(99989.01435, -314.09334))\n", "vn1 = dpsimpy.sp.SimNode('vn1')\n", + "vn1.set_initial_voltage(complex(99990.001099, 0.031409))\n", "gnd = dpsimpy.sp.SimNode.gnd\n", "\n", "vs = dpsimpy.sp.ph1.VoltageSource('v_1')\n", "trafo_res = dpsimpy.sp.ph1.Resistor('trafo_res')\n", - "trafo_snubber_res_hv_side = dpsimpy.sp.ph1.Resistor('trafo_snub_res_mv') ##FIXME: Is the naming correct here?\n", - "trafo_snubber_res_mv_side = dpsimpy.sp.ph1.Resistor('trafo_snub_res_hv')\n", - "trafo_snubber_cap_mv_side = dpsimpy.sp.ph1.Capacitor('trafo_snub_cap_mv')\n", "trafo_ind = dpsimpy.sp.ph1.Inductor('trafo_ind')\n", "load_res = dpsimpy.sp.ph1.Resistor('r_1')\n", "\n", "vs.connect([gnd, n1])\n", "trafo_res.connect([n1, vn1])\n", "trafo_ind.connect([vn1, n2])\n", - "trafo_snubber_res_hv_side.connect([n1, gnd])\n", - "trafo_snubber_res_mv_side.connect([n2, gnd])\n", - "trafo_snubber_cap_mv_side.connect([n2, gnd])\n", "load_res.connect([n2, gnd])\n", "\n", "vs.set_parameters(complex(voltage_hv_side, 0))\n", "trafo_res.set_parameters(trafo_resistance)\n", "trafo_ind.set_parameters(trafo_inductance)\n", - "trafo_snubber_res_hv_side.set_parameters(snubber_resistance_hv_side)\n", - "trafo_snubber_res_mv_side.set_parameters(snubber_resistance_mv_side_to_hv_side)\n", - "trafo_snubber_cap_mv_side.set_parameters(snubber_capacitance_mv_side_to_hv_side)\n", "load_res.set_parameters(load_resistance_hv_side)\n", "\n", - "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, trafo_snubber_res_hv_side, trafo_snubber_res_mv_side, trafo_snubber_cap_mv_side, load_res])\n", + "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, load_res])\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "logger.log_attribute('v1', 'v', n1)\n", "logger.log_attribute('v2', 'v', n2)\n", + "logger.log_attribute('vn1', 'v', vn1)\n", "logger.log_attribute('itrafo', 'i_intf', trafo_ind)\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", @@ -106,6 +98,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -132,11 +125,13 @@ "load_resistance_mv_side = load_resistance_hv_side / ratio**2\n", "\n", "n1 = dpsimpy.sp.SimNode('n1')\n", + "n1.set_initial_voltage(complex(voltage_hv_side, 0))\n", "n2 = dpsimpy.sp.SimNode('n2')\n", + "n2.set_initial_voltage(complex(9998.901435, -31.409334))\n", "gnd = dpsimpy.sp.SimNode.gnd\n", "\n", "vs = dpsimpy.sp.ph1.VoltageSource('v_1', dpsimpy.LogLevel.debug)\n", - "trafo = dpsimpy.sp.ph1.Transformer('trafo', 'trafo', dpsimpy.LogLevel.debug, with_resistive_losses=True)\n", + "trafo = dpsimpy.sp.ph1.Transformer('trafo', 'trafo', dpsimpy.LogLevel.debug)\n", "load_res = dpsimpy.sp.ph1.Resistor('r_1', dpsimpy.LogLevel.debug)\n", "\n", "vs.connect([gnd, n1])\n", @@ -153,7 +148,7 @@ "logger = dpsimpy.Logger(sim_name)\n", "logger.log_attribute('v1', 'v', n1)\n", "logger.log_attribute('v2', 'v', n2)\n", - "logger.log_attribute('itrafo', 'i_intf', trafo)\n", + "logger.log_attribute('itrafo', 'i_intf', trafo) #primary side current\n", "\n", "sim = dpsimpy.Simulation(sim_name)\n", "sim.set_system(sys)\n", @@ -166,6 +161,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -189,52 +185,41 @@ "voltage_mv_side = 10000\n", "trafo_resistance = 1\n", "trafo_inductance = 0.1\n", - "trafo_power = 1e6\n", - "p_snub = dpsimpy.P_SNUB_TRANSFORMER * trafo_power\n", - "q_snub = dpsimpy.Q_SNUB_TRANSFORMER * trafo_power\n", "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", - "snubber_resistance_hv_side = np.abs(voltage_hv_side)**2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side)**2 / p_snub\n", - "snubber_capacitance_mv_side_to_hv_side = 1/(omega * ratio**2 * np.abs(voltage_mv_side)**2 / q_snub) \n", "\n", "n1 = dpsimpy.dp.SimNode('n1')\n", + "n1.set_initial_voltage(complex(voltage_hv_side, 0))\n", "n2 = dpsimpy.dp.SimNode('n2')\n", + "n2.set_initial_voltage(complex(99989.01435, -314.09334))\n", "vn1 = dpsimpy.dp.SimNode('vn1')\n", + "vn1.set_initial_voltage(complex(99990.001099, 0.031409))\n", "gnd = dpsimpy.dp.SimNode.gnd\n", "\n", - "vs = dpsimpy.dp.ph1.VoltageSource('v_1')\n", - "trafo_res = dpsimpy.dp.ph1.Resistor('trafo_res')\n", - "trafo_snubber_res_hv_side = dpsimpy.dp.ph1.Resistor('trafo_snub_res_mv') ##FIXME: Is the naming correct here?\n", - "trafo_snubber_res_mv_side = dpsimpy.dp.ph1.Resistor('trafo_snub_res_hv')\n", - "trafo_snubber_cap_mv_side = dpsimpy.dp.ph1.Capacitor('trafo_snub_cap_mv')\n", - "trafo_ind = dpsimpy.dp.ph1.Inductor('trafo_ind')\n", - "load_res = dpsimpy.dp.ph1.Resistor('r_1')\n", + "vs = dpsimpy.dp.ph1.VoltageSource('v_1', dpsimpy.LogLevel.debug)\n", + "trafo_res = dpsimpy.dp.ph1.Resistor('trafo_res', dpsimpy.LogLevel.debug)\n", + "trafo_ind = dpsimpy.dp.ph1.Inductor('trafo_ind', dpsimpy.LogLevel.debug)\n", + "load_res = dpsimpy.dp.ph1.Resistor('r_1', dpsimpy.LogLevel.debug)\n", "\n", "vs.connect([gnd, n1])\n", "trafo_res.connect([n1, vn1])\n", "trafo_ind.connect([vn1, n2])\n", - "trafo_snubber_res_hv_side.connect([n1, gnd])\n", - "trafo_snubber_res_mv_side.connect([n2, gnd])\n", - "trafo_snubber_cap_mv_side.connect([n2, gnd])\n", "load_res.connect([n2, gnd])\n", "\n", "vs.set_parameters(complex(voltage_hv_side, 0))\n", "trafo_res.set_parameters(trafo_resistance)\n", "trafo_ind.set_parameters(trafo_inductance)\n", - "trafo_snubber_res_hv_side.set_parameters(snubber_resistance_hv_side)\n", - "trafo_snubber_res_mv_side.set_parameters(snubber_resistance_mv_side_to_hv_side)\n", - "trafo_snubber_cap_mv_side.set_parameters(snubber_capacitance_mv_side_to_hv_side)\n", "load_res.set_parameters(load_resistance_hv_side)\n", "\n", - "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, trafo_snubber_res_hv_side, trafo_snubber_res_mv_side, trafo_snubber_cap_mv_side, load_res])\n", + "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, load_res])\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "logger.log_attribute('v1', 'v', n1)\n", "logger.log_attribute('v2', 'v', n2)\n", + "logger.log_attribute('vn1', 'v', vn1)\n", "logger.log_attribute('itrafo', 'i_intf', trafo_ind)\n", "\n", - "sim = dpsimpy.Simulation(sim_name)\n", + "sim = dpsimpy.Simulation(sim_name, dpsimpy.LogLevel.debug)\n", "sim.set_system(sys)\n", "sim.set_time_step(time_step)\n", "sim.set_final_time(final_time)\n", @@ -245,6 +230,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -271,11 +257,13 @@ "load_resistance_mv_side = load_resistance_hv_side / ratio**2\n", "\n", "n1 = dpsimpy.dp.SimNode('n1')\n", + "n1.set_initial_voltage(complex(voltage_hv_side, 0))\n", "n2 = dpsimpy.dp.SimNode('n2')\n", + "n2.set_initial_voltage(complex(9998.901435, -31.409334))\n", "gnd = dpsimpy.dp.SimNode.gnd\n", "\n", "vs = dpsimpy.dp.ph1.VoltageSource('v_1', dpsimpy.LogLevel.debug)\n", - "trafo = dpsimpy.dp.ph1.Transformer('trafo', 'trafo', dpsimpy.LogLevel.debug, with_resistive_losses=True)\n", + "trafo = dpsimpy.dp.ph1.Transformer('trafo', dpsimpy.LogLevel.debug)\n", "load_res = dpsimpy.dp.ph1.Resistor('r_1', dpsimpy.LogLevel.debug)\n", "\n", "vs.connect([gnd, n1])\n", @@ -283,8 +271,7 @@ "load_res.connect([n2, gnd])\n", "\n", "vs.set_parameters(complex(voltage_hv_side, 0))\n", - "trafo.set_parameters(voltage_hv_side, voltage_mv_side, trafo_power, ratio, 0,\n", - " trafo_resistance, trafo_inductance)\n", + "trafo.set_parameters(voltage_hv_side, voltage_mv_side, ratio, 0, trafo_resistance, trafo_inductance)\n", "load_res.set_parameters(load_resistance_mv_side)\n", "\n", "sys = dpsimpy.SystemTopology(50, [n1, n2], [vs, trafo, load_res])\n", @@ -305,6 +292,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -329,45 +317,34 @@ "trafo_resistance = 1\n", "trafo_inductance = 0.1\n", "trafo_power = 1e6\n", - "p_snub = dpsimpy.P_SNUB_TRANSFORMER * trafo_power\n", - "q_snub = dpsimpy.Q_SNUB_TRANSFORMER * trafo_power\n", "load_resistance_hv_side = 10000\n", "ratio = voltage_hv_side / voltage_mv_side\n", - "snubber_resistance_hv_side = np.abs(voltage_hv_side)**2 / p_snub\n", - "snubber_resistance_mv_side_to_hv_side = ratio**2 * np.abs(voltage_mv_side)**2 / p_snub\n", - "snubber_capacitance_mv_side_to_hv_side = 1/(omega * ratio**2 * np.abs(voltage_mv_side)**2 / q_snub) \n", "\n", "\n", "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", + "n1.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(complex(voltage_hv_side, 0)))\n", "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "n2.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(complex(99989.01435, -314.09334)))\n", "vn1 = dpsimpy.emt.SimNode('vn1', dpsimpy.PhaseType.ABC)\n", + "vn1.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(complex(99990.001099, 0.031409)))\n", "gnd = dpsimpy.emt.SimNode.gnd\n", "\n", "vs = dpsimpy.emt.ph3.VoltageSource('v_1')\n", "trafo_res = dpsimpy.emt.ph3.Resistor('trafo_res')\n", - "trafo_snubber_res_hv_side = dpsimpy.emt.ph3.Resistor('trafo_snub_res_mv') ##FIXME: Is the naming correct here?\n", - "trafo_snubber_res_mv_side = dpsimpy.emt.ph3.Resistor('trafo_snub_res_hv')\n", - "trafo_snubber_cap_mv_side = dpsimpy.emt.ph3.Capacitor('trafo_snub_cap_mv')\n", "trafo_ind = dpsimpy.emt.ph3.Inductor('trafo_ind')\n", "load_res = dpsimpy.emt.ph3.Resistor('r_1')\n", "\n", "vs.connect([gnd, n1])\n", "trafo_res.connect([n1, vn1])\n", "trafo_ind.connect([vn1, n2])\n", - "trafo_snubber_res_hv_side.connect([n1, gnd])\n", - "trafo_snubber_res_mv_side.connect([n2, gnd])\n", - "trafo_snubber_cap_mv_side.connect([n2, gnd])\n", "load_res.connect([n2, gnd])\n", "\n", "vs.set_parameters(dpsimpy.Math.single_phase_variable_to_three_phase(complex(voltage_hv_side, 0)), 50)\n", "trafo_res.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_resistance))\n", "trafo_ind.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_inductance))\n", - "trafo_snubber_res_hv_side.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(snubber_resistance_hv_side))\n", - "trafo_snubber_res_mv_side.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(snubber_resistance_mv_side_to_hv_side))\n", - "trafo_snubber_cap_mv_side.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(snubber_capacitance_mv_side_to_hv_side))\n", "load_res.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(load_resistance_hv_side))\n", "\n", - "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, trafo_snubber_res_hv_side, trafo_snubber_res_mv_side, trafo_snubber_cap_mv_side, load_res])\n", + "sys = dpsimpy.SystemTopology(50, [n1, n2, vn1], [vs, trafo_res, trafo_ind, load_res])\n", "\n", "logger = dpsimpy.Logger(sim_name)\n", "logger.log_attribute('v1', 'v', n1)\n", @@ -385,6 +362,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -411,19 +389,21 @@ "load_resistance_mv_side = load_resistance_hv_side / ratio**2\n", "\n", "n1 = dpsimpy.emt.SimNode('n1', dpsimpy.PhaseType.ABC)\n", + "n1.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(complex(voltage_hv_side, 0)))\n", "n2 = dpsimpy.emt.SimNode('n2', dpsimpy.PhaseType.ABC)\n", + "n2.set_initial_voltage(dpsimpy.Math.single_phase_variable_to_three_phase(complex(9998.901435, -31.409334)))\n", "gnd = dpsimpy.emt.SimNode.gnd\n", "\n", - "vs = dpsimpy.emt.ph3.VoltageSource('v_1', dpsimpy.LogLevel.debug)\n", - "trafo = dpsimpy.emt.ph3.Transformer('trafo', 'trafo', dpsimpy.LogLevel.debug, with_resistive_losses=True)\n", - "load_res = dpsimpy.emt.ph3.Resistor('r_1', dpsimpy.LogLevel.debug)\n", + "vs = dpsimpy.emt.ph3.VoltageSource('v_1', dpsimpy.LogLevel.info)\n", + "trafo = dpsimpy.emt.ph3.Transformer('trafo', 'trafo', dpsimpy.LogLevel.info)\n", + "load_res = dpsimpy.emt.ph3.Resistor('r_1', dpsimpy.LogLevel.info)\n", "\n", "vs.connect([gnd, n1])\n", "trafo.connect([n1, n2])\n", "load_res.connect([n2, gnd])\n", "\n", "vs.set_parameters(dpsimpy.Math.single_phase_variable_to_three_phase(complex(voltage_hv_side, 0)), 50)\n", - "trafo.set_parameters(voltage_hv_side, voltage_mv_side, trafo_power, ratio, 0,\n", + "trafo.set_parameters(voltage_hv_side, voltage_mv_side, ratio, 0,\n", " dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_resistance),\n", " dpsimpy.Math.single_phase_parameter_to_three_phase(trafo_inductance))\n", "load_res.set_parameters(dpsimpy.Math.single_phase_parameter_to_three_phase(load_resistance_mv_side))\n", @@ -445,6 +425,14 @@ "sim.run()" ] }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## SP Trafo with elements" + ] + }, { "cell_type": "code", "execution_count": null, @@ -483,6 +471,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -527,6 +516,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -547,6 +537,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -567,6 +558,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -611,6 +603,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -627,7 +620,7 @@ "log_name = 'DP_Trafo_Component'\n", "print(work_dir + log_name + '.csv')\n", "trafo_component = rt.read_timeseries_dpsim(work_dir + log_name + '.csv')\n", - "trafo_component_dp_shifted = ts.frequency_shift_list(trafo_component, 50)" + "trafo_component_dp_shifted = ts.frequency_shift_list(trafo_component, 50)\n" ] }, { @@ -655,6 +648,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -675,6 +669,13 @@ ] }, { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [] + }, + { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -695,6 +696,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -738,6 +740,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -763,9 +766,9 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_component_emt['v1_0'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_0'].values, label='v1_0')\n", - "plt.plot(trafo_component_emt['v1_1'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_1'].values, label='v1_1')\n", - "plt.plot(trafo_component_emt['v1_2'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_2'].values, label='v1_2')\n", + "plt.plot(trafo_component_emt['v1_0'].time, -PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_0'].values, label='v1_0')\n", + "#plt.plot(trafo_component_emt['v1_1'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_1'].values, label='v1_1')\n", + "#plt.plot(trafo_component_emt['v1_2'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['v1_2'].values, label='v1_2')\n", "plt.legend()\n", "plt.show()" ] @@ -777,14 +780,15 @@ "outputs": [], "source": [ "plt.figure()\n", - "plt.plot(trafo_component_emt['itrafo_0'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_0'].values, label='itrafo_0')\n", - "plt.plot(trafo_component_emt['itrafo_1'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_1'].values, label='itrafo_1')\n", - "plt.plot(trafo_component_emt['itrafo_2'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_2'].values, label='itrafo_2')\n", + "plt.plot(trafo_component_emt['itrafo_0'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_2'].values, label='itrafo_0')\n", + "#plt.plot(trafo_component_emt['itrafo_1'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_1'].values, label='itrafo_1')\n", + "#plt.plot(trafo_component_emt['itrafo_2'].time, PEAK1PH_TO_RMS3PH*trafo_component_emt['itrafo_2'].values, label='itrafo_2')\n", "plt.legend()\n", "plt.show()" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -798,13 +802,15 @@ "outputs": [], "source": [ "plt.figure()\n", - "for name in ['v1_0', 'v1_1', 'v1_1', 'itrafo_0', 'itrafo_1', 'itrafo_2']:\n", + "#for name in ['v1_0', 'v1_1', 'v1_1', 'itrafo_0', 'itrafo_1', 'itrafo_2']:\n", + "for name in ['v1_0']:\n", " plt.plot(trafo_elements_emt[name].time, trafo_elements_emt[name].values - trafo_component_emt[name].values, label=name+'_error')\n", "plt.legend()\n", "plt.show()" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -818,13 +824,14 @@ "outputs": [], "source": [ "errors_emt = []\n", - "for name in ['v1_0', 'v1_1', 'v1_1', 'itrafo_0', 'itrafo_1', 'itrafo_2']:\n", + "for name in ['v1_0', 'v1_1', 'v1_2', 'itrafo_0', 'itrafo_1', 'itrafo_2']:\n", " errors_emt.append(np.absolute(trafo_elements_emt[name].values - trafo_component_emt[name].values).max())\n", " print(name + ': ' + str(errors_emt[-1]))\n", "assert np.max(errors_emt) < epsilon" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -858,6 +865,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -878,10 +886,11 @@ " print(name[0]+' vs. '+name[1] + ' (abs): ' + str(compare_errors_abs[-1]))\n", " print(name[0]+' vs. '+name[1] + ' (rel): ' + str(compare_errors_rel[-1]))\n", "print('Max rel error: '+ '{:.2}'.format(np.max(compare_errors_rel)*100) +'%')\n", - "assert np.max(compare_errors_rel) < 3e-1" + "assert np.max(compare_errors_rel) < 1e-12" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -915,6 +924,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -935,7 +945,7 @@ " print(name[0]+' vs. '+name[1] + ' (abs): ' + str(compare_errors_abs[-1]))\n", " print(name[0]+' vs. '+name[1] + ' (rel): ' + str(compare_errors_rel[-1]))\n", "print('Max rel error: '+ '{:.2}'.format(np.max(compare_errors_rel)*100) +'%')\n", - "assert np.max(compare_errors_rel) < 1e-4" + "assert np.max(compare_errors_rel) < 3.8e-6" ] } ], @@ -944,7 +954,8 @@ "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" }, "kernelspec": { - "display_name": "Python 3.9.6 64-bit", + "display_name": "Python 3 (ipykernel)", + "language": "python", "name": "python3" }, "language_info": { diff --git a/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab.ipynb b/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab.ipynb index 204e721545..8d8b068725 100644 --- a/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab.ipynb +++ b/examples/Notebooks/Grids/DP_WSCC9bus_SGTrStab.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -22,7 +23,7 @@ " out_file.write(content)\n", "\n", "url = 'https://raw.githubusercontent.com/dpsim-simulator/cim-grid-data/master/WSCC-09/WSCC-09_RX_Dyn/WSCC-09_RX'\n", - "filename = 'WSCC-09'\n", + "filename = 'WSCC-09_RX_Dyn_Second'\n", "download_grid_data(filename+'_EQ.xml', url+'_EQ.xml')\n", "download_grid_data(filename+'_TP.xml', url+'_TP.xml')\n", "download_grid_data(filename+'_SV.xml', url+'_SV.xml')\n", @@ -55,6 +56,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -91,6 +93,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -112,6 +115,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -131,6 +135,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -148,6 +153,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -165,6 +171,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -187,6 +194,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -207,6 +215,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -224,6 +233,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -256,7 +266,7 @@ "pt.plot_timeseries(2, phasors['v7']['abs'])\n", "pt.plot_timeseries(2, phasors['v8']['abs'])\n", "pt.plot_timeseries(2, phasors['v9']['abs'])\n", - "plt.ylim([200000,240000])\n", + "#plt.ylim([200000,240000])\n", "plt.xlim([0,0.1])" ] }, diff --git a/examples/Notebooks/Grids/DP_WSCC9bus_SGVoltageSource.ipynb b/examples/Notebooks/Grids/DP_WSCC9bus_SGVoltageSource.ipynb index 6747701970..0e42616c5a 100644 --- a/examples/Notebooks/Grids/DP_WSCC9bus_SGVoltageSource.ipynb +++ b/examples/Notebooks/Grids/DP_WSCC9bus_SGVoltageSource.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -55,6 +56,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -62,6 +64,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -109,6 +112,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -128,6 +132,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -145,6 +150,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -162,6 +168,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -184,6 +191,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -204,6 +212,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -219,10 +228,11 @@ "outputs": [], "source": [ "pt.plot_timeseries(1, phasors['v9']['phase'])\n", - "plt.ylim([2.10405, 2.1042])" + "#plt.ylim([2.10405, 2.1042])" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -240,6 +250,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -276,6 +287,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ diff --git a/examples/Notebooks/Grids/SP_WSCC9bus_SGTrStab_Switch_PSAT_Validation.ipynb b/examples/Notebooks/Grids/SP_WSCC9bus_SGTrStab_Switch_PSAT_Validation.ipynb index 16099921b3..710c6682e4 100644 --- a/examples/Notebooks/Grids/SP_WSCC9bus_SGTrStab_Switch_PSAT_Validation.ipynb +++ b/examples/Notebooks/Grids/SP_WSCC9bus_SGTrStab_Switch_PSAT_Validation.ipynb @@ -1,6 +1,7 @@ { "cells": [ { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -55,6 +56,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -111,6 +113,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -133,6 +136,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -153,6 +157,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -184,6 +189,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -208,6 +214,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -249,6 +256,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -274,6 +282,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -286,12 +295,13 @@ "metadata": {}, "outputs": [], "source": [ - "assert(ts_dpsim[syngen_omega_name_dpsim_list[0]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[0]], ts_psat[syngen_omega_name_psat_list[2]]) < 2e-4)\n", - "assert(ts_dpsim[syngen_omega_name_dpsim_list[1]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[1]], ts_psat[syngen_omega_name_psat_list[0]]) < 2e-4)\n", - "assert(ts_dpsim[syngen_omega_name_dpsim_list[2]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[2]], ts_psat[syngen_omega_name_psat_list[1]]) < 2e-4)" + "assert(ts_dpsim[syngen_omega_name_dpsim_list[0]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[0]], ts_psat[syngen_omega_name_psat_list[2]]) < 1.1e-5)\n", + "assert(ts_dpsim[syngen_omega_name_dpsim_list[1]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[1]], ts_psat[syngen_omega_name_psat_list[0]]) < 1.2e-4)\n", + "assert(ts_dpsim[syngen_omega_name_dpsim_list[2]].rmse(ts_dpsim[syngen_omega_name_dpsim_list[2]], ts_psat[syngen_omega_name_psat_list[1]]) < 9.93e-5)" ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -316,6 +326,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -347,6 +358,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ @@ -371,6 +383,7 @@ ] }, { + "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [