Update the elements after the power flow calculation.
458{
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;
465 }
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);
471 }
472
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];
480 }
481 else {
482 data.voltage = std::complex<double>(0.0, 0.0);
483 data.power = std::complex<double>(0.0, 0.0);
484 }
485 bus->SetElectricalData(data);
486 }
487
488
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();
494
495 if (dataBus1.isConnected && dataBus2.isConnected) {
496 int n1 = dataBus1.number;
497 int n2 = dataBus2.number;
498
501 std::complex<double> v1 = voltage[n1];
502 std::complex<double> v2 = voltage[n2];
503
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);
508
509 data.powerFlow[0] = v1 * std::conj(data.current[0]);
510 data.powerFlow[1] = v2 * std::conj(data.current[1]);
511
512 if (data.powerFlow[0].real() > data.powerFlow[1].real())
514 else
516
517 line->SetElectricalData(data);
518 }
519 }
520 }
521
522
526 auto dataBus1 =
static_cast<Bus*
>(transformer->
GetParentList()[0])->GetElectricalData();
527 auto dataBus2 =
static_cast<Bus*
>(transformer->
GetParentList()[1])->GetElectricalData();
528
529 if (dataBus1.isConnected && dataBus2.isConnected) {
532
533 int n1 = dataBus1.number;
534 int n2 = dataBus2.number;
535
536 std::complex<double> v1 = voltage[n1];
537 std::complex<double> v2 = voltage[n2];
538
539
540 std::complex<double> y = 1.0 / std::complex<double>(dataPU.resistance, dataPU.indReactance);
541
542 if (dataPU.turnsRatio == 1.0 && dataPU.phaseShift == 0.0) {
543 data.current[0] = (v1 - v2) * y;
544 data.current[1] = (v2 - v1) * y;
545 }
546 else {
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));
550
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;
553 }
554
555 data.powerFlow[0] = v1 * std::conj(data.current[0]);
556 data.powerFlow[1] = v2 * std::conj(data.current[1]);
557
558 if (data.powerFlow[0].real() > data.powerFlow[1].real())
560 else
562
563 transformer->SetElectricaData(data);
564 }
565 }
566 }
567
568
571 auto data = motor->GetElectricalData();
572 if (motor->
IsOnline() && data.calcQInPowerFlow) {
573 double reactivePower = data.qValue * systemPowerBase;
574
575 switch (data.reactivePowerUnit) {
576 case ElectricalUnit::UNIT_PU: {
577 reactivePower /= systemPowerBase;
578 } break;
579 case ElectricalUnit::UNIT_kvar: {
580 reactivePower /= 1e3;
581 } break;
582 case ElectricalUnit::UNIT_Mvar: {
583 reactivePower /= 1e6;
584 } break;
585 default:
586 break;
587 }
588
589 data.reactivePower = reactivePower;
590
591 motor->SetElectricalData(data);
592 }
593 }
594
595
597
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);
603 }
604 else {
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);
610 data.power = power;
611 emtElement->SetEMTElementData(data);
612 }
613 }
614
615
616
619 int i = data.number;
620
621 if (data.isConnected) {
622
623 std::vector<SyncGenerator*> syncGeneratorsOnBus;
624 std::vector<SyncMotor*> syncMotorsOnBus;
625 std::complex<double> loadPower(0.0, 0.0);
626
630 syncGeneratorsOnBus.push_back(syncGenerator);
631 auto cData = syncGenerator->GetPUElectricalData(systemPowerBase);
632 if (cData.activePower >= 0.0)
634 else
636 }
637 }
641 syncMotorsOnBus.push_back(syncMotor);
643 loadPower += std::complex<double>(childData.activePower, 0.0);
644 if (childData.activePower >= 0.0)
646 else
648 }
649 }
654 if (childData.loadType == CONST_POWER)
655 loadPower += std::complex<double>(childData.activePower, childData.reactivePower);
656
657 if (childData.activePower >= 0.0)
659 else
661 }
662 }
667 loadPower += std::complex<double>(childData.activePower, childData.reactivePower);
668
669 if (childData.activePower >= 0.0)
671 else
673 }
674 }
675
676
677 std::vector<ReactiveMachine> machines;
678 for (auto* gen : syncGeneratorsOnBus) {
679
680 if (data.slackBus) {
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;
686 break;
687 case ElectricalUnit::UNIT_kW:
688 activePower /= 1e3;
689 break;
690 case ElectricalUnit::UNIT_MW:
691 activePower /= 1e6;
692 break;
693 default:
694 break;
695 }
696
697 dataG.activePower = activePower;
698 gen->SetElectricalData(dataG);
699 }
700
701 auto dataG = gen->GetPUElectricalData(systemPowerBase);
702
704 m.
qMax = dataG.maxReactive;
705 m.
qMin = dataG.minReactive;
706
707 m.
hasMax = dataG.haveMaxReactive;
708 m.
hasMin = dataG.haveMinReactive;
709
712
713 machines.push_back(m);
714 }
715 for (auto* mot : syncMotorsOnBus) {
716
717 auto data = mot->GetPUElectricalData(systemPowerBase);
718
720 m.
qMax = data.maxReactive;
721 m.
qMin = data.minReactive;
722
723 m.
hasMax = data.haveMaxReactive;
724 m.
hasMin = data.haveMinReactive;
725
728
729 machines.push_back(m);
730 }
731
732
733 double qTotal = power[i].imag() + loadPower.imag();
735
736
737 for (auto& m : machines) {
738
740
742 auto data = gen->GetElectricalData();
743
744 double reactivePower = m.
q * systemPowerBase;
745
746 switch (data.reactivePowerUnit) {
747 case ElectricalUnit::UNIT_PU:
748 reactivePower /= systemPowerBase;
749 break;
750 case ElectricalUnit::UNIT_kvar:
751 reactivePower /= 1e3;
752 break;
753 case ElectricalUnit::UNIT_Mvar:
754 reactivePower /= 1e6;
755 break;
756 default:
757 break;
758 }
759
760 data.reactivePower = reactivePower;
761 gen->SetElectricalData(data);
762 }
763 else {
764
766 auto data = mot->GetElectricalData();
767
768 double reactivePower = m.
q * systemPowerBase;
769
770 switch (data.reactivePowerUnit) {
771 case ElectricalUnit::UNIT_PU:
772 reactivePower /= systemPowerBase;
773 break;
774 case ElectricalUnit::UNIT_kvar:
775 reactivePower /= 1e3;
776 break;
777 case ElectricalUnit::UNIT_Mvar:
778 reactivePower /= 1e6;
779 break;
780 default:
781 break;
782 }
783
784 data.reactivePower = reactivePower;
785 mot->SetElectricalData(data);
786 }
787 }
788 }
789 }
790}
void DistributeReactivePower(std::vector< ReactiveMachine > &machines, double qTotal)
Distribute reactive power among synchronous machines connected to the same bus.
virtual void SetPowerFlowDirection(PowerFlowDirection pfDirection)
Set the direction of the power flow.
virtual void SetPowerFlowDirection(PowerFlowDirection pfDirection)
Set the direction of the power flow.
virtual void SetPowerFlowDirection(PowerFlowDirection pfDirection)
Set the direction of the power flow.
Auxiliary structure used to distribute reactive power among machines connected to a bus.