DPsim
Loading...
Searching...
No Matches
MNASolverPlugin.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 <Eigen/Eigen>
10#include <dlfcn.h>
11#include <dpsim/MNASolverPlugin.h>
12#include <dpsim/SequentialScheduler.h>
13
14using namespace DPsim;
15using namespace CPS;
16
17namespace DPsim {
18
19template <typename VarType>
20MnaSolverPlugin<VarType>::MnaSolverPlugin(String pluginName, String name,
21 CPS::Domain domain,
22 CPS::Logger::Level logLevel)
23 : MnaSolverDirect<VarType>(name, domain, logLevel), mPluginName(pluginName),
24 mPlugin(nullptr), mDlHandle(nullptr) {}
25
26template <typename VarType> MnaSolverPlugin<VarType>::~MnaSolverPlugin() {
27 if (mPlugin != nullptr) {
28 mPlugin->cleanup();
29 }
30 if (mDlHandle != nullptr) {
31 dlclose(mDlHandle);
32 }
33}
34
35extern "C" void pluginLogger(const char *str) {
36 CPS::Logger::Log log = CPS::Logger::get("Plugin", CPS::Logger::Level::debug,
37 CPS::Logger::Level::debug);
38 log->info(str);
39}
40
41template <typename VarType>
43 // Start from base matrix
45
46 // Now stamp switches into matrix
47 for (auto sw : this->mMNAIntfSwitches)
48 sw->mnaApplySystemMatrixStamp(this->mVariableSystemMatrix);
49
50 // Now stamp variable elements into matrix
51 for (auto comp : this->mMNAIntfVariableComps)
52 comp->mnaApplySystemMatrixStamp(this->mVariableSystemMatrix);
53
54 int size = this->mRightSideVector.rows();
55 int nnz = this->mVariableSystemMatrix.nonZeros();
56 struct dpsim_csr_matrix matrix = {
57 .values = this->mVariableSystemMatrix.valuePtr(),
58 .rowIndex = this->mVariableSystemMatrix.outerIndexPtr(),
59 .colIndex = this->mVariableSystemMatrix.innerIndexPtr(),
60 .row_number = size,
61 .nnz = nnz,
62 };
63 // Refactorization of matrix assuming that structure remained
64 // constant by omitting analyzePattern
65 if (mPlugin->lu_decomp(&matrix) != 0) {
66 SPDLOG_LOGGER_ERROR(this->mSLog, "error recomputing decomposition");
67 return;
68 }
69 ++this->mNumRecomputations;
70}
71
72template <typename VarType> void MnaSolverPlugin<VarType>::initialize() {
74 int size = this->mRightSideVector.rows();
75 std::vector<SparseMatrix> hMat;
76 int nnz = 0;
78 SPDLOG_LOGGER_ERROR(this->mSLog,
79 "System matrix recomputation not supported");
80 return;
81 } else {
82 hMat = this->mSwitchedMatrices[std::bitset<SWITCH_NUM>(0)];
83 nnz = hMat[0].nonZeros();
84 }
85
86 struct dpsim_mna_plugin *(*get_mna_plugin)(const char *);
87
88 String pluginFileName = mPluginName + ".so";
89
90 if ((mDlHandle = dlopen(pluginFileName.c_str(), RTLD_NOW)) == nullptr) {
91 SPDLOG_LOGGER_ERROR(this->mSLog, "error opening dynamic library {}: {}",
92 mPluginName, dlerror());
93 throw CPS::SystemError("error opening dynamic library.");
94 }
95
96 get_mna_plugin = (struct dpsim_mna_plugin * (*)(const char *))
97 dlsym(mDlHandle, "get_mna_plugin");
98 if (get_mna_plugin == NULL) {
99 SPDLOG_LOGGER_ERROR(this->mSLog, "error reading symbol from library {}: {}",
100 mPluginName, dlerror());
101 throw CPS::SystemError("error reading symbol from library.");
102 }
103
104 if ((mPlugin = get_mna_plugin(mPluginName.c_str())) == nullptr) {
105 SPDLOG_LOGGER_ERROR(this->mSLog, "error getting plugin class");
106 throw CPS::SystemError("error getting plugin class.");
107 }
108
109 mPlugin->log = pluginLogger;
110
111 struct dpsim_csr_matrix matrix = {
112 .values = hMat[0].valuePtr(),
113 .rowIndex = hMat[0].outerIndexPtr(),
114 .colIndex = hMat[0].innerIndexPtr(),
115 .row_number = size,
116 .nnz = nnz,
117 };
118
119 if (mPlugin->init(&matrix) != 0) {
120 SPDLOG_LOGGER_ERROR(this->mSLog, "error initializing plugin");
121 return;
122 }
123}
124
125template <typename VarType> Task::List MnaSolverPlugin<VarType>::getTasks() {
126 Task::List l;
127
128 for (auto comp : this->mMNAComponents) {
129 for (auto task : comp->mnaTasks()) {
130 l.push_back(task);
131 }
132 }
133 for (auto node : this->mNodes) {
134 for (auto task : node->mnaTasks())
135 l.push_back(task);
136 }
137 // TODO signal components should be moved out of MNA solver
138 for (auto comp : this->mSimSignalComps) {
139 for (auto task : comp->getTasks()) {
140 l.push_back(task);
141 }
142 }
143 l.push_back(std::make_shared<MnaSolverPlugin<VarType>::SolveTask>(*this));
144 l.push_back(std::make_shared<MnaSolverPlugin<VarType>::LogTask>(*this));
145 return l;
146}
147
148template <typename VarType>
149void MnaSolverPlugin<VarType>::solve(Real time, Int timeStepCount) {
150 // Reset source vector
151 this->mRightSideVector.setZero();
152
153 // Add together the right side vector (computed by the components'
154 // pre-step tasks)
155 for (const auto &stamp : this->mRightVectorStamps)
156 this->mRightSideVector += *stamp;
157
158 if (!this->mIsInInitialization)
159 this->updateSwitchStatus();
160
161 mPlugin->solve((double *)this->mRightSideVector.data(),
162 (double *)this->leftSideVector().data());
163
164 // TODO split into separate task? (dependent on x, updating all v attributes)
165 for (UInt nodeIdx = 0; nodeIdx < this->mNumNetNodes; ++nodeIdx)
166 this->mNodes[nodeIdx]->mnaUpdateVoltage(**(this->mLeftSideVector));
167
168 // Components' states will be updated by the post-step tasks
169}
170
171} // namespace DPsim
172template class DPsim::MnaSolverPlugin<Real>;
Solver class using Modified Nodal Analysis (MNA).
SparseMatrix mVariableSystemMatrix
System matrix including stamp of static and variable elements.
SparseMatrix mBaseSystemMatrix
System matrix including all static elements.
std::unordered_map< std::bitset< SWITCH_NUM >, std::vector< SparseMatrix > > mSwitchedMatrices
Map of system matrices where the key is the bitset describing the switch states.
Matrix mRightSideVector
Source vector of known quantities.
Definition MNASolver.h:83
virtual void initialize() override
Calls subroutines to set up everything that is required before simulation.
Definition MNASolver.cpp:35
CPS::MNAInterface::List mMNAIntfVariableComps
List of variable components if they must be accessed as MNAInterface objects.
Definition MNASolver.h:98
UInt mNumNetNodes
Number of network nodes, single line equivalent.
Definition MNASolver.h:46
CPS::MNAInterface::List mMNAIntfSwitches
List of switches if they must be accessed as MNAInterface objects.
Definition MNASolver.h:74
std::vector< const Matrix * > mRightVectorStamps
List of all right side vector contributions.
Definition MNASolver.h:85
void updateSwitchStatus()
Collects the status of switches to select correct system matrix.
Int mNumRecomputations
Number of system matrix recomputations.
Definition MNASolver.h:93
CPS::MNAInterface::List mMNAComponents
List of MNA components with static stamp into system matrix.
Definition MNASolver.h:69
CPS::Attribute< Matrix >::Ptr mLeftSideVector
Solution vector of unknown quantities.
Definition MNASolver.h:196
CPS::SimSignalComp::List mSimSignalComps
List of signal type components that do not directly interact with the MNA solver.
Definition MNASolver.h:76
CPS::SimNode< VarType >::List mNodes
List of simulation nodes.
Definition MNASolver.h:65
CPS::Task::List getTasks() override
Get tasks for scheduler.
CPS::Logger::Log mSLog
Logger.
Definition Solver.h:45
void solve(Real time, Int timeStepCount) override
Solves system for single frequency.
void recomputeSystemMatrix(Real time) override
Recomputes systems matrix.
void initialize() override
Initialize cuSparse-library.
Bool mSystemMatrixRecomputation
Enable recomputation of system matrix during simulation.
Definition Solver.h:64
Bool mIsInInitialization
Determines if solver is in initialization phase, which requires different behavior.
Definition Solver.h:59