9#include <CIMExceptions.hpp>
10#include <CIMModel.hpp>
11#include <IEC61970.hpp>
21using CIMPP::UnitMultiplier;
27 mModel =
new CIMModel();
28 mModel->setDependencyCheckOff();
29 mComponentLogLevel = componentLogLevel;
35 const std::list<CPS::String> &filenamesString,
38 std::list<fs::path> filenames;
39 for (
auto f : filenamesString)
40 filenames.emplace_back(f);
42 return loadCIM(systemFrequency, filenames, domain, phase, genType);
48 mShuntCapacitorValue = v;
49 mSetShuntCapacitor =
true;
53 mShuntConductanceValue = v;
54 mSetShuntConductance =
true;
59 mUseProtectionSwitches = value;
63 mExtnetVoltageTargetUnit = unit;
66Real Reader::unitValue(
Real value, CIMPP::UnitMultiplier mult) {
68 case UnitMultiplier::p:
71 case UnitMultiplier::n:
74 case UnitMultiplier::micro:
77 case UnitMultiplier::m:
80 case UnitMultiplier::c:
83 case UnitMultiplier::d:
86 case UnitMultiplier::k:
89 case UnitMultiplier::M:
92 case UnitMultiplier::G:
95 case UnitMultiplier::T:
104Bool Reader::isSupportedConductingEquipment(BaseClass *obj)
const {
108 if (
dynamic_cast<CIMPP::ACLineSegment *
>(obj))
111 if (
dynamic_cast<CIMPP::EnergyConsumer *
>(obj))
114 if (
dynamic_cast<CIMPP::PowerTransformer *
>(obj))
117 if (
dynamic_cast<CIMPP::SynchronousMachine *
>(obj))
120 if (
dynamic_cast<CIMPP::ExternalNetworkInjection *
>(obj))
123 if (
dynamic_cast<CIMPP::EquivalentShunt *
>(obj))
126 if (
dynamic_cast<CIMPP::Disconnector *
>(obj))
129 if (
dynamic_cast<CIMPP::Breaker *
>(obj))
136 if (CIMPP::ACLineSegment *line =
dynamic_cast<CIMPP::ACLineSegment *
>(obj))
137 return mapACLineSegment(line);
138 if (CIMPP::EnergyConsumer *consumer =
139 dynamic_cast<CIMPP::EnergyConsumer *
>(obj))
140 return mapEnergyConsumer(consumer);
141 if (CIMPP::PowerTransformer *trans =
142 dynamic_cast<CIMPP::PowerTransformer *
>(obj))
143 return mapPowerTransformer(trans);
144 if (CIMPP::SynchronousMachine *syncMachine =
145 dynamic_cast<CIMPP::SynchronousMachine *
>(obj))
146 return mapSynchronousMachine(syncMachine);
147 if (CIMPP::ExternalNetworkInjection *extnet =
148 dynamic_cast<CIMPP::ExternalNetworkInjection *
>(obj))
149 return mapExternalNetworkInjection(extnet);
150 if (CIMPP::EquivalentShunt *shunt =
151 dynamic_cast<CIMPP::EquivalentShunt *
>(obj))
152 return mapEquivalentShunt(shunt);
153 if (CIMPP::Disconnector *disc =
dynamic_cast<CIMPP::Disconnector *
>(obj))
154 return mapDisconnector(disc);
155 if (CIMPP::Breaker *cb =
dynamic_cast<CIMPP::Breaker *
>(obj))
156 return mapBreaker(cb);
160void Reader::addFiles(
const fs::path &filename) {
161 if (!mModel->addCIMFile(filename.string()))
162 SPDLOG_LOGGER_ERROR(mSLog,
"Failed to read file {}", filename);
165void Reader::addFiles(
const std::list<fs::path> &filenames) {
166 for (
auto filename : filenames)
170void Reader::parseFiles() {
172 mModel->parseFiles();
174 SPDLOG_LOGGER_ERROR(mSLog,
"Failed to parse CIM files");
180 "#### List of TopologicalNodes, associated Terminals and Equipment");
181 for (
auto obj : mModel->Objects) {
182 if (CIMPP::TopologicalNode *topNode =
183 dynamic_cast<CIMPP::TopologicalNode *
>(obj)) {
185 processTopologicalNode<Real>(topNode);
187 processTopologicalNode<Complex>(topNode);
193 SPDLOG_LOGGER_INFO(mSLog,
194 "#### List of Node voltages and Terminal power flow data");
195 for (
auto obj : mModel->Objects) {
197 if (CIMPP::SvVoltage *volt =
dynamic_cast<CIMPP::SvVoltage *
>(obj)) {
198 processSvVoltage(volt);
201 else if (CIMPP::SvPowerFlow *flow =
202 dynamic_cast<CIMPP::SvPowerFlow *
>(obj)) {
203 processSvPowerFlow(flow);
207 SPDLOG_LOGGER_INFO(mSLog,
"#### Create other components");
208 for (
auto obj : mModel->Objects) {
211 if (!
dynamic_cast<CIMPP::TopologicalNode *
>(obj) &&
212 !
dynamic_cast<CIMPP::SvVoltage *
>(obj) &&
213 !
dynamic_cast<CIMPP::SvPowerFlow *
>(obj)) {
215 if (CIMPP::IdentifiedObject *idObj =
216 dynamic_cast<CIMPP::IdentifiedObject *
>(obj)) {
219 const auto &rid =
cimString(idObj->mRID);
220 if (mPowerflowEquipment.find(rid) == mPowerflowEquipment.end()) {
223 mPowerflowEquipment.insert(std::make_pair(comp->uid(), comp));
229 SPDLOG_LOGGER_INFO(mSLog,
"#### Check topology for unconnected components");
230 for (
auto pfe : mPowerflowEquipment) {
235 std::dynamic_pointer_cast<SimPowerComp<Real>>(c)) {
236 if (powercomp->terminalNumberConnected() < powercomp->terminalNumber())
237 throw InvalidTopology();
241 std::dynamic_pointer_cast<SimPowerComp<Complex>>(c)) {
242 if (powercomp->terminalNumberConnected() < powercomp->terminalNumber())
243 throw InvalidTopology();
252 mFrequency = systemFrequency;
253 mOmega = 2 *
PI * mFrequency;
256 mGeneratorType = genType;
259 return systemTopology();
263 const std::list<fs::path> &filenames,
266 mFrequency = systemFrequency;
267 mOmega = 2 *
PI * mFrequency;
270 mGeneratorType = genType;
273 return systemTopology();
276void Reader::processSvVoltage(CIMPP::SvVoltage *volt) {
277 CIMPP::TopologicalNode *node = volt->TopologicalNode;
280 mSLog,
"SvVoltage references missing Topological Node, ignoring");
283 const auto &nodeRid =
cimString(node->mRID);
284 auto search = mPowerflowNodes.find(nodeRid);
285 if (search == mPowerflowNodes.end()) {
286 SPDLOG_LOGGER_WARN(mSLog,
287 "SvVoltage references Topological Node {}"
288 " missing from mTopNodes, ignoring",
293 Real voltageAbs = Reader::unitValue(volt->v.value, UnitMultiplier::k);
296 SPDLOG_LOGGER_INFO(mSLog,
" Angle={}", (
float)volt->angle.value);
297 }
catch (ReadingUninitializedField *e) {
298 volt->angle.value = 0;
299 std::cerr <<
"Uninitialized Angle for SVVoltage at "
300 << volt->TopologicalNode->name <<
".Setting default value of "
301 << volt->angle.value << std::endl;
303 Real voltagePhase = volt->angle.value *
PI / 180;
304 mPowerflowNodes[nodeRid]->setInitialVoltage(
305 std::polar<Real>(voltageAbs, voltagePhase));
308 mSLog,
"Node {} MatrixNodeIndex {}: {} V, {} deg",
309 mPowerflowNodes[nodeRid]->uid(),
310 mPowerflowNodes[nodeRid]->matrixNodeIndex(),
311 std::abs(mPowerflowNodes[nodeRid]->initialSingleVoltage()),
312 std::arg(mPowerflowNodes[nodeRid]->initialSingleVoltage()) * 180 /
PI);
315void Reader::processSvPowerFlow(CIMPP::SvPowerFlow *flow) {
317 SPDLOG_LOGGER_WARN(mSLog,
"Cannot process null SvPowerFlow, ignoring");
321 CIMPP::Terminal *term = flow->Terminal;
324 SPDLOG_LOGGER_WARN(mSLog,
325 "SvPowerFlow references missing Terminal, ignoring");
329 const auto &terminalRid =
cimString(term->mRID);
330 auto terminalIt = mPowerflowTerminals.find(terminalRid);
332 if (terminalIt == mPowerflowTerminals.end() || !terminalIt->second) {
333 SPDLOG_LOGGER_WARN(mSLog,
334 "SvPowerFlow references Terminal {} missing from "
335 "mPowerflowTerminals, ignoring",
340 terminalIt->second->setPower(
341 Complex(Reader::unitValue(flow->p.value, UnitMultiplier::M),
342 Reader::unitValue(flow->q.value, UnitMultiplier::M)));
344 SPDLOG_LOGGER_INFO(mSLog,
"Terminal {}: {} W + j {} Var", terminalRid,
345 terminalIt->second->singleActivePower(),
346 terminalIt->second->singleReactivePower());
352 for (
auto comp : mPowerflowEquipment) {
353 system.addComponent(comp.second);
356 std::dynamic_pointer_cast<SimPowerComp<Complex>>(comp.second)) {
357 for (
auto term : powercomp->topologicalTerminals()) {
360 if (system.mComponentsAtNode.find(node) ==
361 system.mComponentsAtNode.end()) {
363 complist.push_back(powercomp);
364 system.mComponentsAtNode.insert(std::make_pair(node, complist));
366 system.mComponentsAtNode[node].push_back(powercomp);
372 system.mNodes.resize(mPowerflowNodes.size());
374 for (
auto node : mPowerflowNodes) {
377 system.addNodeAt(node.second, node.second->matrixNodeIndex());
383Matrix::Index Reader::mapTopologicalNode(
String mrid) {
384 auto search = mPowerflowNodes.find(mrid);
385 if (search == mPowerflowNodes.end()) {
388 return search->second->matrixNodeIndex();
392Reader::mapEnergyConsumer(CIMPP::EnergyConsumer *consumer) {
393 const auto &consumerName =
cimString(consumer->name);
394 const auto &consumerRid =
cimString(consumer->mRID);
396 SPDLOG_LOGGER_INFO(mSLog,
" Found EnergyConsumer {}", consumerName);
399 return std::make_shared<EMT::Ph3::RXLoad>(consumerRid, consumerName,
402 SPDLOG_LOGGER_INFO(mSLog,
" RXLoad for EMT not implemented yet");
403 return std::make_shared<DP::Ph1::RXLoad>(consumerRid, consumerName,
407 auto load = std::make_shared<SP::Ph1::Load>(consumerRid, consumerName,
413 if (consumer->p.initialized || consumer->q.initialized) {
416 if (consumer->p.initialized)
417 p = unitValue(consumer->p.value, UnitMultiplier::M);
418 if (consumer->q.initialized)
419 q = unitValue(consumer->q.value, UnitMultiplier::M);
420 Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(consumer);
421 load->setParameters(p, q, baseVoltage);
424 load->modifyPowerFlowBusType(
429 if (mUseProtectionSwitches)
430 return std::make_shared<DP::Ph1::RXLoadSwitch>(consumerRid, consumerName,
433 return std::make_shared<DP::Ph1::RXLoad>(consumerRid, consumerName,
439 const auto &lineName =
cimString(line->name);
440 const auto &lineRid =
cimString(line->mRID);
442 SPDLOG_LOGGER_INFO(mSLog,
443 " Found ACLineSegment {} r={} x={} bch={} gch={}",
444 lineName, (
float)line->r.value, (
float)line->x.value,
445 (
float)line->bch.value, (
float)line->gch.value);
447 Real resistance = line->r.value;
448 Real inductance = line->x.value / mOmega;
452 Real capacitance = mShuntCapacitorValue;
453 Real conductance = mShuntConductanceValue;
455 if (line->bch.value > 1e-9 && !mSetShuntCapacitor)
456 capacitance =
Real(line->bch.value / mOmega);
458 if (line->gch.value > 1e-9 && !mSetShuntConductance)
459 conductance =
Real(line->gch.value);
461 Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(line);
471 auto cpsLine = std::make_shared<EMT::Ph3::PiLine>(lineRid, lineName,
473 cpsLine->setParameters(res_3ph, ind_3ph, cap_3ph, cond_3ph);
476 SPDLOG_LOGGER_INFO(mSLog,
" PiLine for EMT not implemented yet");
477 auto cpsLine = std::make_shared<DP::Ph1::PiLine>(lineRid, lineName,
479 cpsLine->setParameters(resistance, inductance, capacitance, conductance);
483 auto cpsLine = std::make_shared<SP::Ph1::PiLine>(lineRid, lineName,
485 cpsLine->setParameters(resistance, inductance, capacitance, conductance);
486 cpsLine->setBaseVoltage(baseVoltage);
489 auto cpsLine = std::make_shared<DP::Ph1::PiLine>(lineRid, lineName,
491 cpsLine->setParameters(resistance, inductance, capacitance, conductance);
497Reader::mapPowerTransformer(CIMPP::PowerTransformer *trans) {
498 const auto &transRid =
cimString(trans->mRID);
499 if (trans->PowerTransformerEnd.size() != 2) {
502 "PowerTransformer {} does not have exactly two windings, ignoring",
506 SPDLOG_LOGGER_INFO(mSLog,
"Found PowerTransformer {}",
510 CIMPP::PowerTransformerEnd *end1 =
nullptr, *end2 =
nullptr;
511 for (
auto end : trans->PowerTransformerEnd) {
512 if (end->Terminal->sequenceNumber == 1)
514 else if (end->Terminal->sequenceNumber == 2)
521 SPDLOG_LOGGER_INFO(mSLog,
" PowerTransformerEnd_1 {}",
523 SPDLOG_LOGGER_INFO(mSLog,
" Srated={} Vrated={}",
524 (
float)end1->ratedS.value, (
float)end1->ratedU.value);
526 SPDLOG_LOGGER_INFO(mSLog,
" R={}", (
float)end1->r.value);
527 }
catch (ReadingUninitializedField *e1) {
528 end1->r.value = 1e-12;
529 SPDLOG_LOGGER_WARN(mSLog,
530 " Uninitialized value for PowerTrafoEnd1 setting "
531 "default value of R={}",
532 (
float)end1->r.value);
535 SPDLOG_LOGGER_INFO(mSLog,
" X={}", (
float)end1->x.value);
536 }
catch (ReadingUninitializedField *e1) {
537 end1->x.value = 1e-12;
538 SPDLOG_LOGGER_WARN(mSLog,
539 " Uninitialized value for PowerTrafoEnd1 setting "
540 "default value of X={}",
541 (
float)end1->x.value);
543 SPDLOG_LOGGER_INFO(mSLog,
" PowerTransformerEnd_2 {}",
545 SPDLOG_LOGGER_INFO(mSLog,
" Srated={} Vrated={}",
546 (
float)end2->ratedS.value, (
float)end2->ratedU.value);
548 SPDLOG_LOGGER_INFO(mSLog,
" R={}", (
float)end2->r.value);
549 }
catch (ReadingUninitializedField *e1) {
550 end2->r.value = 1e-12;
551 SPDLOG_LOGGER_WARN(mSLog,
552 " Uninitialized value for PowerTrafoEnd2 setting "
553 "default value of R={}",
554 (
float)end2->r.value);
557 SPDLOG_LOGGER_INFO(mSLog,
" X={}", (
float)end2->x.value);
558 }
catch (ReadingUninitializedField *e1) {
559 end2->x.value = 1e-12;
560 SPDLOG_LOGGER_WARN(mSLog,
561 " Uninitialized value for PowerTrafoEnd2 setting "
562 "default value of X={}",
563 (
float)end2->x.value);
566 if (end1->ratedS.value != end2->ratedS.value) {
569 " PowerTransformerEnds of {} come with distinct rated power values. "
570 "Using rated power of PowerTransformerEnd_1.",
573 Real ratedPower = unitValue(end1->ratedS.value, UnitMultiplier::M);
574 Real voltageNode1 = unitValue(end1->ratedU.value, UnitMultiplier::k);
575 Real voltageNode2 = unitValue(end2->ratedU.value, UnitMultiplier::k);
577 Real ratioAbsNominal = voltageNode1 / voltageNode2;
578 Real ratioAbs = ratioAbsNominal;
581 if (end1->RatioTapChanger) {
583 voltageNode1 / voltageNode2 *
584 (1 + (end1->RatioTapChanger->normalStep -
585 end1->RatioTapChanger->neutralStep) *
586 end1->RatioTapChanger->stepVoltageIncrement.value / 100);
590 if (end1->RatioTapChanger) {
591 for (
auto obj : mModel->Objects) {
592 auto tapStep =
dynamic_cast<CIMPP::SvTapStep *
>(obj);
593 if (tapStep && tapStep->TapChanger == end1->RatioTapChanger) {
595 voltageNode1 / voltageNode2 *
596 (1 + (tapStep->position - end1->RatioTapChanger->neutralStep) *
597 end1->RatioTapChanger->stepVoltageIncrement.value / 100);
608 if (voltageNode1 >= voltageNode2 && abs(end1->x.value) > 1e-12) {
609 inductance = end1->x.value / mOmega;
610 resistance = end1->r.value;
611 }
else if (voltageNode1 >= voltageNode2 && abs(end2->x.value) > 1e-12) {
612 inductance = end2->x.value / mOmega * std::pow(ratioAbsNominal, 2);
613 resistance = end2->r.value * std::pow(ratioAbsNominal, 2);
614 }
else if (voltageNode2 > voltageNode1 && abs(end2->x.value) > 1e-12) {
615 inductance = end2->x.value / mOmega;
616 resistance = end2->r.value;
617 }
else if (voltageNode2 > voltageNode1 && abs(end1->x.value) > 1e-12) {
618 inductance = end1->x.value / mOmega / std::pow(ratioAbsNominal, 2);
619 resistance = end1->r.value / std::pow(ratioAbsNominal, 2);
622 CIMPP::PowerTransformerEnd *referenceEnd =
623 (voltageNode1 >= voltageNode2) ? end1 : end2;
624 Real referenceVoltage = std::max(voltageNode1, voltageNode2);
625 Real magnetizingConductance = referenceEnd->g.value;
626 Real magnetizingSusceptance = referenceEnd->b.value;
627 Real noLoadCurrent = 0;
629 Bool magnetizingFromFile =
false;
631 if (ratedPower > 0) {
632 Real base = std::pow(referenceVoltage, 2) / ratedPower;
633 Real defaultNoLoadCurrent = 0.01;
634 Real defaultNoLoadLoss = 1e-3;
635 Real defaultSusceptancePerUnit = std::sqrt(
636 std::pow(defaultNoLoadCurrent, 2) - std::pow(defaultNoLoadLoss, 2));
644 " {}: PowerTransformerEnd.b={} [S] is capacitive; the magnetizing "
645 "branch is inductive, so the default susceptance is used instead",
646 cimString(trans->name), magnetizingSusceptance);
649 lossFromFile ? magnetizingConductance * base : defaultNoLoadLoss;
650 Real susceptancePerUnit = susceptanceFromFile
651 ? std::abs(magnetizingSusceptance) * base
652 : defaultSusceptancePerUnit;
653 noLoadCurrent = std::hypot(susceptancePerUnit, noLoadLoss);
654 magnetizingFromFile = lossFromFile || susceptanceFromFile;
656 if (magnetizingFromFile)
658 mSLog,
" {}: magnetizing branch i0={} ({}) P0={} ({})",
660 susceptanceFromFile ?
"from the file" :
"default susceptance",
661 noLoadLoss, lossFromFile ?
"from the file" :
"default loss");
663 SPDLOG_LOGGER_WARN(mSLog,
664 " {}: no magnetizing data on PowerTransformerEnd "
665 "(b={} [S], g={} [S]); using the built-in default",
666 cimString(trans->name), magnetizingSusceptance,
667 magnetizingConductance);
669 SPDLOG_LOGGER_WARN(mSLog,
670 " {}: rated power is {} [VA], so the magnetizing "
671 "branch cannot be sized from the file",
681 Bool withResistiveLosses = resistance > 0;
682 auto transformer = std::make_shared<EMT::Ph3::Transformer>(
683 transRid,
cimString(trans->name), mComponentLogLevel,
684 withResistiveLosses);
685 transformer->setParameters(voltageNode1, voltageNode2, ratedPower,
686 ratioAbs, ratioPhase, resistance_3ph,
688 if (magnetizingFromFile)
689 transformer->setMagnetizingBranch(noLoadCurrent, noLoadLoss);
692 SPDLOG_LOGGER_INFO(mSLog,
" Transformer for EMT not implemented yet");
696 auto transformer = std::make_shared<SP::Ph1::Transformer>(
697 transRid,
cimString(trans->name), mComponentLogLevel);
698 transformer->setParameters(voltageNode1, voltageNode2, ratedPower, ratioAbs,
699 ratioPhase, resistance, inductance);
700 if (magnetizingFromFile)
701 transformer->setMagnetizingBranch(noLoadCurrent, noLoadLoss);
702 Real baseVolt = voltageNode1 >= voltageNode2 ? voltageNode1 : voltageNode2;
703 transformer->setBaseVoltage(baseVolt);
706 Bool withResistiveLosses = resistance > 0;
707 auto transformer = std::make_shared<DP::Ph1::Transformer>(
708 transRid,
cimString(trans->name), mComponentLogLevel,
709 withResistiveLosses);
710 transformer->setParameters(voltageNode1, voltageNode2, ratedPower, ratioAbs,
711 ratioPhase, resistance, inductance);
712 if (magnetizingFromFile)
713 transformer->setMagnetizingBranch(noLoadCurrent, noLoadLoss);
719Reader::mapSynchronousMachine(CIMPP::SynchronousMachine *machine) {
720 const auto &machineName =
cimString(machine->name);
721 const auto &machineRid =
cimString(machine->mRID);
723 SPDLOG_LOGGER_INFO(mSLog,
" Found Synchronous machine {}", machineName);
726 SPDLOG_LOGGER_INFO(mSLog,
" Create generator in DP domain.");
736 Real ratedPower = unitValue(machine->ratedS.value, UnitMultiplier::M);
737 Real ratedVoltage = unitValue(machine->ratedU.value, UnitMultiplier::k);
739 for (
auto obj : mModel->Objects) {
741 if (CIMPP::SynchronousMachineTimeConstantReactance *genDyn =
742 dynamic_cast<CIMPP::SynchronousMachineTimeConstantReactance *
>(
744 if (
cimString(genDyn->SynchronousMachine->mRID) == machineRid) {
746 Real Rs = genDyn->statorResistance.value;
747 Real Ll = genDyn->statorLeakageReactance.value;
750 Real Ld = genDyn->xDirectSync.value;
751 Real Lq = genDyn->xQuadSync.value;
752 Real Ld_t = genDyn->xDirectTrans.value;
753 Real Lq_t = genDyn->xQuadTrans.value;
754 Real Ld_s = genDyn->xDirectSubtrans.value;
755 Real Lq_s = genDyn->xQuadSubtrans.value;
758 Real Td0_t = genDyn->tpdo.value;
759 Real Tq0_t = genDyn->tpqo.value;
760 Real Td0_s = genDyn->tppdo.value;
761 Real Tq0_s = genDyn->tppqo.value;
764 Real H = genDyn->inertia.value;
768 Real nomFieldCurr = 0;
771 SPDLOG_LOGGER_DEBUG(mSLog,
772 " GeneratorType is TransientStability.");
774 machineRid, machineName, mComponentLogLevel);
775 gen->setStandardParametersPU(ratedPower, ratedVoltage, mFrequency,
780 mSLog,
" GeneratorType is SynchronGenerator6aOrderVBR.");
781 auto gen = std::make_shared<DP::Ph1::SynchronGenerator6aOrderVBR>(
782 machineRid, machineName, mComponentLogLevel);
783 gen->setOperationalParametersPerUnit(
784 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
785 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s);
789 mSLog,
" GeneratorType is SynchronGenerator6bOrderVBR.");
790 auto gen = std::make_shared<DP::Ph1::SynchronGenerator6bOrderVBR>(
791 machineRid, machineName, mComponentLogLevel);
792 gen->setOperationalParametersPerUnit(
793 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
794 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s);
798 mSLog,
" GeneratorType is SynchronGenerator5OrderVBR.");
799 auto gen = std::make_shared<DP::Ph1::SynchronGenerator5OrderVBR>(
800 machineRid, machineName, mComponentLogLevel);
801 gen->setOperationalParametersPerUnit(
802 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
803 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s, 0.0);
807 mSLog,
" GeneratorType is SynchronGenerator4OrderVBR.");
808 auto gen = std::make_shared<DP::Ph1::SynchronGenerator4OrderVBR>(
809 machineRid, machineName, mComponentLogLevel);
810 gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage,
811 mFrequency, H, Ld, Lq, Ll,
812 Ld_t, Lq_t, Td0_t, Tq0_t);
816 mSLog,
" GeneratorType is SynchronGenerator3OrderVBR.");
817 auto gen = std::make_shared<DP::Ph1::SynchronGenerator3OrderVBR>(
818 machineRid, machineName, mComponentLogLevel);
819 gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage,
820 mFrequency, H, Ld, Lq, Ll,
825 mSLog,
" GeneratorType is SynchronGenerator4OrderPCM.");
826 auto gen = std::make_shared<DP::Ph1::SynchronGenerator4OrderPCM>(
827 machineRid, machineName, mComponentLogLevel);
828 gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage,
829 mFrequency, H, Ld, Lq, Ll,
830 Ld_t, Lq_t, Td0_t, Tq0_t);
834 mSLog,
" GeneratorType is SynchronGenerator4OrderTPM.");
835 auto gen = std::make_shared<DP::Ph1::SynchronGenerator4OrderTPM>(
836 machineRid, machineName, mComponentLogLevel);
837 gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage,
838 mFrequency, H, Ld, Lq, Ll,
839 Ld_t, Lq_t, Td0_t, Tq0_t);
843 mSLog,
" GeneratorType is SynchronGenerator6OrderPCM.");
844 auto gen = std::make_shared<DP::Ph1::SynchronGenerator6OrderPCM>(
845 machineRid, machineName, mComponentLogLevel);
846 gen->setOperationalParametersPerUnit(
847 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
848 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s);
855 SPDLOG_LOGGER_DEBUG(mSLog,
" GeneratorType is IdealVoltageSource.");
856 return std::make_shared<DP::Ph1::SynchronGeneratorIdeal>(
857 machineRid, machineName, mComponentLogLevel);
859 throw SystemError(
"GeneratorType is None. Specify!");
861 throw SystemError(
"GeneratorType setting unfeasible.");
864 SPDLOG_LOGGER_INFO(mSLog,
" Create generator in SP domain.");
872 Real ratedPower = unitValue(machine->ratedS.value, UnitMultiplier::M);
873 Real ratedVoltage = unitValue(machine->ratedU.value, UnitMultiplier::k);
875 for (
auto obj : mModel->Objects) {
877 if (CIMPP::SynchronousMachineTimeConstantReactance *genDyn =
878 dynamic_cast<CIMPP::SynchronousMachineTimeConstantReactance *
>(
880 if (
cimString(genDyn->SynchronousMachine->mRID) == machineRid) {
882 Real Rs = genDyn->statorResistance.value;
883 Real Ll = genDyn->statorLeakageReactance.value;
886 Real Ld = genDyn->xDirectSync.value;
887 Real Lq = genDyn->xQuadSync.value;
888 Real Ld_t = genDyn->xDirectTrans.value;
889 Real Lq_t = genDyn->xQuadTrans.value;
890 Real Ld_s = genDyn->xDirectSubtrans.value;
891 Real Lq_s = genDyn->xQuadSubtrans.value;
894 Real Td0_t = genDyn->tpdo.value;
895 Real Tq0_t = genDyn->tpqo.value;
896 Real Td0_s = genDyn->tppdo.value;
897 Real Tq0_s = genDyn->tppqo.value;
900 Real H = genDyn->inertia.value;
904 Real nomFieldCurr = 0;
907 SPDLOG_LOGGER_DEBUG(mSLog,
908 " GeneratorType is TransientStability.");
910 machineRid, machineName, mComponentLogLevel);
911 gen->setStandardParametersPU(ratedPower, ratedVoltage, mFrequency,
916 mSLog,
" GeneratorType is SynchronGenerator6aOrderVBR.");
917 auto gen = std::make_shared<SP::Ph1::SynchronGenerator6aOrderVBR>(
918 machineRid, machineName, mComponentLogLevel);
919 gen->setOperationalParametersPerUnit(
920 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
921 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s);
925 mSLog,
" GeneratorType is SynchronGenerator6bOrderVBR.");
926 auto gen = std::make_shared<SP::Ph1::SynchronGenerator6bOrderVBR>(
927 machineRid, machineName, mComponentLogLevel);
928 gen->setOperationalParametersPerUnit(
929 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
930 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s);
934 mSLog,
" GeneratorType is SynchronGenerator5OrderVBR.");
935 auto gen = std::make_shared<SP::Ph1::SynchronGenerator5OrderVBR>(
936 machineRid, machineName, mComponentLogLevel);
937 gen->setOperationalParametersPerUnit(
938 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
939 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s, 0.0);
943 mSLog,
" GeneratorType is SynchronGenerator4OrderVBR.");
944 auto gen = std::make_shared<SP::Ph1::SynchronGenerator4OrderVBR>(
945 machineRid, machineName, mComponentLogLevel);
946 gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage,
947 mFrequency, H, Ld, Lq, Ll,
948 Ld_t, Lq_t, Td0_t, Tq0_t);
952 mSLog,
" GeneratorType is SynchronGenerator3OrderVBR.");
953 auto gen = std::make_shared<SP::Ph1::SynchronGenerator3OrderVBR>(
954 machineRid, machineName, mComponentLogLevel);
955 gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage,
956 mFrequency, H, Ld, Lq, Ll,
964 SPDLOG_LOGGER_DEBUG(mSLog,
" GeneratorType is PVNode.");
965 for (
auto obj : mModel->Objects) {
966 if (CIMPP::GeneratingUnit *genUnit =
967 dynamic_cast<CIMPP::GeneratingUnit *
>(obj)) {
968 for (
auto syncGen : genUnit->RotatingMachine) {
969 if (
cimString(syncGen->mRID) == machineRid) {
971 Real setPointActivePower = 0;
972 Real setPointVoltage = 0;
973 Real maximumReactivePower = 1e12;
976 setPointActivePower =
977 unitValue(genUnit->initialP.value, UnitMultiplier::M);
978 SPDLOG_LOGGER_INFO(mSLog,
" setPointActivePower={}",
979 setPointActivePower);
980 }
catch (ReadingUninitializedField *e) {
982 <<
"Uninitalized setPointActivePower for GeneratingUnit "
983 << machineName <<
". Using default value of "
984 << setPointActivePower << std::endl;
986 if (machine->RegulatingControl) {
988 unitValue(machine->RegulatingControl->targetValue.value,
990 SPDLOG_LOGGER_INFO(mSLog,
" setPointVoltage={}",
997 " No RegulatingControl for {}, mapping as PQ generator",
1001 maximumReactivePower =
1002 unitValue(machine->maxQ.value, UnitMultiplier::M);
1003 SPDLOG_LOGGER_INFO(mSLog,
" maximumReactivePower={}",
1004 maximumReactivePower);
1005 }
catch (ReadingUninitializedField *e) {
1007 <<
"Uninitalized maximumReactivePower for GeneratingUnit "
1008 << machineName <<
". Using default value of "
1009 << maximumReactivePower << std::endl;
1012 auto gen = std::make_shared<SP::Ph1::SynchronGenerator>(
1013 machineRid, machineName, mComponentLogLevel);
1015 unitValue(machine->ratedS.value, UnitMultiplier::M),
1016 unitValue(machine->ratedU.value, UnitMultiplier::k),
1017 setPointActivePower, setPointVoltage, busType);
1018 gen->setBaseVoltage(
1019 unitValue(machine->ratedU.value, UnitMultiplier::k));
1025 SPDLOG_LOGGER_INFO(mSLog,
"no corresponding initial power for {}",
1027 return std::make_shared<SP::Ph1::SynchronGenerator>(
1028 machineRid, machineName, mComponentLogLevel);
1030 throw SystemError(
"GeneratorType is None. Specify!");
1032 throw SystemError(
"GeneratorType setting unfeasible.");
1035 SPDLOG_LOGGER_INFO(mSLog,
" Create generator in EMT domain.");
1043 Real ratedPower = unitValue(machine->ratedS.value, UnitMultiplier::M);
1044 Real ratedVoltage = unitValue(machine->ratedU.value, UnitMultiplier::k);
1046 for (
auto obj : mModel->Objects) {
1048 if (CIMPP::SynchronousMachineTimeConstantReactance *genDyn =
1049 dynamic_cast<CIMPP::SynchronousMachineTimeConstantReactance *
>(
1051 if (
cimString(genDyn->SynchronousMachine->mRID) == machineRid) {
1054 Real Rs = genDyn->statorResistance.value;
1055 Real Ll = genDyn->statorLeakageReactance.value;
1058 Real Ld = genDyn->xDirectSync.value;
1059 Real Lq = genDyn->xQuadSync.value;
1060 Real Ld_t = genDyn->xDirectTrans.value;
1061 Real Lq_t = genDyn->xQuadTrans.value;
1062 Real Ld_s = genDyn->xDirectSubtrans.value;
1063 Real Lq_s = genDyn->xQuadSubtrans.value;
1066 Real Td0_t = genDyn->tpdo.value;
1067 Real Tq0_t = genDyn->tpqo.value;
1068 Real Td0_s = genDyn->tppdo.value;
1069 Real Tq0_s = genDyn->tppqo.value;
1072 Real H = genDyn->inertia.value;
1076 Real nomFieldCurr = 0;
1079 SPDLOG_LOGGER_DEBUG(mSLog,
" GeneratorType is FullOrder.");
1080 auto gen = std::make_shared<EMT::Ph3::SynchronGeneratorDQTrapez>(
1081 machineRid, machineName, mComponentLogLevel);
1082 gen->setParametersOperationalPerUnit(
1083 ratedPower, ratedVoltage, mFrequency, poleNum, nomFieldCurr,
1084 Rs, Ld, Lq, Ld_t, Lq_t, Ld_s, Lq_s, Ll, Td0_t, Tq0_t, Td0_s,
1088 SPDLOG_LOGGER_DEBUG(mSLog,
" GeneratorType is FullOrderVBR.");
1089 auto gen = std::make_shared<EMT::Ph3::SynchronGeneratorVBR>(
1090 machineRid, machineName, mComponentLogLevel);
1091 gen->setBaseAndOperationalPerUnitParameters(
1092 ratedPower, ratedVoltage, mFrequency, poleNum, nomFieldCurr,
1093 Rs, Ld, Lq, Ld_t, Lq_t, Ld_s, Lq_s, Ll, Td0_t, Tq0_t, Td0_s,
1097 SPDLOG_LOGGER_DEBUG(
1098 mSLog,
" GeneratorType is SynchronGenerator6aOrderVBR.");
1100 std::make_shared<EMT::Ph3::SynchronGenerator6aOrderVBR>(
1101 machineRid, machineName, mComponentLogLevel);
1102 gen->setOperationalParametersPerUnit(
1103 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
1104 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s);
1107 SPDLOG_LOGGER_DEBUG(
1108 mSLog,
" GeneratorType is SynchronGenerator6bOrderVBR.");
1110 std::make_shared<EMT::Ph3::SynchronGenerator6bOrderVBR>(
1111 machineRid, machineName, mComponentLogLevel);
1112 gen->setOperationalParametersPerUnit(
1113 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
1114 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s);
1117 SPDLOG_LOGGER_DEBUG(
1118 mSLog,
" GeneratorType is SynchronGenerator5OrderVBR.");
1119 auto gen = std::make_shared<EMT::Ph3::SynchronGenerator5OrderVBR>(
1120 machineRid, machineName, mComponentLogLevel);
1121 gen->setOperationalParametersPerUnit(
1122 ratedPower, ratedVoltage, mFrequency, H, Ld, Lq, Ll, Ld_t,
1123 Lq_t, Td0_t, Tq0_t, Ld_s, Lq_s, Td0_s, Tq0_s, 0.0);
1126 SPDLOG_LOGGER_DEBUG(
1127 mSLog,
" GeneratorType is SynchronGenerator4OrderVBR.");
1128 auto gen = std::make_shared<EMT::Ph3::SynchronGenerator4OrderVBR>(
1129 machineRid, machineName, mComponentLogLevel);
1130 gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage,
1131 mFrequency, H, Ld, Lq, Ll,
1132 Ld_t, Lq_t, Td0_t, Tq0_t);
1135 SPDLOG_LOGGER_DEBUG(
1136 mSLog,
" GeneratorType is SynchronGenerator3OrderVBR.");
1137 auto gen = std::make_shared<EMT::Ph3::SynchronGenerator3OrderVBR>(
1138 machineRid, machineName, mComponentLogLevel);
1139 gen->setOperationalParametersPerUnit(ratedPower, ratedVoltage,
1140 mFrequency, H, Ld, Lq, Ll,
1148 SPDLOG_LOGGER_DEBUG(mSLog,
" GeneratorType is IdealVoltageSource.");
1149 return std::make_shared<EMT::Ph3::SynchronGeneratorIdeal>(
1150 machineRid, machineName, mComponentLogLevel,
1153 SPDLOG_LOGGER_DEBUG(mSLog,
" GeneratorType is IdealCurrentSource.");
1154 return std::make_shared<EMT::Ph3::SynchronGeneratorIdeal>(
1155 machineRid, machineName, mComponentLogLevel,
1158 throw SystemError(
"GeneratorType is None. Specify!");
1160 throw SystemError(
"GeneratorType setting unfeasible.");
1167Reader::mapExternalNetworkInjection(CIMPP::ExternalNetworkInjection *extnet) {
1168 SPDLOG_LOGGER_INFO(mSLog,
"Found External Network Injection {}",
1171 Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(extnet);
1175 return std::make_shared<EMT::Ph3::NetworkInjection>(
1176 extnet->mRID, extnet->name, mComponentLogLevel);
1179 "Mapping of ExternalNetworkInjection for EMT::Ph1 not existent!");
1184 auto cpsextnet = std::make_shared<SP::Ph1::NetworkInjection>(
1185 extnet->mRID, extnet->name, mComponentLogLevel);
1186 cpsextnet->modifyPowerFlowBusType(
1189 cpsextnet->setBaseVoltage(baseVoltage);
1192 if (extnet->RegulatingControl) {
1194 Real rawTarget = extnet->RegulatingControl->targetValue.value;
1196 switch (mExtnetVoltageTargetUnit) {
1205 perUnit = std::abs(rawTarget) >= 0.5 && std::abs(rawTarget) <= 1.5;
1208 Real voltageSetPoint = perUnit
1209 ? rawTarget * baseVoltage
1210 : unitValue(rawTarget, UnitMultiplier::k);
1211 SPDLOG_LOGGER_INFO(mSLog,
" Voltage set-point={}",
1213 cpsextnet->setParameters(voltageSetPoint);
1216 mSLog,
" No voltage set-point defined. Using 1 per unit.");
1217 cpsextnet->setParameters(1. * baseVoltage);
1219 }
catch (ReadingUninitializedField *e) {
1220 std::cerr <<
"Ignore incomplete RegulatingControl" << std::endl;
1226 "Mapping of ExternalNetworkInjection for SP::Ph3 not existent!");
1231 return std::make_shared<DP::Ph1::NetworkInjection>(
1232 extnet->mRID, extnet->name, mComponentLogLevel);
1235 "Mapping of ExternalNetworkInjection for DP::Ph3 not existent!");
1242Reader::mapEquivalentShunt(CIMPP::EquivalentShunt *shunt) {
1243 SPDLOG_LOGGER_INFO(mSLog,
"Found shunt {}",
cimString(shunt->name));
1245 Real baseVoltage = determineBaseVoltageAssociatedWithEquipment(shunt);
1247 auto cpsShunt = std::make_shared<SP::Ph1::Shunt>(shunt->mRID, shunt->name,
1248 mComponentLogLevel);
1249 cpsShunt->setParameters(shunt->g.value, shunt->b.value);
1250 cpsShunt->setBaseVoltage(baseVoltage);
1256 SPDLOG_LOGGER_INFO(mSLog,
"Found Disconnector {} with status {}",
1257 cimString(disc->name), (
bool)disc->open.value);
1259 Real openResistance = 1e12;
1260 Real closedResistance = 1e-6;
1262 Bool status = disc->open.value;
1265 Matrix openResistance3Ph =
1267 Matrix closedResistance3Ph =
1271 auto cpsSwitch = std::make_shared<EMT::Ph3::Switch>(
1272 disc->mRID, disc->name, mComponentLogLevel);
1274 cpsSwitch->setParameters(openResistance3Ph, closedResistance3Ph);
1276 if (status ==
true) {
1277 cpsSwitch->openSwitch();
1279 cpsSwitch->closeSwitch();
1284 SPDLOG_LOGGER_INFO(mSLog,
1285 "Mapping of Disconnector for DP::Ph3 not existent!");
1289 SPDLOG_LOGGER_INFO(mSLog,
1290 "Mapping of Disconnector for SP::Ph3 not existent!");
1294 std::shared_ptr<CPS::TopologicalPowerComp> topoSwitch;
1295 std::shared_ptr<CPS::Base::Ph1::Switch> cpsSwitch;
1298 auto sw = std::make_shared<EMT::Ph1::Switch>(disc->mRID, disc->name,
1299 mComponentLogLevel);
1303 auto sw = std::make_shared<DP::Ph1::Switch>(disc->mRID, disc->name,
1304 mComponentLogLevel);
1308 auto sw = std::make_shared<SP::Ph1::Switch>(disc->mRID, disc->name,
1309 mComponentLogLevel);
1314 cpsSwitch->setParameters(openResistance, closedResistance);
1326 SPDLOG_LOGGER_INFO(mSLog,
"Found Breaker {} with status {}",
1327 cimString(cb->name), (
bool)cb->open.value);
1329 Real openResistance = 1e12;
1330 Real closedResistance = 1e-6;
1332 Bool status = cb->open.value;
1335 Matrix openResistance3Ph =
1337 Matrix closedResistance3Ph =
1341 auto cpsSwitch = std::make_shared<EMT::Ph3::Switch>(cb->mRID, cb->name,
1342 mComponentLogLevel);
1344 cpsSwitch->setParameters(openResistance3Ph, closedResistance3Ph);
1346 if (status ==
true) {
1347 cpsSwitch->openSwitch();
1349 cpsSwitch->closeSwitch();
1354 SPDLOG_LOGGER_INFO(mSLog,
"Mapping of Breaker for DP::Ph3 not existent!");
1358 SPDLOG_LOGGER_INFO(mSLog,
"Mapping of Breaker for SP::Ph3 not existent!");
1362 std::shared_ptr<CPS::TopologicalPowerComp> topoSwitch;
1363 std::shared_ptr<CPS::Base::Ph1::Switch> cpsSwitch;
1366 auto sw = std::make_shared<EMT::Ph1::Switch>(cb->mRID, cb->name,
1367 mComponentLogLevel);
1371 auto sw = std::make_shared<DP::Ph1::Switch>(cb->mRID, cb->name,
1372 mComponentLogLevel);
1376 auto sw = std::make_shared<SP::Ph1::Switch>(cb->mRID, cb->name,
1377 mComponentLogLevel);
1382 cpsSwitch->setParameters(openResistance, closedResistance);
1393Real Reader::determineBaseVoltageAssociatedWithEquipment(
1394 CIMPP::ConductingEquipment *equipment) {
1395 Real baseVoltage = 0;
1398 for (
auto obj : mModel->Objects) {
1399 if (CIMPP::BaseVoltage *baseVolt =
1400 dynamic_cast<CIMPP::BaseVoltage *
>(obj)) {
1401 for (
auto comp : baseVolt->ConductingEquipment) {
1404 unitValue(baseVolt->nominalVoltage.value, UnitMultiplier::k);
1410 if (baseVoltage == 0) {
1411 for (
auto obj : mModel->Objects) {
1412 if (CIMPP::TopologicalNode *topNode =
1413 dynamic_cast<CIMPP::TopologicalNode *
>(obj)) {
1414 for (
auto term : topNode->Terminal) {
1415 if (
cimString(term->ConductingEquipment->name) ==
1417 baseVoltage = unitValue(topNode->BaseVoltage->nominalVoltage.value,
1428template <
typename VarType>
1429void Reader::processTopologicalNode(CIMPP::TopologicalNode *topNode) {
1433 SPDLOG_LOGGER_WARN(mSLog,
"Cannot process null TopologicalNode, ignoring");
1437 Bool hasSupportedEquipment =
false;
1439 for (
auto term : topNode->Terminal) {
1440 if (!term || !term->ConductingEquipment)
1443 if (isSupportedConductingEquipment(term->ConductingEquipment)) {
1444 hasSupportedEquipment =
true;
1449 if (!hasSupportedEquipment) {
1452 "Skipping TopologicalNode {} ({}) because it has no terminals "
1453 "connected to supported equipment",
1458 int matrixNodeIndex =
Int(mPowerflowNodes.size());
1459 const auto &nodeRid =
cimString(topNode->mRID);
1461 nodeRid,
cimString(topNode->name), matrixNodeIndex, mPhase);
1465 mSLog,
"TopologicalNode {} phase A as simulation node {} ", nodeRid,
1466 mPowerflowNodes[nodeRid]->matrixNodeIndex(
PhaseType::A));
1468 mSLog,
"TopologicalNode {} phase B as simulation node {}", nodeRid,
1469 mPowerflowNodes[nodeRid]->matrixNodeIndex(
PhaseType::B));
1471 mSLog,
"TopologicalNode {} phase C as simulation node {}", nodeRid,
1472 mPowerflowNodes[nodeRid]->matrixNodeIndex(
PhaseType::C));
1474 SPDLOG_LOGGER_INFO(mSLog,
1475 "TopologicalNode id: {}, name: {} as simulation node {}",
1477 mPowerflowNodes[nodeRid]->matrixNodeIndex());
1479 for (
auto term : topNode->Terminal) {
1482 mSLog,
"TopologicalNode {} contains a null Terminal, ignoring",
1487 const auto &termRid =
cimString(term->mRID);
1489 mPowerflowTerminals.insert(std::make_pair(termRid, cpsTerm));
1491 std::dynamic_pointer_cast<SimNode<VarType>>(mPowerflowNodes[nodeRid]));
1493 if (!term->sequenceNumber.initialized)
1494 term->sequenceNumber = 1;
1496 SPDLOG_LOGGER_INFO(mSLog,
" Terminal {}, sequenceNumber {}", termRid,
1497 (
int)term->sequenceNumber);
1500 CIMPP::ConductingEquipment *equipment = term->ConductingEquipment;
1502 SPDLOG_LOGGER_WARN(mSLog,
"Terminal {} has no Equipment, ignoring!",
1508 if (!isSupportedConductingEquipment(equipment)) {
1511 "Terminal {} references unsupported ConductingEquipment {}, ignoring",
1518 const auto &equipmentRid =
cimString(equipment->mRID);
1519 if (mPowerflowEquipment.find(equipmentRid) == mPowerflowEquipment.end()) {
1522 mPowerflowEquipment.insert(std::make_pair(equipmentRid, comp));
1524 SPDLOG_LOGGER_WARN(mSLog,
"Could not map equipment {}", equipmentRid);
1529 auto pfEquipment = mPowerflowEquipment.at(equipmentRid);
1530 if (pfEquipment ==
nullptr) {
1531 SPDLOG_LOGGER_ERROR(mSLog,
"Equipment {} is null in equipment list",
1533 throw SystemError(
"Equipment is null in equipment list.");
1535 std::dynamic_pointer_cast<SimPowerComp<VarType>>(pfEquipment)
1536 ->setTerminalAt(std::dynamic_pointer_cast<SimTerminal<VarType>>(
1537 mPowerflowTerminals[termRid]),
1538 term->sequenceNumber - 1);
1540 SPDLOG_LOGGER_INFO(mSLog,
" Added Terminal {} to Equipment {}",
1541 termRid, equipmentRid);
1546Reader::processTopologicalNode<Real>(CIMPP::TopologicalNode *topNode);
1548Reader::processTopologicalNode<Complex>(CIMPP::TopologicalNode *topNode);
void setExtnetVoltageTargetUnit(VoltageTargetUnit unit)
void setShuntConductance(Real v)
set shunt conductance value
SystemTopology loadCIM(Real systemFrequency, const fs::path &filename, Domain domain=Domain::DP, PhaseType phase=PhaseType::Single, GeneratorType genType=GeneratorType::None)
Parses data from CIM files into the CPS data structure.
void useProtectionSwitches(Bool value=true)
If set, some components like loads include protection switches.
Reader(String name, Logger::Level logLevel=Logger::Level::info, Logger::Level componentLogLevel=Logger::Level::off)
void setShuntCapacitor(Real v)
set shunt capacitor value
spdlog::level::level_enum Level
static Log get(const std::string &name, Level filelevel=Level::info, Level clilevel=Level::off)
static Matrix singlePhaseParameterToThreePhase(Real parameter)
To convert single phase parameters to symmetrical three phase ones.
std::shared_ptr< SimPowerComp< VarType > > Ptr
std::shared_ptr< TopologicalNode > Ptr
std::shared_ptr< TopologicalPowerComp > Ptr
static std::shared_ptr< SynchronGeneratorTrStab > make(Args &&...args)
const auto & cimString(const T &field)
Eigen::Matrix< Real, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor > Matrix
Dense matrix for real numbers.
std::complex< Real > Complex
CPS::SystemTopology SystemTopology