DPsim
SP_Ph1_RXLine.cpp
1 /* Copyright 2017-2021 Institute for Automation of Complex Power Systems,
2  * EONERC, RWTH Aachen University
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7  *********************************************************************************/
8 
9 #include "dpsim-models/SP/SP_Ph1_RXLine.h"
10 
11 using namespace CPS;
12 
13 SP::Ph1::RXLine::RXLine(String uid, String name, Real baseVoltage,
14  Real resistance, Real inductance,
15  Logger::Level logLevel)
16  : Base::Ph1::PiLine(mAttributes),
17  CompositePowerComp<Complex>(uid, name, true, true, logLevel),
18  mBaseVoltage(mAttributes->create<Real>("base_Voltage", baseVoltage)),
19  mInductance(mAttributes->create<Real>("L_series")),
20  mActivePowerInjection(mAttributes->create<Real>("p_inj")),
21  mReactivePowerInjection(mAttributes->create<Real>("q_inj")),
22  mCurrent(mAttributes->create<MatrixComp>("current_vector")),
23  mActivePowerBranch(mAttributes->create<Matrix>("p_branch_vector")),
24  mReactivePowerBranch(mAttributes->create<Matrix>("q_branch_vector")) {
25 
26  setTerminalNumber(2);
27 
28  **mSeriesRes = resistance;
29  **mInductance = inductance;
30 
31  **mCurrent = MatrixComp::Zero(2, 1);
32  **mActivePowerBranch = Matrix::Zero(2, 1);
33  **mReactivePowerBranch = Matrix::Zero(2, 1);
34  // mLog.Log(Logger::Level::DEBUG) << "Create " << this->type() << " " << name
35  // << " R=" << resistance << " L=" << inductance
36  // << std::endl;
37 }
38 
39 SP::Ph1::RXLine::RXLine(String uid, String name, Logger::Level logLevel)
40  : Base::Ph1::PiLine(mAttributes),
41  CompositePowerComp<Complex>(uid, name, true, true, logLevel),
42  mBaseVoltage(mAttributes->create<Real>("base_Voltage")),
43  mInductance(mAttributes->create<Real>("L_series")),
44  mActivePowerInjection(mAttributes->create<Real>("p_inj")),
45  mReactivePowerInjection(mAttributes->create<Real>("q_inj")),
46  mCurrent(mAttributes->create<MatrixComp>("current_vector")),
47  mActivePowerBranch(mAttributes->create<Matrix>("p_branch_vector")),
48  mReactivePowerBranch(mAttributes->create<Matrix>("q_branch_vector")) {
49 
50  setVirtualNodeNumber(1);
51  setTerminalNumber(2);
52  **mIntfVoltage = MatrixComp::Zero(1, 1);
53  **mIntfCurrent = MatrixComp::Zero(1, 1);
54 }
55 
56 void SP::Ph1::RXLine::setPerUnitSystem(Real baseApparentPower, Real baseOmega) {
57  mBaseApparentPower = baseApparentPower;
58  mBaseOmega = baseOmega;
59  mBaseImpedance = (**mBaseVoltage * **mBaseVoltage) / mBaseApparentPower;
60  mBaseAdmittance = 1.0 / mBaseImpedance;
61  mBaseInductance = mBaseImpedance / mBaseOmega;
63  mBaseCurrent = baseApparentPower / (**mBaseVoltage * sqrt(3));
64  /*
65  mLog.Log(Logger::Level::INFO) << "#### Set Per Unit System for " << **mName << std::endl;
66  mLog.Log(Logger::Level::INFO) << " Base Voltage= " << mBaseVoltage << " [V] " << " Base Impedance= " << mBaseImpedance << " [Ohm] " << std::endl;
67  */
68 
69  mSeriesResPerUnit = **mSeriesRes / mBaseImpedance;
70  mSeriesIndPerUnit = **mInductance / mBaseInductance;
71  /*
72  mLog.Log(Logger::Level::INFO) << "Series Resistance Per Unit= " << " " << mSeriesResPerUnit << " [Ohm] "
73  << " Series Inductance Per Unit= " << " " << mSeriesIndPerUnit << " [H] "
74  << std::endl;
75  mLog.Log(Logger::Level::INFO) << "r " << mSeriesResPerUnit << std::endl << " x: " << mBaseOmega * mInductance / mBaseImpedance<<std::endl;*/
76 }
77 
78 void SP::Ph1::RXLine::pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow &Y) {
79  updateMatrixNodeIndices();
80  int bus1 = this->matrixNodeIndex(0);
81  int bus2 = this->matrixNodeIndex(1);
82 
83  //dimension check
84  /* TODO: FIX
85  if (bus1 > (n - 1) || bus2 > (n - 1)) {
86  std::stringstream ss;
87  ss << "Line>>" << this->getName() << ": Wrong Y dimension: " << n;
88  throw std::invalid_argument(ss.str());
89  //std::cout << "Line>>" << Name << ": Wrong Y dimension: " << n << endl;
90  return;
91  }
92  */
93 
94  //create the element admittance matrix
95  Complex y =
96  Complex(1, 0) / Complex(mSeriesResPerUnit, 1. * mSeriesIndPerUnit);
97 
98  //Fill the internal matrix
99  mY_element = MatrixComp(2, 2);
100  mY_element(0, 0) = y;
101  mY_element(0, 1) = -y;
102  mY_element(1, 0) = -y;
103  mY_element(1, 1) = y;
104 
105  //check for inf or nan
106  for (int i = 0; i < 2; i++)
107  for (int j = 0; j < 2; j++)
108  if (std::isinf(mY_element.coeff(i, j).real()) ||
109  std::isinf(mY_element.coeff(i, j).imag())) {
110  std::cout << mY_element << std::endl;
111  std::stringstream ss;
112  ss << "Line>>" << this->name()
113  << ": infinite or nan values in the element Y at: " << i << "," << j;
114  throw std::invalid_argument(ss.str());
115  std::cout << "Line>>" << this->name()
116  << ": infinite or nan values in the element Y at: " << i
117  << "," << j << std::endl;
118  }
119 
120  //set the circuit matrix values
121  Y.coeffRef(bus1, bus1) += mY_element.coeff(0, 0);
122  Y.coeffRef(bus1, bus2) += mY_element.coeff(0, 1);
123  Y.coeffRef(bus2, bus1) += mY_element.coeff(1, 0);
124  Y.coeffRef(bus2, bus2) += mY_element.coeff(1, 1);
125 
126  //mLog.Log(Logger::Level::INFO) << "#### Y matrix stamping: " << std::endl;
127  //mLog.Log(Logger::Level::INFO) << mY_element << std::endl;
128 }
129 
130 void SP::Ph1::RXLine::updateBranchFlow(VectorComp &current,
131  VectorComp &powerflow) {
132  **mCurrent = current * mBaseCurrent;
133  **mActivePowerBranch = powerflow.real() * mBaseApparentPower;
134  **mReactivePowerBranch = powerflow.imag() * mBaseApparentPower;
135 }
136 
137 void SP::Ph1::RXLine::storeNodalInjection(Complex powerInjection) {
138  **mActivePowerInjection = std::real(powerInjection) * mBaseApparentPower;
139  **mReactivePowerInjection = std::imag(powerInjection) * mBaseApparentPower;
140 }
141 
142 MatrixComp SP::Ph1::RXLine::Y_element() { return mY_element; }
143 
146  auto copy = RXLine::make(name, mLogLevel);
147  copy->setParameters(**mSeriesRes, **mSeriesInd);
148  return copy;
149 }
150 
152 
153  (**mIntfVoltage)(0, 0) = initialSingleVoltage(1) - initialSingleVoltage(0);
154  Complex impedance = {**mSeriesRes, **mSeriesInd * 2. * PI * frequency};
155  (**mIntfCurrent)(0, 0) = (**mIntfVoltage)(0, 0) / impedance;
156  mVirtualNodes[0]->setInitialVoltage(initialSingleVoltage(0) +
157  (**mIntfCurrent)(0, 0) * **mSeriesRes);
158 
159  // Default model with virtual node in between
160  mSubResistor =
161  std::make_shared<SP::Ph1::Resistor>(**mName + "_res", mLogLevel);
162  mSubResistor->setParameters(**mSeriesRes);
163  mSubResistor->connect({mTerminals[0]->node(), mVirtualNodes[0]});
164  mSubResistor->initializeFromNodesAndTerminals(frequency);
165  addMNASubComponent(mSubResistor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
166  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
167 
168  mSubInductor =
169  std::make_shared<SP::Ph1::Inductor>(**mName + "_ind", mLogLevel);
170  mSubInductor->setParameters(**mSeriesInd);
171  mSubInductor->connect({mVirtualNodes[0], mTerminals[1]->node()});
172  mSubInductor->initializeFromNodesAndTerminals(frequency);
173  addMNASubComponent(mSubInductor, MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
174  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
175 
176  mInitialResistor =
177  std::make_shared<SP::Ph1::Resistor>(**mName + "_snubber_res", mLogLevel);
178  mInitialResistor->setParameters(1e6);
179  mInitialResistor->connect({SimNode::GND, mTerminals[1]->node()});
180  mInitialResistor->initializeFromNodesAndTerminals(frequency);
181  addMNASubComponent(mInitialResistor,
182  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT,
183  MNA_SUBCOMP_TASK_ORDER::TASK_BEFORE_PARENT, true);
184 
185  SPDLOG_LOGGER_INFO(mSLog,
186  "\n--- Initialization from powerflow ---"
187  "\nVoltage across: {:s}"
188  "\nCurrent: {:s}"
189  "\nTerminal 0 voltage: {:s}"
190  "\nTerminal 1 voltage: {:s}"
191  "\n--- Initialization from powerflow finished ---",
192  Logger::phasorToString((**mIntfVoltage)(0, 0)),
193  Logger::phasorToString((**mIntfCurrent)(0, 0)),
194  Logger::phasorToString(initialSingleVoltage(0)),
195  Logger::phasorToString(initialSingleVoltage(1)));
196 }
197 
198 void SP::Ph1::RXLine::mnaParentAddPreStepDependencies(
199  AttributeBase::List &prevStepDependencies,
200  AttributeBase::List &attributeDependencies,
201  AttributeBase::List &modifiedAttributes) {
202  modifiedAttributes.push_back(mRightVector);
203 };
204 
205 void SP::Ph1::RXLine::mnaParentAddPostStepDependencies(
206  AttributeBase::List &prevStepDependencies,
207  AttributeBase::List &attributeDependencies,
208  AttributeBase::List &modifiedAttributes,
209  Attribute<Matrix>::Ptr &leftVector) {
210  attributeDependencies.push_back(leftVector);
211  modifiedAttributes.push_back(mIntfCurrent);
212  modifiedAttributes.push_back(mIntfVoltage);
213 };
214 
215 void SP::Ph1::RXLine::mnaParentPreStep(Real time, Int timeStepCount) {
216  mnaCompApplyRightSideVectorStamp(**mRightVector);
217 }
218 
219 void SP::Ph1::RXLine::mnaParentPostStep(Real time, Int timeStepCount,
220  Attribute<Matrix>::Ptr &leftVector) {
221  mnaCompUpdateVoltage(**leftVector);
222  mnaCompUpdateCurrent(**leftVector);
223 }
224 
225 void SP::Ph1::RXLine::mnaCompUpdateVoltage(const Matrix &leftVector) {
226  (**mIntfVoltage)(0, 0) = 0;
227  if (terminalNotGrounded(1))
228  (**mIntfVoltage)(0, 0) =
229  Math::complexFromVectorElement(leftVector, matrixNodeIndex(1));
230  if (terminalNotGrounded(0))
231  (**mIntfVoltage)(0, 0) =
232  (**mIntfVoltage)(0, 0) -
233  Math::complexFromVectorElement(leftVector, matrixNodeIndex(0));
234 }
235 
236 void SP::Ph1::RXLine::mnaCompUpdateCurrent(const Matrix &leftVector) {
237  (**mIntfCurrent)(0, 0) = mSubInductor->intfCurrent()(0, 0);
238 }
const Attribute< Real >::Ptr mSeriesRes
Resistance along the line [ohms].
Base class for composite power components.
PI-line static phasor model.
Definition: SP_Ph1_PiLine.h:30
void initializeFromNodesAndTerminals(Real frequency) override
Initializes component from power flow data.
const Attribute< Real >::Ptr mInductance
Definition: SP_Ph1_RXLine.h:66
SimPowerComp< Complex >::Ptr clone(String name) override
DEPRECATED: Delete method.
void setPerUnitSystem(Real baseApparentPower, Real baseOmega)
Specify per-unit system by base voltage, base apparent power and omega (rms value for voltage expecte...
const Attribute< Matrix >::Ptr mActivePowerBranch
branch active powerflow [W], coef(0) has data from node 0, coef(1) from node 1.
Definition: SP_Ph1_RXLine.h:78
void pfApplyAdmittanceMatrixStamp(SparseMatrixCompRow &Y) override
Stamps admittance matrix.
void updateBranchFlow(VectorComp &current, VectorComp &powerflow)
updates branch current and power flow, input pu value, update with real value
const Attribute< MatrixComp >::Ptr mCurrent
branch Current flow [A], coef(0) has data from node 0, coef(1) from node 1.
Definition: SP_Ph1_RXLine.h:75
const Attribute< Matrix >::Ptr mReactivePowerBranch
branch reactive powerflow [Var], coef(0) has data from node 0, coef(1) from node 1.
Definition: SP_Ph1_RXLine.h:81
RXLine(String uid, String name, Real baseVoltage, Real resistance, Real inductance, Logger::Level logLevel=Logger::Level::off)
Defines UID, name, base voltage, component parameters and logging level.
void storeNodalInjection(Complex powerInjection)
stores nodal injection power in this line object
MatrixComp Y_element()
get admittance matrix
Base class for all components that are transmitting power.
Definition: SimPowerComp.h:17
const Attribute< MatrixVar< Complex > >::Ptr mIntfCurrent
Current through component.
Definition: SimPowerComp.h:47
const Attribute< MatrixVar< Complex > >::Ptr mIntfVoltage
Voltage between terminals.
Definition: SimPowerComp.h:45