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) {
669 auto data = gen->GetPUElectricalData(systemPowerBase);
672 m.
qMax = data.maxReactive;
673 m.
qMin = data.minReactive;
675 m.
hasMax = data.haveMaxReactive;
676 m.
hasMin = data.haveMinReactive;
681 machines.push_back(m);
683 for (
auto* mot : syncMotorsOnBus) {
685 auto data = mot->GetPUElectricalData(systemPowerBase);
688 m.
qMax = data.maxReactive;
689 m.
qMin = data.minReactive;
691 m.
hasMax = data.haveMaxReactive;
692 m.
hasMin = data.haveMinReactive;
697 machines.push_back(m);
701 double qTotal = power[i].imag() + loadPower.imag();
705 for (
auto& m : machines) {
710 auto data = gen->GetElectricalData();
712 double reactivePower = m.q * systemPowerBase;
714 switch (data.reactivePowerUnit) {
716 reactivePower /= systemPowerBase;
719 reactivePower /= 1e3;
722 reactivePower /= 1e6;
728 data.reactivePower = reactivePower;
729 gen->SetElectricalData(data);
734 auto data = mot->GetElectricalData();
736 double reactivePower = m.q * systemPowerBase;
738 switch (data.reactivePowerUnit) {
740 reactivePower /= systemPowerBase;
743 reactivePower /= 1e3;
746 reactivePower /= 1e6;
752 data.reactivePower = reactivePower;
753 mot->SetElectricalData(data);
761 std::vector<std::vector<std::complex<double> > >& inverse)
763 int order =
static_cast<int>(matrix.size());
767 for (
int i = 0; i < order; ++i) {
768 std::vector<std::complex<double> > line;
769 for (
int j = 0; j < order; ++j) {
770 line.push_back(i == j ? std::complex<double>(1.0, 0.0) : std::complex<double>(0.0, 0.0));
772 inverse.push_back(line);
776 for (
int i = 0; i < order; ++i) {
777 for (
int j = 0; j < order; ++j) {
778 if (i == j && matrix[i][j] == std::complex<double>(0.0, 0.0)) {
780 while (row < order) {
781 if (matrix[row][j] != std::complex<double>(0.0, 0.0)) {
782 for (
int k = 0; k < order; ++k) {
783 matrix[i][k] += matrix[row][k];
784 inverse[i][k] += inverse[row][k];
791 if (row == order)
return false;
798 for (
int i = 0; i < order; ++i) {
799 for (
int j = 0; j < order; ++j) {
801 if (matrix[i][i] == std::complex<double>(0.0, 0.0))
return false;
803 std::complex<double> factor = matrix[j][i] / matrix[i][i];
804 for (
int k = 0; k < order; ++k) {
805 matrix[j][k] -= factor * matrix[i][k];
806 inverse[j][k] -= factor * inverse[i][k];
812 for (
int i = 0; i < order; ++i) {
813 for (
int j = 0; j < order; ++j) {
815 if (matrix[i][j] == std::complex<double>(0.0, 0.0))
return false;
817 std::complex<double> factor = (matrix[i][j] - std::complex<double>(1.0, 0.0)) / matrix[i][j];
818 for (
int k = 0; k < order; ++k) {
819 matrix[j][k] -= factor * matrix[i][k];
820 inverse[j][k] -= factor * inverse[i][k];
843 std::vector<std::vector<std::complex<double> > > matrix,
844 std::vector<std::complex<double> > array)
848 std::vector<std::complex<double> > solution;
850 std::vector<std::vector<std::complex<double> > > triangMatrix;
851 triangMatrix.resize(matrix.size());
852 for (
unsigned int i = 0; i < matrix.size(); i++) { triangMatrix[i].resize(matrix.size()); }
854 for (
unsigned int i = 0; i < matrix.size(); i++) { solution.push_back(array[i]); }
856 for (
unsigned int i = 0; i < matrix.size(); i++) {
857 for (
unsigned int j = 0; j < matrix.size(); j++) { triangMatrix[i][j] = matrix[i][j]; }
860 for (
unsigned int k = 0; k < matrix.size(); k++) {
861 unsigned int k1 = k + 1;
862 for (
unsigned int i = k; i < matrix.size(); i++) {
863 if (triangMatrix[i][k] != std::complex<double>(0.0, 0.0)) {
864 for (
unsigned int j = k1; j < matrix.size(); j++) {
865 triangMatrix[i][j] = triangMatrix[i][j] / triangMatrix[i][k];
867 solution[i] = solution[i] / triangMatrix[i][k];
870 for (
unsigned int i = k1; i < matrix.size(); i++) {
871 if (triangMatrix[i][k] != std::complex<double>(0.0, 0.0)) {
872 for (
unsigned int j = k1; j < matrix.size(); j++) { triangMatrix[i][j] -= triangMatrix[k][j]; }
873 solution[i] -= solution[k];
877 for (
int i =
static_cast<int>(matrix.size()) - 2; i >= 0; i--) {
878 for (
int j =
static_cast<int>(matrix.size()) - 1; j >= i + 1; j--) {
879 solution[i] -= triangMatrix[i][j] * solution[j];
887 std::vector<double> array)
891 std::vector<double> solution;
893 std::vector<std::vector<double> > triangMatrix;
894 triangMatrix.resize(matrix.size());
895 for (
unsigned int i = 0; i < matrix.size(); i++) { triangMatrix[i].resize(matrix.size()); }
897 for (
unsigned int i = 0; i < matrix.size(); i++) { solution.push_back(array[i]); }
899 for (
unsigned int i = 0; i < matrix.size(); i++) {
900 for (
unsigned int j = 0; j < matrix.size(); j++) { triangMatrix[i][j] = matrix[i][j]; }
903 for (
unsigned int k = 0; k < matrix.size(); k++) {
904 unsigned int k1 = k + 1;
905 for (
unsigned int i = k; i < matrix.size(); i++) {
906 if (triangMatrix[i][k] != 0.0) {
907 for (
unsigned int j = k1; j < matrix.size(); j++) {
908 triangMatrix[i][j] = triangMatrix[i][j] / triangMatrix[i][k];
910 solution[i] = solution[i] / triangMatrix[i][k];
913 for (
unsigned int i = k1; i < matrix.size(); i++) {
914 if (triangMatrix[i][k] != 0.0) {
915 for (
unsigned int j = k1; j < matrix.size(); j++) { triangMatrix[i][j] -= triangMatrix[k][j]; }
916 solution[i] -= solution[k];
920 for (
int i =
static_cast<int>(matrix.size()) - 2; i >= 0; i--) {
921 for (
int j =
static_cast<int>(matrix.size()) - 1; j >= i + 1; j--) {
922 solution[i] -= triangMatrix[i][j] * solution[j];
961 std::vector<std::vector<std::complex<double> > >& matrixL,
962 std::vector<std::vector<std::complex<double> > >& matrixU)
968 int size =
static_cast<int>(matrix.size());
971 matrixL.resize(size);
972 matrixU.resize(size);
973 for (
int i = 0; i < size; i++) {
974 matrixL[i].resize(size);
975 matrixU[i].resize(size);
979 for (
int i = 0; i < size; i++) {
980 matrixU[0][i] = matrix[0][i];
981 matrixL[i][0] = matrix[i][0] / matrixU[0][0];
985 for (
int i = 1; i < size; i++) { matrixL[i][i] = std::complex<double>(1.0, 0.0); }
987 for (
int i = 1; i < size - 1; i++) {
989 matrixU[i][i] = matrix[i][i];
990 for (
int k = 0; k < i; k++) { matrixU[i][i] -= matrixL[i][k] * matrixU[k][i]; }
993 for (
int j = i + 1; j < size; j++) {
994 matrixU[i][j] = matrix[i][j];
995 for (
int k = 0; k < i; k++) { matrixU[i][j] -= matrixL[i][k] * matrixU[k][j]; }
999 for (
int j = i + 1; j < size; j++) {
1000 matrixL[j][i] = matrix[j][i];
1001 for (
int k = 0; k < i; k++) { matrixL[j][i] -= matrixL[j][k] * matrixU[k][i]; }
1002 matrixL[j][i] = matrixL[j][i] / matrixU[i][i];
1007 matrixU[size - 1][size - 1] = matrix[size - 1][size - 1];
1008 for (
int k = 0; k < size - 1; k++) { matrixU[size - 1][size - 1] -= matrixL[size - 1][k] * matrixU[k][size - 1]; }