Examples.h 12.6 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* Copyright 2017-2020 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 <cps/Definitions.h>
#include <cps/SystemTopology.h>
#include <cps/Components.h>

#pragma once

namespace CPS {
namespace CIM {
Jan Dinkelbach's avatar
Jan Dinkelbach committed
17
namespace Examples {
18
19
20
21
22
23
24

namespace SGIB {

    struct ScenarioConfig {
        Real systemFrequency = 50;
        Real systemNominalVoltage = 20e3;

25
26
        // Line parameters (R/X = 1)
        Real lineResistance = 31.4;
27
28
29
	    Real lineInductance = 0.1;

        // PV controller parameters
30
31
32
33
34
35
36
37
38
        Real scaling_P = 10.0;
        Real scaling_I = 1000.0;

        Real KpPLL = 0.25/scaling_P;
        Real KiPLL = 2/scaling_I;
        Real KpPowerCtrl = 0.001/scaling_P;
        Real KiPowerCtrl = 0.08/scaling_I;
        Real KpCurrCtrl = 0.3/scaling_P;
        Real KiCurrCtrl = 10/scaling_I;
39
40
        Real OmegaCutoff = 2 * PI * systemFrequency;

41
        // Initial state values
42
43
        Real thetaPLLInit = 0; // only for debug
        Real phiPLLInit = 0; // only for debug
44
45
46
47
48
        Real phi_dInit = 823.721*scaling_I;
        Real phi_qInit = -411.861*scaling_I;
        Real gamma_dInit = 131.401*scaling_I;
        Real gamma_qInit = 7.31206*scaling_I;

49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
        // Nominal generated power values of PV
        Real pvNominalVoltage = 1500.;
        Real pvNominalActivePower = 100e3;
        Real pvNominalReactivePower = 50e3;

        // PV filter parameters
        Real Lf = 0.002;
        Real Cf = 789.3e-6;
        Real Rf = 0.1;
        Real Rc = 0.1;

        // PV connection transformer parameters
        Real transformerNominalPower = 5e6;
        Real transformerInductance = 0.928e-3;

        // Further parameters
        Real systemOmega = 2 * PI * systemFrequency;
    };
}

69
namespace CIGREMV {
70
71

    struct ScenarioConfig {
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
        Real systemFrequency = 50;
        Real systemNominalVoltage = 20e3;
        Real penetrationLevel = 1;
        Real totalLoad = 4319.1e3; // calculated total load in CIGRE MV left feeder (see CIM data)

        // parameters of one PV unit
        Real pvUnitNominalVoltage = 1500.;
        Real pvUnitNominalPower = 50e3;
        Real pvUnitPowerFactor = 1;
        
        // calculate PV units per plant to reach penetration level
        Int numberPVUnits = Int(totalLoad * penetrationLevel / pvUnitNominalPower);
        Int numberPVPlants = 9;
        Int numberPVUnitsPerPlant = numberPVUnits / numberPVPlants;
                
        // PV controller parameters
88
89
90
91
92
93
94
95
96
        Real scaling_P = 10.0;
        Real scaling_I = 1000.0;

        Real KpPLL = 0.25/scaling_P;
        Real KiPLL = 2/scaling_I;
        Real KpPowerCtrl = 0.001/scaling_P;
        Real KiPowerCtrl = 0.08/scaling_I;
        Real KpCurrCtrl = 0.3/scaling_P;
        Real KiCurrCtrl = 10/scaling_I;
97
98
99
100
101
        Real OmegaCutoff = 2 * PI * systemFrequency;

        // PV filter parameters
        Real Lf = 0.002;
        Real Cf = 789.3e-6;
102
103
        Real Rf = 0.1;
        Real Rc = 0.1;
104
105
106
107
108
109
110

        // PV connection transformer parameters
        Real transformerNominalPower = 5e6;
        Real transformerInductance = 0.928e-3;

        // Further parameters
        Real systemOmega = 2 * PI * systemFrequency;
111
112
113
114
115
116
117
118
119
120

        // Initial state values (use known values with scaled control params)
        Real thetaPLLInit = 314.168313-systemOmega;
        Real phiPLLInit = 8e-06;
        Real pInit = 450000.716605;
        Real qInit = -0.577218;
        Real phi_dInit = 3854.197405*scaling_I;
        Real phi_qInit = -0.003737*scaling_I;
        Real gamma_dInit = 128.892668*scaling_I;
        Real gamma_qInit = 23.068682*scaling_I;
121
122
    };

123
124
125
126
    void addInvertersToCIGREMV(SystemTopology& system, CIGREMV::ScenarioConfig scenario, Domain domain) {
        Real pvActivePower = scenario.pvUnitNominalPower*scenario.numberPVUnitsPerPlant;
        Real pvReactivePower = sqrt(std::pow(pvActivePower / scenario.pvUnitPowerFactor, 2) - std::pow(pvActivePower, 2));

127
128
        // add PVs to network topology
        for (Int n = 3; n <= 11; n++) {	
129
130
            // TODO: cast to BaseAverageVoltageSourceInverter and move set functions out of case distinction
            if (domain == Domain::SP) {
131
132
133
134
135
136
                SimNode<Complex>::Ptr connectionNode = system.node<CPS::SimNode<Complex>>("N" + std::to_string(n));
                auto pv = SP::Ph1::AvVoltageSourceInverterDQ::make("pv_" + connectionNode->name(), "pv_" + connectionNode->name(), Logger::Level::debug, true);
                pv->setParameters(scenario.systemOmega, Complex(scenario.pvUnitNominalVoltage, 0), pvActivePower, pvReactivePower);
                pv->setTransformerParameters(scenario.systemNominalVoltage, scenario.pvUnitNominalVoltage, scenario.transformerNominalPower, scenario.systemNominalVoltage/scenario.pvUnitNominalVoltage, 0, 0, scenario.transformerInductance, scenario.systemOmega);
                system.addComponent(pv);
                system.connectComponentToNodes<Complex>(pv, { connectionNode });
137
            } else if (domain == Domain::DP) {
138
139
                SimNode<Complex>::Ptr connectionNode = system.node<CPS::SimNode<Complex>>("N" + std::to_string(n));
                auto pv = DP::Ph1::AvVoltageSourceInverterDQ::make("pv_" + connectionNode->name(), "pv_" + connectionNode->name(), Logger::Level::debug, true);
140
                pv->setParameters(scenario.systemOmega, scenario.pvUnitNominalVoltage, pvActivePower, pvReactivePower);
141
142
143
                pv->setControllerParameters(scenario.KpPLL, scenario.KiPLL, scenario.KpPowerCtrl, scenario.KiPowerCtrl, scenario.KpCurrCtrl, scenario.KiCurrCtrl, scenario.OmegaCutoff);
                pv->setFilterParameters(scenario.Lf, scenario.Cf, scenario.Rf, scenario.Rc);
                pv->setTransformerParameters(scenario.systemNominalVoltage, scenario.pvUnitNominalVoltage, scenario.transformerNominalPower, scenario.systemNominalVoltage/scenario.pvUnitNominalVoltage, 0, 0, scenario.transformerInductance, scenario.systemOmega);
144
                pv->setInitialStateValues(scenario.pInit, scenario.qInit, scenario.phi_dInit, scenario.phi_qInit, scenario.gamma_dInit, scenario.gamma_qInit);
145
146
147
148
149
                system.addComponent(pv);
                system.connectComponentToNodes<Complex>(pv, { connectionNode });
            } else if (domain == Domain::EMT) {
                SimNode<Real>::Ptr connectionNode = system.node<CPS::SimNode<Real>>("N" + std::to_string(n));
                auto pv = EMT::Ph3::AvVoltageSourceInverterDQ::make("pv_" + connectionNode->name(), "pv_" + connectionNode->name(), Logger::Level::debug, true);
150
                pv->setParameters(scenario.systemOmega, scenario.pvUnitNominalVoltage, pvActivePower, pvReactivePower);
151
                pv->setControllerParameters(scenario.KpPLL, scenario.KiPLL, scenario.KpPowerCtrl, scenario.KiPowerCtrl, scenario.KpCurrCtrl, scenario.KiCurrCtrl, scenario.OmegaCutoff);
152
153
                pv->setFilterParameters(scenario.Lf, scenario.Cf, scenario.Rf, scenario.Rc);
                pv->setTransformerParameters(scenario.systemNominalVoltage, scenario.pvUnitNominalVoltage, scenario.transformerNominalPower, scenario.systemNominalVoltage/scenario.pvUnitNominalVoltage, 0, 0, scenario.transformerInductance, scenario.systemOmega);
154
                pv->setInitialStateValues(scenario.pInit, scenario.qInit, scenario.phi_dInit, scenario.phi_qInit, scenario.gamma_dInit, scenario.gamma_qInit);
155
156
                system.addComponent(pv);
                system.connectComponentToNodes<Real>(pv, { connectionNode });
157
158
            }
        }
159
    }
160

161
    void logPVAttributes(DPsim::DataLogger::Ptr logger, CPS::TopologicalPowerComp::Ptr pv) {
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
        // state variables
        logger->addAttribute(pv->name() + "_state_" + "theta", pv->attribute("theta"));
        logger->addAttribute(pv->name() + "_state_" + "phipll", pv->attribute("phipll"));
        logger->addAttribute(pv->name() + "_state_" + "p", pv->attribute("p"));
        logger->addAttribute(pv->name() + "_state_" + "q", pv->attribute("q"));
        logger->addAttribute(pv->name() + "_state_" + "phid", pv->attribute("phid"));
        logger->addAttribute(pv->name() + "_state_" + "phiq", pv->attribute("phiq"));
        logger->addAttribute(pv->name() + "_state_" + "gammad", pv->attribute("gammad"));
        logger->addAttribute(pv->name() + "_state_" + "gammaq", pv->attribute("gammaq"));

        // input variables
        logger->addAttribute(pv->name() + "_input_" + "Vcdq", pv->attribute("Vcdq"));
        logger->addAttribute(pv->name() + "_input_" + "Ircdq", pv->attribute("Ircdq"));

        // output variables
        logger->addAttribute(pv->name() + "_output_" + "Vsdq", pv->attribute("Vsdq"));

        // interface variables
        logger->addAttribute(pv->name() + "_v_intf", pv->attribute("v_intf"));
        logger->addAttribute(pv->name() + "_i_intf", pv->attribute("i_intf"));
    }

    void logPVDecomposedAttributes(DPsim::DataLogger::Ptr logger, CPS::TopologicalPowerComp::Ptr pv) {
185

186
187
188
189
190
191
192
193
194
195
196
        // power controller
        std::vector<String> inputNames = {  pv->name() + "_powerctrl_input_pref", pv->name() + "_powerctrl_input_qref",
                                            pv->name() + "_powerctrl_input_vcd", pv->name() + "_powerctrl_input_vcq",
                                            pv->name() + "_powerctrl_input_ircd", pv->name() + "_powerctrl_input_ircq"};
        logger->addAttribute(inputNames, pv->attribute("powerctrl_inputs"));
        std::vector<String> stateNames = {  pv->name() + "_powerctrl_state_p", pv->name() + "_powerctrl_state_q",
                                            pv->name() + "_powerctrl_state_phid", pv->name() + "_powerctrl_state_phiq",
                                            pv->name() + "_powerctrl_state_gammad", pv->name() + "_powerctrl_state_gammaq"};
        logger->addAttribute(stateNames, pv->attribute("powerctrl_states"));
        std::vector<String> outputNames = {  pv->name() + "_powerctrl_output_vsd", pv->name() + "_powerctrl_output_vsq"};
        logger->addAttribute(outputNames, pv->attribute("powerctrl_outputs"));
197
198
199
200

        // interface variables
        logger->addAttribute(pv->name() + "_v_intf", pv->attribute("v_intf"));
        logger->addAttribute(pv->name() + "_i_intf", pv->attribute("i_intf"));
201
202
203
204

        // additional variables
        logger->addAttribute(pv->name() + "_pll_output", pv->attribute("pll_output"));
        logger->addAttribute(pv->name() + "_vsref", pv->attribute("Vsref"));
205
206
207
    }	

}
208
        std::shared_ptr<DPsim::SwitchEvent> createEventAddPowerConsumption(String nodeName, Real eventTime, Real additionalActivePower, SystemTopology& system, Domain domain, DPsim::DataLogger::Ptr logger) {
209
        
210
211
212
        // TODO: use base classes ph1
        if (domain == CPS::Domain::DP) {
            auto loadSwitch = DP::Ph1::Switch::make("Load_Add_Switch_" + nodeName, Logger::Level::debug);
213
214
215
            auto connectionNode = system.node<CPS::SimNode<Complex>>(nodeName);
            Real resistance = std::abs(connectionNode->initialSingleVoltage())*std::abs(connectionNode->initialSingleVoltage())/additionalActivePower;
            loadSwitch->setParameters(1e9, resistance);
216
217
            loadSwitch->open();
            system.addComponent(loadSwitch);
218
            system.connectComponentToNodes<Complex>(loadSwitch, { CPS::SimNode<Complex>::GND, connectionNode});
219
            logger->addAttribute("pv_switchedload_i", loadSwitch->attribute("i_intf"));
220
221
222
223
224
            return DPsim::SwitchEvent::make(eventTime, loadSwitch, true);
        } else {
            return nullptr;
        }
    }
225

226
    std::shared_ptr<DPsim::SwitchEvent3Ph> createEventAddPowerConsumption3Ph(String nodeName, Real eventTime, Real additionalActivePower, SystemTopology& system, Domain domain) {
227
228
229
230
        
        // TODO: use base classes ph3
         if (domain == CPS::Domain::EMT) {
            auto loadSwitch = EMT::Ph3::Switch::make("Load_Add_Switch_" + nodeName, Logger::Level::debug);
231
232
233
            auto connectionNode = system.node<CPS::SimNode<Real>>(nodeName);
            Real resistance = std::abs(connectionNode->initialSingleVoltage())*std::abs(connectionNode->initialSingleVoltage())/additionalActivePower;
            loadSwitch->setParameters(Matrix::Identity(3,3)*1e9, Matrix::Identity(3,3)*resistance);
234
235
236
237
238
239
240
            loadSwitch->openSwitch();
            system.addComponent(loadSwitch);
            system.connectComponentToNodes<Real>(loadSwitch, { CPS::SimNode<Real>::GND, system.node<CPS::SimNode<Real>>(nodeName) });
            return DPsim::SwitchEvent3Ph::make(eventTime, loadSwitch, true);
        } else {
            return nullptr;
        }
241
    }
242
    
243
244
245
}
}
}