From 6ed23d19a487fb6abd737fa3765d08b14f3bcb7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20LAIGRE?= Date: Fri, 29 Apr 2022 18:54:03 +0200 Subject: [PATCH] Add Twtdata (WIP) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sébastien LAIGRE --- include/powsybl/iidm/util/LinkData.hpp | 23 + include/powsybl/iidm/util/TwtData.hpp | 211 ++++++++ src/CMakeLists.txt | 1 + src/iidm/util/LinkData.cpp | 110 +++++ src/iidm/util/TwtData.cpp | 619 ++++++++++++++++++++++++ test/iidm/CMakeLists.txt | 1 + test/iidm/util/DanglingLineDataTest.cpp | 5 +- test/iidm/util/TwtDataTest.cpp | 127 +++++ 8 files changed, 1093 insertions(+), 4 deletions(-) create mode 100644 include/powsybl/iidm/util/TwtData.hpp create mode 100644 src/iidm/util/TwtData.cpp create mode 100644 test/iidm/util/TwtDataTest.cpp diff --git a/include/powsybl/iidm/util/LinkData.hpp b/include/powsybl/iidm/util/LinkData.hpp index 400bf35b..59cb3897 100644 --- a/include/powsybl/iidm/util/LinkData.hpp +++ b/include/powsybl/iidm/util/LinkData.hpp @@ -10,6 +10,8 @@ #include +#include + namespace powsybl { namespace iidm { @@ -25,6 +27,10 @@ struct Flow { struct BranchAdmittanceMatrix { public: + BranchAdmittanceMatrix() = default; + + BranchAdmittanceMatrix(const std::complex& y11, const std::complex& y12, const std::complex& y21, const std::complex& y22); + std::complex y11; std::complex y12; @@ -37,6 +43,23 @@ struct BranchAdmittanceMatrix { BranchAdmittanceMatrix calculateBranchAdmittance(double r, double x, double ratio1, double angle1, double ratio2, double angle2, const std::complex& ysh1, const std::complex& ysh2); +double getFixedX(double x, double epsilonX, bool applyReactanceCorrection); + +Flow flowBothEnds(const std::complex& y11, const std::complex& y12, const std::complex& y21, const std::complex& y22, + double u1, double theta1, double u2, double theta2); + +Flow flowBothEnds(const std::complex& y11, const std::complex& y12, const std::complex& y21, const std::complex& y22, + const std::complex& v1, const std::complex& v2); + +std::complex flowYshunt(const std::complex& ysh, double u, double theta); + +double getPhaseAngleClockDegrees(int phaseAngleClock); + +BranchAdmittanceMatrix kronChain(const BranchAdmittanceMatrix& firstAdm, const Branch::Side& firstChainNodeSide, + const BranchAdmittanceMatrix& secondAdm, const Branch::Side& secondChainNodeSide); + +std::complex kronAntenna(const std::complex& y11, const std::complex& y12, const std::complex& y21, const std::complex& y22, bool isOpenFrom); + } // namespace LinkData } // namespace iidm diff --git a/include/powsybl/iidm/util/TwtData.hpp b/include/powsybl/iidm/util/TwtData.hpp new file mode 100644 index 00000000..099a9d55 --- /dev/null +++ b/include/powsybl/iidm/util/TwtData.hpp @@ -0,0 +1,211 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#ifndef POWSYBL_IIDM_UTIL_TWTDATA_HPP +#define POWSYBL_IIDM_UTIL_TWTDATA_HPP + +#include +#include + +#include +#include + +namespace powsybl { + +namespace iidm { + +class ThreeWindingsTransformer; + +class TwtData { +public: + TwtData(const ThreeWindingsTransformer& twt, double epsilonX, bool applyReactanceCorrection); + + TwtData(const ThreeWindingsTransformer& twt, double epsilonX, bool applyReactanceCorrection, + bool twtSplitShuntAdmittance); + + TwtData(const ThreeWindingsTransformer& twt, int phaseAngleClock2, int phaseAngleClock3, double epsilonX, + bool applyReactanceCorrection, bool twtSplitShuntAdmittance); + + double getB1(const ThreeWindingsTransformer::Side& side) const; + + double getB2(const ThreeWindingsTransformer::Side& side) const; + + double getComputedP(const ThreeWindingsTransformer::Side& side) const; + + double getComputedQ(const ThreeWindingsTransformer::Side& side) const; + + double getG1(const ThreeWindingsTransformer::Side& side) const; + + double getG2(const ThreeWindingsTransformer::Side& side) const; + + const std::string& getId() const; + + double getP(const ThreeWindingsTransformer::Side& side) const; + + double getQ(const ThreeWindingsTransformer::Side& side) const; + + double getR(const ThreeWindingsTransformer::Side& side) const; + + double getRatedU(const ThreeWindingsTransformer::Side& side) const; + + double getStarTheta() const; + + double getStarU() const; + + double getTheta(const ThreeWindingsTransformer::Side& side) const; + + double getU(const ThreeWindingsTransformer::Side& side) const; + + double getX(const ThreeWindingsTransformer::Side& side) const; + + bool isConnected(const ThreeWindingsTransformer::Side& side) const; + + bool isMainComponent(const ThreeWindingsTransformer::Side& side) const; + + int getPhaseAngleClock2() const; + + int getPhaseAngleClock3() const; + + double getRatedU0() const; + +private: + static double alpha(const ThreeWindingsTransformer::Leg& leg); + + static double getB1(const ThreeWindingsTransformer::Leg& leg, bool twtSplitShuntAdmittance); + + static double getB2(const ThreeWindingsTransformer::Leg& leg, bool twtSplitShuntAdmittance); + + static double getG1(const ThreeWindingsTransformer::Leg& leg, bool twtSplitShuntAdmittance); + + static double getG2(const ThreeWindingsTransformer::Leg& leg, bool twtSplitShuntAdmittance); + + static double getR(const ThreeWindingsTransformer::Leg& leg); + + static double getTheta(const ThreeWindingsTransformer::Leg& leg); + + static double getV(const ThreeWindingsTransformer::Leg& leg); + + static double getValue(double initialValue, double rtcStepValue, double ptcStepValue); + + static double getX(const ThreeWindingsTransformer::Leg& leg); + + static bool isMainComponent(const ThreeWindingsTransformer::Leg& leg); + + static double rho(const ThreeWindingsTransformer::Leg& leg, double ratedU0); + + static bool valid(double voltage, double theta); + +private: + std::complex calculateOneConnectedLegFlow(double u, double theta, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixFirstOpenLeg, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixSecondOpenLeg); + + std::complex calculateOneConnectedLegShunt(const LinkData::BranchAdmittanceMatrix& closeLeg, + const LinkData::BranchAdmittanceMatrix& firstOpenLeg, + const LinkData::BranchAdmittanceMatrix& secondOpenLeg); + + std::complex calculateOneConnectedLegStarBusVoltage(double u, double theta, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixFirstOpenLeg, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixSecondOpenLeg); + + void calculateThreeConnectedLegsFlowAndStarBusVoltage(double u1, double theta1, double u2, double theta2, + double u3, double theta3, + const LinkData::BranchAdmittanceMatrix& branchAdmittanceLeg1, + const LinkData::BranchAdmittanceMatrix& branchAdmittanceLeg2, + const LinkData::BranchAdmittanceMatrix& branchAdmittanceLeg3); + + LinkData::BranchAdmittanceMatrix calculateTwoConnectedLegsAdmittance(const LinkData::BranchAdmittanceMatrix& firstCloseLeg, + const LinkData::BranchAdmittanceMatrix& secondCloseLeg, + const LinkData::BranchAdmittanceMatrix& openLeg); + + LinkData::Flow calculateTwoConnectedLegsFlow(double u1, double theta1, double u2, double theta2, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg1, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg2, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixOpenLeg); + + std::complex calculateTwoConnectedLegsStarBusVoltage(double u1, double theta1, double u2, double theta2, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg1, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg2, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixOpenLeg); + +private: + std::string id; + + double p1; + double q1; + double p2; + double q2; + double p3; + double q3; + + double u1; + double theta1; + double u2; + double theta2; + double u3; + double theta3; + + double r1; + double x1; + double r2; + double x2; + double r3; + double x3; + + double g11; + double b11; + double g12; + double b12; + double g21; + double b21; + double g22; + double b22; + double g31; + double b31; + double g32; + double b32; + + double rho1; + double alpha1; + double rho2; + double alpha2; + double rho3; + double alpha3; + + double ratedU1; + double ratedU2; + double ratedU3; + + bool connected1; + bool connected2; + bool connected3; + bool mainComponent1; + bool mainComponent2; + bool mainComponent3; + + double computedP1; + double computedQ1; + double computedP2; + double computedQ2; + double computedP3; + double computedQ3; + + double starU; + double starTheta; + + int phaseAngleClock2; + int phaseAngleClock3; + double ratedU0; +}; + +} // namespace iidm + +} // namespace powsybl + +#endif // POWSYBL_IIDM_UTIL_TWTDATA_HPP diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cb9da53b..6e93ced1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -209,6 +209,7 @@ set(IIDM_SOURCES iidm/util/Substations.cpp iidm/util/SV.cpp iidm/util/TerminalFinder.cpp + iidm/util/TwtData.cpp iidm/util/VoltageLevels.cpp logging/ConsoleLogger.cpp diff --git a/src/iidm/util/LinkData.cpp b/src/iidm/util/LinkData.cpp index 0a7478d3..caf5c205 100644 --- a/src/iidm/util/LinkData.cpp +++ b/src/iidm/util/LinkData.cpp @@ -7,12 +7,21 @@ #include +#include + namespace powsybl { namespace iidm { namespace LinkData { +BranchAdmittanceMatrix::BranchAdmittanceMatrix(const std::complex& y11, const std::complex& y12, const std::complex& y21, const std::complex& y22) : + y11(y11), + y12(y12), + y21(y21), + y22(y22) { +} + BranchAdmittanceMatrix calculateBranchAdmittance(double r, double x, double ratio1, double angle1, double ratio2, double angle2, const std::complex& ysh1, const std::complex& ysh2) { std::complex a1 = std::polar(ratio1, angle1); @@ -33,6 +42,107 @@ BranchAdmittanceMatrix calculateBranchAdmittance(double r, double x, double rati return branchAdmittance; } +double getFixedX(double x, double epsilonX, bool applyReactanceCorrection) { + return std::abs(x) < epsilonX && applyReactanceCorrection ? epsilonX : x; +} + +Flow flowBothEnds(const std::complex& y11, const std::complex& y12, const std::complex& y21, const std::complex& y22, + double u1, double theta1, double u2, double theta2) { + + const std::complex& v1 = math::ComplexUtils::polar2Complex(u1, theta1); + const std::complex& v2 = math::ComplexUtils::polar2Complex(u2, theta2); + + return flowBothEnds(y11, y12, y21, y22, v1, v2); +} + +Flow flowBothEnds(const std::complex& y11, const std::complex& y12, const std::complex& y21, const std::complex& y22, + const std::complex& v1, const std::complex& v2) { + + Flow flow; + const std::complex& ift = y12 * v2 + y11 * v1; + flow.fromTo = std::conj(ift) * v1; + + const std::complex& itf = y21 * v1 + y22 * v2; + flow.toFrom = std::conj(itf) * v2; + + return flow; +} + +std::complex flowYshunt(const std::complex& ysh, double u, double theta) { + std::complex v = math::ComplexUtils::polar2Complex(u, theta); + + return std::conj(ysh) * std::conj(v) *v; +} + +double getPhaseAngleClockDegrees(int phaseAngleClock) { + double phaseAngleClockDegree = 0.0; + phaseAngleClockDegree += phaseAngleClock * 30.0; + phaseAngleClockDegree = std::remainder(phaseAngleClockDegree, 360.0); + if (phaseAngleClockDegree > 180.0) { + phaseAngleClockDegree -= 360.0; + } + return phaseAngleClockDegree; +} + +BranchAdmittanceMatrix kronChain(const BranchAdmittanceMatrix& firstAdm, const Branch::Side& firstChainNodeSide, + const BranchAdmittanceMatrix& secondAdm, const Branch::Side& secondChainNodeSide) { + BranchAdmittanceMatrix admittance; + + std::complex yFirst11; + std::complex yFirst1C; + std::complex yFirstC1; + std::complex yFirstCC; + if (firstChainNodeSide == Branch::Side::TWO) { + yFirst11 = firstAdm.y11; + yFirst1C = firstAdm.y12; + yFirstC1 = firstAdm.y21; + yFirstCC = firstAdm.y22; + } else { + yFirst11 = firstAdm.y22; + yFirst1C = firstAdm.y21; + yFirstC1 = firstAdm.y12; + yFirstCC = firstAdm.y11; + } + + std::complex ySecond22; + std::complex ySecond2C; + std::complex ySecondC2; + std::complex ySecondCC; + if (secondChainNodeSide == Branch::Side::TWO) { + ySecond22 = secondAdm.y11; + ySecond2C = secondAdm.y12; + ySecondC2 = secondAdm.y21; + ySecondCC = secondAdm.y22; + } else { + ySecond22 = secondAdm.y22; + ySecond2C = secondAdm.y21; + ySecondC2 = secondAdm.y12; + ySecondCC = secondAdm.y11; + } + + admittance.y11 = yFirst11 - (yFirst1C * yFirstC1 / (yFirstCC + ySecondCC)); + admittance.y12 = yFirst1C * ySecondC2 / -(yFirstCC + ySecondCC); + admittance.y21 = ySecond2C * yFirstC1 / -(yFirstCC + ySecondCC); + admittance.y22 = ySecond22 - (ySecond2C * ySecondC2 / (yFirstCC + ySecondCC)); + + return admittance; +} + +std::complex kronAntenna(const std::complex& y11, const std::complex& y12, const std::complex& y21, const std::complex& y22, bool isOpenFrom) { + std::complex ysh(0.0, 0.0); + + if (isOpenFrom) { + if (y11 != std::complex(0.0, 0.0)) { + ysh = y22 - (y21 * y12 / y11); + } + } else { + if (y22 != std::complex(0.0, 0.0)) { + ysh = y11 - (y12 * y21 / y22); + } + } + return ysh; +} + } // namespace LinkData } // namespace iidm diff --git a/src/iidm/util/TwtData.cpp b/src/iidm/util/TwtData.cpp new file mode 100644 index 00000000..c7b0b6a6 --- /dev/null +++ b/src/iidm/util/TwtData.cpp @@ -0,0 +1,619 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace powsybl { + +namespace iidm { + +std::string UNEXPECTED_SIDE = "Unexpected side"; + +TwtData::TwtData(const ThreeWindingsTransformer& twt, double epsilonX, bool applyReactanceCorrection) { + TwtData(twt, 0, 0, epsilonX, applyReactanceCorrection, false); +} + +TwtData::TwtData(const ThreeWindingsTransformer& twt, double epsilonX, bool applyReactanceCorrection, + bool twtSplitShuntAdmittance) { + TwtData(twt, 0, 0, epsilonX, applyReactanceCorrection, twtSplitShuntAdmittance); +} + +TwtData::TwtData(const ThreeWindingsTransformer& twt, int phaseAngleClock2, int phaseAngleClock3, double epsilonX, + bool applyReactanceCorrection, bool twtSplitShuntAdmittance) { + id = twt.getId(); + + p1 = twt.getLeg1().getTerminal().getP(); + q1 = twt.getLeg1().getTerminal().getQ(); + p2 = twt.getLeg2().getTerminal().getP(); + q2 = twt.getLeg2().getTerminal().getQ(); + p3 = twt.getLeg3().getTerminal().getP(); + q3 = twt.getLeg3().getTerminal().getQ(); + + u1 = getV(twt.getLeg1()); + theta1 = getTheta(twt.getLeg1()); + u2 = getV(twt.getLeg2()); + theta2 = getTheta(twt.getLeg2()); + u3 = getV(twt.getLeg3()); + theta3 = getTheta(twt.getLeg3()); + + r1 = getR(twt.getLeg1()); + x1 = LinkData::getFixedX(getX(twt.getLeg1()), epsilonX, applyReactanceCorrection); + r2 = getR(twt.getLeg2()); + x2 = LinkData::getFixedX(getX(twt.getLeg2()), epsilonX, applyReactanceCorrection); + r3 = getR(twt.getLeg3()); + x3 = LinkData::getFixedX(getX(twt.getLeg3()), epsilonX, applyReactanceCorrection); + + g11 = getG1(twt.getLeg1(), twtSplitShuntAdmittance); + b11 = getB1(twt.getLeg1(), twtSplitShuntAdmittance); + g12 = getG2(twt.getLeg1(), twtSplitShuntAdmittance); + b12 = getB2(twt.getLeg1(), twtSplitShuntAdmittance); + g21 = getG1(twt.getLeg2(), twtSplitShuntAdmittance); + b21 = getB1(twt.getLeg2(), twtSplitShuntAdmittance); + g22 = getG2(twt.getLeg2(), twtSplitShuntAdmittance); + b22 = getB2(twt.getLeg2(), twtSplitShuntAdmittance); + g31 = getG1(twt.getLeg3(), twtSplitShuntAdmittance); + b31 = getB1(twt.getLeg3(), twtSplitShuntAdmittance); + g32 = getG2(twt.getLeg3(), twtSplitShuntAdmittance); + b32 = getB2(twt.getLeg3(), twtSplitShuntAdmittance); + + ratedU0 = twt.getRatedU0(); + this->phaseAngleClock2 = phaseAngleClock2; + this->phaseAngleClock3 = phaseAngleClock3; + + rho1 = rho(twt.getLeg1(), ratedU0); + alpha1 = alpha(twt.getLeg1()); + rho2 = rho(twt.getLeg2(), ratedU0); + alpha2 = alpha(twt.getLeg2()); + rho3 = rho(twt.getLeg3(), ratedU0); + alpha3 = alpha(twt.getLeg3()); + + ratedU1 = twt.getLeg1().getRatedU(); + ratedU2 = twt.getLeg2().getRatedU(); + ratedU3 = twt.getLeg3().getRatedU(); + + double rhof = 1.0; + double alphaf = 0.0; + + double angle1 = -alpha1; + double angle2 = -alpha2 - stdcxx::toRadians * LinkData::getPhaseAngleClockDegrees(phaseAngleClock2); + double angle3 = -alpha3 - stdcxx::toRadians * LinkData::getPhaseAngleClockDegrees(phaseAngleClock3); + double anglef = -alphaf; + + LinkData::BranchAdmittanceMatrix branchAdmittanceLeg1 = LinkData::calculateBranchAdmittance(r1, x1, 1 / rho1, angle1, 1 / rhof, anglef, std::complex(g11, b11), std::complex(g12, b12)); + + LinkData::BranchAdmittanceMatrix branchAdmittanceLeg2 = LinkData::calculateBranchAdmittance(r2, x2, 1 / rho2, angle2, 1 / rhof, anglef, std::complex(g21, b21), std::complex(g22, b22)); + + LinkData::BranchAdmittanceMatrix branchAdmittanceLeg3 = LinkData::calculateBranchAdmittance(r3, x3, 1 / rho3, angle3, 1 / rhof, anglef, std::complex(g31, b31), std::complex(g32, b32)); + + connected1 = twt.getLeg1().getTerminal().isConnected(); + connected2 = twt.getLeg2().getTerminal().isConnected(); + connected3 = twt.getLeg3().getTerminal().isConnected(); + mainComponent1 = isMainComponent(twt.getLeg1()); + mainComponent2 = isMainComponent(twt.getLeg2()); + mainComponent3 = isMainComponent(twt.getLeg3()); + + // Assume the ratedU at the star bus is equal to ratedU of Leg1 + + if (connected1 && connected2 && connected3 && valid(u1, theta1) && valid(u2, theta2) && valid(u3, theta3)) { + + calculateThreeConnectedLegsFlowAndStarBusVoltage(u1, theta1, u2, theta2, u3, theta3, branchAdmittanceLeg1, + branchAdmittanceLeg2, branchAdmittanceLeg3); + } else if (connected1 && connected2 && valid(u1, theta1) && valid(u2, theta2)) { + + LinkData::Flow flow = calculateTwoConnectedLegsFlow(u1, theta1, u2, theta2, + branchAdmittanceLeg1, branchAdmittanceLeg2, branchAdmittanceLeg3); + computedP1 = std::real(flow.fromTo); + computedQ1 = std::imag(flow.fromTo); + computedP2 = std::real(flow.toFrom); + computedQ2 = std::imag(flow.toFrom); + computedP3 = 0.0; + computedQ3 = 0.0; + + std::complex v0 = calculateTwoConnectedLegsStarBusVoltage(u1, theta1, u2, theta2, + branchAdmittanceLeg1, branchAdmittanceLeg2, branchAdmittanceLeg3); + starU = std::abs(v0); + starTheta = std::arg(v0); + } else if (connected1 && connected3 && valid(u1, theta1) && valid(u3, theta3)) { + + LinkData::Flow flow = calculateTwoConnectedLegsFlow(u1, theta1, u3, theta3, + branchAdmittanceLeg1, branchAdmittanceLeg3, branchAdmittanceLeg2); + computedP1 = std::real(flow.fromTo); + computedQ1 = std::imag(flow.fromTo); + computedP2 = 0.0; + computedQ2 = 0.0; + computedP3 = std::real(flow.toFrom); + computedQ3 = std::imag(flow.toFrom); + + std::complex v0 = calculateTwoConnectedLegsStarBusVoltage(u1, theta1, u3, theta3, + branchAdmittanceLeg1, branchAdmittanceLeg3, branchAdmittanceLeg2); + + starU = std::abs(v0); + starTheta = std::arg(v0); + } else if (connected2 && connected3 && valid(u2, theta2) && valid(u3, theta3)) { + + LinkData::Flow flow = calculateTwoConnectedLegsFlow(u2, theta2, u3, theta3, + branchAdmittanceLeg2, branchAdmittanceLeg3, branchAdmittanceLeg1); + computedP1 = 0.0; + computedQ1 = 0.0; + computedP2 = std::real(flow.fromTo); + computedQ2 = std::imag(flow.fromTo); + computedP3 = std::real(flow.toFrom); + computedQ3 = std::imag(flow.toFrom); + + std::complex v0 = calculateTwoConnectedLegsStarBusVoltage(u2, theta2, u3, theta3, + branchAdmittanceLeg2, branchAdmittanceLeg3, branchAdmittanceLeg1); + starU = std::abs(v0); + starTheta = std::arg(v0); + } else if (connected1 && valid(u1, theta1)) { + + std::complex flow = calculateOneConnectedLegFlow(u1, theta1, branchAdmittanceLeg1, + branchAdmittanceLeg2, branchAdmittanceLeg3); + computedP1 = std::real(flow); + computedQ1 = std::imag(flow); + computedP2 = 0.0; + computedQ2 = 0.0; + computedP3 = 0.0; + computedQ3 = 0.0; + + std::complex v0 = calculateOneConnectedLegStarBusVoltage(u1, theta1, branchAdmittanceLeg1, + branchAdmittanceLeg2, branchAdmittanceLeg3); + + starU = std::abs(v0); + starTheta = std::arg(v0); + } else if (connected2 && valid(u2, theta2)) { + + std::complex flow = calculateOneConnectedLegFlow(u2, theta2, branchAdmittanceLeg2, + branchAdmittanceLeg1, branchAdmittanceLeg3); + + computedP1 = 0.0; + computedQ1 = 0.0; + computedP2 = std::real(flow); + computedQ2 = std::imag(flow); + computedP3 = 0.0; + computedQ3 = 0.0; + + std::complex v0 = calculateOneConnectedLegStarBusVoltage(u2, theta2, branchAdmittanceLeg2, + branchAdmittanceLeg1, branchAdmittanceLeg3); + starU = std::abs(v0); + starTheta = std::arg(v0); + } else if (connected3 && valid(u3, theta3)) { + + std::complex flow = calculateOneConnectedLegFlow(u3, theta3, branchAdmittanceLeg3, + branchAdmittanceLeg1, branchAdmittanceLeg2); + + computedP1 = 0.0; + computedQ1 = 0.0; + computedP2 = 0.0; + computedQ2 = 0.0; + computedP3 = std::real(flow); + computedQ3 = std::imag(flow); + + std::complex v0 = calculateOneConnectedLegStarBusVoltage(u3, theta3, branchAdmittanceLeg3, + branchAdmittanceLeg1, branchAdmittanceLeg2); + starU = std::abs(v0); + starTheta = std::arg(v0); + } else { + + computedP1 = stdcxx::nan(); + computedQ1 = stdcxx::nan(); + computedP2 = stdcxx::nan(); + computedQ2 = stdcxx::nan(); + computedP3 = stdcxx::nan(); + computedQ3 = stdcxx::nan(); + + starU = stdcxx::nan(); + starTheta = stdcxx::nan(); + } +} + +double TwtData::alpha(const ThreeWindingsTransformer::Leg& leg) { + return leg.getOptionalPhaseTapChanger() ? leg.getPhaseTapChanger().getCurrentStep().getAlpha() : 0.0; +} + +std::complex TwtData::calculateOneConnectedLegFlow(double u, double theta, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixFirstOpenLeg, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixSecondOpenLeg) { + + std::complex ysh = calculateOneConnectedLegShunt(admittanceMatrixLeg, + admittanceMatrixFirstOpenLeg, admittanceMatrixSecondOpenLeg); + + return LinkData::flowYshunt(ysh, u, theta); +} + +std::complex TwtData::calculateOneConnectedLegShunt(const LinkData::BranchAdmittanceMatrix& closeLeg, + const LinkData::BranchAdmittanceMatrix& firstOpenLeg, + const LinkData::BranchAdmittanceMatrix& secondOpenLeg) { + std::complex ysh1 = LinkData::kronAntenna(firstOpenLeg.y11, firstOpenLeg.y12, firstOpenLeg.y21, firstOpenLeg.y22, true); + std::complex ysh2 = LinkData::kronAntenna(secondOpenLeg.y11, secondOpenLeg.y12, secondOpenLeg.y21, secondOpenLeg.y22, true); + std::complex y22 = closeLeg.y22 + ysh1 + ysh2; + + return LinkData::kronAntenna(closeLeg.y11, closeLeg.y12, closeLeg.y21, y22, false); +} + +std::complex TwtData::calculateOneConnectedLegStarBusVoltage(double u, double theta, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixFirstOpenLeg, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixSecondOpenLeg) { + + std::complex v = math::ComplexUtils::polar2Complex(u, theta); + + std::complex ysh1O = LinkData::kronAntenna(admittanceMatrixFirstOpenLeg.y11, admittanceMatrixFirstOpenLeg.y12, + admittanceMatrixFirstOpenLeg.y21, admittanceMatrixFirstOpenLeg.y22, true); + std::complex ysh2O = LinkData::kronAntenna(admittanceMatrixSecondOpenLeg.y11, admittanceMatrixSecondOpenLeg.y12, + admittanceMatrixSecondOpenLeg.y21, admittanceMatrixSecondOpenLeg.y22, true); + + return (-admittanceMatrixLeg.y21 * v) / (admittanceMatrixLeg.y22 + ysh1O + ysh2O); +} + +void TwtData::calculateThreeConnectedLegsFlowAndStarBusVoltage(double u1, double theta1, double u2, double theta2, + double u3, double theta3, + const LinkData::BranchAdmittanceMatrix& branchAdmittanceLeg1, + const LinkData::BranchAdmittanceMatrix& branchAdmittanceLeg2, + const LinkData::BranchAdmittanceMatrix& branchAdmittanceLeg3) { + std::complex v1 = math::ComplexUtils::polar2Complex(u1, theta1); + std::complex v2 = math::ComplexUtils::polar2Complex(u2, theta2); + std::complex v3 = math::ComplexUtils::polar2Complex(u3, theta3); + + std::complex v0 = (branchAdmittanceLeg1.y21 * v1 + (branchAdmittanceLeg2.y21 * v2) - (branchAdmittanceLeg3.y21 * v3)) + / (branchAdmittanceLeg1.y22 + branchAdmittanceLeg2.y22 + branchAdmittanceLeg3.y22); + + LinkData::Flow flowLeg1 = LinkData::flowBothEnds(branchAdmittanceLeg1.y11, branchAdmittanceLeg1.y12, + branchAdmittanceLeg1.y21, branchAdmittanceLeg1.y22, v1, v0); + + LinkData::Flow flowLeg2 = LinkData::flowBothEnds(branchAdmittanceLeg2.y11, branchAdmittanceLeg2.y12, + branchAdmittanceLeg2.y21, branchAdmittanceLeg2.y22, v2, v0); + + LinkData::Flow flowLeg3 = LinkData::flowBothEnds(branchAdmittanceLeg3.y11, branchAdmittanceLeg3.y12, + branchAdmittanceLeg3.y21, branchAdmittanceLeg3.y22, v3, v0); + + computedP1 = std::real(flowLeg1.fromTo); + computedQ1 = std::imag(flowLeg1.fromTo); + computedP2 = std::real(flowLeg2.fromTo); + computedQ2 = std::imag(flowLeg2.fromTo); + computedP3 = std::real(flowLeg3.fromTo); + computedQ3 = std::imag(flowLeg3.fromTo); + + starU = std::abs(v0); + starTheta = std::arg(v0); +} + +LinkData::BranchAdmittanceMatrix TwtData::calculateTwoConnectedLegsAdmittance(const LinkData::BranchAdmittanceMatrix& firstCloseLeg, + const LinkData::BranchAdmittanceMatrix& secondCloseLeg, + const LinkData::BranchAdmittanceMatrix& openLeg) { + + std::complex ysh = LinkData::kronAntenna(openLeg.y11, openLeg.y12, openLeg.y21, openLeg.y22, true); + LinkData::BranchAdmittanceMatrix secondCloseLegMod(secondCloseLeg.y11, secondCloseLeg.y12, secondCloseLeg.y21, secondCloseLeg.y22 + ysh); + return LinkData::kronChain(firstCloseLeg, Branch::Side::TWO, secondCloseLegMod, Branch::Side::TWO); +} + +LinkData::Flow TwtData::calculateTwoConnectedLegsFlow(double u1, double theta1, double u2, double theta2, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg1, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg2, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixOpenLeg) { + + std::complex v1 = math::ComplexUtils::polar2Complex(u1, theta1); + std::complex v2 = math::ComplexUtils::polar2Complex(u2, theta2); + + LinkData::BranchAdmittanceMatrix admittance = calculateTwoConnectedLegsAdmittance(admittanceMatrixLeg1, + admittanceMatrixLeg2, admittanceMatrixOpenLeg); + + return LinkData::flowBothEnds(admittance.y11, admittance.y12, admittance.y21, admittance.y22, v1, v2); +} + +std::complex TwtData::calculateTwoConnectedLegsStarBusVoltage(double u1, double theta1, double u2, double theta2, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg1, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixLeg2, + const LinkData::BranchAdmittanceMatrix& admittanceMatrixOpenLeg) { + + std::complex v1 = math::ComplexUtils::polar2Complex(u1, theta1); + std::complex v2 = math::ComplexUtils::polar2Complex(u2, theta2); + + std::complex yshO = LinkData::kronAntenna(admittanceMatrixOpenLeg.y11, admittanceMatrixOpenLeg.y12, admittanceMatrixOpenLeg.y21, admittanceMatrixOpenLeg.y22, true); + return -(admittanceMatrixLeg1.y21 * v1 + (admittanceMatrixLeg2.y21 * v2)) + / (admittanceMatrixLeg1.y22 + admittanceMatrixLeg2.y22 + yshO); +} + +double TwtData::getB1(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return b11; + case ThreeWindingsTransformer::Side::TWO: + return b21; + case ThreeWindingsTransformer::Side::THREE: + return b31; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getB1(const ThreeWindingsTransformer::Leg& leg, bool twtSplitShuntAdmittance) { + return getValue(twtSplitShuntAdmittance ? leg.getB() / 2 : leg.getB(), + leg.getOptionalRatioTapChanger() ? leg.getRatioTapChanger().getCurrentStep().getB() : 0.0, + leg.getOptionalPhaseTapChanger() ? leg.getPhaseTapChanger().getCurrentStep().getB() : 0.0); +} + +double TwtData::getB2(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return b12; + case ThreeWindingsTransformer::Side::TWO: + return b22; + case ThreeWindingsTransformer::Side::THREE: + return b32; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getB2(const ThreeWindingsTransformer::Leg& leg, bool twtSplitShuntAdmittance) { + return getValue(twtSplitShuntAdmittance ? leg.getB() / 2 : 0.0, + leg.getOptionalRatioTapChanger() ? leg.getRatioTapChanger().getCurrentStep().getB() : 0.0, + leg.getOptionalPhaseTapChanger() ? leg.getPhaseTapChanger().getCurrentStep().getB() : 0.0); +} + +double TwtData::getComputedP(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return computedP1; + case ThreeWindingsTransformer::Side::TWO: + return computedP2; + case ThreeWindingsTransformer::Side::THREE: + return computedP3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getComputedQ(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return computedQ1; + case ThreeWindingsTransformer::Side::TWO: + return computedQ2; + case ThreeWindingsTransformer::Side::THREE: + return computedQ3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getG1(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return g11; + case ThreeWindingsTransformer::Side::TWO: + return g21; + case ThreeWindingsTransformer::Side::THREE: + return g31; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getG1(const ThreeWindingsTransformer::Leg& leg, bool twtSplitShuntAdmittance) { + return getValue(twtSplitShuntAdmittance ? leg.getG() / 2 : leg.getG(), + leg.getOptionalRatioTapChanger() ? leg.getRatioTapChanger().getCurrentStep().getG() : 0.0, + leg.getOptionalPhaseTapChanger() ? leg.getPhaseTapChanger().getCurrentStep().getG() : 0.0); +} + +double TwtData::getG2(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return g12; + case ThreeWindingsTransformer::Side::TWO: + return g22; + case ThreeWindingsTransformer::Side::THREE: + return g32; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getG2(const ThreeWindingsTransformer::Leg& leg, bool twtSplitShuntAdmittance) { + return getValue(twtSplitShuntAdmittance ? leg.getG() / 2 : 0.0, + leg.getOptionalRatioTapChanger() ? leg.getRatioTapChanger().getCurrentStep().getG() : 0.0, + leg.getOptionalPhaseTapChanger() ? leg.getPhaseTapChanger().getCurrentStep().getG() : 0.0); +} + +const std::string& TwtData::getId() const { + return id; +} + +double TwtData::getP(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return p1; + case ThreeWindingsTransformer::Side::TWO: + return p2; + case ThreeWindingsTransformer::Side::THREE: + return p3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +int TwtData::getPhaseAngleClock2() const { + return phaseAngleClock2; +} + +int TwtData::getPhaseAngleClock3() const { + return phaseAngleClock3; +} + +double TwtData::getQ(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return q1; + case ThreeWindingsTransformer::Side::TWO: + return q2; + case ThreeWindingsTransformer::Side::THREE: + return q3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getR(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return r1; + case ThreeWindingsTransformer::Side::TWO: + return r2; + case ThreeWindingsTransformer::Side::THREE: + return r3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getR(const ThreeWindingsTransformer::Leg& leg) { + return getValue(leg.getR(), + leg.getOptionalRatioTapChanger() ? leg.getRatioTapChanger().getCurrentStep().getR() : 0.0, + leg.getOptionalPhaseTapChanger() ? leg.getPhaseTapChanger().getCurrentStep().getR() : 0.0); +} + +double TwtData::getRatedU(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return ratedU1; + case ThreeWindingsTransformer::Side::TWO: + return ratedU2; + case ThreeWindingsTransformer::Side::THREE: + return ratedU3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getRatedU0() const { + return ratedU0; +} + +double TwtData::getStarTheta() const { + return starTheta; +} + +double TwtData::getStarU() const { + return starU; +} + +double TwtData::getTheta(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return theta1; + case ThreeWindingsTransformer::Side::TWO: + return theta2; + case ThreeWindingsTransformer::Side::THREE: + return theta3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getTheta(const ThreeWindingsTransformer::Leg& leg) { + return leg.getTerminal().isConnected() ? stdcxx::toRadians * leg.getTerminal().getBusView().getBus().get().getAngle() : stdcxx::nan(); +} + +double TwtData::getU(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return u1; + case ThreeWindingsTransformer::Side::TWO: + return u2; + case ThreeWindingsTransformer::Side::THREE: + return u3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getV(const ThreeWindingsTransformer::Leg& leg) { + return leg.getTerminal().isConnected() ? leg.getTerminal().getBusView().getBus().get().getV() : stdcxx::nan(); +} + +double TwtData::getValue(double initialValue, double rtcStepValue, double ptcStepValue) { + return initialValue * (1 + rtcStepValue / 100) * (1 + ptcStepValue / 100); +} + +double TwtData::getX(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return x1; + case ThreeWindingsTransformer::Side::TWO: + return x2; + case ThreeWindingsTransformer::Side::THREE: + return x3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +double TwtData::getX(const ThreeWindingsTransformer::Leg& leg) { + return getValue(leg.getX(), + leg.getOptionalRatioTapChanger() ? leg.getRatioTapChanger().getCurrentStep().getX() : 0.0, + leg.getOptionalPhaseTapChanger() ? leg.getPhaseTapChanger().getCurrentStep().getX() : 0.0); +} + +bool TwtData::isConnected(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return connected1; + case ThreeWindingsTransformer::Side::TWO: + return connected2; + case ThreeWindingsTransformer::Side::THREE: + return connected3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +bool TwtData::isMainComponent(const ThreeWindingsTransformer::Side& side) const { + switch (side) { + case ThreeWindingsTransformer::Side::ONE: + return mainComponent1; + case ThreeWindingsTransformer::Side::TWO: + return mainComponent2; + case ThreeWindingsTransformer::Side::THREE: + return mainComponent3; + default: + throw AssertionError(UNEXPECTED_SIDE + ": " + Enum::toString(side)); + } +} + +bool TwtData::isMainComponent(const ThreeWindingsTransformer::Leg& leg) { + const auto& bus = leg.getTerminal().getBusView().getBus(); + const auto& connectableBus = leg.getTerminal().getBusView().getConnectableBus(); + bool connectableMainComponent = connectableBus && connectableBus.get().isInMainConnectedComponent(); + return bus ? bus.get().isInMainConnectedComponent() : connectableMainComponent; +} + +double TwtData::rho(const ThreeWindingsTransformer::Leg& leg, double ratedU0) { + double rho = ratedU0 / leg.getRatedU(); + rho *= leg.getOptionalRatioTapChanger() ? leg.getRatioTapChanger().getCurrentStep().getRho() : 1.0; + rho *= leg.getOptionalPhaseTapChanger() ? leg.getPhaseTapChanger().getCurrentStep().getRho() : 1.0; + return rho; +} + +bool TwtData::valid(double voltage, double theta) { + if (std::isnan(voltage) || voltage <= 0.0) { + return false; + } + return !std::isnan(theta); +} + +} // namespace iidm + +} // namespace powsybl diff --git a/test/iidm/CMakeLists.txt b/test/iidm/CMakeLists.txt index 150dc3d2..f858e342 100644 --- a/test/iidm/CMakeLists.txt +++ b/test/iidm/CMakeLists.txt @@ -61,6 +61,7 @@ set(UNIT_TEST_SOURCES util/DanglingLineDataTest.cpp util/SVTest.cpp util/TerminalFinderTest.cpp + util/TwtDataTest.cpp ) add_executable(unit-tests-iidm ${UNIT_TEST_SOURCES}) diff --git a/test/iidm/util/DanglingLineDataTest.cpp b/test/iidm/util/DanglingLineDataTest.cpp index e1d62296..a8b86791 100644 --- a/test/iidm/util/DanglingLineDataTest.cpp +++ b/test/iidm/util/DanglingLineDataTest.cpp @@ -71,10 +71,7 @@ Network createDanglingDataNetwork() { bool dlCompareBoundaryBusVoltage(const DanglingLineData& dlData, double boundaryBusU, double boundaryBusAngle) { double tol = 0.00001; - if (std::abs(dlData.getBoundaryBusU() - boundaryBusU) > tol || std::abs(stdcxx::toDegrees * dlData.getBoundaryBusTheta() - boundaryBusAngle) > tol) { - return false; - } - return true; + return !(std::abs(dlData.getBoundaryBusU() - boundaryBusU) > tol || std::abs(stdcxx::toDegrees * dlData.getBoundaryBusTheta() - boundaryBusAngle) > tol); } BOOST_AUTO_TEST_SUITE(DanglingLineDataTestSuite) diff --git a/test/iidm/util/TwtDataTest.cpp b/test/iidm/util/TwtDataTest.cpp new file mode 100644 index 00000000..4a7e1f2f --- /dev/null +++ b/test/iidm/util/TwtDataTest.cpp @@ -0,0 +1,127 @@ +///** +// * Copyright (c) 2022, RTE (http://www.rte-france.com) +// * This Source Code Form is subject to the terms of the Mozilla Public +// * License, v. 2.0. If a copy of the MPL was not distributed with this +// * file, You can obtain one at http://mozilla.org/MPL/2.0/. +// */ +// +//#include +// +//#include +//#include +//#include +//#include +// +//#include "NetworkFactory.hpp" +// +//namespace powsybl { +// +//namespace iidm { +// +//Network createTwtDataTestNetwork() { +// double P1 = 99.218431; +// double Q1 = 2.7304328; +// double P2 = -216.19819; +// double Q2 = -85.368180; +// double P3 = 118; +// double Q3 = 92.612077; +// +// double COMPUTED_P1 = 99.227288294050368; +// double COMPUTED_Q1 = 2.747147185209846; +// double COMPUTED_P2 = -216.195866533486196; +// double COMPUTED_Q2 = -85.490493190353362; +// double COMPUTED_P3 = 117.988318295632794; +// double COMPUTED_Q3 = 92.500849015581423; +// +// double U1 = 412.989001; +// double ANGLE1 = -6.78071; +// double U2 = 224.315268; +// double ANGLE2 = -8.77012; +// double U3 = 21.987; +// double ANGLE3 = -6.6508; +// +// double STAR_U = 412.662007016922757; +// double STAR_ANGLE = -7.353686938578365; +// +// double R1 = 0.898462; +// double X1 = 17.204128; +// double G11 = 0; +// double B11 = 2.4375E-6; +// double G12 = 0; +// double B12 = 0; +// double RATED_U1 = 400; +// double R2 = 1.070770247933884; +// double X2 = 19.6664; +// double G21 = 0; +// double B21 = 0; +// double G22 = 0; +// double B22 = 0; +// double RATED_U2 = 220; +// double R3 = 4.837006802721089; +// double X3 = 21.76072562358277; +// double G31 = 0; +// double B31 = 0; +// double G32 = 0; +// double B32 = 0; +// double RATED_U3 = 21; +// int PHASE_ANGLE_CLOCK_2 = 0; +// int PHASE_ANGLE_CLOCK_3 = 0; +// double RATED_U0 = RATED_U1; +// +// bool CONNECTED1 = true; +// bool CONNECTED2 = true; +// bool CONNECTED3 = true; +// bool MAIN_COMPONENT1 = true; +// bool MAIN_COMPONENT2 = true; +// bool MAIN_COMPONENT3 = true; +// +// Network network = createComponentsTestNetworkBB(); +// ThreeWindingsTransformer& twt = network.getThreeWindingsTransformer("3WT_VL1_VL2_VL3"); +// twt.getLeg1().getTerminal().getBusBreakerView().getBus().get().setV(U1); +// twt.getLeg1().getTerminal().getBusBreakerView().getBus().get().setAngle(ANGLE1); +// twt.getLeg1().getTerminal().setP(P1); +// twt.getLeg1().getTerminal().setP(Q1); +// twt.getLeg1().setR(R1); +// twt.getLeg1().setX(X1); +// twt.getLeg1().setRatedU(RATED_U1); +// twt.getLeg1().setB(B11 + B12); +// twt.getLeg1().setG(G11 + G12); +// +// twt.getLeg2().getTerminal().getBusBreakerView().getBus().get().setV(U2); +// twt.getLeg2().getTerminal().getBusBreakerView().getBus().get().setAngle(ANGLE2); +// twt.getLeg2().getTerminal().setP(P2); +// twt.getLeg2().getTerminal().setP(Q2); +// twt.getLeg2().setR(R2); +// twt.getLeg2().setX(X2); +// twt.getLeg2().setRatedU(RATED_U2); +// twt.getLeg2().setB(B21 + B22); +// twt.getLeg2().setG(G21 + G22); +// +// twt.getLeg3().getTerminal().getBusBreakerView().getBus().get().setV(U3); +// twt.getLeg3().getTerminal().getBusBreakerView().getBus().get().setAngle(ANGLE3); +// twt.getLeg3().getTerminal().setP(P3); +// twt.getLeg3().getTerminal().setP(Q3); +// twt.getLeg3().setR(R3); +// twt.getLeg3().setX(X3); +// twt.getLeg3().setRatedU(RATED_U3); +// twt.getLeg3().setB(B31 + B32); +// twt.getLeg3().setG(G31 + G32); +// +// return network; +//} +// +//BOOST_AUTO_TEST_SUITE(TwtDataTestSuite) +// +//BOOST_AUTO_TEST_CASE(test) { +//// Network network = createTwtDataTestNetwork(); +//// const ThreeWindingsTransformer& twt = network.getThreeWindingsTransformer("3WT_VL1_VL2_VL3"); +//// TwtData twtData(twt); +//// +//// BOOST_CHECK(dlCompareBoundaryBusVoltage(dlData, 406.63382758266334, -8.573434828294932)); +//} +// +//BOOST_AUTO_TEST_SUITE_END() +// +//} // namespace iidm +// +//} // namespace powsybl