DPsim
Loading...
Searching...
No Matches
SP_Ph1_SolidStateTransformer.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_SolidStateTransformer.h>
10
11using namespace CPS;
12
13SP::Ph1::SolidStateTransformer::SolidStateTransformer(String uid, String name,
14 Logger::Level logLevel)
15 : CompositePowerComp<Complex>(uid, name, false, false, logLevel),
16 mPref(mAttributes->create<Real>("P_ref",
17 std::numeric_limits<double>::infinity())),
18 mQ1ref(mAttributes->create<Real>("Q1_ref")),
19 mQ2ref(mAttributes->create<Real>("Q2_ref")) {
20 SPDLOG_LOGGER_INFO(mSLog, "Create {} of type {}", **mName, this->type());
21 mSLog->flush();
22 **mIntfVoltage = MatrixComp::Zero(1, 1);
23 **mIntfCurrent = MatrixComp::Zero(1, 1);
24 setTerminalNumber(2);
25};
26
27SimPowerComp<Complex>::Ptr SP::Ph1::SolidStateTransformer::clone(String name) {
28 // everything set by initializeFromNodesAndTerminals
29 return SolidStateTransformer::make(name, mLogLevel);
30}
31
32void SP::Ph1::SolidStateTransformer::setParameters(Real nomV1, Real nomV2,
33 Real Pref, Real Q1ref,
34 Real Q2ref) {
35 mNominalVoltageEnd1 = nomV1;
36 mNominalVoltageEnd2 = nomV2;
37 **mPref = Pref;
38 **mQ1ref = Q1ref;
39 **mQ2ref = Q2ref;
40 mP2 = -1 * std::sqrt(Pref * Pref + Q1ref * Q1ref - Q2ref * Q2ref);
41}
42
45 return;
46 mSubCompCreated = true;
47
48 mSubLoadSide1 = Load::make(**mName + "_subLoad1", mLogLevel);
49 mSubLoadSide2 = Load::make(**mName + "_subLoad2", mLogLevel);
50 mSubLoadSide1->connect({mTerminals[0]->node()});
51 mSubLoadSide2->connect({mTerminals[1]->node()});
52
53 addMNASubComponent(mSubLoadSide1, MNA_SUBCOMP_TASK_ORDER::NO_TASK,
54 MNA_SUBCOMP_TASK_ORDER::NO_TASK, false);
55 addMNASubComponent(mSubLoadSide2, MNA_SUBCOMP_TASK_ORDER::NO_TASK,
56 MNA_SUBCOMP_TASK_ORDER::NO_TASK, false);
57}
58
60 Real frequency) {
61
62 // Parametrize the sub-loads before the recursive sub-init runs, else each Load wrongly reads its own terminal.
63 mSubLoadSide1->setParameters(**mPref, **mQ1ref, mNominalVoltageEnd1);
64 mSubLoadSide2->setParameters(mP2, **mQ2ref, mNominalVoltageEnd2);
65
66 if (std::isinf(mP2)) {
67 std::stringstream ss;
68 ss << "SST >>" << this->name()
69 << ": infinite or nan values. Or initialized before setting parameters.";
70 throw std::invalid_argument(ss.str());
71 }
72 if ((**mPref * mP2) > 0) {
73 throw std::invalid_argument(
74 "power at primary and secondary sides should be opposite");
75 }
76
77 SPDLOG_LOGGER_INFO(mSLog,
78 "\n--- Initialization from powerflow ---"
79 "\nTerminal 0 power flow: {:s} VA"
80 "\nTerminal 1 power flow: {:s} VA"
81 "\n--- Initialization from powerflow finished ---",
82 Logger::complexToString(Complex(**mPref, **mQ1ref)),
83 Logger::complexToString(Complex(mP2, **mQ2ref)));
84}
85
86void SP::Ph1::SolidStateTransformer::calculatePerUnitParameters(
87 Real baseApparentPower, Real baseOmega) {
88 mPref_perUnit = **mPref / baseApparentPower;
89 mP2_perUnit = mP2 / baseApparentPower;
90 mQ1ref_perUnit = **mQ1ref / baseApparentPower;
91 mQ2ref_perUnit = **mQ2ref / baseApparentPower;
92 mSubLoadSide1->calculatePerUnitParameters(baseApparentPower, baseOmega);
93 mSubLoadSide2->calculatePerUnitParameters(baseApparentPower, baseOmega);
94 SPDLOG_LOGGER_INFO(
95 mSLog,
96 "\n#### Calculate Per Unit Parameters for {}"
97 "\nTerminal 0 power flow: {:s} p.u."
98 "\nTerminal 1 power flow: {:s} p.u."
99 "\n#### Calculate Per Unit Parameters finished ---",
100 **mName, Logger::complexToString(Complex(mPref_perUnit, mQ1ref_perUnit)),
101 Logger::complexToString(Complex(mP2_perUnit, mQ2ref_perUnit)));
102}
103
104Complex SP::Ph1::SolidStateTransformer::getNodalInjection(
105 CPS::TopologicalNode::Ptr node) {
106 if (node->name() == mTerminals[0]->node()->name()) {
107 SPDLOG_LOGGER_INFO(
108 mSLog,
109 "\n#### get nodal injection for primary side"
110 "\nreturned {:s} p.u.",
111 Logger::complexToString(Complex(mPref_perUnit, mQ1ref_perUnit)));
112 return Complex(mPref_perUnit, mQ1ref_perUnit);
113 } else if (node->name() == mTerminals[1]->node()->name()) {
114 SPDLOG_LOGGER_INFO(
115 mSLog,
116 "\n#### get nodal injection for secondary side"
117 "\nreturned {:s} p.u.",
118 Logger::complexToString(Complex(mP2_perUnit, mQ2ref_perUnit)));
119 return Complex(mP2_perUnit, mQ2ref_perUnit);
120 } else {
121 throw std::invalid_argument(
122 "Failed to process nodal power injection of Solid State Transformer" +
123 this->name());
124 }
125}
Base class for composite power components.
void addMNASubComponent(typename SimPowerComp< Complex >::Ptr subc, MNA_SUBCOMP_TASK_ORDER preStepOrder, MNA_SUBCOMP_TASK_ORDER postStepOrder, Bool contributeToRightVector)
const Attribute< String >::Ptr mName
Human readable name.
const Attribute< Real >::Ptr mQ2ref
Reactive power at secondary side [var].
const Attribute< Real >::Ptr mQ1ref
Reactive power at primary side [var].
void createSubComponents() override
Constructs and registers MNA subcomponents; idempotent.
void initializeParentFromNodesAndTerminals(Real frequency) override
Initializes component.
const Attribute< Real >::Ptr mPref
Power [watt].
SimPowerComp< Complex >::Ptr clone(String name) override
Returns a modified copy of the component with the given suffix added to the name and without.
SimTerminal< Complex >::List mTerminals
Logger::Level mLogLevel
Component logger control for internal variables.
Logger::Log mSLog
Component logger.