82 double systemPowerBase,
84 bool includeSyncMachines,
85 bool allLoadsAsImpedances,
86 bool usePowerFlowVoltagesOnImpedances)
92 for (
int i = 0; i < (int)
m_busList.size(); i++) {
93 std::vector<std::complex<double> > line;
94 for (
int j = 0; j < (int)
m_busList.size(); j++) { line.push_back(std::complex<double>(0.0, 0.0)); }
103 data.number = busNumber;
104 data.isConnected =
true;
106 bus->SetElectricalData(data);
114 int n =
static_cast<Bus*
>(load->
GetParentList()[0])->GetElectricalData().number;
116 if (data.loadType == CONST_IMPEDANCE || allLoadsAsImpedances) {
117 std::complex<double> yLoad = std::complex<double>(data.activePower, -data.reactivePower);
118 if (allLoadsAsImpedances && usePowerFlowVoltagesOnImpedances) {
119 std::complex<double> v =
static_cast<Bus*
>(load->
GetParentList()[0])->GetElectricalData().voltage;
120 yLoad /= (std::abs(v) * std::abs(v));
131 int n =
static_cast<Bus*
>(capacitor->
GetParentList()[0])->GetElectricalData().number;
133 yBus[n][n] += std::complex<double>(0.0, data.reactivePower);
141 int n =
static_cast<Bus*
>(inductor->
GetParentList()[0])->GetElectricalData().number;
143 yBus[n][n] += std::complex<double>(0.0, -data.reactivePower);
149 if (emtElement->IsOnline()) {
150 auto data = emtElement->GetEMTElementData();
151 int n =
static_cast<Bus*
>(emtElement->GetParentList()[0])->GetElectricalData().number;
152 yBus[n][n] += data.y0;
163 int n1 =
static_cast<Bus*
>(line->
GetParentList()[0])->GetElectricalData().number;
164 int n2 =
static_cast<Bus*
>(line->
GetParentList()[1])->GetElectricalData().number;
169 yBus[n1][n2] -= 1.0 / std::complex<double>(data.resistance, data.indReactance);
170 yBus[n2][n1] -= 1.0 / std::complex<double>(data.resistance, data.indReactance);
172 yBus[n1][n1] += 1.0 / std::complex<double>(data.resistance, data.indReactance);
173 yBus[n2][n2] += 1.0 / std::complex<double>(data.resistance, data.indReactance);
175 yBus[n1][n1] += std::complex<double>(0.0, data.capSusceptance / 2.0);
176 yBus[n2][n2] += std::complex<double>(0.0, data.capSusceptance / 2.0);
179 yBus[n1][n2] -= 1.0 / std::complex<double>(data.zeroResistance, data.zeroIndReactance);
180 yBus[n2][n1] -= 1.0 / std::complex<double>(data.zeroResistance, data.zeroIndReactance);
182 yBus[n1][n1] += 1.0 / std::complex<double>(data.zeroResistance, data.zeroIndReactance);
183 yBus[n2][n2] += 1.0 / std::complex<double>(data.zeroResistance, data.zeroIndReactance);
185 yBus[n1][n1] += std::complex<double>(0.0, data.zeroCapSusceptance / 2.0);
186 yBus[n2][n2] += std::complex<double>(0.0, data.zeroCapSusceptance / 2.0);
199 int n1 =
static_cast<Bus*
>(transformer->
GetParentList()[0])->GetElectricalData().number;
200 int n2 =
static_cast<Bus*
>(transformer->
GetParentList()[1])->GetElectricalData().number;
204 if (data.turnsRatio == 1.0 && data.phaseShift == 0.0 && sequence !=
ZERO_SEQ) {
205 yBus[n1][n2] += -1.0 / std::complex<double>(data.resistance, data.indReactance);
206 yBus[n2][n1] += -1.0 / std::complex<double>(data.resistance, data.indReactance);
208 yBus[n1][n1] += 1.0 / std::complex<double>(data.resistance, data.indReactance);
209 yBus[n2][n2] += 1.0 / std::complex<double>(data.resistance, data.indReactance);
218 double radPhaseShift = wxDegToRad(data.phaseShift);
219 std::complex<double> a = std::complex<double>(data.turnsRatio * std::cos(radPhaseShift),
220 -data.turnsRatio * std::sin(radPhaseShift));
223 std::complex<double> y = 1.0 / std::complex<double>(data.resistance, data.indReactance);
226 yBus[n1][n1] += y / std::pow(std::abs(a), 2.0);
227 yBus[n1][n2] += -(y / std::conj(a));
228 yBus[n2][n1] += -(y / a);
232 yBus[n1][n1] += y / std::pow(std::abs(a), 2.0);
233 yBus[n1][n2] += -(y / a);
234 yBus[n2][n1] += -(y / std::conj(a));
239 switch (data.connection) {
241 std::complex<double> y =
243 std::complex<double>(
244 data.zeroResistance + 3.0 * (data.primaryGrndResistance + data.secondaryGrndResistance),
245 data.zeroIndReactance +
246 3.0 * (data.primaryGrndReactance + data.secondaryGrndReactance));
247 std::complex<double> a = std::complex<double>(data.turnsRatio, 0.0);
249 yBus[n1][n1] += y / (a * a);
250 yBus[n1][n2] += -(y / a);
251 yBus[n2][n1] += -(y / a);
255 std::complex<double> y =
256 1.0 / std::complex<double>(data.zeroResistance + 3.0 * (data.secondaryGrndResistance),
257 data.zeroIndReactance + 3.0 * (data.secondaryGrndReactance));
259 yBus[n1][n1] += 1e-4;
260 yBus[n1][n2] += 1e-4;
261 yBus[n2][n1] += 1e-4;
265 std::complex<double> y =
266 1.0 / std::complex<double>(data.zeroResistance + 3.0 * (data.primaryGrndResistance),
267 data.zeroIndReactance + 3.0 * (data.primaryGrndReactance));
269 yBus[n2][n2] += 1e-4;
270 yBus[n1][n2] += 1e-4;
271 yBus[n2][n1] += 1e-4;
281 if (includeSyncMachines) {
286 int n =
static_cast<Bus*
>(syncGenerator->
GetParentList()[0])->GetElectricalData().number;
290 yBus[n][n] += 1.0 / std::complex<double>(data.positiveResistance, data.positiveReactance);
293 yBus[n][n] += 1.0 / std::complex<double>(data.negativeResistance, data.negativeReactance);
296 if (data.groundNeutral) {
297 yBus[n][n] += 1.0 / std::complex<double>(data.zeroResistance + 3.0 * data.groundResistance,
298 data.zeroReactance + 3.0 * data.groundReactance);
308 int n =
static_cast<Bus*
>(syncMotor->
GetParentList()[0])->GetElectricalData().number;
312 yBus[n][n] += 1.0 / std::complex<double>(data.positiveResistance, data.positiveReactance);
315 yBus[n][n] += 1.0 / std::complex<double>(data.negativeResistance, data.negativeReactance);
318 if (data.groundNeutral) {
319 yBus[n][n] += 1.0 / std::complex<double>(data.zeroResistance + 3.0 * data.groundResistance,
320 data.zeroReactance + 3.0 * data.groundReactance);
330 std::vector<bool> connectedToSlack(
m_busList.size(),
false);
333 std::vector<int> checkBusVector;
336 if (bus->GetElectricalData().slackBus)
338 connectedToSlack[busNumber] =
true;
339 slackBus = busNumber;
346 bool hasIsolatedBus =
false;
347 for (
auto isConnectedToSlack : connectedToSlack)
349 if (!isConnectedToSlack) hasIsolatedBus =
true;
352 if (hasIsolatedBus) {
355 for (
unsigned int i = 0; i <
m_busList.size(); ++i)
357 auto data =
m_busList[i]->GetElectricalData();
358 data.isConnected = connectedToSlack[i];
359 if (connectedToSlack[i])
361 data.number = busNumber;
371 std::vector< std::vector< std::complex<double> > > newYBus;
372 for (
unsigned int i = 0; i < yBus.size(); ++i) {
373 if (connectedToSlack[i]) {
374 std::vector< std::complex<double> > newLine;
375 for (
unsigned int j = 0; j < yBus.size(); ++j) {
376 if (connectedToSlack[j]) {
377 newLine.push_back(yBus[i][j]);
380 newYBus.push_back(newLine);
454 std::vector<std::complex<double> > power,
455 std::vector<BusType> busType,
456 std::vector<ReactiveLimits> reactiveLimit,
457 double systemPowerBase)
459 double zeroLimit = 1e-4;
460 for (
unsigned int i = 0; i < reactiveLimit.size(); ++i) {
461 if (reactiveLimit[i].maxLimit > -zeroLimit && reactiveLimit[i].maxLimit < zeroLimit)
462 reactiveLimit[i].maxLimit = zeroLimit;
463 if (reactiveLimit[i].minLimit > -zeroLimit && reactiveLimit[i].minLimit < zeroLimit)
464 reactiveLimit[i].minLimit = zeroLimit;
466 for (
unsigned int i = 0; i < power.size(); ++i) {
467 if (std::real(power[i]) > -zeroLimit && std::real(power[i]) < zeroLimit)
468 power[i] = std::complex<double>(0.0, std::imag(power[i]));
469 if (std::imag(power[i]) > -zeroLimit && std::imag(power[i]) < zeroLimit)
470 power[i] = std::complex<double>(std::real(power[i]), 0.0);
473 for (
int i = 0; i < (int)
m_busList.size(); i++) {
476 if (data.isConnected) {
477 data.voltage = voltage[data.number];
478 data.power = power[data.number];
479 data.busType = busType[data.number];
482 data.voltage = std::complex<double>(0.0, 0.0);
483 data.power = std::complex<double>(0.0, 0.0);
485 bus->SetElectricalData(data);
489 for (
int i = 0; i < (int)
m_lineList.size(); i++) {
492 auto dataBus1 =
static_cast<Bus*
>(line->
GetParentList()[0])->GetElectricalData();
493 auto dataBus2 =
static_cast<Bus*
>(line->
GetParentList()[1])->GetElectricalData();
495 if (dataBus1.isConnected && dataBus2.isConnected) {
496 int n1 = dataBus1.number;
497 int n2 = dataBus2.number;
501 std::complex<double> v1 = voltage[n1];
502 std::complex<double> v2 = voltage[n2];
504 data.current[0] = (v1 - v2) / std::complex<double>(dataPU.resistance, dataPU.indReactance) +
505 v1 * std::complex<double>(0.0, dataPU.capSusceptance / 2.0);
506 data.current[1] = (v2 - v1) / std::complex<double>(dataPU.resistance, dataPU.indReactance) +
507 v2 * std::complex<double>(0.0, dataPU.capSusceptance / 2.0);
509 data.powerFlow[0] = v1 * std::conj(data.current[0]);
510 data.powerFlow[1] = v2 * std::conj(data.current[1]);
512 if (data.powerFlow[0].real() > data.powerFlow[1].real())
517 line->SetElectricalData(data);
526 auto dataBus1 =
static_cast<Bus*
>(transformer->
GetParentList()[0])->GetElectricalData();
527 auto dataBus2 =
static_cast<Bus*
>(transformer->
GetParentList()[1])->GetElectricalData();
529 if (dataBus1.isConnected && dataBus2.isConnected) {
533 int n1 = dataBus1.number;
534 int n2 = dataBus2.number;
536 std::complex<double> v1 = voltage[n1];
537 std::complex<double> v2 = voltage[n2];
540 std::complex<double> y = 1.0 / std::complex<double>(dataPU.resistance, dataPU.indReactance);
542 if (dataPU.turnsRatio == 1.0 && dataPU.phaseShift == 0.0) {
543 data.current[0] = (v1 - v2) * y;
544 data.current[1] = (v2 - v1) * y;
547 double radPS = wxDegToRad(dataPU.phaseShift);
548 std::complex<double> a =
549 std::complex<double>(dataPU.turnsRatio * std::cos(radPS), -dataPU.turnsRatio * std::sin(radPS));
551 data.current[0] = v1 * (y / std::pow(std::abs(a), 2)) - v2 * (y / std::conj(a));
552 data.current[1] = -v1 * (y / a) + v2 * y;
555 data.powerFlow[0] = v1 * std::conj(data.current[0]);
556 data.powerFlow[1] = v2 * std::conj(data.current[1]);
558 if (data.powerFlow[0].real() > data.powerFlow[1].real())
563 transformer->SetElectricaData(data);
571 auto data = motor->GetElectricalData();
572 if (motor->
IsOnline() && data.calcQInPowerFlow) {
573 double reactivePower = data.qValue * systemPowerBase;
575 switch (data.reactivePowerUnit) {
576 case ElectricalUnit::UNIT_PU: {
577 reactivePower /= systemPowerBase;
579 case ElectricalUnit::UNIT_kvar: {
580 reactivePower /= 1e3;
582 case ElectricalUnit::UNIT_Mvar: {
583 reactivePower /= 1e6;
589 data.reactivePower = reactivePower;
591 motor->SetElectricalData(data);
598 if (!emtElement->IsOnline()) {
599 auto data = emtElement->GetEMTElementData();
600 data.power = std::complex<double>(0.0, 0.0);
601 data.currHarmonics[1] = std::complex<double>(0.0, 0.0);
602 emtElement->SetEMTElementData(data);
605 emtElement->UpdateData();
606 auto data = emtElement->GetEMTElementData();
607 double baseCurrent = systemPowerBase / (sqrt(3.0) * data.baseVoltage);
608 std::complex<double> current = data.currHarmonics[1] / baseCurrent;
609 std::complex<double> power = data.puVoltage * std::conj(current);
611 emtElement->SetEMTElementData(data);
621 if (data.isConnected) {
623 std::vector<SyncGenerator*> syncGeneratorsOnBus;
624 std::vector<SyncMotor*> syncMotorsOnBus;
625 std::complex<double> loadPower(0.0, 0.0);
630 syncGeneratorsOnBus.push_back(syncGenerator);
631 auto cData = syncGenerator->GetPUElectricalData(systemPowerBase);
632 if (cData.activePower >= 0.0)
641 syncMotorsOnBus.push_back(syncMotor);
643 loadPower += std::complex<double>(childData.activePower, 0.0);
644 if (childData.activePower >= 0.0)
654 if (childData.loadType == CONST_POWER)
655 loadPower += std::complex<double>(childData.activePower, childData.reactivePower);
657 if (childData.activePower >= 0.0)
667 loadPower += std::complex<double>(childData.activePower, childData.reactivePower);
669 if (childData.activePower >= 0.0)
677 std::vector<ReactiveMachine> machines;
678 for (
auto* gen : syncGeneratorsOnBus) {
681 auto dataG = gen->GetElectricalData();
682 double activePower = (power[data.number].real() + loadPower.real()) * (systemPowerBase /
static_cast<double>(syncGeneratorsOnBus.size()));
683 switch (dataG.activePowerUnit) {
684 case ElectricalUnit::UNIT_PU:
685 activePower /= systemPowerBase;
687 case ElectricalUnit::UNIT_kW:
690 case ElectricalUnit::UNIT_MW:
697 dataG.activePower = activePower;
698 gen->SetElectricalData(dataG);
701 auto dataG = gen->GetPUElectricalData(systemPowerBase);
704 m.
qMax = dataG.maxReactive;
705 m.
qMin = dataG.minReactive;
707 m.
hasMax = dataG.haveMaxReactive;
708 m.
hasMin = dataG.haveMinReactive;
713 machines.push_back(m);
715 for (
auto* mot : syncMotorsOnBus) {
717 auto data = mot->GetPUElectricalData(systemPowerBase);
720 m.
qMax = data.maxReactive;
721 m.
qMin = data.minReactive;
723 m.
hasMax = data.haveMaxReactive;
724 m.
hasMin = data.haveMinReactive;
729 machines.push_back(m);
733 double qTotal = power[i].imag() + loadPower.imag();
737 for (
auto& m : machines) {
742 auto data = gen->GetElectricalData();
744 double reactivePower = m.q * systemPowerBase;
746 switch (data.reactivePowerUnit) {
747 case ElectricalUnit::UNIT_PU:
748 reactivePower /= systemPowerBase;
750 case ElectricalUnit::UNIT_kvar:
751 reactivePower /= 1e3;
753 case ElectricalUnit::UNIT_Mvar:
754 reactivePower /= 1e6;
760 data.reactivePower = reactivePower;
761 gen->SetElectricalData(data);
766 auto data = mot->GetElectricalData();
768 double reactivePower = m.q * systemPowerBase;
770 switch (data.reactivePowerUnit) {
771 case ElectricalUnit::UNIT_PU:
772 reactivePower /= systemPowerBase;
774 case ElectricalUnit::UNIT_kvar:
775 reactivePower /= 1e3;
777 case ElectricalUnit::UNIT_Mvar:
778 reactivePower /= 1e6;
784 data.reactivePower = reactivePower;
785 mot->SetElectricalData(data);
793 std::vector<std::vector<std::complex<double> > >& inverse)
795 int order =
static_cast<int>(matrix.size());
799 for (
int i = 0; i < order; ++i) {
800 std::vector<std::complex<double> > line;
801 for (
int j = 0; j < order; ++j) {
802 line.push_back(i == j ? std::complex<double>(1.0, 0.0) : std::complex<double>(0.0, 0.0));
804 inverse.push_back(line);
808 for (
int i = 0; i < order; ++i) {
809 for (
int j = 0; j < order; ++j) {
810 if (i == j && matrix[i][j] == std::complex<double>(0.0, 0.0)) {
812 while (row < order) {
813 if (matrix[row][j] != std::complex<double>(0.0, 0.0)) {
814 for (
int k = 0; k < order; ++k) {
815 matrix[i][k] += matrix[row][k];
816 inverse[i][k] += inverse[row][k];
823 if (row == order)
return false;
830 for (
int i = 0; i < order; ++i) {
831 for (
int j = 0; j < order; ++j) {
833 if (matrix[i][i] == std::complex<double>(0.0, 0.0))
return false;
835 std::complex<double> factor = matrix[j][i] / matrix[i][i];
836 for (
int k = 0; k < order; ++k) {
837 matrix[j][k] -= factor * matrix[i][k];
838 inverse[j][k] -= factor * inverse[i][k];
844 for (
int i = 0; i < order; ++i) {
845 for (
int j = 0; j < order; ++j) {
847 if (matrix[i][j] == std::complex<double>(0.0, 0.0))
return false;
849 std::complex<double> factor = (matrix[i][j] - std::complex<double>(1.0, 0.0)) / matrix[i][j];
850 for (
int k = 0; k < order; ++k) {
851 matrix[j][k] -= factor * matrix[i][k];
852 inverse[j][k] -= factor * inverse[i][k];
875 std::vector<std::vector<std::complex<double> > > matrix,
876 std::vector<std::complex<double> > array)
880 std::vector<std::complex<double> > solution;
882 std::vector<std::vector<std::complex<double> > > triangMatrix;
883 triangMatrix.resize(matrix.size());
884 for (
unsigned int i = 0; i < matrix.size(); i++) { triangMatrix[i].resize(matrix.size()); }
886 for (
unsigned int i = 0; i < matrix.size(); i++) { solution.push_back(array[i]); }
888 for (
unsigned int i = 0; i < matrix.size(); i++) {
889 for (
unsigned int j = 0; j < matrix.size(); j++) { triangMatrix[i][j] = matrix[i][j]; }
892 for (
unsigned int k = 0; k < matrix.size(); k++) {
893 unsigned int k1 = k + 1;
894 for (
unsigned int i = k; i < matrix.size(); i++) {
895 if (triangMatrix[i][k] != std::complex<double>(0.0, 0.0)) {
896 for (
unsigned int j = k1; j < matrix.size(); j++) {
897 triangMatrix[i][j] = triangMatrix[i][j] / triangMatrix[i][k];
899 solution[i] = solution[i] / triangMatrix[i][k];
902 for (
unsigned int i = k1; i < matrix.size(); i++) {
903 if (triangMatrix[i][k] != std::complex<double>(0.0, 0.0)) {
904 for (
unsigned int j = k1; j < matrix.size(); j++) { triangMatrix[i][j] -= triangMatrix[k][j]; }
905 solution[i] -= solution[k];
909 for (
int i =
static_cast<int>(matrix.size()) - 2; i >= 0; i--) {
910 for (
int j =
static_cast<int>(matrix.size()) - 1; j >= i + 1; j--) {
911 solution[i] -= triangMatrix[i][j] * solution[j];
919 std::vector<double> array)
923 std::vector<double> solution;
925 std::vector<std::vector<double> > triangMatrix;
926 triangMatrix.resize(matrix.size());
927 for (
unsigned int i = 0; i < matrix.size(); i++) { triangMatrix[i].resize(matrix.size()); }
929 for (
unsigned int i = 0; i < matrix.size(); i++) { solution.push_back(array[i]); }
931 for (
unsigned int i = 0; i < matrix.size(); i++) {
932 for (
unsigned int j = 0; j < matrix.size(); j++) { triangMatrix[i][j] = matrix[i][j]; }
935 for (
unsigned int k = 0; k < matrix.size(); k++) {
936 unsigned int k1 = k + 1;
937 for (
unsigned int i = k; i < matrix.size(); i++) {
938 if (triangMatrix[i][k] != 0.0) {
939 for (
unsigned int j = k1; j < matrix.size(); j++) {
940 triangMatrix[i][j] = triangMatrix[i][j] / triangMatrix[i][k];
942 solution[i] = solution[i] / triangMatrix[i][k];
945 for (
unsigned int i = k1; i < matrix.size(); i++) {
946 if (triangMatrix[i][k] != 0.0) {
947 for (
unsigned int j = k1; j < matrix.size(); j++) { triangMatrix[i][j] -= triangMatrix[k][j]; }
948 solution[i] -= solution[k];
952 for (
int i =
static_cast<int>(matrix.size()) - 2; i >= 0; i--) {
953 for (
int j =
static_cast<int>(matrix.size()) - 1; j >= i + 1; j--) {
954 solution[i] -= triangMatrix[i][j] * solution[j];