예제 #1
0
    def __init__(self, power_circle_type: str, power_factor: float = None,
                 Vr: complex = None, Vs: complex = None,
                 Pr: float = None, Qr: float = None, Sr: complex = None,
                 Ps: float = None, Qs: float = None, Ss: complex = None,
                 A: complex = None, B: complex = None, C: complex = None,
                 D: complex = None) -> None:
        r"""Initialize the class."""
        if C is not None:
            assert abs(A*D - B*C - 1) < 1e-6, "ABCD Matrix is not a valid ABCD Matrix"

        if power_circle_type.lower() == "receiving":

            if A != None and B != None and Vr != None:
                self.radius, self.center, self.operating_point = PowerCircle._build_circle(A, B, "receiving_end", Vr,
                Pr, Qr, Sr, power_factor, Vs)
            else:
                raise ValueError("Not enough attributes to build circle")

        elif power_circle_type.lower() == "sending":

            if B != None and D != None and Vs != None:
                self.radius, self.center, self.operating_point = PowerCircle._build_circle(D, B, "sending_end", Vs,
                Ps, Qs, Ss, power_factor, Vr)
            else:
                raise ValueError("Not enough attributes to build power circle")

        else:
            raise ValueError("Invalid power circle type")

        self.circle = Circle(self.center, self.radius)
        self.parameters = locals()
예제 #2
0
    def test_1():

        from test import compare_lines

        c = Circle((0, 0), 1)
        p0 = Point(cmath.cos(cmath.pi / 4), cmath.sin(cmath.pi / 4))
        p1 = Point(-cmath.cos(cmath.pi / 4), cmath.sin(cmath.pi / 4))

        assert compare_lines(c.normal(p0), Line(1, -1, 0))
        assert compare_lines(c.normal(p1), Line(1, 1, 0))
예제 #3
0
    def test_1():

        from test import compare_lines

        c = Circle((0, 0), 1)

        p = Point(cmath.cos(cmath.pi / 4), cmath.sin(cmath.pi / 4))
        p1 = Point(cmath.sqrt(2), 0)
        p2 = Point(0, cmath.sqrt(2))

        assert compare_lines(c.tangent(p), Line.construct(p1, p2))
예제 #4
0
    def test_0():
        c = Circle((0, 0), 1)

        assert c.normal(Point(0, 1)) == Line(1, 0, 0)
        assert c.normal(Point(0, -1)) == Line(1, 0, 0)
        assert c.normal(Point(1, 0)) == Line(0, 1, 0)
        assert c.normal(Point(-1, 0)) == Line(0, 1, 0)
예제 #5
0
    def test_0():

        c = Circle((0, 0), 1)
        assert c.area() == cmath.pi

        c = Circle((0, 0), 2)
        assert c.area() == cmath.pi * 4
예제 #6
0
    def test_0():
        c = Circle((0, 0), 1)

        assert c.tangent(Point(0, 1)) == Line(0, 1, -1)
        assert c.tangent(Point(0, -1)) == Line(0, -1, -1)
        assert c.tangent(Point(1, 0)) == Line(1, 0, -1)
        assert c.tangent(Point(-1, 0)) == Line(-1, 0, -1)
예제 #7
0
    def test_1():

        c = Circle((0, 0), 1.1)
        assert c.circumference() == cmath.pi * 2.2

        c = Circle((0, 0), 2.2)
        assert c.circumference() == cmath.pi * 4.4
예제 #8
0
    def test_0():

        c = Circle((0, 0), 1)
        assert c.circumference() == cmath.pi * 2

        c = Circle((0, 0), 2)
        assert c.circumference() == cmath.pi * 4
예제 #9
0
    def test_1():

        c = Circle((0, 0), 1.1)
        assert c.area() == cmath.pi * 1.1**2

        c = Circle((0, 0), 2.2)
        assert c.area() == cmath.pi * 2.2**2
예제 #10
0
class PowerCircle:
    r"""
    Plot Power Circle Diagram of Transmission System.

    This class is designed to plot the power circle diagram of a transmission
    system both sending and reciving ends.

    Examples
    --------
    >>> import math, cmath
    >>> from electricpy import visu
    >>> visu.PowerCircle(
    ...     power_circle_type="receiving",
    ...     A=cmath.rect(0.895, math.radians(1.4)),
    ...     B=cmath.rect(182.5, math.radians(78.6)),
    ...     Vr=cmath.rect(215, 0),
    ...     Pr=50,
    ...     power_factor=-0.9
    ... )

    .. image:: /static/ReceivingPowerCircleExample.png

    Parameters
    ----------
    power_circle_type:  ["sending", "receiving"]
                        Type of power circle diagram to plot.
    Vr:                 complex
                        Transmission Line Receiving End Voltage (phasor complex
                        value)
    Vs:                 complex
                        Transmission Line Sending End Voltage (phasor complex
                        value)
    power_factor:       float
                        Power Factor of the transmission system, default = None
    Pr:                 float
                        Receiving End Real Power, default = None
    Qr:                 float
                        Receiving End Reactive Power, default = None
    Sr:                 complex
                        Receiving End Total Complex Power, default = None
    Ps:                 float
                        Sending End Real Power, default = None
    Qs:                 float
                        Sending End Reactive Power, default = None
    Ss:                 complex
                        Sending End Total Complex Power, default = None
    A:                  float
                        Transmission System ABCD Parameters, A, default = None
    B:                  float
                        Transmission System ABCD Parameters, B, default = None
    C:                  float
                        Transmission System ABCD Parameters, C, default = None
    D:                  float
                        Transmission System ABCD Parameters, D, default = None
    """

    def __init__(self, power_circle_type: str, power_factor: float = None,
                 Vr: complex = None, Vs: complex = None,
                 Pr: float = None, Qr: float = None, Sr: complex = None,
                 Ps: float = None, Qs: float = None, Ss: complex = None,
                 A: complex = None, B: complex = None, C: complex = None,
                 D: complex = None) -> None:
        r"""Initialize the class."""
        if C is not None:
            assert abs(A*D - B*C - 1) < 1e-6, "ABCD Matrix is not a valid ABCD Matrix"

        if power_circle_type.lower() == "receiving":

            if A != None and B != None and Vr != None:
                self.radius, self.center, self.operating_point = PowerCircle._build_circle(A, B, "receiving_end", Vr,
                Pr, Qr, Sr, power_factor, Vs)
            else:
                raise ValueError("Not enough attributes to build circle")

        elif power_circle_type.lower() == "sending":

            if B != None and D != None and Vs != None:
                self.radius, self.center, self.operating_point = PowerCircle._build_circle(D, B, "sending_end", Vs,
                Ps, Qs, Ss, power_factor, Vr)
            else:
                raise ValueError("Not enough attributes to build power circle")

        else:
            raise ValueError("Invalid power circle type")

        self.circle = Circle(self.center, self.radius)
        self.parameters = locals()

    @staticmethod
    def _build_circle(a1, a2, circle_type, V, P = None, Q = None, S = None, power_factor = None, V_ref = None):

        k = (abs(V)**2)*abs(a1)/abs(a2)
        alpha = cmath.phase(a1)
        beta = cmath.phase(a2)

        if circle_type == "receiving_end":
            center = Point(-k*cmath.cos(alpha - beta), -k*cmath.sin(alpha - beta))

        elif circle_type == "sending_end":
            center = Point(k*cmath.cos(alpha -beta), -k*cmath.sin(alpha - beta))

        if V_ref != None and P != None and Q != None:
            radius = abs(V)*abs(V_ref)/(abs(a2))
            operation_point = Point(P, Q)

        elif V_ref != None and S != None:
            radius = abs(V)*abs(V_ref)/(abs(a2))
            operation_point = Point(S.real, S.imag)

        elif P != None and Q != None:
            radius = geometry.distance(center, Point(P, Q))
            operation_point = Point(P, Q)

        elif S != None:
            radius = geometry.distance(center, Point(S.real, S.imag))
            operation_point = Point(S.real, S.imag)

        elif P != None and power_factor != None:

            Q = P*cmath.sqrt(1/power_factor**2 - 1).real

            if power_factor < 0:
                Q = -Q

            radius = geometry.distance(center, Point(P, Q))
            operation_point = Point(P, Q)

        elif Q != None and power_factor != None:
            P = Q/cmath.sqrt(1/power_factor**2 - 1).real
            radius = geometry.distance(center, Point(P, Q))
            operation_point = Point(P, Q)

        else:
            raise AttributeError("Enought attributes to calculate not found")

        return radius, center, operation_point

    def _cal_parameters(self, type1, type2):

        if self.parameters['V'+type2] == None:
            self.parameters['V' + type2] = abs(self.parameters['B'])*self.radius/self.parameters['V' + type1]

        if self.parameters['P'+type1] == None:
            self.parameters['P' + type1] = self.operating_point.x

        if self.parameters['Q'+type1] == None:
            self.parameters['Q' + type1] = self.operating_point.y

        if self.parameters['S'+type1] == None:
            self.parameters['S' + type1] = self.operating_point.x + 1j*self.operating_point.y

        if self.parameters['power_factor'] == None:
            self.parameters['power_factor'] = self.operating_point.y/self.operating_point.x

        if type1 == 'r' and type2 == 's':
            self.parameters["Vs"] = self.parameters['B']*self.parameters["Sr"] + self.parameters["A"] * abs(self.parameters["Vr"])**2
            self.parameters["Vs"] = self.parameters["Vs"]/self.parameters["Vr"].conjugate()

        elif type1 == 's' and type2 == 'r':
            self.parameters["Vr"] = -self.parameters['B']*self.parameters["Ss"] + self.parameters["D"] * abs(self.parameters["Vs"])**2
            self.parameters["Vr"] = self.parameters["Vr"]/self.parameters["Vs"].conjugate()

    def print_data(self):
        r"""Print the data of the circle."""
        if self.operating_point == None:
            return self.center, self.radius

        if self.parameters["power_circle_type"] == "receiving":

            self._cal_parameters("r", "s")

        if self.parameters["power_circle_type"] == "sending":

            self._cal_parameters("s", "r")

        for key, value in self.parameters.items():
            print(key, " => ", value)

    def __call__(self) -> dict:
        r"""Return the data of the circle."""
        if self.parameters["power_circle_type"] == "receiving":

            self._cal_parameters("r", "s")

        if self.parameters["power_circle_type"] == "sending":

            self._cal_parameters("s", "r")

        return self.parameters

    def plot(self):
        r"""Plot the circle."""
        circle_x = []
        circle_y = []

        for data in self.circle.parametric_equation(theta_resolution=1e-5):
            [x, y] = data
            circle_x.append(x)
            circle_y.append(y)

        c_x = self.center.x
        c_y = self.center.y

        op_x = self.operating_point.x
        op_y = self.operating_point.y

        #plot Circle and Diameter
        _plt.plot(circle_x, circle_y)
        _plt.plot([c_x - self.radius, c_x + self.radius], [c_y, c_y], 'g--')
        _plt.plot([c_x, c_x], [c_y - self.radius, c_y + self.radius], 'g--')

        _plt.plot([c_x, op_x], [c_y, op_y], 'y*-.')
        _plt.plot([op_x, op_x], [op_y, c_y], 'b*-.')
        _plt.scatter(op_x, op_y, marker='*', color='r')
        _plt.title(
            f"{self.parameters['power_circle_type'].capitalize()} Power Circle"
        )
        _plt.xlabel("Active Power")
        _plt.ylabel("Reactive Power")
        _plt.grid()
        return _plt