21PowerFlow::PowerFlow(std::vector<Element*> elementList) :
ElectricCalculation() { GetElementsFromList(elementList); }
22PowerFlow::~PowerFlow() {}
23bool PowerFlow::InitPowerFlow(std::vector<BusType>& busType,
24 std::vector<std::complex<double> >& voltage,
25 std::vector<std::complex<double> >& power,
26 std::vector<std::complex<double> >& loadPower,
27 std::vector<ReactiveLimits>& reactiveLimit,
28 double systemPowerBase,
31 double radInitAngle = wxDegToRad(initAngle);
37 if (!
GetYBus(m_yBus, systemPowerBase)) {
38 m_errorMsg = _(
"No buses found on the system.");
47 m_numberOfBuses =
static_cast<int>(m_yBus.size());
53 reactiveLimit.clear();
55 reactiveLimit.resize(m_numberOfBuses);
58 Bus* slackBus =
nullptr;
62 if (data.isConnected) {
70 else if (data.isVoltageControlled) {
71 bool hasSyncMachine =
false;
94 v = data.controlledVoltage;
97 else if (busType[busNumber] ==
BUS_PV) {
98 v = data.controlledVoltage;
99 t = std::arg(data.voltage);
102 v = std::abs(data.voltage);
103 if (v <= 0.1) v = 1.0;
104 t = std::arg(data.voltage);
106 voltage.push_back(std::complex<double>(v * std::cos(t), v * std::sin(t)));
117 power.push_back(std::complex<double>(0.0, 0.0));
118 loadPower.push_back(std::complex<double>(0.0, 0.0));
126 power[busNumber] += std::complex<double>(childData.activePower, childData.reactivePower);
128 if (busType[busNumber] ==
BUS_PV) {
129 if (childData.haveMaxReactive && reactiveLimit[busNumber].maxLimitType !=
RL_UNLIMITED_SOURCE) {
130 reactiveLimit[busNumber].maxLimitType =
RL_LIMITED;
131 reactiveLimit[busNumber].maxLimit += childData.maxReactive;
133 else if (!childData.haveMaxReactive)
136 if (childData.haveMinReactive && reactiveLimit[busNumber].minLimitType !=
RL_UNLIMITED_SOURCE) {
137 reactiveLimit[busNumber].minLimitType =
RL_LIMITED;
138 reactiveLimit[busNumber].minLimit += childData.minReactive;
140 else if (!childData.haveMinReactive)
152 power[busNumber] += std::complex<double>(-childData.activePower, childData.reactivePower);
153 loadPower[busNumber] += std::complex<double>(-childData.activePower, 0.0);
155 if (busType[busNumber] ==
BUS_PV) {
156 if (childData.haveMaxReactive && reactiveLimit[busNumber].maxLimitType !=
RL_UNLIMITED_SOURCE) {
157 reactiveLimit[busNumber].maxLimitType =
RL_LIMITED;
158 reactiveLimit[busNumber].maxLimit += childData.maxReactive;
160 else if (!childData.haveMaxReactive)
163 if (childData.haveMinReactive && reactiveLimit[busNumber].minLimitType !=
RL_UNLIMITED_SOURCE) {
164 reactiveLimit[busNumber].minLimitType =
RL_LIMITED;
165 reactiveLimit[busNumber].minLimit += childData.minReactive;
167 else if (!childData.haveMinReactive)
179 if (childData.loadType == CONST_POWER) {
180 power[busNumber] += std::complex<double>(-childData.activePower, -childData.reactivePower);
181 loadPower[busNumber] += std::complex<double>(-childData.activePower, -childData.reactivePower);
193 double reactivePower = childData.reactivePower;
195 if (childData.calcQInPowerFlow) {
196 indMotor->InitPowerFlowMotor(systemPowerBase, data.number);
197 if (!indMotor->CalculateReactivePower(std::abs(voltage[childData.busNum]))) {
198 m_errorMsg = _(
"It was not possible to solve the induction motors.");
201 reactivePower = indMotor->GetElectricalData().qValue;
204 power[busNumber] += std::complex<double>(-childData.activePower, -reactivePower);
205 loadPower[busNumber] += std::complex<double>(-childData.activePower, -reactivePower);
212 if (emtElement->IsOnline() && !emtElement->GetParentList().empty()) {
213 if (bus == emtElement->GetParentList()[0]) {
215 power[busNumber] -= childData.power;
216 loadPower[busNumber] -= childData.power;
226 bool haveSlackBus =
false;
227 bool slackBusHaveGeneration =
false;
228 for (
unsigned int i = 0; i < busType.size(); i++) {
232 if (syncGenerator->
IsOnline() && slackBus == syncGenerator->
GetParentList()[0]) slackBusHaveGeneration =
true;
238 m_errorMsg = _(
"There is no slack bus on the system.");
241 if (!slackBusHaveGeneration) {
242 m_errorMsg = _(
"The slack bus don't have generation.");
246 m_tapAdjustmentsCount = 0;
250bool PowerFlow::RunGaussSeidel(
double systemPowerBase,
256 std::vector<BusType> busType;
257 std::vector<std::complex<double> > voltage;
258 std::vector<std::complex<double> > power;
259 std::vector<std::complex<double> > loadPower;
260 std::vector<ReactiveLimits> reactiveLimit;
262 if (!InitPowerFlow(busType, voltage, power, loadPower, reactiveLimit, systemPowerBase, initAngle))
return false;
265 std::vector<std::complex<double> > oldVoltage;
266 oldVoltage.resize(voltage.size());
268 auto oldBusType = busType;
271 double emtPowerError = 1e3;
275 if (iteration >= maxIteration) {
276 m_errorMsg = _(
"The maximum number of iterations was reached.");
281 if (!CalculateMotorsReactivePower(voltage, power)) {
282 m_errorMsg = _(
"It was not possible to solve the induction motors.");
287 for (
int i = 0; i < m_numberOfBuses; i++) oldVoltage[i] = voltage[i];
289 double iterationError = GaussSeidel(busType, voltage, oldVoltage, power, accFactor);
291 if (HasInvalidValue(voltage)) {
292 m_errorMsg = _(
"The power flow solution has invalid voltage values.");
296 if (HasInvalidValue(power)) {
297 m_errorMsg = _(
"The power flow solution has invalid power values.");
302 if (iterationError < error) {
305 double oldError = emtPowerError;
308 if (abs(emtPowerError - oldError) < 1e-12) {
309 m_errorMsg = _(
"Impossible to reach a convergence with the current Electromagnetic Transient Elements.");
313 else emtPowerError = 0.0;
315 bool qLimitReached = CheckReactiveLimits(busType, reactiveLimit, power, loadPower);
316 bool tapAdjusted = AdjustTapChangers(voltage, systemPowerBase);
318 if (!qLimitReached && !tapAdjusted && emtPowerError < error)
break;
323 m_iterations = iteration;
326 for (
int i = 0; i < m_numberOfBuses; i++) {
327 std::complex<double> sBus = std::complex<double>(0.0, 0.0);
328 for (
int j = 0; j < m_numberOfBuses; j++) sBus += voltage[i] * std::conj(voltage[j]) * std::conj(m_yBus[i][j]);
338bool PowerFlow::HasInvalidValue(
const std::vector< std::complex<double> >& value)
340 for (
size_t i = 0; i < value.size(); i++)
342 if (!std::isfinite(value[i].real()) ||
343 !std::isfinite(value[i].imag()))
351bool PowerFlow::RunNewtonRaphson(
double systemPowerBase,
357 std::vector<BusType> busType;
358 std::vector<std::complex<double> > voltage;
359 std::vector<std::complex<double> > power;
360 std::vector<std::complex<double> > loadPower;
361 std::vector<ReactiveLimits> reactiveLimit;
363 if (!InitPowerFlow(busType, voltage, power, loadPower, reactiveLimit, systemPowerBase, initAngle))
return false;
364 auto oldBusType = busType;
369 GetNumPVPQ(busType, numPQ, numPV);
372 std::vector<double> dPdQ;
373 dPdQ.resize(numPV + 2 * numPQ, 0.0);
378 if (iteration >= maxIteration) {
379 m_errorMsg = _(
"The maximum number of iterations was reached.");
384 if (!CalculateMotorsReactivePower(voltage, power)) {
385 m_errorMsg = _(
"It was not possible to solve the induction motors.");
392 std::fill(dPdQ.begin(), dPdQ.end(), 0.0);
395 int indexDQ = numPQ + numPV;
396 for (
int i = 0; i < m_numberOfBuses; i++) {
398 for (
int j = 0; j < m_numberOfBuses; j++) {
400 std::complex<double> sInj = std::conj(m_yBus[i][j]) * voltage[i] * std::conj(voltage[j]);
401 dPdQ[indexDP] += sInj.real();
404 if (busType[i] ==
BUS_PQ) dPdQ[indexDQ] += sInj.imag();
408 dPdQ[indexDP] = power[i].real() - dPdQ[indexDP];
412 if (busType[i] ==
BUS_PQ) {
413 dPdQ[indexDQ] = power[i].imag() - dPdQ[indexDQ];
420 double iterationError = 0.0;
421 for (
unsigned int i = 0; i < dPdQ.size(); ++i) {
422 if (iterationError < std::abs(dPdQ[i])) iterationError = std::abs(dPdQ[i]);
427 if (iterationError < error) {
428 for (
int i = 0; i < m_numberOfBuses; i++) {
429 std::complex<double> sBus(0.0, 0.0);
430 for (
int j = 0; j < m_numberOfBuses; j++)
431 sBus += voltage[i] * std::conj(voltage[j]) * std::conj(m_yBus[i][j]);
437 bool qLimitReached = CheckReactiveLimits(busType, reactiveLimit, power, loadPower);
438 bool tapAdjusted = AdjustTapChangers(voltage, systemPowerBase);
440 if (!qLimitReached && !tapAdjusted && emtPowerError < error)
443 GetNumPVPQ(busType, numPQ, numPV);
444 dPdQ.assign(numPV + 2 * numPQ, 0.0);
448 NewtonRaphson(busType, voltage, power, numPV, numPQ, dPdQ, inertia);
450 if (HasInvalidValue(voltage)) {
451 m_errorMsg = _(
"The power flow solution has invalid voltage values.");
455 if (HasInvalidValue(power)) {
456 m_errorMsg = _(
"The power flow solution has invalid power values.");
463 m_iterations = iteration;
468 for (
int i = 0; i < m_numberOfBuses; i++) {
469 std::complex<double> sBus = std::complex<double>(0.0, 0.0);
470 for (
int j = 0; j < m_numberOfBuses; j++) sBus += voltage[i] * std::conj(voltage[j]) * std::conj(m_yBus[i][j]);
479bool PowerFlow::RunGaussNewton(
double systemPowerBase,
487 std::vector<BusType> busType;
488 std::vector<std::complex<double> > voltage;
489 std::vector<std::complex<double> > power;
490 std::vector<std::complex<double> > loadPower;
491 std::vector<ReactiveLimits> reactiveLimit;
493 if (!InitPowerFlow(busType, voltage, power, loadPower, reactiveLimit, systemPowerBase, initAngle))
return false;
496 std::vector<std::complex<double> > oldVoltage;
497 oldVoltage.resize(voltage.size());
499 auto oldBusType = busType;
505 if (iteration >= maxIteration) {
506 m_errorMsg = _(
"The maximum number of iterations was reached.");
511 if (!CalculateMotorsReactivePower(voltage, power)) {
512 m_errorMsg = _(
"It was not possible to solve the induction motors.");
517 for (
int i = 0; i < m_numberOfBuses; i++) oldVoltage[i] = voltage[i];
519 double iterationError = GaussSeidel(busType, voltage, oldVoltage, power, accFactor);
521 if (iterationError < gaussTol)
break;
529 GetNumPVPQ(busType, numPQ, numPV);
532 std::vector<double> dPdQ;
533 dPdQ.resize(numPV + 2 * numPQ, 0.0);
537 if (iteration >= maxIteration) {
538 m_errorMsg = _(
"The maximum number of iterations was reached.");
543 if (!CalculateMotorsReactivePower(voltage, power)) {
544 m_errorMsg = _(
"It was not possible to solve the induction motors.");
551 std::fill(dPdQ.begin(), dPdQ.end(), 0.0);
554 int indexDQ = numPQ + numPV;
555 for (
int i = 0; i < m_numberOfBuses; i++) {
557 for (
int j = 0; j < m_numberOfBuses; j++) {
559 std::complex<double> sInj = std::conj(m_yBus[i][j]) * voltage[i] * std::conj(voltage[j]);
560 dPdQ[indexDP] += sInj.real();
563 if (busType[i] ==
BUS_PQ) dPdQ[indexDQ] += sInj.imag();
567 dPdQ[indexDP] = power[i].real() - dPdQ[indexDP];
571 if (busType[i] ==
BUS_PQ) {
572 dPdQ[indexDQ] = power[i].imag() - dPdQ[indexDQ];
579 double iterationError = 0.0;
580 for (
unsigned int i = 0; i < dPdQ.size(); ++i) {
581 if (iterationError < std::abs(dPdQ[i])) iterationError = std::abs(dPdQ[i]);
586 if (iterationError < error) {
589 bool qLimitReached = CheckReactiveLimits(busType, reactiveLimit, power, loadPower);
590 bool tapAdjusted = AdjustTapChangers(voltage, systemPowerBase);
592 if (!qLimitReached && !tapAdjusted && emtPowerError < error)
595 GetNumPVPQ(busType, numPQ, numPV);
597 dPdQ.resize(numPV + 2 * numPQ, 0.0);
601 NewtonRaphson(busType, voltage, power, numPV, numPQ, dPdQ, inertia);
605 m_iterations = iteration;
608 for (
int i = 0; i < m_numberOfBuses; i++) {
609 std::complex<double> sBus = std::complex<double>(0.0, 0.0);
610 for (
int j = 0; j < m_numberOfBuses; j++) sBus += voltage[i] * std::conj(voltage[j]) * std::conj(m_yBus[i][j]);
619void PowerFlow::ResetVoltages()
624 data.voltage = std::complex<double>(1.0, 0.0);
625 if (data.isVoltageControlled) {
626 data.voltage = std::complex<double>(data.controlledVoltage, 0.0);
630 data.voltage = std::complex<double>(0.0, 0.0);
631 data.harmonicOrder.clear();
632 data.harmonicVoltage.clear();
634 bus->SetElectricalData(data);
637 auto data = transf->GetElectricalData();
638 if (data.hasTapChanger && data.nominalTurnsRatio > 0.0) {
639 data.turnsRatio = data.nominalTurnsRatio;
640 transf->SetElectricaData(data);
645void PowerFlow::GetNumPVPQ(std::vector<BusType> busType,
int& numPQ,
int& numPV)
649 for (
auto it = busType.begin(), itEnd = busType.end(); it != itEnd; ++it) {
657double PowerFlow::GaussSeidel(std::vector<BusType> busType,
658 std::vector<std::complex<double> >& voltage,
659 std::vector<std::complex<double> > oldVoltage,
660 std::vector<std::complex<double> >& power,
665 for (
int i = 0; i < m_numberOfBuses; i++) {
666 if (busType[i] ==
BUS_PQ) {
667 std::complex<double> yeSum(0.0, 0.0);
668 for (
int k = 0; k < m_numberOfBuses; k++) {
671 yeSum += m_yBus[i][k] * voltage[k];
676 std::complex<double> newVolt = (1.0 / m_yBus[i][i]) * (std::conj(power[i]) / std::conj(voltage[i]) - yeSum);
679 newVolt = std::complex<double>(accFactor * (newVolt.real() - voltage[i].real()) + voltage[i].real(),
680 accFactor * (newVolt.imag() - voltage[i].imag()) + voltage[i].imag());
682 voltage[i] = newVolt;
684 if (busType[i] ==
BUS_PV) {
685 std::complex<double> yeSum(0.0, 0.0);
686 for (
int k = 0; k < m_numberOfBuses; k++) {
689 yeSum += m_yBus[i][k] * voltage[k];
692 std::complex<double> yeSumT = yeSum + (m_yBus[i][i] * voltage[i]);
695 std::complex<double> qCalc = std::conj(voltage[i]) * yeSumT;
696 power[i] = std::complex<double>(power[i].real(), -qCalc.imag());
699 std::complex<double> newVolt = (1.0 / m_yBus[i][i]) * (std::conj(power[i]) / std::conj(voltage[i]) - yeSum);
702 newVolt = std::complex<double>(accFactor * (newVolt.real() - voltage[i].real()) + voltage[i].real(),
703 accFactor * (newVolt.imag() - voltage[i].imag()) + voltage[i].imag());
706 voltage[i] = std::complex<double>(std::abs(voltage[i]) * std::cos(std::arg(newVolt)),
707 std::abs(voltage[i]) * std::sin(std::arg(newVolt)));
710 double busError = std::max(std::abs(voltage[i].real() - oldVoltage[i].real()),
711 std::abs(voltage[i].imag() - oldVoltage[i].imag()));
713 if (busError > error) error = busError;
718void PowerFlow::NewtonRaphson(std::vector<BusType> busType,
719 std::vector<std::complex<double> >& voltage,
720 std::vector<std::complex<double> > power,
723 std::vector<double> dPdQ,
727 std::vector<std::vector<double> > jacobMatrix = CalculateJacobianMatrix(voltage, power, busType, numPV, numPQ);
730 for (
unsigned int i = 0; i < dPdQ.size(); ++i) { dPdQ[i] = inertia * dPdQ[i]; }
737 int indexDV = numPQ + numPV;
738 for (
int i = 0; i < m_numberOfBuses; i++) {
740 if (busType[i] ==
BUS_PV) {
741 double newV = std::abs(voltage[i]);
742 double newT = std::arg(voltage[i]) + dTdV[indexDT];
743 voltage[i] = std::complex<double>(newV * std::cos(newT), newV * std::sin(newT));
748 double newV = std::abs(voltage[i]) + dTdV[indexDV];
749 double newT = std::arg(voltage[i]) + dTdV[indexDT];
750 voltage[i] = std::complex<double>(newV * std::cos(newT), newV * std::sin(newT));
758std::vector<std::vector<double>>
759PowerFlow::CalculateJacobianMatrix(
760 const std::vector<std::complex<double>>& voltage,
761 const std::vector<std::complex<double>>& power,
762 const std::vector<BusType>& busType,
766 int nvar = 2 * numPQ + numPV;
768 std::vector<std::vector<double>> J(nvar, std::vector<double>(nvar, 0.0));
770 int n = m_numberOfBuses;
773 std::vector<double> V(n);
774 std::vector<double> T(n);
776 for (
int i = 0; i < n; i++)
778 V[i] = std::abs(voltage[i]);
779 T[i] = std::arg(voltage[i]);
783 std::vector<std::complex<double>> I(n);
785 for (
int i = 0; i < n; i++)
788 for (
int k = 0; k < n; k++)
789 I[i] += m_yBus[i][k] * voltage[k];
793 std::vector<std::complex<double>> S(n);
795 for (
int i = 0; i < n; i++)
796 S[i] = voltage[i] * std::conj(I[i]);
799 int rowQ = numPV + numPQ;
801 for (
int i = 0; i < n; i++)
807 int colV = numPV + numPQ;
809 for (
int j = 0; j < n; j++)
814 double G = m_yBus[i][j].real();
815 double B = m_yBus[i][j].imag();
817 double dtheta = T[i] - T[j];
821 double Pi = S[i].real();
822 double Qi = S[i].imag();
825 J[rowP][colTheta] = -Qi - B * V[i] * V[i];
829 J[rowQ][colTheta] = Pi - G * V[i] * V[i];
834 J[rowP][colTheta] = V[i] * V[j] * (G * sin(dtheta) - B * cos(dtheta));
837 J[rowQ][colTheta] = -V[i] * V[j] * (G * cos(dtheta) + B * sin(dtheta));
845 for (
int j = 0; j < n; j++)
850 double G = m_yBus[i][j].real();
851 double B = m_yBus[i][j].imag();
853 double dtheta = T[i] - T[j];
857 double Pi = S[i].real();
858 double Qi = S[i].imag();
861 J[rowP][colV] = Pi / V[i] + G * V[i];
864 J[rowQ][colV] = Qi / V[i] - B * V[i];
869 J[rowP][colV] = V[i] * (G * cos(dtheta) + B * sin(dtheta));
872 J[rowQ][colV] = V[i] * (G * sin(dtheta) - B * cos(dtheta));
885bool PowerFlow::CheckReactiveLimits(std::vector<BusType>& busType,
886 std::vector<ReactiveLimits>& reactiveLimit,
887 std::vector<std::complex<double> >& power,
888 std::vector<std::complex<double> > loadPower)
890 bool limitReach =
false;
891 for (
int i = 0; i < m_numberOfBuses; i++) {
892 if (busType[i] ==
BUS_PV) {
893 if (reactiveLimit[i].maxLimitType ==
RL_LIMITED) {
894 if (power[i].imag() - loadPower[i].imag() > reactiveLimit[i].maxLimit) {
895 power[i] = std::complex<double>(power[i].real(), reactiveLimit[i].maxLimit + loadPower[i].imag());
901 if (reactiveLimit[i].minLimitType ==
RL_LIMITED) {
902 if (power[i].imag() - loadPower[i].imag() < reactiveLimit[i].minLimit) {
903 power[i] = std::complex<double>(power[i].real(), reactiveLimit[i].minLimit + loadPower[i].imag());
914bool PowerFlow::CalculateMotorsReactivePower(std::vector<std::complex<double> > voltage,
915 std::vector<std::complex<double> >& power)
919 auto data = motor->GetElectricalData();
920 if (motor->
IsOnline() && data.calcQInPowerFlow) {
921 double oldQ = data.qValue;
922 if (!motor->CalculateReactivePower(std::abs(voltage[data.busNum])))
return false;
923 double dQ = oldQ - motor->GetElectricalData().qValue;
924 power[data.busNum] += std::complex<double>(0.0, dQ);
930bool PowerFlow::AdjustTapChangers(
const std::vector<std::complex<double> >& voltage,
double systemPowerBase)
932 if (m_tapAdjustmentsCount >= 40) {
937 bool anyAdjusted =
false;
940 if (!transformer->IsOnline() || transformer->GetParentList().size() < 2)
continue;
943 if (!data.hasTapChanger)
continue;
945 Bus* bus1 =
static_cast<Bus*
>(transformer->GetParentList()[0]);
946 Bus* bus2 =
static_cast<Bus*
>(transformer->GetParentList()[1]);
947 if (!bus1 || !bus2)
continue;
949 int n1 = bus1->GetElectricalData().number;
950 int n2 = bus2->GetElectricalData().number;
952 int nCtrl = (data.oltcControlledBus == 0) ? n1 : n2;
953 bool isPrimary = (data.oltcControlledBus == 0);
955 if (nCtrl < 0 || nCtrl >= (
int)voltage.size())
continue;
957 double vCtrl = std::abs(voltage[nCtrl]);
958 double vTarget = data.oltcTargetVoltage;
959 double deadband = std::max(data.oltcVoltageDeadband, 1e-4);
961 if (data.oltcIsDiscrete && data.oltcTapStep > 1e-4) {
962 deadband = std::max(deadband, 0.5 * data.oltcTapStep * vCtrl);
965 double vDiff = vCtrl - vTarget;
966 if (std::abs(vDiff) <= deadband)
continue;
968 double currentTap = data.turnsRatio;
969 if (currentTap <= 1e-4) currentTap = 1.0;
998 double damping = 0.8;
999 double deltaTap = (isPrimary ? -1.0 : 1.0) * (currentTap / std::max(vCtrl, 0.1)) * vDiff * damping;
1001 if (data.oltcIsDiscrete && data.oltcTapStep > 1e-4) {
1002 double step = data.oltcTapStep;
1003 double numSteps = std::round(deltaTap / step);
1004 if (numSteps == 0.0) {
1005 numSteps = (deltaTap > 0.0) ? 1.0 : -1.0;
1007 deltaTap = numSteps * step;
1010 double newTap = currentTap + deltaTap;
1013 if (newTap < data.oltcMinTap) newTap = data.oltcMinTap;
1014 if (newTap > data.oltcMaxTap) newTap = data.oltcMaxTap;
1016 if (data.oltcIsDiscrete && data.oltcTapStep > 1e-4) {
1017 double step = data.oltcTapStep;
1018 newTap = 1.0 + std::round((newTap - 1.0) / step) * step;
1019 if (newTap < data.oltcMinTap) newTap = data.oltcMinTap;
1020 if (newTap > data.oltcMaxTap) newTap = data.oltcMaxTap;
1023 if (std::abs(newTap - currentTap) > 1e-5) {
1024 data.turnsRatio = newTap;
1025 transformer->SetElectricaData(data);
1031 m_tapAdjustmentsCount++;
1032 GetYBus(m_yBus, systemPowerBase);
Node for power elements. All others power elements are connected through this.
Element to connect ATP-EMTP.
Base class for electrical calculations providing general utility methods.
std::vector< Bus * > m_busList
List of buses in the system.
virtual void UpdateElementsPowerFlow(std::vector< std::complex< double > > voltage, std::vector< std::complex< double > > power, std::vector< BusType > busType, std::vector< ReactiveLimits > reactiveLimit, double systemPowerBase)
Update the elements after the power flow calculation.
std::vector< Load * > m_loadList
List of load elements in the system.
bool CalculateEMTElementsAdmittance(const double &basePower, wxString &errorMsg)
Calculate the admittance of EMT elements.
double CalculateEMTPowerError(const std::vector< std::complex< double > > &voltage, std::vector< std::complex< double > > &power, const double &basePower, wxString &errorMsg)
Calculate the power mismatch error for EMT simulation.
std::vector< IndMotor * > m_indMotorList
List of induction motors in the system.
std::vector< Transformer * > m_transformerList
List of transformers in the system.
bool CalculateEMTElementsPower(const double &basePower, wxString &errorMsg, bool updateCurrent=true)
Calculate the power of EMT elements.
std::vector< SyncGenerator * > m_syncGeneratorList
List of synchronous generators in the system.
std::vector< EMTElement * > m_emtElementList
List of electromagnetic transient (EMT) elements in the system.
std::vector< std::complex< double > > GaussianElimination(std::vector< std::vector< std::complex< double > > > matrix, std::vector< std::complex< double > > array)
Solve a linear system using Gaussian elimination (complex version).
virtual bool GetYBus(std::vector< std::vector< std::complex< double > > > &yBus, double systemPowerBase, YBusSequence sequence=POSITIVE_SEQ, bool includeSyncMachines=false, bool allLoadsAsImpedances=false, bool usePowerFlowVoltagesOnImpedances=false)
Get the admittance matrix from the list of elements (use GetElementsFromList first).
std::vector< SyncMotor * > m_syncMotorList
List of synchronous motors in the system.
virtual std::vector< Element * > GetParentList() const
Get the parent list.
bool IsOnline() const
Checks if the element is online or offline.
Induction motor power element.
Loas shunt power element.
Synchronous generator power element.
Synchronous motor (synchronous compensator) power element.