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) {
577 reactivePower /= systemPowerBase;
580 reactivePower /= 1e3;
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);
620 if (data.isConnected) {
622 std::vector<SyncGenerator*> syncGeneratorsOnBus;
623 std::vector<SyncMotor*> syncMotorsOnBus;
624 std::complex<double> loadPower(0.0, 0.0);
629 syncGeneratorsOnBus.push_back(syncGenerator);
634 syncMotorsOnBus.push_back(syncMotor);
636 loadPower += std::complex<double>(childData.activePower, 0.0);
643 if (childData.loadType == CONST_POWER)
644 loadPower += std::complex<double>(childData.activePower, childData.reactivePower);
646 if (childData.activePower >= 0.0)
656 loadPower += std::complex<double>(childData.activePower, childData.reactivePower);
658 if (childData.activePower >= 0.0)
666 std::vector<ReactiveMachine> machines;
667 for (
auto* gen : syncGeneratorsOnBus) {
670 auto dataG = gen->GetElectricalData();
671 double activePower = (power[data.number].real() + loadPower.real()) * (systemPowerBase /
static_cast<double>(syncGeneratorsOnBus.size()));
672 switch (dataG.activePowerUnit) {
674 activePower /= systemPowerBase;
686 dataG.activePower = activePower;
687 gen->SetElectricalData(dataG);
690 auto dataG = gen->GetPUElectricalData(systemPowerBase);
693 m.
qMax = dataG.maxReactive;
694 m.
qMin = dataG.minReactive;
696 m.
hasMax = dataG.haveMaxReactive;
697 m.
hasMin = dataG.haveMinReactive;
702 machines.push_back(m);
704 for (
auto* mot : syncMotorsOnBus) {
706 auto data = mot->GetPUElectricalData(systemPowerBase);
709 m.
qMax = data.maxReactive;
710 m.
qMin = data.minReactive;
712 m.
hasMax = data.haveMaxReactive;
713 m.
hasMin = data.haveMinReactive;
718 machines.push_back(m);
722 double qTotal = power[i].imag() + loadPower.imag();
726 for (
auto& m : machines) {
731 auto data = gen->GetElectricalData();
733 double reactivePower = m.q * systemPowerBase;
735 switch (data.reactivePowerUnit) {
737 reactivePower /= systemPowerBase;
740 reactivePower /= 1e3;
743 reactivePower /= 1e6;
749 data.reactivePower = reactivePower;
750 gen->SetElectricalData(data);
755 auto data = mot->GetElectricalData();
757 double reactivePower = m.q * systemPowerBase;
759 switch (data.reactivePowerUnit) {
761 reactivePower /= systemPowerBase;
764 reactivePower /= 1e3;
767 reactivePower /= 1e6;
773 data.reactivePower = reactivePower;
774 mot->SetElectricalData(data);
782 std::vector<std::vector<std::complex<double> > >& inverse)
784 int order =
static_cast<int>(matrix.size());
788 for (
int i = 0; i < order; ++i) {
789 std::vector<std::complex<double> > line;
790 for (
int j = 0; j < order; ++j) {
791 line.push_back(i == j ? std::complex<double>(1.0, 0.0) : std::complex<double>(0.0, 0.0));
793 inverse.push_back(line);
797 for (
int i = 0; i < order; ++i) {
798 for (
int j = 0; j < order; ++j) {
799 if (i == j && matrix[i][j] == std::complex<double>(0.0, 0.0)) {
801 while (row < order) {
802 if (matrix[row][j] != std::complex<double>(0.0, 0.0)) {
803 for (
int k = 0; k < order; ++k) {
804 matrix[i][k] += matrix[row][k];
805 inverse[i][k] += inverse[row][k];
812 if (row == order)
return false;
819 for (
int i = 0; i < order; ++i) {
820 for (
int j = 0; j < order; ++j) {
822 if (matrix[i][i] == std::complex<double>(0.0, 0.0))
return false;
824 std::complex<double> factor = matrix[j][i] / matrix[i][i];
825 for (
int k = 0; k < order; ++k) {
826 matrix[j][k] -= factor * matrix[i][k];
827 inverse[j][k] -= factor * inverse[i][k];
833 for (
int i = 0; i < order; ++i) {
834 for (
int j = 0; j < order; ++j) {
836 if (matrix[i][j] == std::complex<double>(0.0, 0.0))
return false;
838 std::complex<double> factor = (matrix[i][j] - std::complex<double>(1.0, 0.0)) / matrix[i][j];
839 for (
int k = 0; k < order; ++k) {
840 matrix[j][k] -= factor * matrix[i][k];
841 inverse[j][k] -= factor * inverse[i][k];
864 std::vector<std::vector<std::complex<double> > > matrix,
865 std::vector<std::complex<double> > array)
869 std::vector<std::complex<double> > solution;
871 std::vector<std::vector<std::complex<double> > > triangMatrix;
872 triangMatrix.resize(matrix.size());
873 for (
unsigned int i = 0; i < matrix.size(); i++) { triangMatrix[i].resize(matrix.size()); }
875 for (
unsigned int i = 0; i < matrix.size(); i++) { solution.push_back(array[i]); }
877 for (
unsigned int i = 0; i < matrix.size(); i++) {
878 for (
unsigned int j = 0; j < matrix.size(); j++) { triangMatrix[i][j] = matrix[i][j]; }
881 for (
unsigned int k = 0; k < matrix.size(); k++) {
882 unsigned int k1 = k + 1;
883 for (
unsigned int i = k; i < matrix.size(); i++) {
884 if (triangMatrix[i][k] != std::complex<double>(0.0, 0.0)) {
885 for (
unsigned int j = k1; j < matrix.size(); j++) {
886 triangMatrix[i][j] = triangMatrix[i][j] / triangMatrix[i][k];
888 solution[i] = solution[i] / triangMatrix[i][k];
891 for (
unsigned int i = k1; i < matrix.size(); i++) {
892 if (triangMatrix[i][k] != std::complex<double>(0.0, 0.0)) {
893 for (
unsigned int j = k1; j < matrix.size(); j++) { triangMatrix[i][j] -= triangMatrix[k][j]; }
894 solution[i] -= solution[k];
898 for (
int i =
static_cast<int>(matrix.size()) - 2; i >= 0; i--) {
899 for (
int j =
static_cast<int>(matrix.size()) - 1; j >= i + 1; j--) {
900 solution[i] -= triangMatrix[i][j] * solution[j];
908 std::vector<double> array)
912 std::vector<double> solution;
914 std::vector<std::vector<double> > triangMatrix;
915 triangMatrix.resize(matrix.size());
916 for (
unsigned int i = 0; i < matrix.size(); i++) { triangMatrix[i].resize(matrix.size()); }
918 for (
unsigned int i = 0; i < matrix.size(); i++) { solution.push_back(array[i]); }
920 for (
unsigned int i = 0; i < matrix.size(); i++) {
921 for (
unsigned int j = 0; j < matrix.size(); j++) { triangMatrix[i][j] = matrix[i][j]; }
924 for (
unsigned int k = 0; k < matrix.size(); k++) {
925 unsigned int k1 = k + 1;
926 for (
unsigned int i = k; i < matrix.size(); i++) {
927 if (triangMatrix[i][k] != 0.0) {
928 for (
unsigned int j = k1; j < matrix.size(); j++) {
929 triangMatrix[i][j] = triangMatrix[i][j] / triangMatrix[i][k];
931 solution[i] = solution[i] / triangMatrix[i][k];
934 for (
unsigned int i = k1; i < matrix.size(); i++) {
935 if (triangMatrix[i][k] != 0.0) {
936 for (
unsigned int j = k1; j < matrix.size(); j++) { triangMatrix[i][j] -= triangMatrix[k][j]; }
937 solution[i] -= solution[k];
941 for (
int i =
static_cast<int>(matrix.size()) - 2; i >= 0; i--) {
942 for (
int j =
static_cast<int>(matrix.size()) - 1; j >= i + 1; j--) {
943 solution[i] -= triangMatrix[i][j] * solution[j];
982 std::vector<std::vector<std::complex<double> > >& matrixL,
983 std::vector<std::vector<std::complex<double> > >& matrixU)
989 int size =
static_cast<int>(matrix.size());
992 matrixL.resize(size);
993 matrixU.resize(size);
994 for (
int i = 0; i < size; i++) {
995 matrixL[i].resize(size);
996 matrixU[i].resize(size);
1000 for (
int i = 0; i < size; i++) {
1001 matrixU[0][i] = matrix[0][i];
1002 matrixL[i][0] = matrix[i][0] / matrixU[0][0];
1006 for (
int i = 1; i < size; i++) { matrixL[i][i] = std::complex<double>(1.0, 0.0); }
1008 for (
int i = 1; i < size - 1; i++) {
1010 matrixU[i][i] = matrix[i][i];
1011 for (
int k = 0; k < i; k++) { matrixU[i][i] -= matrixL[i][k] * matrixU[k][i]; }
1014 for (
int j = i + 1; j < size; j++) {
1015 matrixU[i][j] = matrix[i][j];
1016 for (
int k = 0; k < i; k++) { matrixU[i][j] -= matrixL[i][k] * matrixU[k][j]; }
1020 for (
int j = i + 1; j < size; j++) {
1021 matrixL[j][i] = matrix[j][i];
1022 for (
int k = 0; k < i; k++) { matrixL[j][i] -= matrixL[j][k] * matrixU[k][i]; }
1023 matrixL[j][i] = matrixL[j][i] / matrixU[i][i];
1028 matrixU[size - 1][size - 1] = matrix[size - 1][size - 1];
1029 for (
int k = 0; k < size - 1; k++) { matrixU[size - 1][size - 1] -= matrixL[size - 1][k] * matrixU[k][size - 1]; }