Commit f0cd7151 authored by Jan Dinkelbach's avatar Jan Dinkelbach
Browse files

add DP example with slack, line, VSI and PF init

parent 3a7bb3cc
......@@ -17,6 +17,8 @@ set(CIRCUIT_SOURCES
Circuits/DP_Diakoptics.cpp
Circuits/DP_VSI.cpp
Circuits/DP_Slack_PiLine_PQLoad_with_PF_Init.cpp
Circuits/DP_Slack_PiLine_VSI_with_PF_Init.cpp
# Powerflow examples
Circuits/PF_Slack_PiLine_PQLoad.cpp
......
/* Copyright 2017-2020 Institute for Automation of Complex Power Systems,
* EONERC, RWTH Aachen University
* DPsim
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*********************************************************************************/
#include <DPsim.h>
using namespace DPsim;
using namespace CPS;
using namespace CPS::CIM;
int main(int argc, char* argv[]) {
Scenarios::SGIB::ScenarioConfig scenario;
Real finalTime = 2.0;
// ----- POWERFLOW FOR INITIALIZATION -----
Real timeStepPF = 2.0;
Real finalTimePF = finalTime+timeStepPF;
String simNamePF = "DP_Slack_PiLine_VSI_with_PF_Init_PF";
Logger::setLogDir("logs/" + simNamePF);
// Components
auto n1PF = SimNode<Complex>::make("n1", PhaseType::Single);
auto n2PF = SimNode<Complex>::make("n2", PhaseType::Single);
auto extnetPF = SP::Ph1::externalGridInjection::make("Slack", Logger::Level::debug);
extnetPF->setParameters(scenario.systemNominalVoltage);
extnetPF->setBaseVoltage(scenario.systemNominalVoltage);
extnetPF->modifyPowerFlowBusType(PowerflowBusType::VD);
auto linePF = SP::Ph1::PiLine::make("PiLine", Logger::Level::debug);
linePF->setParameters(scenario.lineResistance, scenario.lineInductance, 0);
linePF->setBaseVoltage(scenario.systemNominalVoltage);
auto loadPF = SP::Ph1::Load::make("Load", Logger::Level::debug);
loadPF->setParameters(-scenario.pvNominalActivePower, -scenario.pvNominalReactivePower, scenario.systemNominalVoltage);
loadPF->modifyPowerFlowBusType(PowerflowBusType::PQ);
// Topology
extnetPF->connect({ n1PF });
linePF->connect({ n1PF, n2PF });
loadPF->connect({ n2PF });
auto systemPF = SystemTopology(50,
SystemNodeList{n1PF, n2PF},
SystemComponentList{extnetPF, linePF, loadPF});
// Logging
auto loggerPF = DataLogger::make(simNamePF);
loggerPF->addAttribute("v1", n1PF->attribute("v"));
loggerPF->addAttribute("v2", n2PF->attribute("v"));
// Simulation
Simulation simPF(simNamePF, Logger::Level::debug);
simPF.setSystem(systemPF);
simPF.setTimeStep(timeStepPF);
simPF.setFinalTime(finalTimePF);
simPF.setDomain(Domain::SP);
simPF.setSolverType(Solver::Type::NRP);
simPF.doPowerFlowInit(false);
simPF.addLogger(loggerPF);
simPF.run();
// ----- DYNAMIC SIMULATION -----
Real timeStepDP = 0.001;
Real finalTimeDP = finalTime+timeStepDP;
String simNameDP = "DP_Slack_PiLine_VSI_with_PF_Init_DP";
Logger::setLogDir("logs/" + simNameDP);
// Components
auto n1DP = SimNode<Complex>::make("n1", PhaseType::Single);
auto n2DP = SimNode<Complex>::make("n2", PhaseType::Single);
auto extnetDP = DP::Ph1::NetworkInjection::make("Slack", Logger::Level::debug);
extnetDP->setParameters(Complex(scenario.systemNominalVoltage,0));
auto lineDP = DP::Ph1::PiLine::make("PiLine", Logger::Level::debug);
lineDP->setParameters(scenario.lineResistance, scenario.lineInductance);
auto pv = DP::Ph1::AvVoltageSourceInverterDQ::make("pv", "pv", Logger::Level::debug, true);
pv->setParameters(scenario.systemOmega, scenario.pvNominalVoltage, scenario.pvNominalActivePower, scenario.pvNominalReactivePower);
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.pvNominalVoltage, scenario.transformerNominalPower, scenario.systemNominalVoltage/scenario.pvNominalVoltage, 0, 0, scenario.transformerInductance, scenario.systemOmega);
pv->setInitialStateValues(0, 0, scenario.pvNominalActivePower, scenario.pvNominalReactivePower, 0, 0, 0, 0);
// Topology
extnetDP->connect({ n1DP });
lineDP->connect({ n1DP, n2DP });
pv->connect({ n2DP });
auto systemDP = SystemTopology(50,
SystemNodeList{n1DP, n2DP},
SystemComponentList{extnetDP, lineDP, pv});
// Initialization of dynamic topology with values from powerflow
CIM::Reader reader(simNameDP, Logger::Level::debug);
reader.initDynamicSystemTopologyWithPowerflow(systemPF, systemDP);
// Logging
auto loggerDP = DataLogger::make(simNameDP);
loggerDP->addAttribute("v1", n1DP->attribute("v"));
loggerDP->addAttribute("v2", n2DP->attribute("v"));
Scenarios::CIGREMV::logPVAttributes(loggerDP, pv);
// load step sized in absolute terms
// std::shared_ptr<SwitchEvent> loadStepEvent = Scenarios::CIGREMV::createEventAddPowerConsumption("n2", 1-timeStepDP, 1000.0e3, systemDP, Domain::DP);
// Simulation
Simulation sim(simNameDP, Logger::Level::debug);
sim.setSystem(systemDP);
sim.setTimeStep(timeStepDP);
sim.setFinalTime(finalTimeDP);
sim.setDomain(Domain::DP);
// sim.addEvent(loadStepEvent);
sim.doPowerFlowInit(false);
sim.addLogger(loggerDP);
sim.run();
}
%% Cell type:markdown id: tags:
# DP Simulation of topology with slack, line and PQ load
%% Cell type:code id: tags:
``` python
%%bash
TOP=${TOP:-$(git rev-parse --show-toplevel)}
PATH=${TOP}/build/Examples/Cxx
DP_Slack_PiLine_PQLoad_with_PF_Init
```
%% Cell type:code id: tags:
``` python
from villas.dataprocessing.readtools import *
from villas.dataprocessing.timeseries import *
import matplotlib.pyplot as plt
import re
%matplotlib widget
```
%% Cell type:markdown id: tags:
## PF results
%% Cell type:code id: tags:
``` python
modelName = 'DP_Slack_PiLine_PQLoad_with_PF_Init_PF'
path = 'logs/' + modelName + '/'
dpsim_result_file = path + modelName + '.csv'
ts_dpsim_pf = read_timeseries_csv(dpsim_result_file)
```
%% Cell type:markdown id: tags:
## DP results
%% Cell type:code id: tags:
``` python
modelName = 'DP_Slack_PiLine_PQLoad_with_PF_Init_DP'
path = 'logs/' + modelName + '/'
dpsim_result_file = path + modelName + '.csv'
ts_dpsim = read_timeseries_csv(dpsim_result_file)
```
%% Cell type:code id: tags:
``` python
plt.figure(figsize=(12,6))
for ts_name, ts_obj in ts_dpsim.items():
plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)
for ts_name, ts_obj in ts_dpsim_pf.items():
plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name+'_pf', linestyle=':')
plt.legend()
plt.show()
```
%% Cell type:code id: tags:
``` python
```
%% Cell type:markdown id: tags:
# DP Simulation of topology with slack, line and VSI
%% Cell type:code id: tags:
``` python
%%bash
TOP=${TOP:-$(git rev-parse --show-toplevel)}
PATH=${TOP}/build/Examples/Cxx
DP_Slack_PiLine_VSI_with_PF_Init
```
%% Cell type:code id: tags:
``` python
from villas.dataprocessing.readtools import *
from villas.dataprocessing.timeseries import *
import matplotlib.pyplot as plt
import re
%matplotlib widget
```
%% Cell type:markdown id: tags:
## PF results
%% Cell type:code id: tags:
``` python
modelName = 'DP_Slack_PiLine_VSI_with_PF_Init_PF'
path = 'logs/' + modelName + '/'
dpsim_result_file = path + modelName + '.csv'
ts_dpsim_pf = read_timeseries_csv(dpsim_result_file)
```
%% Cell type:markdown id: tags:
## DP results
%% Cell type:code id: tags:
``` python
modelName = 'DP_Slack_PiLine_VSI_with_PF_Init_DP'
path = 'logs/' + modelName + '/'
dpsim_result_file = path + modelName + '.csv'
ts_dpsim = read_timeseries_csv(dpsim_result_file)
```
%% Cell type:code id: tags:
``` python
plt.figure(figsize=(12,6))
for ts_name, ts_obj in ts_dpsim.items():
if ts_name == 'v1' or ts_name == 'v2':
plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name)
for ts_name, ts_obj in ts_dpsim_pf.items():
if ts_name == 'v1' or ts_name == 'v2':
plt.plot(ts_obj.time, ts_obj.abs().values, label=ts_name+'_pf', linestyle=':')
plt.legend()
plt.show()
```
......@@ -15,6 +15,46 @@
namespace CPS {
namespace CIM {
namespace Scenarios {
namespace SGIB {
struct ScenarioConfig {
Real systemFrequency = 50;
Real systemNominalVoltage = 20e3;
// Line paramerters
Real lineResistance = 0.05;
Real lineInductance = 0.1;
// PV controller parameters
Real KpPLL = 0.25;
Real KiPLL = 2;
Real KpPowerCtrl = 0.001;
Real KiPowerCtrl = 0.08;
Real KpCurrCtrl = 0.3;
Real KiCurrCtrl = 10;
Real OmegaCutoff = 2 * PI * systemFrequency;
// 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;
};
}
namespace CIGREMV {
struct ScenarioConfig {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment