Commit b93a5c5a authored by Markus Mirz's avatar Markus Mirz
Browse files

use new subcomp approach in rxload and add rxloadswitch

parent fdbd51d8
......@@ -29,8 +29,13 @@ namespace Ph1 {
mClosedResistance = closedResistance;
mIsClosed = closed;
}
/// Close switch
void close() { mIsClosed = true; }
/// Open switch
void open() { mIsClosed = false; }
/// Check if switch is closed
Bool isClosed() { return mIsClosed; }
};
}
}
......
......@@ -92,6 +92,8 @@ namespace CIM {
std::map<String, TopologicalPowerComp::Ptr> mPowerflowEquipment;
/// Maps the RID of a Terminal to a PowerflowTerminal
std::map<String, TopologicalTerminal::Ptr> mPowerflowTerminals;
///
Bool mUseProtectionSwitches = false;
// #### shunt component settings ####
/// activates global shunt capacitor setting
......@@ -194,6 +196,9 @@ namespace CIM {
mShuntConductanceValue = v;
mSetShuntConductance = true;
}
/// If set, some components like loads include protection switches
void useProtectionSwitches(Bool value = true) { mUseProtectionSwitches = value; }
};
}
}
......
......@@ -34,6 +34,8 @@ namespace CPS {
std::list<std::experimental::filesystem::path> mFileList;
/// assign pattern, used when the MANUAL mode is selected
std::map <String, String> mAssignPattern;
/// Skip first row if it has no digits at beginning
Bool mSkipFirstRow = true;
public:
/// set load profile assigning pattern. AUTO for assigning load profile name (csv file name) to load object with the same name (mName)
......@@ -60,6 +62,8 @@ namespace CPS {
/// convert HH:MM:SS format timestamp into total seconds.
/// e.g.: 00 : 01 : 00 -- > 60.
Real time_format_convert(const String& time);
/// Skip first row if it has no digits at beginning
void doSkipFirstRow(Bool value = true) { mSkipFirstRow = value; }
std::vector<PQData> readLoadProfileDP(std::experimental::filesystem::path file,
......
......@@ -38,6 +38,7 @@
#include <cps/DP/DP_Ph1_Inductor.h>
#include <cps/DP/DP_Ph1_PiLine.h>
#include <cps/DP/DP_Ph1_RXLoad.h>
#include <cps/DP/DP_Ph1_RXLoadSwitch.h>
#include <cps/DP/DP_Ph1_PQLoadCS.h>
#include <cps/DP/DP_Ph1_RxLine.h>
#include <cps/DP/DP_Ph1_Resistor.h>
......
......@@ -38,8 +38,9 @@ namespace Ph1 {
std::shared_ptr<Capacitor> mSubParallelCapacitor0;
/// Parallel resistor submodel at Terminal 1
std::shared_ptr<Resistor> mSubParallelResistor1;
// Parallel capacitor submodel at Terminal 1
/// Parallel capacitor submodel at Terminal 1
std::shared_ptr<Capacitor> mSubParallelCapacitor1;
/// Right side vectors of subcomponents
std::vector<const Matrix*> mRightVectorStamps;
public:
/// Defines UID, name and logging level
......
......@@ -17,9 +17,7 @@
namespace CPS {
namespace DP {
namespace Ph1 {
/// \brief
/// TODO: currently modelled as an impedance, which obviously doesn't have a constant power characteristic
/// Model as current source and read from CSV files
/// Constant impedance load model consisting of RLC elements
class RXLoad :
public SimPowerComp<Complex>,
public MNAInterface,
......@@ -39,8 +37,6 @@ namespace Ph1 {
Complex mCurrent;
/// Resistance [Ohm]
Real mResistance;
/// Conductance [S]
Real mConductance;
/// Reactance [Ohm]
Real mReactance;
/// Inductance [H]
......@@ -53,6 +49,8 @@ namespace Ph1 {
std::shared_ptr<DP::Ph1::Capacitor> mSubCapacitor;
/// Internal resistance
std::shared_ptr<DP::Ph1::Resistor> mSubResistor;
/// Right side vectors of subcomponents
std::vector<const Matrix*> mRightVectorStamps;
public:
/// Defines UID, name and logging level
RXLoad(String uid, String name,
......@@ -60,19 +58,15 @@ namespace Ph1 {
/// Defines name, component parameters and logging level
RXLoad(String name,
Logger::Level logLevel = Logger::Level::off);
/// Defines name, component parameters and logging level
RXLoad(String name,
Real activePower, Real reactivePower, Real volt,
Logger::Level logLevel = Logger::Level::off);
SimPowerComp<Complex>::Ptr clone(String name);
// #### General ####
///
/// Initialize components with network frequencies
void initialize(Matrix frequencies);
/// Initializes component from power flow data
/// Initialize component from power flow data
void initializeFromPowerflow(Real frequency);
/// Sets model specific parameters
/// Set model specific parameters
void setParameters(Real activePower, Real ReactivePower, Real volt);
// #### MNA section ####
......@@ -82,47 +76,40 @@ namespace Ph1 {
void mnaApplySystemMatrixStamp(Matrix& systemMatrix);
/// Stamps right side (source) vector
void mnaApplyRightSideVectorStamp(Matrix& rightVector);
/// Update interface current from MNA system result
void mnaUpdateCurrent(const Matrix& leftVector);
/// Update interface voltage from MNA system result
void mnaUpdateVoltage(const Matrix& leftVector);
/// MNA pre step operations
void mnaPreStep(Real time, Int timeStepCount);
/// MNA post step operations
void mnaPostStep(Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector);
/// Add MNA pre step dependencies
void mnaAddPreStepDependencies(AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes);
/// Add MNA post step dependencies
void mnaAddPostStepDependencies(AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes,
Attribute<Matrix>::Ptr &leftVector);
class MnaPreStep : public Task {
public:
MnaPreStep(RXLoad& load) :
Task(load.mName + ".MnaPreStep"), mLoad(load) {
if (load.mSubResistor)
mAttributeDependencies.push_back(load.mSubResistor->attribute("right_vector"));
if (load.mSubInductor)
mAttributeDependencies.push_back(load.mSubInductor->attribute("right_vector"));
if (load.mSubCapacitor)
mAttributeDependencies.push_back(load.mSubCapacitor->attribute("right_vector"));
mModifiedAttributes.push_back(load.attribute("right_vector"));
mLoad.mnaAddPreStepDependencies(mPrevStepDependencies, mAttributeDependencies, mModifiedAttributes);
}
void execute(Real time, Int timeStepCount);
void execute(Real time, Int timeStepCount) { mLoad.mnaPreStep(time, timeStepCount); }
private:
RXLoad& mLoad;
};
class MnaPostStep : public Task {
public:
MnaPostStep(RXLoad& load, Attribute<Matrix>::Ptr leftVector) :
Task(load.mName + ".MnaPostStep"), mLoad(load), mLeftVector(leftVector) {
mAttributeDependencies.push_back(leftVector);
if (load.mSubResistor)
mAttributeDependencies.push_back(load.mSubResistor->attribute("i_intf"));
if (load.mSubInductor)
mAttributeDependencies.push_back(load.mSubInductor->attribute("i_intf"));
if (load.mSubCapacitor)
mAttributeDependencies.push_back(load.mSubCapacitor->attribute("i_intf"));
mModifiedAttributes.push_back(load.attribute("i_intf"));
mModifiedAttributes.push_back(load.attribute("v_intf"));
mLoad.mnaAddPostStepDependencies(mPrevStepDependencies, mAttributeDependencies, mModifiedAttributes, mLeftVector);
}
void execute(Real time, Int timeStepCount);
void execute(Real time, Int timeStepCount) { mLoad.mnaPostStep(time, timeStepCount, mLeftVector); }
private:
RXLoad& mLoad;
Attribute<Matrix>::Ptr mLeftVector;
......
/* 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/.
*********************************************************************************/
#pragma once
#include <cps/DP/DP_Ph1_RXLoad.h>
#include <cps/DP/DP_Ph1_Switch.h>
namespace CPS {
namespace DP {
namespace Ph1 {
/// Constant impedance load model consisting of RLC elements
class RXLoadSwitch :
public SimPowerComp<Complex>,
public MNASwitchInterface,
public SharedFactory<RXLoadSwitch> {
protected:
/// Internal RXLoad
std::shared_ptr<DP::Ph1::RXLoad> mSubRXLoad;
/// Internal protection switch
std::shared_ptr<DP::Ph1::Switch> mSubSwitch;
/// internal switch is only opened after this time offset
Real mSwitchTimeOffset = 1.0;
/// Right side vectors of subcomponents
std::vector<const Matrix*> mRightVectorStamps;
public:
/// Defines UID, name and logging level
RXLoadSwitch(String uid, String name, Logger::Level logLevel = Logger::Level::off);
/// Defines name, component parameters and logging level
RXLoadSwitch(String name, Logger::Level logLevel = Logger::Level::off);
// #### General ####
///
void initialize(Matrix frequencies);
/// Initializes component from power flow data
void initializeFromPowerflow(Real frequency);
/// Sets model specific parameters
void setParameters(Real activePower, Real reactivePower, Real nomVolt,
Real openResistance, Real closedResistance, Bool closed = false);
/// Sets only switch parameters so that load parameters could be calculated from powerflow
void setSwitchParameters(Real openResistance, Real closedResistance, Bool closed = false);
/// built-in logic for protection switch
void updateSwitchState(Real time);
// #### MNA section ####
/// Initializes internal variables of the component
void mnaInitialize(Real omega, Real timeStep, Attribute<Matrix>::Ptr leftVector);
/// Stamps system matrix
void mnaApplySystemMatrixStamp(Matrix& systemMatrix);
/// Stamps right side (source) vector
void mnaApplyRightSideVectorStamp(Matrix& rightVector);
/// Update interface current from MNA system result
void mnaUpdateCurrent(const Matrix& leftVector) { }
/// Update interface voltage from MNA system result
void mnaUpdateVoltage(const Matrix& leftVector) { }
/// MNA pre step operations
void mnaPreStep(Real time, Int timeStepCount);
/// MNA post step operations
void mnaPostStep(Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector);
/// Add MNA pre step dependencies
void mnaAddPreStepDependencies(AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes);
/// Add MNA post step dependencies
void mnaAddPostStepDependencies(AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes,
Attribute<Matrix>::Ptr &leftVector);
// #### MNA section for switch ####
/// Check if switch is closed
Bool mnaIsClosed() { return mSubSwitch->isClosed(); }
/// Stamps system matrix considering the defined switch position
void mnaApplySwitchSystemMatrixStamp(Matrix& systemMatrix, Bool closed);
class MnaPreStep : public Task {
public:
MnaPreStep(RXLoadSwitch& load) : Task(load.mName + ".MnaPreStep"), mLoad(load) {
mLoad.mnaAddPreStepDependencies(mPrevStepDependencies, mAttributeDependencies, mModifiedAttributes);
}
void execute(Real time, Int timeStepCount) { mLoad.mnaPreStep(time, timeStepCount); }
private:
RXLoadSwitch& mLoad;
};
class MnaPostStep : public Task {
public:
MnaPostStep(RXLoadSwitch& load, Attribute<Matrix>::Ptr leftVector) :
Task(load.mName + ".MnaPostStep"), mLoad(load), mLeftVector(leftVector) {
mLoad.mnaAddPostStepDependencies(mPrevStepDependencies, mAttributeDependencies, mModifiedAttributes, mLeftVector);
}
void execute(Real time, Int timeStepCount) { mLoad.mnaPostStep(time, timeStepCount, mLeftVector); }
private:
RXLoadSwitch& mLoad;
Attribute<Matrix>::Ptr mLeftVector;
};
};
}
}
}
......@@ -52,26 +52,29 @@ namespace Ph1 {
void mnaUpdateVoltage(const Matrix& leftVector);
/// Update interface current from MNA system result
void mnaUpdateCurrent(const Matrix& leftVector);
/// MNA post step operations
void mnaPostStep(Real time, Int timeStepCount, Attribute<Matrix>::Ptr &leftVector);
/// Add MNA post step dependencies
void mnaAddPostStepDependencies(AttributeBase::List &prevStepDependencies,
AttributeBase::List &attributeDependencies, AttributeBase::List &modifiedAttributes,
Attribute<Matrix>::Ptr &leftVector);
class MnaPostStep : public Task {
public:
MnaPostStep(Switch& switchRef, Attribute<Matrix>::Ptr leftSideVector) :
Task(switchRef.mName + ".MnaPostStep"), mSwitch(switchRef), mLeftVector(leftSideVector) {
mAttributeDependencies.push_back(mLeftVector);
mModifiedAttributes.push_back(mSwitch.attribute("v_intf"));
mModifiedAttributes.push_back(mSwitch.attribute("i_intf"));
mSwitch.mnaAddPostStepDependencies(mPrevStepDependencies, mAttributeDependencies, mModifiedAttributes, mLeftVector);
}
void execute(Real time, Int timeStepCount);
void execute(Real time, Int timeStepCount) { mSwitch.mnaPostStep(time, timeStepCount, mLeftVector); }
private:
Switch& mSwitch;
Attribute<Matrix>::Ptr mLeftVector;
};
// #### MNA section for switches ####
// #### MNA section for switch ####
/// Check if switch is closed
Bool mnaIsClosed() { return mIsClosed; }
Bool mnaIsClosed() { return isClosed(); }
/// Stamps system matrix considering the defined switch position
void mnaApplySwitchSystemMatrixStamp(Matrix& systemMatrix, Bool closed);
};
......
......@@ -20,14 +20,8 @@ namespace CPS {
typedef std::vector<Ptr> List;
// #### MNA section ####
/// Open switch
virtual void mnaOpen() { }
/// Close switch
virtual void mnaClose() { }
/// Check if switch is closed
virtual Bool mnaIsClosed() = 0;
/// Close switch if true and open switch if false
virtual void mnaSetClosed(Bool value) { }
/// Stamps system matrix considering the defined switch position
virtual void mnaApplySwitchSystemMatrixStamp(Matrix& systemMatrix, Bool closed) { }
};
......
......@@ -37,7 +37,7 @@ namespace CPS {
/// special behavior for components during initialization
Bool mBehaviour = Behaviour::Simulation;
/// Flag indicating that parameters are set via setParameters() function
bool parametersSet = false;
bool mParametersSet = false;
public:
typedef std::shared_ptr<TopologicalPowerComp> Ptr;
......
......@@ -320,7 +320,10 @@ TopologicalPowerComp::Ptr Reader::mapEnergyConsumer(EnergyConsumer* consumer) {
return load;
}
else {
return std::make_shared<DP::Ph1::RXLoad>(consumer->mRID, consumer->name, mComponentLogLevel);
if (mUseProtectionSwitches)
return std::make_shared<DP::Ph1::RXLoadSwitch>(consumer->mRID, consumer->name, mComponentLogLevel);
else
return std::make_shared<DP::Ph1::RXLoad>(consumer->mRID, consumer->name, mComponentLogLevel);
}
}
......
......@@ -21,6 +21,7 @@ list(APPEND CPS_SOURCES
DP/DP_Ph1_PiLine.cpp
DP/DP_Ph1_RxLine.cpp
DP/DP_Ph1_RXLoad.cpp
DP/DP_Ph1_RXLoadSwitch.cpp
DP/DP_Ph1_PQLoadCS.cpp
DP/DP_Ph1_Resistor.cpp
DP/DP_Ph1_Transformer.cpp
......
......@@ -120,10 +120,12 @@ std::vector<PQData> CSVReader::readLoadProfileDP(std::experimental::filesystem::
std::ifstream csvfile(file);
CSVReaderIterator row_(csvfile);
// ignore the first row if it is a title
if (!std::isdigit((*row_).get(0)[0])) {
if (mSkipFirstRow && !std::isdigit((*row_).get(0)[0])) {
row_.next();
}
/*
loop over rows of the csv file to find the entry point to read in.
if start_time and end_time are negative (as default), it reads in all rows.
......@@ -353,9 +355,10 @@ PowerProfile CSVReader::readLoadProfile(std::experimental::filesystem::path file
CSVReaderIterator loop(csvfile);
// ignore the first row if it is a title
if (!std::isdigit((*loop).get(0)[0])) {
if (mSkipFirstRow && !std::isdigit((*loop).get(0)[0])) {
loop.next();
}
/*
loop over rows of the csv file to find the entry point to read in.
and determine data type prior to read in. (assuming only time,p,q or time,weighting factor)
......@@ -424,9 +427,10 @@ std::vector<Real> CSVReader::readPQData(fs::path file,
CSVReaderIterator row_(csvfile);
// ignore the first row if it is a title
if (!std::isdigit((*row_).get(0)[0])) {
if (mSkipFirstRow && !std::isdigit((*row_).get(0)[0])) {
row_.next();
}
/*
loop over rows of the csv file to find the entry point to read in.
if start_time and end_time are negative (as default), it reads in all rows.
......
......@@ -76,7 +76,7 @@ DP::Ph1::AvVoltageSourceInverterDQ::AvVoltageSourceInverterDQ(String uid, String
}
void DP::Ph1::AvVoltageSourceInverterDQ::setParameters(Real sysOmega, Real sysVoltNom, Real Pref, Real Qref) {
parametersSet = true;
mParametersSet = true;
mSLog->info("General Parameters:");
mSLog->info("Nominal Voltage={} [V] Nominal Omega={} [1/s]", sysVoltNom, sysOmega);
......@@ -209,7 +209,7 @@ void DP::Ph1::AvVoltageSourceInverterDQ::initializeFromPowerflow(Real frequency)
mVcq = vcdq.imag();
mIrcd = ircdq.real();
mIrcq = ircdq.imag();
// angle input
// angle input
Matrix matrixStateInit = Matrix::Zero(2,1);
matrixStateInit(0,0) = std::arg(mVirtualNodes[3]->initialSingleVoltage());
mPLL->setInitialValues(mVcq, matrixStateInit, Matrix::Zero(2,1));
......@@ -278,7 +278,7 @@ void DP::Ph1::AvVoltageSourceInverterDQ::addControlPreStepDependencies(Attribute
mPowerControllerVSI->signalAddPreStepDependencies(prevStepDependencies, attributeDependencies, modifiedAttributes);
}
void DP::Ph1::AvVoltageSourceInverterDQ::controlPreStep(Real time, Int timeStepCount) {
void DP::Ph1::AvVoltageSourceInverterDQ::controlPreStep(Real time, Int timeStepCount) {
// add pre-step of subcomponents
mPLL->signalPreStep(time, timeStepCount);
mPowerControllerVSI->signalPreStep(time, timeStepCount);
......@@ -307,7 +307,7 @@ void DP::Ph1::AvVoltageSourceInverterDQ::controlStep(Real time, Int timeStepCoun
// add step of subcomponents
mPLL->signalStep(time, timeStepCount);
mPowerControllerVSI->signalStep(time, timeStepCount);
// Transformation interface backward
mVsref(0,0) = Math::rotatingFrame2to1(Complex(mPowerControllerVSI->attribute<Matrix>("output_curr")->get()(0, 0), mPowerControllerVSI->attribute<Matrix>("output_curr")->get()(1, 0)), mThetaN, mPLL->attribute<Matrix>("output_prev")->get()(0, 0));
......@@ -320,7 +320,7 @@ void DP::Ph1::AvVoltageSourceInverterDQ::mnaAddPreStepDependencies(AttributeBase
for (auto subcomp: mSubComponents)
if (auto mnasubcomp = std::dynamic_pointer_cast<MNAInterface>(subcomp))
mnasubcomp->mnaAddPreStepDependencies(prevStepDependencies, attributeDependencies, modifiedAttributes);
// add pre-step dependencies of component itself
// add pre-step dependencies of component itself
prevStepDependencies.push_back(attribute("Vsref"));
prevStepDependencies.push_back(attribute("i_intf"));
prevStepDependencies.push_back(attribute("v_intf"));
......@@ -329,7 +329,7 @@ void DP::Ph1::AvVoltageSourceInverterDQ::mnaAddPreStepDependencies(AttributeBase
modifiedAttributes.push_back(attribute("right_vector"));
}
void DP::Ph1::AvVoltageSourceInverterDQ::mnaPreStep(Real time, Int timeStepCount) {
void DP::Ph1::AvVoltageSourceInverterDQ::mnaPreStep(Real time, Int timeStepCount) {
// pre-steo of subcomponents - controlled source
mSubCtrledVoltageSource->setParameters(mVsref(0,0));
// pre-step of subcomponents - others
......
......@@ -20,7 +20,7 @@ DP::Ph1::ControlledVoltageSource::ControlledVoltageSource(String uid, String nam
void DP::Ph1::ControlledVoltageSource::setParameters(MatrixComp voltageRefABC) {
mIntfVoltage = voltageRefABC;
parametersSet = true;
mParametersSet = true;
}
SimPowerComp<Complex>::Ptr DP::Ph1::ControlledVoltageSource::clone(String name) {
......
......@@ -26,7 +26,7 @@ DP::Ph1::CurrentSource::CurrentSource(String name, Complex current, Logger::Leve
void DP::Ph1::CurrentSource::setParameters(Complex current) {
attribute<Complex>("I_ref")->set(current);
parametersSet = true;
mParametersSet = true;
}
SimPowerComp<Complex>::Ptr DP::Ph1::CurrentSource::clone(String name) {
......
......@@ -69,7 +69,7 @@ void DP::Ph1::Inductor::initVars(Real timeStep) {
Real preCurrFracImag = (-2. * b) / (1. + b * b);
mPrevCurrFac(freq,0) = { preCurrFracReal, preCurrFracImag };
// TODO: check if this is correct or if it should be only computed before the step
// In steady-state, these variables should not change
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);
}
......
......@@ -29,7 +29,7 @@ void DP::Ph1::Inverter::setParameters(std::vector<Int> carrierHarms, std::vector
mModIdx = ratio;
mPhaseMod = phase;
parametersSet= true;
mParametersSet= true;
}
void DP::Ph1::Inverter::initializeFromPowerflow(Real frequency) {
......
......@@ -41,7 +41,7 @@ void DP::Ph1::NetworkInjection::setParameters(Complex voltageRef, Real srcFreq)
attribute<Complex>("V_ref")->set(voltageRef);
attribute<Real>("f_src")->set(srcFreq);
parametersSet = true;
mParametersSet = true;
}
void DP::Ph1::NetworkInjection::initializeFromPowerflow(Real frequency) {
......
......@@ -47,7 +47,7 @@ void DP::Ph1::PQLoadCS::setParameters(Real activePower, Real reactivePower, Real
attribute<Real>("Q")->set(reactivePower);
attribute<Real>("V_nom")->set(nomVolt);
parametersSet = true;
mParametersSet = true;
}
SimPowerComp<Complex>::Ptr DP::Ph1::PQLoadCS::clone(String name) {
......@@ -63,7 +63,7 @@ void DP::Ph1::PQLoadCS::initializeFromPowerflow(Real frequency) {
mReactivePower = attribute<Real>("Q");
mNomVoltage = attribute<Real>("V_nom");
// Get power from Terminals if it was not set previously.
if (mActivePower->get() == 0 && mReactivePower->get() == 0 && !parametersSet) {
if (mActivePower->get() == 0 && mReactivePower->get() == 0 && !mParametersSet) {
mActivePower->set(mTerminals[0]->singleActivePower());
mReactivePower->set(mTerminals[0]->singleReactivePower());
mNomVoltage->set(std::abs(mTerminals[0]->initialSingleVoltage()));
......
Markdown is supported
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