9#include <dpsim/DiakopticsSolver.h>
13#include <dpsim-models/MathUtils.h>
14#include <dpsim-models/Solver/MNATearInterface.h>
15#include <dpsim/Definitions.h>
16#include <dpsim/KLUAdapter.h>
23template <
typename VarType>
24DiakopticsSolver<VarType>::DiakopticsSolver(
25 String name, SystemTopology system, IdentifiedObject::List tearComponents,
26 Real timeStep, Logger::Level logLevel)
28 mMappedTearCurrents(AttributeStatic<Matrix>::make()),
29 mOrigLeftSideVector(AttributeStatic<Matrix>::make()) {
33 mLeftVectorLog = std::make_shared<DataLogger>(
34 name +
"_LeftVector", logLevel != CPS::Logger::Level::off);
35 mRightVectorLog = std::make_shared<DataLogger>(
36 name +
"_RightVector", logLevel != CPS::Logger::Level::off);
38 for (
auto comp : tearComponents) {
39 auto pcomp = std::dynamic_pointer_cast<SimPowerComp<VarType>>(comp);
41 mTearComponents.push_back(pcomp);
46template <
typename VarType>
48 std::vector<SystemTopology> subnets;
50 if (mSystem.mNodes.size() > 0)
51 mPhaseType = mSystem.
mNodes.at(0)->phaseType();
54 system.splitSubnets<VarType>(subnets);
62template <
typename VarType>
63void DiakopticsSolver<VarType>::initSubnets(
64 const std::vector<SystemTopology> &subnets) {
65 mSubnets.resize(subnets.size());
66 for (UInt i = 0; i < subnets.size(); ++i) {
68 for (
auto baseNode : subnets[i].mNodes) {
69 if (!baseNode->isGround()) {
70 auto node = std::dynamic_pointer_cast<CPS::SimNode<VarType>>(baseNode);
71 mSubnets[i].nodes.push_back(node);
75 for (
auto comp : subnets[i].mComponents) {
77 auto mnaComp = std::dynamic_pointer_cast<CPS::MNAInterface>(comp);
79 mSubnets[i].components.push_back(mnaComp);
81 auto sigComp = std::dynamic_pointer_cast<CPS::SimSignalComp>(comp);
83 mSimSignalComps.push_back(sigComp);
86 std::dynamic_pointer_cast<CPS::MNAVariableCompInterface>(comp);
88 mSubnets[i].mVariableComps.push_back(mnaVarComp);
93 for (
auto &net : mSubnets) {
94 for (
auto &node : net.nodes) {
95 mNodeSubnetMap[node] = &net;
99 for (UInt idx = 0; idx < mTearComponents.size(); ++idx) {
100 auto comp = mTearComponents[idx];
101 auto tComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
103 throw SystemError(
"Unsupported component type for diakoptics");
105 if (comp->hasVirtualNodes()) {
106 for (UInt node = 0; node < comp->virtualNodesNumber(); ++node) {
113 tComp->mnaTearSetIdx(idx);
114 comp->initializeFromNodesAndTerminals(mSystemFrequency);
115 tComp->mnaTearInitialize(2 * PI * mSystemFrequency, mTimeStep);
117 for (
auto gndComp : tComp->mnaTearGroundComponents()) {
118 auto pComp = std::dynamic_pointer_cast<SimPowerComp<VarType>>(gndComp);
119 Subnet *net =
nullptr;
120 if (pComp->node(0)->isGround()) {
121 net = mNodeSubnetMap[pComp->node(1)];
122 }
else if (pComp->node(1)->isGround()) {
123 net = mNodeSubnetMap[pComp->node(0)];
126 "Invalid ground component passed from torn component");
128 net->components.push_back(gndComp);
132 for (UInt i = 0; i < subnets.size(); ++i) {
133 collectVirtualNodes(i);
134 assignMatrixNodeIndices(i);
138template <
typename VarType>
139void DiakopticsSolver<VarType>::collectVirtualNodes(
int net) {
140 mSubnets[net].mVirtualNodeNum = 0;
141 mSubnets[net].mRealNetNodeNum =
static_cast<UInt
>(mSubnets[net].nodes.size());
143 for (
auto comp : mSubnets[net].components) {
144 auto pComp = std::dynamic_pointer_cast<SimPowerComp<VarType>>(comp);
148 if (pComp->hasVirtualNodes()) {
149 for (UInt node = 0; node < pComp->virtualNodesNumber(); ++node) {
150 ++(mSubnets[net].mVirtualNodeNum);
151 mSubnets[net].nodes.push_back(pComp->virtualNode(node));
155 if (pComp->hasSubComponents()) {
156 for (
auto pSubComp : pComp->subComponents()) {
157 for (UInt node = 0; node < pSubComp->virtualNodesNumber(); ++node) {
158 auto vnode = pSubComp->virtualNode(node);
159 bool alreadyRegistered =
false;
160 for (
auto registeredNode : mSubnets[net].nodes) {
161 if (registeredNode == vnode) {
162 alreadyRegistered =
true;
166 if (alreadyRegistered)
168 ++(mSubnets[net].mVirtualNodeNum);
169 mSubnets[net].nodes.push_back(vnode);
174 SPDLOG_LOGGER_INFO(mSLog,
"Subnet {} has {} real network nodes.", net,
175 mSubnets[net].mRealNetNodeNum);
176 SPDLOG_LOGGER_INFO(mSLog,
"Subnet {} has {} virtual nodes.", net,
177 mSubnets[net].mVirtualNodeNum);
180template <
typename VarType>
181void DiakopticsSolver<VarType>::assignMatrixNodeIndices(
int net) {
182 UInt matrixNodeIndexIdx = 0;
183 for (UInt idx = 0; idx < mSubnets[net].nodes.size(); ++idx) {
184 auto &node = mSubnets[net].nodes[idx];
186 node->setMatrixNodeIndex(0, matrixNodeIndexIdx);
187 SPDLOG_LOGGER_INFO(mSLog,
"Assigned index {} to node {}",
188 matrixNodeIndexIdx, node->name());
189 ++matrixNodeIndexIdx;
191 if (node->phaseType() == CPS::PhaseType::ABC) {
192 node->setMatrixNodeIndex(1, matrixNodeIndexIdx);
193 SPDLOG_LOGGER_INFO(mSLog,
"Assigned index {} to node {} phase B",
194 matrixNodeIndexIdx, node->name());
195 ++matrixNodeIndexIdx;
196 node->setMatrixNodeIndex(2, matrixNodeIndexIdx);
197 SPDLOG_LOGGER_INFO(mSLog,
"Assigned index {} to node {} phase C",
198 matrixNodeIndexIdx, node->name());
199 ++matrixNodeIndexIdx;
202 setSubnetSize(net, matrixNodeIndexIdx);
205 mSubnets[net].sysOff = 0;
207 mSubnets[net].sysOff = mSubnets[net - 1].sysOff + mSubnets[net - 1].sysSize;
210template <>
void DiakopticsSolver<Real>::setSubnetSize(
int net, UInt nodes) {
211 mSubnets[net].sysSize = nodes;
212 mSubnets[net].mCmplOff = 0;
215template <>
void DiakopticsSolver<Complex>::setSubnetSize(
int net, UInt nodes) {
216 mSubnets[net].sysSize = 2 * nodes;
217 mSubnets[net].mCmplOff = nodes;
220template <>
void DiakopticsSolver<Real>::setLogColumns() {
224template <>
void DiakopticsSolver<Complex>::setLogColumns() {
225 std::vector<String> names;
226 for (
auto &subnet : mSubnets) {
227 for (UInt i = subnet.sysOff; i < subnet.sysOff + subnet.sysSize; ++i) {
228 std::stringstream name;
229 if (i < subnet.sysOff + subnet.mCmplOff)
230 name <<
"node" << std::setfill(
'0') << std::setw(5)
231 << i - subnet.sysOff / 2 <<
".real";
233 name <<
"node" << std::setfill(
'0') << std::setw(5)
234 << i - (subnet.sysOff + subnet.sysSize) / 2 <<
".imag";
235 names.push_back(name.str());
238 mLeftVectorLog->setColumnNames(names);
239 mRightVectorLog->setColumnNames(names);
242template <
typename VarType>
void DiakopticsSolver<VarType>::createMatrices() {
243 UInt totalSize = mSubnets.back().sysOff + mSubnets.back().sysSize;
244 mSystemMatrix = Matrix::Zero(totalSize, totalSize);
246 mRightSideVector = Matrix::Zero(totalSize, 1);
247 mLeftSideVector = Matrix::Zero(totalSize, 1);
248 **mOrigLeftSideVector = Matrix::Zero(totalSize, 1);
249 **mMappedTearCurrents = Matrix::Zero(totalSize, 1);
251 for (
auto &net : mSubnets) {
256 net.leftVector->set(Matrix::Zero(net.sysSize, 1));
259 createTearMatrices(totalSize);
262template <>
void DiakopticsSolver<Real>::createTearMatrices(UInt totalSize) {
263 int phaseMultiplier = 1;
264 if (mPhaseType == PhaseType::ABC) {
268 Matrix::Zero(totalSize, mTearComponents.size() * phaseMultiplier);
270 CPS::SparseMatrixRow(mTearComponents.size() * phaseMultiplier,
271 mTearComponents.size() * phaseMultiplier);
272 mTearCurrents = Matrix::Zero(mTearComponents.size() * phaseMultiplier, 1);
273 mTearVoltages = Matrix::Zero(mTearComponents.size() * phaseMultiplier, 1);
276template <>
void DiakopticsSolver<Complex>::createTearMatrices(UInt totalSize) {
277 int phaseMultiplier = 1;
278 if (mPhaseType == PhaseType::ABC) {
282 Matrix::Zero(totalSize, 2 * mTearComponents.size() * phaseMultiplier);
284 CPS::SparseMatrixRow(2 * mTearComponents.size() * phaseMultiplier,
285 2 * mTearComponents.size() * phaseMultiplier);
286 mTearCurrents = Matrix::Zero(2 * mTearComponents.size() * phaseMultiplier, 1);
287 mTearVoltages = Matrix::Zero(2 * mTearComponents.size() * phaseMultiplier, 1);
290template <
typename VarType>
void DiakopticsSolver<VarType>::initComponents() {
291 for (UInt net = 0; net < mSubnets.size(); ++net) {
292 for (
auto comp : mSubnets[net].components) {
293 auto pComp = std::dynamic_pointer_cast<SimPowerComp<VarType>>(comp);
296 pComp->initializeFromNodesAndTerminals(mSystem.mSystemFrequency);
300 for (
auto comp : mSubnets[net].components) {
301 comp->mnaInitialize(mSystem.mSystemOmega, mTimeStep,
302 mSubnets[net].leftVector);
303 const Matrix &stamp = comp->getRightVector()->get();
304 if (stamp.size() != 0) {
305 mSubnets[net].rightVectorStamps.push_back(&stamp);
310 for (
auto comp : mSimSignalComps)
311 comp->initialize(mSystem.mSystemOmega, mTimeStep);
314 for (UInt net = 0; net < mSubnets.size(); ++net)
315 for (
auto node : mSubnets[net].nodes)
319template <
typename VarType>
void DiakopticsSolver<VarType>::initMatrices() {
320 for (
auto &net : mSubnets) {
323 net.systemMatrix = SparseMatrix(net.sysSize, net.sysSize);
324 for (
auto comp : net.components) {
325 comp->mnaApplySystemMatrixStamp(net.systemMatrix);
328 mSystemMatrix.block(net.sysOff, net.sysOff, net.sysSize, net.sysSize);
329 block = net.systemMatrix;
330 SPDLOG_LOGGER_INFO(mSLog,
"Block: \n{}", block);
331 net.listVariableEntries.clear();
332 for (
auto varElem : net.mVariableComps)
333 for (
auto varEntry : varElem->mVariableSystemMatrixEntries)
334 net.listVariableEntries.push_back(varEntry);
335 net.directLinearSolver = std::make_shared<KLUAdapter>(mSLog);
336 net.directLinearSolver->preprocessing(net.systemMatrix,
337 net.listVariableEntries);
338 net.directLinearSolver->factorize(net.systemMatrix);
340 SPDLOG_LOGGER_INFO(mSLog,
"Complete system matrix: \n{}", mSystemMatrix);
343 for (UInt compIdx = 0; compIdx < mTearComponents.size(); ++compIdx) {
344 applyTearComponentStamp(compIdx);
346 SPDLOG_LOGGER_INFO(mSLog,
"Topology matrix: \n{}", mTearTopology);
347 SPDLOG_LOGGER_INFO(mSLog,
"Removed impedance matrix: \n{}", mTearImpedance);
349 mSystemInverseTearTopology =
350 Matrix::Zero(mTearTopology.rows(), mTearTopology.cols());
351 for (
auto &net : mSubnets) {
352 Matrix tearTopoBlock =
353 mTearTopology.block(net.sysOff, 0, net.sysSize, mTearTopology.cols());
354 mSystemInverseTearTopology.block(net.sysOff, 0, net.sysSize,
355 mTearTopology.cols()) =
356 net.directLinearSolver->solve(tearTopoBlock);
359 net.tearColumns.clear();
360 for (UInt col = 0; col < static_cast<UInt>(mTearTopology.cols()); ++col) {
361 if (!tearTopoBlock.col(col).isZero())
362 net.tearColumns.push_back(col);
366 mTearImpedance + mTearTopology.transpose() * mSystemInverseTearTopology;
367 mTotalTearImpedance = Eigen::PartialPivLU<Matrix>(mTearSchur);
368 SPDLOG_LOGGER_INFO(mSLog,
369 "Total removed impedance matrix LU decomposition: \n{}",
370 mTotalTearImpedance.matrixLU());
373 for (
auto &net : mSubnets) {
374 Matrix rInit = Matrix::Zero(net.sysSize, 1);
376 for (
auto comp : net.components) {
377 comp->mnaApplyRightSideVectorStamp(rInit);
379 SPDLOG_LOGGER_INFO(mSLog,
"Source block: \n{}", rInit);
383template <>
void DiakopticsSolver<Real>::applyTearComponentStamp(UInt compIdx) {
384 auto comp = mTearComponents[compIdx];
387 std::vector<Eigen::Triplet<double>> triplets;
390 if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) {
391 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
392 comp->node(0)->matrixNodeIndex(PhaseType::A),
394 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
395 comp->node(0)->matrixNodeIndex(PhaseType::B),
397 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
398 comp->node(0)->matrixNodeIndex(PhaseType::C),
401 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
402 comp->node(0)->matrixNodeIndex(),
407 if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) {
408 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
409 comp->node(1)->matrixNodeIndex(PhaseType::A),
411 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
412 comp->node(1)->matrixNodeIndex(PhaseType::B),
413 compIdx * 3 + 1, -1);
414 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
415 comp->node(1)->matrixNodeIndex(PhaseType::C),
416 compIdx * 3 + 2, -1);
418 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
419 comp->node(1)->matrixNodeIndex(),
424 for (
const auto &triplet : triplets) {
425 mTearTopology.coeffRef(triplet.row(), triplet.col()) += triplet.value();
429 auto tearComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
430 tearComp->mnaTearApplyMatrixStamp(mTearImpedance);
434void DiakopticsSolver<Complex>::applyTearComponentStamp(UInt compIdx) {
435 auto comp = mTearComponents[compIdx];
438 std::vector<Eigen::Triplet<double>> triplets;
441 if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) {
442 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
443 comp->node(0)->matrixNodeIndex(PhaseType::A),
445 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
446 mNodeSubnetMap[comp->node(0)]->mCmplOff +
447 comp->node(0)->matrixNodeIndex(PhaseType::A),
448 mTearComponents.size() * 3 + compIdx * 3,
450 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
451 comp->node(0)->matrixNodeIndex(PhaseType::B),
453 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
454 mNodeSubnetMap[comp->node(0)]->mCmplOff +
455 comp->node(0)->matrixNodeIndex(PhaseType::B),
456 mTearComponents.size() * 3 + compIdx * 3 + 1,
458 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
459 comp->node(0)->matrixNodeIndex(PhaseType::C),
461 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
462 mNodeSubnetMap[comp->node(0)]->mCmplOff +
463 comp->node(0)->matrixNodeIndex(PhaseType::C),
464 mTearComponents.size() * 3 + compIdx * 3 + 2,
467 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
468 comp->node(0)->matrixNodeIndex(),
470 triplets.emplace_back(mNodeSubnetMap[comp->node(0)]->sysOff +
471 mNodeSubnetMap[comp->node(0)]->mCmplOff +
472 comp->node(0)->matrixNodeIndex(),
473 mTearComponents.size() + compIdx,
double(1.0));
476 if (comp->node(0)->phaseType() == CPS::PhaseType::ABC) {
477 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
478 comp->node(1)->matrixNodeIndex(PhaseType::A),
480 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
481 mNodeSubnetMap[comp->node(1)]->mCmplOff +
482 comp->node(1)->matrixNodeIndex(PhaseType::A),
483 mTearComponents.size() * 3 + compIdx * 3,
485 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
486 comp->node(1)->matrixNodeIndex(PhaseType::B),
487 compIdx * 3 + 1, -1);
488 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
489 mNodeSubnetMap[comp->node(1)]->mCmplOff +
490 comp->node(1)->matrixNodeIndex(PhaseType::B),
491 mTearComponents.size() * 3 + compIdx * 3 + 1,
493 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
494 comp->node(1)->matrixNodeIndex(PhaseType::C),
495 compIdx * 3 + 2, -1);
496 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
497 mNodeSubnetMap[comp->node(1)]->mCmplOff +
498 comp->node(1)->matrixNodeIndex(PhaseType::C),
499 mTearComponents.size() * 3 + compIdx * 3 + 2,
502 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
503 comp->node(1)->matrixNodeIndex(),
505 triplets.emplace_back(mNodeSubnetMap[comp->node(1)]->sysOff +
506 mNodeSubnetMap[comp->node(1)]->mCmplOff +
507 comp->node(1)->matrixNodeIndex(),
508 mTearComponents.size() + compIdx,
double(-1.0));
511 for (
const auto &triplet : triplets) {
512 mTearTopology.coeffRef(triplet.row(), triplet.col()) += triplet.value();
516 auto tearComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
517 tearComp->mnaTearApplyMatrixStamp(mTearImpedance);
523 for (UInt net = 0; net < mSubnets.size(); ++net) {
524 for (
auto node : mSubnets[net].nodes) {
525 for (
auto task : node->mnaTasks())
529 for (
auto comp : mSubnets[net].components) {
530 for (
auto task : comp->mnaTasks()) {
534 l.push_back(std::make_shared<SubnetSolveTask>(*
this, net));
535 l.push_back(std::make_shared<SolveTask>(*
this, net));
538 for (
auto comp : mSimSignalComps) {
539 for (
auto task : comp->getTasks()) {
543 l.push_back(std::make_shared<PreSolveTask>(*
this));
544 l.push_back(std::make_shared<PostSolveTask>(*
this));
545 l.push_back(std::make_shared<LogTask>(*
this));
550template <
typename VarType>
551void DiakopticsSolver<VarType>::SubnetSolveTask::recomputeSubnetMatrix(
554 mSubnet.systemMatrix.setZero();
555 for (
auto comp : mSubnet.components) {
556 comp->mnaApplySystemMatrixStamp(mSubnet.systemMatrix);
558 mSubnet.directLinearSolver->partialRefactorize(mSubnet.systemMatrix,
559 mSubnet.listVariableEntries);
565 const auto &cols = mSubnet.tearColumns;
566 const UInt nJ =
static_cast<UInt
>(cols.size());
570 Matrix tearTopoBlock(mSubnet.sysSize, nJ);
571 for (UInt c = 0; c < nJ; ++c)
572 tearTopoBlock.col(c) = mSolver.mTearTopology.block(mSubnet.sysOff, cols[c],
575 Matrix invTopoBlock = mSubnet.directLinearSolver->solve(tearTopoBlock);
577 for (UInt c = 0; c < nJ; ++c)
578 mSolver.mSystemInverseTearTopology.block(
579 mSubnet.sysOff, cols[c], mSubnet.sysSize, 1) = invTopoBlock.col(c);
581 mSolver.mTearSchurNeedsRebuild =
true;
584template <
typename VarType>
586 bool changed =
false;
587 for (
auto varElem : mSubnet.mVariableComps) {
588 if (varElem->hasParameterChanged()) {
589 auto idObj = std::dynamic_pointer_cast<IdentifiedObject>(varElem);
598template <
typename VarType>
599void DiakopticsSolver<VarType>::SubnetSolveTask::execute(Real time,
602 mSolver.mRightSideVector.block(mSubnet.sysOff, 0, mSubnet.sysSize, 1);
605 for (
auto stamp : mSubnet.rightVectorStamps)
608 auto lBlock = (**mSolver.mOrigLeftSideVector)
609 .block(mSubnet.sysOff, 0, mSubnet.sysSize, 1);
611 if (hasVariableComponentChanged()) {
612 recomputeSubnetMatrix(time);
616 lBlock = mSubnet.directLinearSolver->solve(rhs);
619template <
typename VarType>
620void DiakopticsSolver<VarType>::PreSolveTask::execute(Real time,
624 if (mSolver.mTearSchurNeedsRebuild.exchange(
false)) {
626 mSolver.mTearImpedance +
627 mSolver.mTearTopology.transpose() * mSolver.mSystemInverseTearTopology;
628 mSolver.mTotalTearImpedance =
629 Eigen::PartialPivLU<Matrix>(mSolver.mTearSchur);
632 mSolver.mTearVoltages.setZero();
633 for (
auto comp : mSolver.mTearComponents) {
634 auto tComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
635 tComp->mnaTearApplyVoltageStamp(mSolver.mTearVoltages);
638 mSolver.mTearVoltages -=
639 mSolver.mTearTopology.transpose() * **mSolver.mOrigLeftSideVector;
641 mSolver.mTearCurrents =
642 mSolver.mTotalTearImpedance.solve(mSolver.mTearVoltages);
644 **mSolver.mMappedTearCurrents = mSolver.mTearTopology * mSolver.mTearCurrents;
645 mSolver.mLeftSideVector = **mSolver.mOrigLeftSideVector;
648template <
typename VarType>
649void DiakopticsSolver<VarType>::SolveTask::execute(Real time,
652 mSolver.mLeftSideVector.block(mSubnet.sysOff, 0, mSubnet.sysSize, 1);
653 auto rBlock = (**mSolver.mMappedTearCurrents)
654 .block(mSubnet.sysOff, 0, mSubnet.sysSize, 1);
658 lBlock += mSubnet.directLinearSolver->solve(rhs);
659 **mSubnet.leftVector = lBlock;
663void DiakopticsSolver<Real>::PostSolveTask::execute(Real time,
666 mSolver.mTearVoltages =
667 -mSolver.mTearTopology.transpose() * mSolver.mLeftSideVector;
668 for (UInt compIdx = 0; compIdx < mSolver.mTearComponents.size(); ++compIdx) {
669 auto comp = mSolver.mTearComponents[compIdx];
670 auto tComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
671 if (mSolver.mPhaseType == CPS::PhaseType::ABC) {
672 Matrix voltage = Matrix::Zero(3, 1);
673 voltage << mSolver.mTearVoltages(compIdx * 3),
674 mSolver.mTearVoltages(compIdx * 3 + 1),
675 mSolver.mTearVoltages(compIdx * 3 + 2);
677 Matrix current = Matrix::Zero(3, 1);
678 current << mSolver.mTearCurrents(compIdx * 3),
679 mSolver.mTearCurrents(compIdx * 3 + 1),
680 mSolver.mTearCurrents(compIdx * 3 + 2);
681 tComp->mnaTearPostStep(voltage, current);
684 Math::complexFromVectorElement(mSolver.mTearVoltages, compIdx);
686 Math::complexFromVectorElement(mSolver.mTearCurrents, compIdx);
687 tComp->mnaTearPostStep(voltage, current);
692 for (UInt net = 0; net < mSolver.mSubnets.size(); ++net) {
693 for (UInt node = 0; node < mSolver.mSubnets[net].mRealNetNodeNum; ++node) {
694 mSolver.mSubnets[net].nodes[node]->mnaUpdateVoltage(
695 *(mSolver.mSubnets[net].leftVector));
701void DiakopticsSolver<Complex>::PostSolveTask::execute(Real time,
704 mSolver.mTearVoltages =
705 -mSolver.mTearTopology.transpose() * mSolver.mLeftSideVector;
706 for (UInt compIdx = 0; compIdx < mSolver.mTearComponents.size(); ++compIdx) {
707 auto comp = mSolver.mTearComponents[compIdx];
708 auto tComp = std::dynamic_pointer_cast<MNATearInterface>(comp);
709 if (mSolver.mPhaseType == CPS::PhaseType::ABC) {
710 MatrixComp voltage = MatrixComp::Zero(3, 1);
711 voltage << Math::complexFromVectorElement(mSolver.mTearVoltages,
713 Math::complexFromVectorElement(mSolver.mTearVoltages,
715 Math::complexFromVectorElement(mSolver.mTearVoltages,
717 MatrixComp current = MatrixComp::Zero(3, 1);
718 current << Math::complexFromVectorElement(mSolver.mTearCurrents,
720 Math::complexFromVectorElement(mSolver.mTearCurrents,
722 Math::complexFromVectorElement(mSolver.mTearCurrents,
724 tComp->mnaTearPostStep(voltage, current);
727 Math::complexFromVectorElement(mSolver.mTearVoltages, compIdx);
729 Math::complexFromVectorElement(mSolver.mTearCurrents, compIdx);
730 tComp->mnaTearPostStep(voltage, current);
735 for (UInt net = 0; net < mSolver.mSubnets.size(); ++net) {
736 for (UInt node = 0; node < mSolver.mSubnets[net].mRealNetNodeNum; ++node) {
737 mSolver.mSubnets[net].nodes[node]->mnaUpdateVoltage(
738 *(mSolver.mSubnets[net].leftVector));
743template <>
void DiakopticsSolver<Real>::log(Real time, Int timeStepCount) {
744 mLeftVectorLog->logEMTNodeValues(time, mLeftSideVector);
745 mRightVectorLog->logEMTNodeValues(time, mRightSideVector);
748template <>
void DiakopticsSolver<Complex>::log(Real time, Int timeStepCount) {
749 mLeftVectorLog->logPhasorNodeValues(time, mLeftSideVector);
750 mRightVectorLog->logPhasorNodeValues(time, mRightSideVector);
753template <
typename VarType>
754void DiakopticsSolver<VarType>::LogTask::execute(Real time, Int timeStepCount) {
755 mSolver.log(time, timeStepCount);
758template class DiakopticsSolver<Real>;
759template class DiakopticsSolver<Complex>;
Real mSystemFrequency
System frequency.
TopologicalNode::List mNodes
List of network nodes.
Bool hasVariableComponentChanged()
Check whether status of variable MNA elements has changed.
CPS::Task::List getTasks() override
Get tasks for scheduler.
Base class for more specific solvers such as MNA, ODE or IDA.