9#include <dpsim/DiakopticsSolver.h>
13#include <dpsim-models/MathUtils.h>
14#include <dpsim-models/Solver/MNATearInterface.h>
15#include <dpsim/Definitions.h>
22template <
typename VarType>
23DiakopticsSolver<VarType>::DiakopticsSolver(
24 String name, SystemTopology system, IdentifiedObject::List tearComponents,
25 Real timeStep, Logger::Level logLevel)
27 mMappedTearCurrents(AttributeStatic<Matrix>::make()),
28 mOrigLeftSideVector(AttributeStatic<Matrix>::make()) {
32 mLeftVectorLog = std::make_shared<DataLogger>(
33 name +
"_LeftVector", logLevel != CPS::Logger::Level::off);
34 mRightVectorLog = std::make_shared<DataLogger>(
35 name +
"_RightVector", logLevel != CPS::Logger::Level::off);
37 for (
auto comp : tearComponents) {
38 auto pcomp = std::dynamic_pointer_cast<SimPowerComp<VarType>>(comp);
40 mTearComponents.push_back(pcomp);
45template <
typename VarType>
47 std::vector<SystemTopology> subnets;
49 if (mSystem.mNodes.size() > 0)
50 mPhaseType = mSystem.
mNodes.at(0)->phaseType();
53 system.splitSubnets<VarType>(subnets);
61template <
typename VarType>
62void DiakopticsSolver<VarType>::initSubnets(
63 const std::vector<SystemTopology> &subnets) {
64 mSubnets.resize(subnets.size());
65 for (UInt i = 0; i < subnets.size(); ++i) {
67 for (
auto baseNode : subnets[i].mNodes) {
68 if (!baseNode->isGround()) {
69 auto node = std::dynamic_pointer_cast<CPS::SimNode<VarType>>(baseNode);
70 mSubnets[i].nodes.push_back(node);
74 for (
auto comp : subnets[i].mComponents) {
76 auto mnaComp = std::dynamic_pointer_cast<CPS::MNAInterface>(comp);
78 mSubnets[i].components.push_back(mnaComp);
80 auto sigComp = std::dynamic_pointer_cast<CPS::SimSignalComp>(comp);
82 mSimSignalComps.push_back(sigComp);
87 for (
auto &net : mSubnets) {
88 for (
auto &node : net.nodes) {
89 mNodeSubnetMap[node] = &net;
93 for (UInt idx = 0; idx < mTearComponents.size(); ++idx) {
94 auto comp = mTearComponents[idx];
95 auto tComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
97 throw SystemError(
"Unsupported component type for diakoptics");
99 if (comp->hasVirtualNodes()) {
100 for (UInt node = 0; node < comp->virtualNodesNumber(); ++node) {
107 tComp->mnaTearSetIdx(idx);
108 comp->initializeFromNodesAndTerminals(mSystemFrequency);
109 tComp->mnaTearInitialize(2 * PI * mSystemFrequency, mTimeStep);
111 for (
auto gndComp : tComp->mnaTearGroundComponents()) {
112 auto pComp = std::dynamic_pointer_cast<SimPowerComp<VarType>>(gndComp);
113 Subnet *net =
nullptr;
114 if (pComp->node(0)->isGround()) {
115 net = mNodeSubnetMap[pComp->node(1)];
116 }
else if (pComp->node(1)->isGround()) {
117 net = mNodeSubnetMap[pComp->node(0)];
120 "Invalid ground component passed from torn component");
122 net->components.push_back(gndComp);
126 for (UInt i = 0; i < subnets.size(); ++i) {
127 collectVirtualNodes(i);
128 assignMatrixNodeIndices(i);
132template <
typename VarType>
133void DiakopticsSolver<VarType>::collectVirtualNodes(
int net) {
134 mSubnets[net].mVirtualNodeNum = 0;
135 mSubnets[net].mRealNetNodeNum =
static_cast<UInt
>(mSubnets[net].nodes.size());
137 for (
auto comp : mSubnets[net].components) {
138 auto pComp = std::dynamic_pointer_cast<SimPowerComp<VarType>>(comp);
142 if (pComp->hasVirtualNodes()) {
143 for (UInt node = 0; node < pComp->virtualNodesNumber(); ++node) {
144 ++(mSubnets[net].mVirtualNodeNum);
145 mSubnets[net].nodes.push_back(pComp->virtualNode(node));
149 SPDLOG_LOGGER_INFO(mSLog,
"Subnet {} has {} real network nodes.", net,
150 mSubnets[net].mRealNetNodeNum);
151 SPDLOG_LOGGER_INFO(mSLog,
"Subnet {} has {} virtual nodes.", net,
152 mSubnets[net].mVirtualNodeNum);
155template <
typename VarType>
156void DiakopticsSolver<VarType>::assignMatrixNodeIndices(
int net) {
157 UInt matrixNodeIndexIdx = 0;
158 for (UInt idx = 0; idx < mSubnets[net].nodes.size(); ++idx) {
159 auto &node = mSubnets[net].nodes[idx];
161 node->setMatrixNodeIndex(0, matrixNodeIndexIdx);
162 SPDLOG_LOGGER_INFO(mSLog,
"Assigned index {} to node {}",
163 matrixNodeIndexIdx, node->name());
164 ++matrixNodeIndexIdx;
166 if (node->phaseType() == CPS::PhaseType::ABC) {
167 node->setMatrixNodeIndex(1, matrixNodeIndexIdx);
168 SPDLOG_LOGGER_INFO(mSLog,
"Assigned index {} to node {} phase B",
169 matrixNodeIndexIdx, node->name());
170 ++matrixNodeIndexIdx;
171 node->setMatrixNodeIndex(2, matrixNodeIndexIdx);
172 SPDLOG_LOGGER_INFO(mSLog,
"Assigned index {} to node {} phase C",
173 matrixNodeIndexIdx, node->name());
174 ++matrixNodeIndexIdx;
177 setSubnetSize(net, matrixNodeIndexIdx);
180 mSubnets[net].sysOff = 0;
182 mSubnets[net].sysOff = mSubnets[net - 1].sysOff + mSubnets[net - 1].sysSize;
185template <>
void DiakopticsSolver<Real>::setSubnetSize(
int net, UInt nodes) {
186 mSubnets[net].sysSize = nodes;
187 mSubnets[net].mCmplOff = 0;
190template <>
void DiakopticsSolver<Complex>::setSubnetSize(
int net, UInt nodes) {
191 mSubnets[net].sysSize = 2 * nodes;
192 mSubnets[net].mCmplOff = nodes;
195template <>
void DiakopticsSolver<Real>::setLogColumns() {
199template <>
void DiakopticsSolver<Complex>::setLogColumns() {
200 std::vector<String> names;
201 for (
auto &subnet : mSubnets) {
202 for (UInt i = subnet.sysOff; i < subnet.sysOff + subnet.sysSize; ++i) {
203 std::stringstream name;
204 if (i < subnet.sysOff + subnet.mCmplOff)
205 name <<
"node" << std::setfill(
'0') << std::setw(5)
206 << i - subnet.sysOff / 2 <<
".real";
208 name <<
"node" << std::setfill(
'0') << std::setw(5)
209 << i - (subnet.sysOff + subnet.sysSize) / 2 <<
".imag";
210 names.push_back(name.str());
213 mLeftVectorLog->setColumnNames(names);
214 mRightVectorLog->setColumnNames(names);
217template <
typename VarType>
void DiakopticsSolver<VarType>::createMatrices() {
218 UInt totalSize = mSubnets.back().sysOff + mSubnets.back().sysSize;
219 mSystemMatrix = Matrix::Zero(totalSize, totalSize);
220 mSystemInverse = Matrix::Zero(totalSize, totalSize);
222 mRightSideVector = Matrix::Zero(totalSize, 1);
223 mLeftSideVector = Matrix::Zero(totalSize, 1);
224 **mOrigLeftSideVector = Matrix::Zero(totalSize, 1);
225 **mMappedTearCurrents = Matrix::Zero(totalSize, 1);
227 for (
auto &net : mSubnets) {
232 net.leftVector->set(Matrix::Zero(net.sysSize, 1));
235 createTearMatrices(totalSize);
238template <>
void DiakopticsSolver<Real>::createTearMatrices(UInt totalSize) {
239 int phaseMultiplier = 1;
240 if (mPhaseType == PhaseType::ABC) {
244 Matrix::Zero(totalSize, mTearComponents.size() * phaseMultiplier);
246 CPS::SparseMatrixRow(mTearComponents.size() * phaseMultiplier,
247 mTearComponents.size() * phaseMultiplier);
248 mTearCurrents = Matrix::Zero(mTearComponents.size() * phaseMultiplier, 1);
249 mTearVoltages = Matrix::Zero(mTearComponents.size() * phaseMultiplier, 1);
252template <>
void DiakopticsSolver<Complex>::createTearMatrices(UInt totalSize) {
253 int phaseMultiplier = 1;
254 if (mPhaseType == PhaseType::ABC) {
258 Matrix::Zero(totalSize, 2 * mTearComponents.size() * phaseMultiplier);
260 CPS::SparseMatrixRow(2 * mTearComponents.size() * phaseMultiplier,
261 2 * mTearComponents.size() * phaseMultiplier);
262 mTearCurrents = Matrix::Zero(2 * mTearComponents.size() * phaseMultiplier, 1);
263 mTearVoltages = Matrix::Zero(2 * mTearComponents.size() * phaseMultiplier, 1);
266template <
typename VarType>
void DiakopticsSolver<VarType>::initComponents() {
267 for (UInt net = 0; net < mSubnets.size(); ++net) {
268 for (
auto comp : mSubnets[net].components) {
269 auto pComp = std::dynamic_pointer_cast<SimPowerComp<VarType>>(comp);
272 pComp->initializeFromNodesAndTerminals(mSystem.mSystemFrequency);
276 for (
auto comp : mSubnets[net].components) {
277 comp->mnaInitialize(mSystem.mSystemOmega, mTimeStep,
278 mSubnets[net].leftVector);
279 const Matrix &stamp = comp->getRightVector()->get();
280 if (stamp.size() != 0) {
281 mSubnets[net].rightVectorStamps.push_back(&stamp);
286 for (
auto comp : mSimSignalComps)
287 comp->initialize(mSystem.mSystemOmega, mTimeStep);
290template <
typename VarType>
void DiakopticsSolver<VarType>::initMatrices() {
291 for (
auto &net : mSubnets) {
296 CPS::SparseMatrixRow partSys =
297 CPS::SparseMatrixRow(net.sysSize, net.sysSize);
298 for (
auto comp : net.components) {
299 comp->mnaApplySystemMatrixStamp(partSys);
302 mSystemMatrix.block(net.sysOff, net.sysOff, net.sysSize, net.sysSize);
304 SPDLOG_LOGGER_INFO(mSLog,
"Block: \n{}", block);
305 net.luFactorization = Eigen::PartialPivLU<Matrix>(partSys);
306 SPDLOG_LOGGER_INFO(mSLog,
"Factorization: \n{}",
307 net.luFactorization.matrixLU());
309 SPDLOG_LOGGER_INFO(mSLog,
"Complete system matrix: \n{}", mSystemMatrix);
312 for (UInt compIdx = 0; compIdx < mTearComponents.size(); ++compIdx) {
313 applyTearComponentStamp(compIdx);
315 SPDLOG_LOGGER_INFO(mSLog,
"Topology matrix: \n{}", mTearTopology);
316 SPDLOG_LOGGER_INFO(mSLog,
"Removed impedance matrix: \n{}", mTearImpedance);
318 for (
auto &net : mSubnets) {
319 mSystemInverse.block(net.sysOff, net.sysOff, net.sysSize, net.sysSize) =
320 net.luFactorization.inverse();
322 mTotalTearImpedance = Eigen::PartialPivLU<Matrix>(
324 mTearTopology.transpose() * mSystemInverse * mTearTopology);
325 SPDLOG_LOGGER_INFO(mSLog,
326 "Total removed impedance matrix LU decomposition: \n{}",
327 mTotalTearImpedance.matrixLU());
330 for (
auto &net : mSubnets) {
331 Matrix rInit = Matrix::Zero(net.sysSize, 1);
333 for (
auto comp : net.components) {
334 comp->mnaApplyRightSideVectorStamp(rInit);
336 SPDLOG_LOGGER_INFO(mSLog,
"Source block: \n{}", rInit);
340template <>
void DiakopticsSolver<Real>::applyTearComponentStamp(UInt compIdx) {
341 auto comp = mTearComponents[compIdx];
344 std::vector<Eigen::Triplet<double>> triplets;
347 if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) {
348 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
349 comp->node(0)->matrixNodeIndex(PhaseType::A),
351 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
352 comp->node(0)->matrixNodeIndex(PhaseType::B),
354 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
355 comp->node(0)->matrixNodeIndex(PhaseType::C),
358 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
359 comp->node(0)->matrixNodeIndex(),
364 if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) {
365 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
366 comp->node(1)->matrixNodeIndex(PhaseType::A),
368 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
369 comp->node(1)->matrixNodeIndex(PhaseType::B),
370 compIdx * 3 + 1, -1);
371 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
372 comp->node(1)->matrixNodeIndex(PhaseType::C),
373 compIdx * 3 + 2, -1);
375 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
376 comp->node(1)->matrixNodeIndex(),
381 for (
const auto &triplet : triplets) {
382 mTearTopology.coeffRef(triplet.row(), triplet.col()) += triplet.value();
386 auto tearComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
387 tearComp->mnaTearApplyMatrixStamp(mTearImpedance);
391void DiakopticsSolver<Complex>::applyTearComponentStamp(UInt compIdx) {
392 auto comp = mTearComponents[compIdx];
395 std::vector<Eigen::Triplet<double>> triplets;
398 if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) {
399 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
400 comp->node(0)->matrixNodeIndex(PhaseType::A),
402 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
403 mNodeSubnetMap[comp->node(0)]->mCmplOff +
404 comp->node(0)->matrixNodeIndex(PhaseType::A),
405 mTearComponents.size() * 3 + compIdx * 3,
407 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
408 comp->node(0)->matrixNodeIndex(PhaseType::B),
410 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
411 mNodeSubnetMap[comp->node(0)]->mCmplOff +
412 comp->node(0)->matrixNodeIndex(PhaseType::B),
413 mTearComponents.size() * 3 + compIdx * 3 + 1,
415 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
416 comp->node(0)->matrixNodeIndex(PhaseType::C),
418 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
419 mNodeSubnetMap[comp->node(0)]->mCmplOff +
420 comp->node(0)->matrixNodeIndex(PhaseType::C),
421 mTearComponents.size() * 3 + compIdx * 3 + 2,
424 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
425 comp->node(0)->matrixNodeIndex(),
427 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
428 mNodeSubnetMap[comp->node(0)]->mCmplOff +
429 comp->node(0)->matrixNodeIndex(),
430 mTearComponents.size() + compIdx,
double(1.0));
433 if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) {
434 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
435 comp->node(1)->matrixNodeIndex(PhaseType::A),
437 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
438 mNodeSubnetMap[comp->node(1)]->mCmplOff +
439 comp->node(1)->matrixNodeIndex(PhaseType::A),
440 mTearComponents.size() * 3 + compIdx * 3,
442 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
443 comp->node(1)->matrixNodeIndex(PhaseType::B),
444 compIdx * 3 + 1, -1);
445 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
446 mNodeSubnetMap[comp->node(1)]->mCmplOff +
447 comp->node(1)->matrixNodeIndex(PhaseType::B),
448 mTearComponents.size() * 3 + compIdx * 3 + 1,
450 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
451 comp->node(1)->matrixNodeIndex(PhaseType::C),
452 compIdx * 3 + 2, -1);
453 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
454 mNodeSubnetMap[comp->node(1)]->mCmplOff +
455 comp->node(1)->matrixNodeIndex(PhaseType::C),
456 mTearComponents.size() * 3 + compIdx * 3 + 2,
459 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
460 comp->node(1)->matrixNodeIndex(),
462 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
463 mNodeSubnetMap[comp->node(1)]->mCmplOff +
464 comp->node(1)->matrixNodeIndex(),
465 mTearComponents.size() + compIdx,
double(-1.0));
468 for (
const auto &triplet : triplets) {
469 mTearTopology.coeffRef(triplet.row(), triplet.col()) += triplet.value();
473 auto tearComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
474 tearComp->mnaTearApplyMatrixStamp(mTearImpedance);
480 for (UInt net = 0; net < mSubnets.size(); ++net) {
481 for (
auto node : mSubnets[net].nodes) {
482 for (
auto task : node->mnaTasks())
486 for (
auto comp : mSubnets[net].components) {
487 for (
auto task : comp->mnaTasks()) {
491 l.push_back(std::make_shared<SubnetSolveTask>(*
this, net));
492 l.push_back(std::make_shared<SolveTask>(*
this, net));
495 for (
auto comp : mSimSignalComps) {
496 for (
auto task : comp->getTasks()) {
500 l.push_back(std::make_shared<PreSolveTask>(*
this));
501 l.push_back(std::make_shared<PostSolveTask>(*
this));
502 l.push_back(std::make_shared<LogTask>(*
this));
507template <
typename VarType>
508void DiakopticsSolver<VarType>::SubnetSolveTask::execute(Real time,
511 mSolver.mRightSideVector.block(mSubnet.sysOff, 0, mSubnet.sysSize, 1);
514 for (
auto stamp : mSubnet.rightVectorStamps)
517 auto lBlock = (**mSolver.mOrigLeftSideVector)
518 .block(mSubnet.sysOff, 0, mSubnet.sysSize, 1);
520 lBlock = mSubnet.luFactorization.solve(rBlock);
523template <
typename VarType>
524void DiakopticsSolver<VarType>::PreSolveTask::execute(Real time,
526 mSolver.mTearVoltages.setZero();
527 for (
auto comp : mSolver.mTearComponents) {
528 auto tComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
529 tComp->mnaTearApplyVoltageStamp(mSolver.mTearVoltages);
532 mSolver.mTearVoltages -=
533 mSolver.mTearTopology.transpose() * **mSolver.mOrigLeftSideVector;
535 mSolver.mTearCurrents =
536 mSolver.mTotalTearImpedance.solve(mSolver.mTearVoltages);
538 **mSolver.mMappedTearCurrents = mSolver.mTearTopology * mSolver.mTearCurrents;
539 mSolver.mLeftSideVector = **mSolver.mOrigLeftSideVector;
542template <
typename VarType>
543void DiakopticsSolver<VarType>::SolveTask::execute(Real time,
546 mSolver.mLeftSideVector.block(mSubnet.sysOff, 0, mSubnet.sysSize, 1);
547 auto rBlock = (**mSolver.mMappedTearCurrents)
548 .block(mSubnet.sysOff, 0, mSubnet.sysSize, 1);
551 lBlock += mSubnet.luFactorization.solve(rBlock);
552 **mSubnet.leftVector = lBlock;
556void DiakopticsSolver<Real>::PostSolveTask::execute(Real time,
559 mSolver.mTearVoltages =
560 -mSolver.mTearTopology.transpose() * mSolver.mLeftSideVector;
561 for (UInt compIdx = 0; compIdx < mSolver.mTearComponents.size(); ++compIdx) {
562 auto comp = mSolver.mTearComponents[compIdx];
563 auto tComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
564 if (mSolver.mPhaseType == CPS::PhaseType::ABC) {
565 Matrix voltage = Matrix::Zero(3, 1);
566 voltage << mSolver.mTearVoltages(compIdx * 3),
567 mSolver.mTearVoltages(compIdx * 3 + 1),
568 mSolver.mTearVoltages(compIdx * 3 + 2);
570 Matrix current = Matrix::Zero(3, 1);
571 current << mSolver.mTearCurrents(compIdx * 3),
572 mSolver.mTearCurrents(compIdx * 3 + 1),
573 mSolver.mTearCurrents(compIdx * 3 + 2);
574 tComp->mnaTearPostStep(voltage, current);
577 Math::complexFromVectorElement(mSolver.mTearVoltages, compIdx);
579 Math::complexFromVectorElement(mSolver.mTearCurrents, compIdx);
580 tComp->mnaTearPostStep(voltage, current);
585 for (UInt net = 0; net < mSolver.mSubnets.size(); ++net) {
586 for (UInt node = 0; node < mSolver.mSubnets[net].mRealNetNodeNum; ++node) {
587 mSolver.mSubnets[net].nodes[node]->mnaUpdateVoltage(
588 *(mSolver.mSubnets[net].leftVector));
594void DiakopticsSolver<Complex>::PostSolveTask::execute(Real time,
597 mSolver.mTearVoltages =
598 -mSolver.mTearTopology.transpose() * mSolver.mLeftSideVector;
599 for (UInt compIdx = 0; compIdx < mSolver.mTearComponents.size(); ++compIdx) {
600 auto comp = mSolver.mTearComponents[compIdx];
601 auto tComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
602 if (mSolver.mPhaseType == CPS::PhaseType::ABC) {
603 MatrixComp voltage = MatrixComp::Zero(3, 1);
604 voltage << Math::complexFromVectorElement(mSolver.mTearVoltages,
606 Math::complexFromVectorElement(mSolver.mTearVoltages,
608 Math::complexFromVectorElement(mSolver.mTearVoltages,
610 MatrixComp current = MatrixComp::Zero(3, 1);
611 current << Math::complexFromVectorElement(mSolver.mTearCurrents,
613 Math::complexFromVectorElement(mSolver.mTearCurrents,
615 Math::complexFromVectorElement(mSolver.mTearCurrents,
617 tComp->mnaTearPostStep(voltage, current);
620 Math::complexFromVectorElement(mSolver.mTearVoltages, compIdx);
622 Math::complexFromVectorElement(mSolver.mTearCurrents, compIdx);
623 tComp->mnaTearPostStep(voltage, current);
628 for (UInt net = 0; net < mSolver.mSubnets.size(); ++net) {
629 for (UInt node = 0; node < mSolver.mSubnets[net].mRealNetNodeNum; ++node) {
630 mSolver.mSubnets[net].nodes[node]->mnaUpdateVoltage(
631 *(mSolver.mSubnets[net].leftVector));
636template <>
void DiakopticsSolver<Real>::log(Real time, Int timeStepCount) {
637 mLeftVectorLog->logEMTNodeValues(time, mLeftSideVector);
638 mRightVectorLog->logEMTNodeValues(time, mRightSideVector);
641template <>
void DiakopticsSolver<Complex>::log(Real time, Int timeStepCount) {
642 mLeftVectorLog->logPhasorNodeValues(time, mLeftSideVector);
643 mRightVectorLog->logPhasorNodeValues(time, mRightSideVector);
646template <
typename VarType>
647void DiakopticsSolver<VarType>::LogTask::execute(Real time, Int timeStepCount) {
648 mSolver.log(time, timeStepCount);
651template class DiakopticsSolver<Real>;
652template class DiakopticsSolver<Complex>;
Real mSystemFrequency
System frequency.
TopologicalNode::List mNodes
List of network nodes.
CPS::Task::List getTasks() override
Get tasks for scheduler.
Base class for more specific solvers such as MNA, ODE or IDA.