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()
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))
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))
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)
def test_0(): c = Circle((0, 0), 1) assert c.area() == cmath.pi c = Circle((0, 0), 2) assert c.area() == cmath.pi * 4
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)
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
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
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
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