def test_transformer_type(): Vhv = 24 # primary voltage in kV Vlv = 0.42 # secondary voltage kV Sn = 100 # nominal power in MVA Psc = 300 # short circuit power (copper losses) kW P0 = 100 # no load power (iron losses) kW V0 = 0.8 # no load voltage in % Vsc = 8 # short-circuit voltage in % obj = TransformerType(hv_nominal_voltage=Vhv, lv_nominal_voltage=Vlv, nominal_power=Sn, copper_losses=Psc, short_circuit_voltage=Vsc, iron_losses=P0, no_load_current=V0, gr_hv1=0.5, gx_hv1=0.5) Sbase = 100 z_series, zsh = obj.get_impedances() # Change the base to the system base power base_change = obj.rating / Sbase z_series *= base_change zsh *= base_change print(z_series, 'Ys ->', 1 / z_series) print(zsh, '-> y_sh ->', 1 / zsh)
def test_reverse_transformer(): # ------------------------------------------------------------------------------------------------------------------ # Revert the calcs # ------------------------------------------------------------------------------------------------------------------ Vf = 11 Vt = 132 G = 0 B = 0 R = 0 X = 0.115 Sn = 30 print() print('R', R) print('X', X) print('G', G) print('B', B) zsc = sqrt(R * R + 1 / (X * X)) Vsc = 100.0 * zsc Pcu = R * Sn * 1000.0 if abs(G) > 0.0 and abs(B) > 0.0: zl = 1.0 / complex(G, B) rfe = zl.real xm = zl.imag Pfe = 1000.0 * Sn / rfe k = 1 / (rfe * rfe) + 1 / (xm * xm) I0 = 100.0 * sqrt(k) else: Pfe = 1e-20 I0 = 1e-20 print('Vsc', Vsc) print('Pcu', Pcu) print('I0', I0) print('Pfe', Pfe) tpe2 = TransformerType(hv_nominal_voltage=Vf, lv_nominal_voltage=Vt, nominal_power=Sn, copper_losses=Pcu, iron_losses=Pfe, no_load_current=I0, short_circuit_voltage=Vsc, gr_hv1=0.5, gx_hv1=0.5) z2, zl2 = tpe2.get_impedances() # print(z2) # print(1/zl2) yl = 1 / zl2 print() print('R', z2.real) print('X', z2.imag) print('G', yl.real) print('B', yl.imag)
def get_transformer_catalogue(): path = os.path.dirname(os.path.abspath(__file__)) fname = os.path.join(path, '..', '..', 'data', 'transformers.csv') if os.path.exists(fname): df = pd.read_csv(fname) lst = list() for i, item in df.iterrows(): tpe = TransformerType( hv_nominal_voltage=item['HV (kV)'], lv_nominal_voltage=item['LV (kV)'], nominal_power=item['Rate (MVA)'], copper_losses=item['Copper losses (kW)'], iron_losses=item['No load losses (kW)'], no_load_current=item['No load current (%)'], short_circuit_voltage=item['V short circuit (%)'], gr_hv1=0.5, gx_hv1=0.5, name=item['Name']) lst.append(tpe) return lst else: return list()
def get_template(self): """ Fabricate template values from the branch values :return: TransformerType instance """ eps = 1e-20 Vf = self.transformer_obj.bus_from.Vnom # kV Vt = self.transformer_obj.bus_to.Vnom # kV Sn = self.sn_spinner.value() + eps # MVA Pcu = self.pcu_spinner.value() + eps # kW Pfe = self.pfe_spinner.value() + eps # kW I0 = self.I0_spinner.value() + eps # % Vsc = self.vsc_spinner.value() # % Pfe = eps if Pfe == 0.0 else Pfe I0 = eps if I0 == 0.0 else I0 tpe = TransformerType(hv_nominal_voltage=Vf, lv_nominal_voltage=Vt, nominal_power=Sn, copper_losses=Pcu, iron_losses=Pfe, no_load_current=I0, short_circuit_voltage=Vsc, gr_hv1=0.5, gx_hv1=0.5) return tpe
def test_transformer_type(): Vhv = 21 # primary voltage in kV Vlv = 0.42 # secondary voltage kV Sn = 0.25 # nominal power in MVA Pcu = 2.35 # short circuit power (copper losses) kW Pfe = 0.27 # no load power (iron losses) kW I0 = 1.0 # no load voltage in % Vsc = 4.6 # short-circuit voltage in % obj = TransformerType(hv_nominal_voltage=Vhv, lv_nominal_voltage=Vlv, nominal_power=Sn, copper_losses=Pcu, short_circuit_voltage=Vsc, iron_losses=Pfe, no_load_current=I0, gr_hv1=0.5, gx_hv1=0.5) Sbase = 100 z_series, y_shunt = obj.get_impedances(VH=Vhv, VL=Vlv, Sbase=Sbase) assert np.allclose(z_series, 3.76+18.01j, rtol=0.01) assert np.allclose(y_shunt, 2.6532597915358445e-06-2.456722029199863e-05j, rtol=0.01)
def test_basic(): """ Basic GridCal test, also useful for a basic tutorial. In this case the magnetizing branch of the transformers is neglected by inputting 1e-20 excitation current and iron core losses. The results are identical to ETAP's, which always uses this assumption in balanced load flow calculations. """ test_name = "test_basic" grid = MultiCircuit(name=test_name) S_base = 100 # MVA grid.Sbase = S_base grid.time_profile = None grid.logger = list() # Create buses POI = Bus( name="POI", vnom=100, #kV is_slack=True) grid.add_bus(POI) B_C3 = Bus(name="B_C3", vnom=10) #kV grid.add_bus(B_C3) B_MV_M32 = Bus(name="B_MV_M32", vnom=10) #kV grid.add_bus(B_MV_M32) B_LV_M32 = Bus(name="B_LV_M32", vnom=0.6) #kV grid.add_bus(B_LV_M32) # Create voltage controlled generators (or slack, a.k.a. swing) UT = Generator(name="Utility") UT.bus = POI grid.add_generator(POI, UT) # Create static generators (with fixed power factor) M32 = StaticGenerator( name="M32", P=4.2, # MW Q=0.0j) # MVAR M32.bus = B_LV_M32 grid.add_static_generator(B_LV_M32, M32) # Create transformer types s = 5 # MVA z = 8 # % xr = 40 SS = TransformerType( name="SS", hv_nominal_voltage=100, # kV lv_nominal_voltage=10, # kV nominal_power=s, copper_losses=complex_impedance(z, xr).real * s * 1000 / S_base, iron_losses=1e-20, no_load_current=1e-20, short_circuit_voltage=z) grid.add_transformer_type(SS) s = 5 # MVA z = 6 # % xr = 20 PM = TransformerType( name="PM", hv_nominal_voltage=10, # kV lv_nominal_voltage=0.6, # kV nominal_power=s, copper_losses=complex_impedance(z, xr).real * s * 1000 / S_base, iron_losses=1e-20, no_load_current=1e-20, short_circuit_voltage=z) grid.add_transformer_type(PM) # Create branches X_C3 = Branch(bus_from=POI, bus_to=B_C3, name="X_C3", branch_type=BranchType.Transformer, template=SS) grid.add_branch(X_C3) C_M32 = Branch(bus_from=B_C3, bus_to=B_MV_M32, name="C_M32", r=0.784, x=0.174) grid.add_branch(C_M32) X_M32 = Branch(bus_from=B_MV_M32, bus_to=B_LV_M32, name="X_M32", branch_type=BranchType.Transformer, template=PM) grid.add_branch(X_M32) # Apply templates (device types) grid.apply_all_branch_types() print("Buses:") for i, b in enumerate(grid.buses): print(f" - bus[{i}]: {b}") print() options = PowerFlowOptions(SolverType.LM, verbose=True, initialize_with_existing_solution=True, multi_core=True, control_q=ReactivePowerControlMode.Direct, tolerance=1e-6, max_iter=99) power_flow = PowerFlow(grid, options) power_flow.run() approx_volt = [round(100 * abs(v), 1) for v in power_flow.results.voltage] solution = [ 100.0, 99.6, 102.7, 102.9 ] # Expected solution from GridCal and ETAP 16.1.0, for reference print() print(f"Test: {test_name}") print(f"Results: {approx_volt}") print(f"Solution: {solution}") print() print("Generators:") for g in grid.get_generators(): print(f" - Generator {g}: q_min={g.Qmin}pu, q_max={g.Qmax}pu") print() print("Branches:") for b in grid.branches: print(f" - {b}:") print(f" R = {round(b.R, 4)} pu") print(f" X = {round(b.X, 4)} pu") print(f" X/R = {round(b.X/b.R, 1)}") print(f" G = {round(b.G, 4)} pu") print(f" B = {round(b.B, 4)} pu") print() print("Transformer types:") for t in grid.transformer_types: print( f" - {t}: Copper losses={int(t.Pcu)}kW, Iron losses={int(t.Pfe)}kW, SC voltage={t.Vsc}%" ) print() print("Losses:") for i in range(len(grid.branches)): print( f" - {grid.branches[i]}: losses={1000*round(power_flow.results.losses[i], 3)} kVA" ) print() equal = True for i in range(len(approx_volt)): if approx_volt[i] != solution[i]: equal = False assert equal
def test_xfo_static_tap_1(): """ Basic test with the main transformer's HV tap (X_C3) set at +5% (1.05 pu), which lowers the LV by the same amount (-5%). """ test_name = "test_xfo_static_tap_1" grid = MultiCircuit(name=test_name) grid.Sbase = Sbase grid.time_profile = None grid.logger = Logger() # Create buses POI = Bus( name="POI", vnom=100, #kV is_slack=True) grid.add_bus(POI) B_C3 = Bus(name="B_C3", vnom=10) #kV grid.add_bus(B_C3) B_MV_M32 = Bus(name="B_MV_M32", vnom=10) #kV grid.add_bus(B_MV_M32) B_LV_M32 = Bus(name="B_LV_M32", vnom=0.6) #kV grid.add_bus(B_LV_M32) # Create voltage controlled generators (or slack, a.k.a. swing) UT = Generator(name="Utility") UT.bus = POI grid.add_generator(POI, UT) # Create static generators (with fixed power factor) M32 = StaticGenerator(name="M32", P=4.2, Q=0.0) # MVA (complex) M32.bus = B_LV_M32 grid.add_static_generator(B_LV_M32, M32) # Create transformer types s = 5 # MVA z = 8 # % xr = 40 SS = TransformerType( name="SS", hv_nominal_voltage=100, # kV lv_nominal_voltage=10, # kV nominal_power=s, copper_losses=complex_impedance(z, xr).real * s * 1000 / Sbase, iron_losses=6.25, # kW no_load_current=0.5, # % short_circuit_voltage=z) grid.add_transformer_type(SS) s = 5 # MVA z = 6 # % xr = 20 PM = TransformerType( name="PM", hv_nominal_voltage=10, # kV lv_nominal_voltage=0.6, # kV nominal_power=s, copper_losses=complex_impedance(z, xr).real * s * 1000 / Sbase, iron_losses=6.25, # kW no_load_current=0.5, # % short_circuit_voltage=z) grid.add_transformer_type(PM) # Create branches X_C3 = Branch(bus_from=POI, bus_to=B_C3, name="X_C3", branch_type=BranchType.Transformer, template=SS, tap=1.05) grid.add_branch(X_C3) C_M32 = Branch(bus_from=B_C3, bus_to=B_MV_M32, name="C_M32", r=0.784, x=0.174) grid.add_branch(C_M32) X_M32 = Branch(bus_from=B_MV_M32, bus_to=B_LV_M32, name="X_M32", branch_type=BranchType.Transformer, template=PM) grid.add_branch(X_M32) # Apply templates (device types) grid.apply_all_branch_types() print("Buses:") for i, b in enumerate(grid.buses): print(f" - bus[{i}]: {b}") print() options = PowerFlowOptions(SolverType.NR, verbose=True, initialize_with_existing_solution=True, multi_core=True, control_q=ReactivePowerControlMode.Direct, tolerance=1e-6, max_iter=99) power_flow = PowerFlowDriver(grid, options) power_flow.run() approx_volt = [round(100 * abs(v), 1) for v in power_flow.results.voltage] solution = [100.0, 94.7, 98.0, 98.1] # Expected solution from GridCal print() print(f"Test: {test_name}") print(f"Results: {approx_volt}") print(f"Solution: {solution}") print() print("Generators:") for g in grid.get_generators(): print(f" - Generator {g}: q_min={g.Qmin} MVAR, q_max={g.Qmax} MVAR") print() print("Branches:") for b in grid.branches: print(f" - {b}:") print(f" R = {round(b.R, 4)} pu") print(f" X = {round(b.X, 4)} pu") print(f" X/R = {round(b.X/b.R, 1)}") print(f" G = {round(b.G, 4)} pu") print(f" B = {round(b.B, 4)} pu") print() print("Transformer types:") for t in grid.transformer_types: print( f" - {t}: Copper losses={int(t.Pcu)}kW, Iron losses={int(t.Pfe)}kW, SC voltage={t.Vsc}%" ) print() print("Losses:") for i in range(len(grid.branches)): print( f" - {grid.branches[i]}: losses={1000*round(power_flow.results.losses[i], 3)} kVA" ) print() equal = True for i in range(len(approx_volt)): if approx_volt[i] != solution[i]: equal = False assert equal
def test_xfo_static_tap_3(): """ Basic test with the main transformer's HV tap (X_C3) set at -2.5% (0.975 pu), which raises the LV by the same amount (+2.5%). """ test_name = "test_xfo_static_tap_3" grid = MultiCircuit(name=test_name) grid.Sbase = Sbase grid.time_profile = None grid.logger = Logger() # Create buses POI = Bus( name="POI", vnom=100, # kV is_slack=True) grid.add_bus(POI) B_C3 = Bus(name="B_C3", vnom=10) # kV grid.add_bus(B_C3) B_MV_M32 = Bus(name="B_MV_M32", vnom=10) # kV grid.add_bus(B_MV_M32) B_LV_M32 = Bus(name="B_LV_M32", vnom=0.6) # kV grid.add_bus(B_LV_M32) # Create voltage controlled generators (or slack, a.k.a. swing) UT = Generator(name="Utility") UT.bus = POI grid.add_generator(POI, UT) # Create static generators (with fixed power factor) M32 = StaticGenerator(name="M32", P=4.2, Q=0.0) # MVA (complex) M32.bus = B_LV_M32 grid.add_static_generator(B_LV_M32, M32) # Create transformer types s = 5 # MVA z = 8 # % xr = 40 SS = TransformerType( name="SS", hv_nominal_voltage=100, # kV lv_nominal_voltage=10, # kV nominal_power=s, copper_losses=complex_impedance(z, xr).real * s * 1000 / Sbase, iron_losses=6.25, # kW no_load_current=0.5, # % short_circuit_voltage=z) grid.add_transformer_type(SS) s = 5 # MVA z = 6 # % xr = 20 PM = TransformerType( name="PM", hv_nominal_voltage=10, # kV lv_nominal_voltage=0.6, # kV nominal_power=s, copper_losses=complex_impedance(z, xr).real * s * 1000 / Sbase, iron_losses=6.25, # kW no_load_current=0.5, # % short_circuit_voltage=z) grid.add_transformer_type(PM) # Create branches X_C3 = Branch(bus_from=POI, bus_to=B_C3, name="X_C3", branch_type=BranchType.Transformer, template=SS, tap=0.975) # update to a more precise tap changer X_C3.apply_tap_changer( TapChanger(taps_up=20, taps_down=20, max_reg=1.1, min_reg=0.9)) grid.add_branch(X_C3) C_M32 = Branch(bus_from=B_C3, bus_to=B_MV_M32, name="C_M32", r=0.784, x=0.174) grid.add_branch(C_M32) X_M32 = Branch(bus_from=B_MV_M32, bus_to=B_LV_M32, name="X_M32", branch_type=BranchType.Transformer, template=PM) grid.add_branch(X_M32) # Apply templates (device types) grid.apply_all_branch_types() print("Buses:") for i, b in enumerate(grid.buses): print(f" - bus[{i}]: {b}") print() options = PowerFlowOptions(SolverType.NR, verbose=True, initialize_with_existing_solution=True, multi_core=True, control_q=ReactivePowerControlMode.Direct, tolerance=1e-6, max_iter=15) power_flow = PowerFlowDriver(grid, options) power_flow.run() print() print(f"Test: {test_name}") print() print("Generators:") for g in grid.get_generators(): print(f" - Generator {g}: q_min={g.Qmin} MVAR, q_max={g.Qmax} MVAR") print() print("Branches:") for b in grid.branches: print(f" - {b}:") print(f" R = {round(b.R, 4)} pu") print(f" X = {round(b.X, 4)} pu") print(f" X/R = {round(b.X/b.R, 1)}") print(f" G = {round(b.G, 4)} pu") print(f" B = {round(b.B, 4)} pu") print() print("Transformer types:") for t in grid.transformer_types: print(f" - {t}: Copper losses={int(t.Pcu)}kW, " f"Iron losses={int(t.Pfe)}kW, SC voltage={t.Vsc}%") print() print("Losses:") for i in range(len(grid.branches)): print( f" - {grid.branches[i]}: losses={1000*round(power_flow.results.losses[i], 3)} kVA" ) print() equal = False for i, branch in enumerate(grid.branches): if branch.name == "X_C3": equal = power_flow.results.tap_module[i] == branch.tap_module if not equal: grid.export_pf(f"{test_name}_results.xlsx", power_flow.results) grid.save_excel(f"{test_name}_grid.xlsx") assert equal
def test_gridcal_regulator(): """ GridCal test for the new implementation of transformer voltage regulators. """ test_name = "test_gridcal_regulator" grid = MultiCircuit(name=test_name) grid.Sbase = 100.0 # MVA grid.time_profile = None grid.logger = Logger() # Create buses POI = Bus( name="POI", vnom=100, # kV is_slack=True) grid.add_bus(POI) B_C3 = Bus(name="B_C3", vnom=10) # kV grid.add_bus(B_C3) B_MV_M32 = Bus(name="B_MV_M32", vnom=10) # kV grid.add_bus(B_MV_M32) B_LV_M32 = Bus(name="B_LV_M32", vnom=0.6) # kV grid.add_bus(B_LV_M32) # Create voltage controlled generators (or slack, a.k.a. swing) UT = Generator(name="Utility") UT.bus = POI grid.add_generator(POI, UT) # Create static generators (with fixed power factor) M32 = StaticGenerator(name="M32", P=4.2, Q=0.0) # MVA (complex) M32.bus = B_LV_M32 grid.add_static_generator(B_LV_M32, M32) # Create transformer types s = 100 # MVA z = 8 # % xr = 40 SS = TransformerType( name="SS", hv_nominal_voltage=100, # kV lv_nominal_voltage=10, # kV nominal_power=s, # MVA copper_losses=complex_impedance(z, xr).real * s * 1000.0 / grid.Sbase, # kW iron_losses=125, # kW no_load_current=0.5, # % short_circuit_voltage=z) # % grid.add_transformer_type(SS) s = 5 # MVA z = 6 # % xr = 20 PM = TransformerType( name="PM", hv_nominal_voltage=10, # kV lv_nominal_voltage=0.6, # kV nominal_power=s, # MVA copper_losses=complex_impedance(z, xr).real * s * 1000.0 / grid.Sbase, # kW iron_losses=6.25, # kW no_load_current=0.5, # % short_circuit_voltage=z) # % grid.add_transformer_type(PM) # Create branches X_C3 = Branch(bus_from=POI, bus_to=B_C3, name="X_C3", branch_type=BranchType.Transformer, template=SS, bus_to_regulated=True, vset=1.05) X_C3.tap_changer = TapChanger(taps_up=16, taps_down=16, max_reg=1.1, min_reg=0.9) X_C3.tap_changer.set_tap(X_C3.tap_module) grid.add_branch(X_C3) C_M32 = Branch(bus_from=B_C3, bus_to=B_MV_M32, name="C_M32", r=7.84, x=1.74) grid.add_branch(C_M32) X_M32 = Branch(bus_from=B_MV_M32, bus_to=B_LV_M32, name="X_M32", branch_type=BranchType.Transformer, template=PM) grid.add_branch(X_M32) # Apply templates (device types) grid.apply_all_branch_types() print("Buses:") for i, b in enumerate(grid.buses): print(f" - bus[{i}]: {b}") print() options = PowerFlowOptions(SolverType.NR, verbose=True, initialize_with_existing_solution=True, multi_core=True, control_q=ReactivePowerControlMode.Direct, control_taps=TapsControlMode.Direct, tolerance=1e-6, max_iter=99) power_flow = PowerFlowDriver(grid, options) power_flow.run() approx_volt = [round(100 * abs(v), 1) for v in power_flow.results.voltage] solution = [100.0, 105.2, 130.0, 130.1] # Expected solution from GridCal print() print(f"Test: {test_name}") print(f"Results: {approx_volt}") print(f"Solution: {solution}") print() print("Generators:") for g in grid.get_generators(): print(f" - Generator {g}: q_min={g.Qmin}pu, q_max={g.Qmax}pu") print() print("Branches:") branches = grid.get_branches() for b in grid.transformers2w: print( f" - {b}: R={round(b.R, 4)}pu, X={round(b.X, 4)}pu, X/R={round(b.X/b.R, 1)}, vset={b.vset}" ) print() print("Transformer types:") for t in grid.transformer_types: print( f" - {t}: Copper losses={int(t.Pcu)}kW, Iron losses={int(t.Pfe)}kW, SC voltage={t.Vsc}%" ) print() print("Losses:") for i in range(len(branches)): print( f" - {branches[i]}: losses={round(power_flow.results.losses[i], 3)} MVA" ) print() tr_vset = [tr.vset for tr in grid.transformers2w] print(f"Voltage settings: {tr_vset}") equal = np.isclose(approx_volt, solution, atol=1e-3).all() assert equal
def test_pv_3(): """ Voltage controlled generator test, also useful for a basic tutorial. In this case the generator M32 regulates the voltage at a setpoint of 1.025 pu, and the slack bus (POI) regulates it at 1.0 pu. The transformers' magnetizing branch losses are considered, as well as the main power transformer's voltage regulator (X_C3) which regulates bus B_MV_M32 at 1.005 pu. In addition, the iterative PV control method is used instead of the usual (faster) method. """ test_name = "test_pv_3" grid = MultiCircuit(name=test_name) Sbase = 100 # MVA grid.Sbase = Sbase grid.time_profile = None grid.logger = Logger() # Create buses POI = Bus( name="POI", vnom=100, # kV is_slack=True) grid.add_bus(POI) B_MV_M32 = Bus(name="B_MV_M32", vnom=10) # kV grid.add_bus(B_MV_M32) B_LV_M32 = Bus(name="B_LV_M32", vnom=0.6) # kV grid.add_bus(B_LV_M32) # Create voltage controlled generators (or slack, a.k.a. swing) UT = Generator(name="Utility") UT.bus = POI grid.add_generator(POI, UT) M32 = Generator(name="M32", active_power=4.2, voltage_module=1.025, Qmin=-2.5, Qmax=2.5) M32.bus = B_LV_M32 grid.add_generator(B_LV_M32, M32) # Create transformer types s = 100 # MVA z = 8 # % xr = 40 SS = TransformerType( name="SS", hv_nominal_voltage=100, # kV lv_nominal_voltage=10, # kV nominal_power=s, copper_losses=complex_impedance(z, xr).real * s * 1000 / Sbase, iron_losses=125, # kW no_load_current=0.5, # % short_circuit_voltage=z) grid.add_transformer_type(SS) s = 5 # MVA z = 6 # % xr = 20 PM = TransformerType( name="PM", hv_nominal_voltage=10, # kV lv_nominal_voltage=0.6, # kV nominal_power=s, copper_losses=complex_impedance(z, xr).real * s * 1000 / Sbase, iron_losses=6.25, # kW no_load_current=0.5, # % short_circuit_voltage=z) grid.add_transformer_type(PM) # Create branches X_C3 = Branch(bus_from=POI, bus_to=B_MV_M32, name="X_C3", branch_type=BranchType.Transformer, template=SS, bus_to_regulated=True, vset=1.005) X_C3.tap_changer = TapChanger(taps_up=16, taps_down=16, max_reg=1.1, min_reg=0.9) X_C3.tap_changer.set_tap(X_C3.tap_module) grid.add_branch(X_C3) X_M32 = Branch(bus_from=B_MV_M32, bus_to=B_LV_M32, name="X_M32", branch_type=BranchType.Transformer, template=PM) grid.add_branch(X_M32) # Apply templates (device types) grid.apply_all_branch_types() print("Buses:") for i, b in enumerate(grid.buses): print(f" - bus[{i}]: {b}") print() options = PowerFlowOptions(SolverType.LM, verbose=True, initialize_with_existing_solution=True, multi_core=True, control_q=ReactivePowerControlMode.Iterative, control_taps=TapsControlMode.Direct, tolerance=1e-6, max_iter=99) power_flow = PowerFlowDriver(grid, options) power_flow.run() approx_volt = [round(100 * abs(v), 1) for v in power_flow.results.voltage] solution = [100.0, 100.7, 102.5] # Expected solution from GridCal print() print(f"Test: {test_name}") print(f"Results: {approx_volt}") print(f"Solution: {solution}") print() print("Generators:") for g in grid.get_generators(): print(f" - Generator {g}: q_min={g.Qmin} MVAR, q_max={g.Qmax} MVAR") print() print("Branches:") for b in grid.branches: print(f" - {b}:") print(f" R = {round(b.R, 4)} pu") print(f" X = {round(b.X, 4)} pu") print(f" X/R = {round(b.X / b.R, 1)}") print(f" G = {round(b.G, 4)} pu") print(f" B = {round(b.B, 4)} pu") print() print("Transformer types:") for t in grid.transformer_types: print( f" - {t}: Copper losses={int(t.Pcu)}kW, Iron losses={int(t.Pfe)}kW, SC voltage={t.Vsc}%" ) print() print("Losses:") for i in range(len(grid.branches)): print( f" - {grid.branches[i]}: losses={1000 * round(power_flow.results.losses[i], 3)} kVA" ) print() equal = True for i in range(len(approx_volt)): if approx_volt[i] != solution[i]: equal = False assert equal
def test_transformer_definition(): Vf = 20.0 # kV Vt = 0.4 # kV Sn = 0.5 # MVA Vsc_ = 6.0 # % Pcu_ = 6.0 # kW # Pfe_ = 1.4 # kW # I0_ = 0.28 # % Pfe_ = 0.0 # kW I0_ = 0.0 # % tpe = TransformerType(hv_nominal_voltage=Vf, lv_nominal_voltage=Vt, nominal_power=Sn, copper_losses=Pcu_, iron_losses=Pfe_, no_load_current=I0_, short_circuit_voltage=Vsc_, gr_hv1=0.5, gx_hv1=0.5) z, zl = tpe.get_impedances() print(z) print(zl) # ------------------------------------------------------------------------------------------------------------------ # Revert the calcs # ------------------------------------------------------------------------------------------------------------------ if zl.real > 0 and zl.imag > 0: yl = 1.0 / zl G = yl.real B = yl.imag else: G = 0 B = 0 R = z.real X = z.imag Sn = Sn print() print('R', R) print('X', X) print('G', G) print('B', B) zsc = sqrt(R * R + 1 / (X * X)) Vsc = 100.0 * zsc Pcu = R * Sn * 1000.0 if abs(G) > 0.0 and abs(B) > 0.0: zl = 1.0 / complex(G, B) rfe = zl.real xm = zl.imag Pfe = 1000.0 * Sn / rfe k = 1 / (rfe * rfe) + 1 / (xm * xm) I0 = 100.0 * sqrt(k) else: Pfe = 1e20 I0 = 1e20 print('Vsc', Vsc, Vsc_) print('Pcu', Pcu, Pcu_) print('I0', I0, I0_) print('Pfe', Pfe, Pfe_) tpe2 = TransformerType(hv_nominal_voltage=Vf, lv_nominal_voltage=Vt, nominal_power=Sn, copper_losses=Pcu, iron_losses=Pfe, no_load_current=I0, short_circuit_voltage=Vsc, gr_hv1=0.5, gx_hv1=0.5) z2, zl2 = tpe2.get_impedances() print(z2) print(zl2)