Commit 5731db15 authored by Markus Mirz's avatar Markus Mirz
Browse files

MNASolver: move matrix recomputation to new class

parent 4ad8c31d
......@@ -60,14 +60,16 @@ namespace DPsim {
// #### MNA specific attributes ####
/// List of MNA components with static stamp into system matrix
CPS::MNAInterface::List mMNAComponents;
/// List of MNA components with extra functionality
CPS::MNAInterface::List mMNAComponentsExt;
/// List of switches that stamp differently depending on their state
/// and indicate the solver to choose a different system matrix
CPS::MNASwitchInterface::List mSwitches;
/// List of MNA components with SwitchInterface
CPS::MNAInterface::List mMNACompSwitches;
/// List of components that indicate the solver to recompute the system matrix
/// depending on their state
CPS::MNAVariableElementInterface::List mVariableElements;
/// List of MNA components with VariableElementInterface
CPS::MNAInterface::List mMNACompVariableElements;
/// List of signal type components that do not directly interact
/// with the MNA solver
CPS::SimSignalComp::List mSimSignalComps;
......@@ -83,6 +85,8 @@ namespace DPsim {
std::vector<Matrix> mLeftSideVectorHarm;
std::vector< CPS::Attribute<Matrix>::Ptr > mLeftVectorHarmAttributes;
/// Base matrix that includes all static MNA elements to speed up recomputation
Matrix mBaseSystemMatrix;
/// Map of system matrices where the key is the bitset describing the switch states
std::unordered_map< std::bitset<SWITCH_NUM>, Matrix > mSwitchedMatrices;
std::unordered_map< std::bitset<SWITCH_NUM>, std::vector<Matrix> > mSwitchedMatricesHarm;
......@@ -90,22 +94,13 @@ namespace DPsim {
std::unordered_map< std::bitset<SWITCH_NUM>, CPS::LUFactorized > mLuFactorizations;
std::unordered_map< std::bitset<SWITCH_NUM>, std::vector<CPS::LUFactorized> > mLuFactorizationsHarm;
// #### Dynamic matrix recomputation ####
/// Base matrix that includes all static MNA elements to speed up recomputation
Matrix mBaseSystemMatrix;
/// Flag that initiates recomputation of system matrix
Bool mUpdateSysMatrix;
/// Recomputes systems matrix
void updateSystemMatrix(Real time);
// #### Attributes related to switching ####
/// Index of the next switching event
UInt mSwitchTimeIndex = 0;
/// Vector of switch times
std::vector<SwitchConfiguration> mSwitchEvents;
/// Determines if static precomputed system matrices should be used
/// or system matrix is recomputed during simulation
Bool mUsePrecomputedMatrices = true;
/// Collects the status of switches to select correct system matrix
void updateSwitchStatus();
// #### Attributes related to logging ####
/// Last simulation time step when log was updated
......@@ -118,13 +113,11 @@ namespace DPsim {
/// Initialization of individual components
void initializeComponents();
/// Initialization of system matrices and source vector
void initializeSystem();
virtual void initializeSystem();
/// Initialization of system matrices and source vector
void initializeSystemWithParallelFrequencies();
/// Initialization of system matrices and source vector
void initializeSystemWithPrecomputedMatrices();
/// Initialization of system matrices and source vector
void initializeSystemWithDynamicMatrix();
/// Identify Nodes and SimPowerComps and SimSignalComps
void identifyTopologyObjects();
/// Assign simulation node index according to index in the vector.
......@@ -138,16 +131,12 @@ namespace DPsim {
void createEmptyVectors();
/// Create system matrix
void createEmptySystemMatrix();
/// Collects the status of switches to select correct system matrix
void updateSwitchStatus();
/// Collects the status of variable MNA elements to decide if system matrix has to be recomputed
void updateVariableElementStatus();
/// Logging of system matrices and source vector
void logSystemMatrices();
// #### Scheduler Task Methods ####
/// Solves system for single frequency
void solve(Real time, Int timeStepCount);
virtual void solve(Real time, Int timeStepCount);
/// Solves system for multiple frequencies
void solveWithHarmonics(Real time, Int timeStepCount, Int freqIdx);
/// Logs left and right vector
......@@ -173,7 +162,7 @@ namespace DPsim {
///
Matrix& rightSideVector() { return mRightSideVector; }
///
CPS::Task::List getTasks();
virtual CPS::Task::List getTasks();
///
Matrix& systemMatrix() { return mSwitchedMatrices[mCurrentSwitchStatus]; }
......
/* 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 <dpsim/MNASolver.h>
namespace DPsim {
/// Solver class using Modified Nodal Analysis (MNA).
template <typename VarType>
class MnaSolverSysRecomp : public MnaSolver<VarType> {
protected:
/// Initialization of system matrices and source vector
virtual void initializeSystem() override;
///
virtual void solve(Real time, Int timeStepCount) override;
// #### Dynamic matrix recomputation ####
/// Flag that initiates recomputation of system matrix
Bool mUpdateSysMatrix;
/// Recomputes systems matrix
void updateSystemMatrix(Real time);
/// Collects the status of variable MNA elements to decide if system matrix has to be recomputed
void updateVariableElementStatus();
/// Initialization of system matrices and source vector
void initializeSystemWithDynamicMatrix();
public:
///
MnaSolverSysRecomp(String name,
CPS::Domain domain = CPS::Domain::DP,
CPS::Logger::Level logLevel = CPS::Logger::Level::info);
///
virtual ~MnaSolverSysRecomp() { };
///
virtual CPS::Task::List getTasks() override;
// #### MNA Solver Tasks ####
///
class SolveTask : public CPS::Task {
public:
SolveTask(MnaSolverSysRecomp<VarType>& solver) :
Task(solver.mName + ".Solve"), mSolver(solver) {
for (auto it : solver.mMNAComponents) {
if (it->template attribute<Matrix>("right_vector")->get().size() != 0)
mAttributeDependencies.push_back(it->attribute("right_vector"));
}
for (auto node : solver.mNodes) {
mModifiedAttributes.push_back(node->attribute("v"));
}
mModifiedAttributes.push_back(solver.attribute("left_vector"));
}
void execute(Real time, Int timeStepCount) { mSolver.solve(time, timeStepCount); }
private:
MnaSolverSysRecomp<VarType>& mSolver;
};
class LogTask : public CPS::Task {
public:
LogTask(MnaSolverSysRecomp<VarType>& solver) :
Task(solver.mName + ".Log"), mSolver(solver) {
mAttributeDependencies.push_back(solver.attribute("left_vector"));
mModifiedAttributes.push_back(Scheduler::external);
}
void execute(Real time, Int timeStepCount) { mSolver.log(time, timeStepCount); }
private:
MnaSolverSysRecomp<VarType>& mSolver;
};
};
}
......@@ -2,6 +2,7 @@ set(DPSIM_SOURCES
Simulation.cpp
RealTimeSimulation.cpp
MNASolver.cpp
MNASolverSysRecomp.cpp
PFSolver.cpp
PFSolverPowerPolar.cpp
Utils.cpp
......
......@@ -175,15 +175,10 @@ void MnaSolver<VarType>::initializeSystem() {
throw SystemError("Too many Switches.");
}
if (mFrequencyParallel) {
if (mFrequencyParallel)
initializeSystemWithParallelFrequencies();
}
else if (mUsePrecomputedMatrices) {
else
initializeSystemWithPrecomputedMatrices();
}
else {
initializeSystemWithDynamicMatrix();
}
}
template <typename VarType>
......@@ -254,40 +249,6 @@ void MnaSolver<VarType>::initializeSystemWithPrecomputedMatrices() {
}
}
template <typename VarType>
void MnaSolver<VarType>::initializeSystemWithDynamicMatrix() {
mSLog->info("Number of variable Elements: {}"
"\nNumber of MNA components: {}",
mVariableElements.size(),
mMNAComponents.size());
mSLog->info("Stamping MNA fixed components");
for (auto comp : mMNAComponents) {
// Do not stamp variable elements yet
auto varcomp = std::dynamic_pointer_cast<MNAVariableElementInterface>(comp);
if (varcomp) continue;
comp->mnaApplySystemMatrixStamp(mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
auto idObj = std::dynamic_pointer_cast<IdentifiedObject>(comp);
}
// Save base matrix with only static elements
mSLog->info("Save base matrix");
mBaseSystemMatrix = mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)];
// Now stamp variable elements
mSLog->info("Stamping variable elements");
for (auto varElem : mMNAComponentsExt) {
varElem->mnaApplySystemMatrixStamp(mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
}
mLuFactorizations[std::bitset<SWITCH_NUM>(0)] = Eigen::PartialPivLU<Matrix>(mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
// Initialize source vector for debugging
for (auto comp : mMNAComponents) {
comp->mnaApplyRightSideVectorStamp(mRightSideVector);
}
}
template <typename VarType>
void MnaSolver<VarType>::updateSwitchStatus() {
for (UInt i = 0; i < mSwitches.size(); i++) {
......@@ -295,39 +256,6 @@ void MnaSolver<VarType>::updateSwitchStatus() {
}
}
/// new for recalculation of system matrix
template <typename VarType>
void MnaSolver<VarType>::updateVariableElementStatus() {
for (auto varElem : mVariableElements) {
if (varElem->hasParameterChanged()) {
auto idObj = std::dynamic_pointer_cast<IdentifiedObject>(varElem);
mSLog->info("Component ({:s} {:s}) value changed -> Update System Matrix",
idObj->type(), idObj->name());
mUpdateSysMatrix = true;
break;
}
}
}
template <typename VarType>
void MnaSolver<VarType>::updateSystemMatrix(Real time) {
mSLog->info("Updating System Matrix at {}\n", time);
// Start from base matrix
mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)] = mBaseSystemMatrix;
// Create system matrix with changed variable elements
for (auto comp : mMNAComponentsExt) {
comp->mnaApplySystemMatrixStamp(mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
auto idObj = std::dynamic_pointer_cast<IdentifiedObject>(comp);
mSLog->debug("Updating {:s} {:s} in system matrix (variabel component)",
idObj->type(), idObj->name());
}
mLuFactorizations[std::bitset<SWITCH_NUM>(0)] = Eigen::PartialPivLU<Matrix>(mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
mUpdateSysMatrix = false;
}
template <typename VarType>
void MnaSolver<VarType>::identifyTopologyObjects() {
for (auto baseNode : mSystem.mNodes) {
......@@ -341,30 +269,27 @@ void MnaSolver<VarType>::identifyTopologyObjects() {
for (auto comp : mSystem.mComponents) {
if (mUsePrecomputedMatrices) {
auto swComp = std::dynamic_pointer_cast<CPS::MNASwitchInterface>(comp);
if (swComp) {
mSwitches.push_back(swComp);
auto mnaComp = std::dynamic_pointer_cast<CPS::MNAInterface>(swComp);
if (mnaComp) mMNAComponentsExt.push_back(mnaComp);
continue;
}
auto swComp = std::dynamic_pointer_cast<CPS::MNASwitchInterface>(comp);
if (swComp) {
mSwitches.push_back(swComp);
auto mnaComp = std::dynamic_pointer_cast<CPS::MNAInterface>(swComp);
if (mnaComp) mMNACompSwitches.push_back(mnaComp);
}
else {
auto varComp = std::dynamic_pointer_cast<CPS::MNAVariableElementInterface>(comp);
if (varComp) {
mVariableElements.push_back(varComp);
auto mnaComp = std::dynamic_pointer_cast<CPS::MNAInterface>(varComp);
if (mnaComp) mMNAComponentsExt.push_back(mnaComp);
continue;
}
auto varComp = std::dynamic_pointer_cast<CPS::MNAVariableElementInterface>(comp);
if (varComp) {
mVariableElements.push_back(varComp);
auto mnaComp = std::dynamic_pointer_cast<CPS::MNAInterface>(varComp);
if (mnaComp) mMNACompVariableElements.push_back(mnaComp);
}
auto mnaComp = std::dynamic_pointer_cast<CPS::MNAInterface>(comp);
if (mnaComp) mMNAComponents.push_back(mnaComp);
if (!(swComp || varComp)) {
auto mnaComp = std::dynamic_pointer_cast<CPS::MNAInterface>(comp);
if (mnaComp) mMNAComponents.push_back(mnaComp);
auto sigComp = std::dynamic_pointer_cast<CPS::SimSignalComp>(comp);
if (sigComp) mSimSignalComps.push_back(sigComp);
auto sigComp = std::dynamic_pointer_cast<CPS::SimSignalComp>(comp);
if (sigComp) mSimSignalComps.push_back(sigComp);
}
}
}
......@@ -522,8 +447,6 @@ void MnaSolver<VarType>::steadyStateInitialization() {
initializeSystem();
logSystemMatrices();
updateSwitchStatus();
// Use sequential scheduler
SequentialScheduler sched;
CPS::Task::List tasks;
......@@ -624,7 +547,6 @@ template <typename VarType>
void MnaSolver<VarType>::solve(Real time, Int timeStepCount) {
// Reset source vector
mRightSideVector.setZero();
mUpdateSysMatrix = false;
// Add together the right side vector (computed by the components'
// pre-step tasks)
......@@ -638,14 +560,9 @@ void MnaSolver<VarType>::solve(Real time, Int timeStepCount) {
for (UInt nodeIdx = 0; nodeIdx < mNumNetNodes; nodeIdx++)
mNodes[nodeIdx]->mnaUpdateVoltage(mLeftSideVector);
if (!mIsInInitialization) {
if (!mIsInInitialization)
updateSwitchStatus();
updateVariableElementStatus();
if (mUpdateSysMatrix)
updateSystemMatrix(time);
}
// Components' states will be updated by the post-step tasks
}
......
/* 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 <dpsim/MNASolverSysRecomp.h>
using namespace DPsim;
using namespace CPS;
namespace DPsim {
template <typename VarType>
MnaSolverSysRecomp<VarType>::MnaSolverSysRecomp(String name,
CPS::Domain domain, CPS::Logger::Level logLevel) :
MnaSolver<VarType>(name, domain, logLevel) { }
template <typename VarType>
void MnaSolverSysRecomp<VarType>::initializeSystem() {
this->mSLog->info("-- Initialize MNA system matrices and source vector");
this->mRightSideVector.setZero();
this->mSLog->info("Number of variable Elements: {}"
"\nNumber of MNA components: {}",
this->mVariableElements.size(),
this->mMNAComponents.size());
this->mSLog->info("Stamping MNA fixed components");
for (auto comp : this->mMNAComponents) {
// Do not stamp variable elements yet
auto varcomp = std::dynamic_pointer_cast<MNAVariableElementInterface>(comp);
if (varcomp) continue;
comp->mnaApplySystemMatrixStamp(this->mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
auto idObj = std::dynamic_pointer_cast<IdentifiedObject>(comp);
}
// Save base matrix with only static elements
this->mSLog->info("Save base matrix");
this->mBaseSystemMatrix = this->mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)];
// Now stamp variable elements
this->mSLog->info("Stamping variable elements");
for (auto varElem : this->mMNACompVariableElements) {
varElem->mnaApplySystemMatrixStamp(this->mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
}
this->mLuFactorizations[std::bitset<SWITCH_NUM>(0)] = Eigen::PartialPivLU<Matrix>(this->mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
// Initialize source vector for debugging
for (auto comp : this->mMNAComponents) {
comp->mnaApplyRightSideVectorStamp(this->mRightSideVector);
}
}
template <typename VarType>
void MnaSolverSysRecomp<VarType>::updateVariableElementStatus() {
for (auto varElem : this->mVariableElements) {
if (varElem->hasParameterChanged()) {
auto idObj = std::dynamic_pointer_cast<IdentifiedObject>(varElem);
this->mSLog->info("Component ({:s} {:s}) value changed -> Update System Matrix",
idObj->type(), idObj->name());
mUpdateSysMatrix = true;
break;
}
}
}
template <typename VarType>
void MnaSolverSysRecomp<VarType>::updateSystemMatrix(Real time) {
this->mSLog->info("Updating System Matrix at {}\n", time);
// Start from base matrix
this->mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)] = this->mBaseSystemMatrix;
// Create system matrix with changed variable elements
for (auto comp : this->mMNACompVariableElements) {
comp->mnaApplySystemMatrixStamp(this->mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
auto idObj = std::dynamic_pointer_cast<IdentifiedObject>(comp);
this->mSLog->debug("Updating {:s} {:s} in system matrix (variabel component)",
idObj->type(), idObj->name());
}
this->mLuFactorizations[std::bitset<SWITCH_NUM>(0)] = Eigen::PartialPivLU<Matrix>(this->mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)]);
mUpdateSysMatrix = false;
}
template <typename VarType>
void MnaSolverSysRecomp<VarType>::solve(Real time, Int timeStepCount) {
// Reset source vector
this->mRightSideVector.setZero();
mUpdateSysMatrix = false;
// Add together the right side vector (computed by the components'
// pre-step tasks)
for (auto stamp : this->mRightVectorStamps)
this->mRightSideVector += *stamp;
if (this->mSwitchedMatrices.size() > 0)
this->mLeftSideVector = this->mLuFactorizations[this->mCurrentSwitchStatus].solve(this->mRightSideVector);
// TODO split into separate task? (dependent on x, updating all v attributes)
for (UInt nodeIdx = 0; nodeIdx < this->mNumNetNodes; nodeIdx++)
this->mNodes[nodeIdx]->mnaUpdateVoltage(this->mLeftSideVector);
if (!this->mIsInInitialization) {
updateVariableElementStatus();
if (mUpdateSysMatrix)
updateSystemMatrix(time);
}
// Components' states will be updated by the post-step tasks
}
template <typename VarType>
Task::List MnaSolverSysRecomp<VarType>::getTasks() {
Task::List l;
for (auto comp : this->mMNAComponents) {
for (auto task : comp->mnaTasks())
l.push_back(task);
}
for (auto comp : this->mMNACompVariableElements) {
for (auto task : comp->mnaTasks())
l.push_back(task);
}
for (auto node : this->mNodes) {
for (auto task : node->mnaTasks())
l.push_back(task);
}
// TODO signal components should be moved out of MNA solver
for (auto comp : this->mSimSignalComps) {
for (auto task : comp->getTasks())
l.push_back(task);
}
l.push_back(std::make_shared<MnaSolverSysRecomp<VarType>::SolveTask>(*this));
l.push_back(std::make_shared<MnaSolverSysRecomp<VarType>::LogTask>(*this));
return l;
}
}
template class DPsim::MnaSolverSysRecomp<Real>;
template class DPsim::MnaSolverSysRecomp<Complex>;
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