diff --git a/tests/test_carsons.py b/tests/test_carsons.py index b359da7..3f10448 100644 --- a/tests/test_carsons.py +++ b/tests/test_carsons.py @@ -11,11 +11,16 @@ # conversion allows us to enter in impedance as ohm-per-mile in the test # harness, which means we can lift matrices directly out of the ieee test # network. -OHM_PER_MILE_TO_OHM_PER_METER = 1 / 1609.344 +OHM_PER_MILE_TO_OHM_PER_METER = 1 / 1_609.344 +OHM_PER_KILOMETER_TO_OHM_PER_METER = 1 / 1_000 class ACBN_geometry_line(): """ IEEE 13 Configuration 601 Line Geometry """ + + def __init__(self, **kwargs): + self.frequency = kwargs.get('ƒ', 60) + @property def resistance(self): return { @@ -56,6 +61,9 @@ def phases(self): class CBN_geometry_line(): """ IEEE 13 Configuration 603 Line Geometry """ + def __init__(self, **kwargs): + self.frequency = kwargs.get('ƒ', 60) + @property def resistance(self): return { @@ -92,6 +100,9 @@ def phases(self): class CN_geometry_line(): """ IEEE 13 Configuration 605 Line Geometry""" + def __init__(self, **kwargs): + self.frequency = kwargs.get('ƒ', 60) + @property def resistance(self): return { @@ -160,7 +171,7 @@ def phases(self): ] -def ACBN_line_geometry_phase_impedance(): +def ACBN_line_phase_impedance(): """ IEEE 13 Configuration 601 Impedance Solution """ return OHM_PER_MILE_TO_OHM_PER_METER * array([ [0.3465 + 1.0179j, 0.1560 + 0.5017j, 0.1580 + 0.4236j], @@ -168,6 +179,14 @@ def ACBN_line_geometry_phase_impedance(): [0.1580 + 0.4236j, 0.1535 + 0.3849j, 0.3414 + 1.0348j]]) +def ACBN_line_phase_impedance_50Hz(): + """ IEEE 13 Configuration 601 Impedance Solution in ohms per km """ + return OHM_PER_KILOMETER_TO_OHM_PER_METER * array([ + [0.2101 + 0.5372j, 0.09171 + 0.2691j, 0.09295 + 0.2289j], + [0.09171 + 0.2691j, 0.20460 + 0.552j, 0.09021 + 0.2085j], + [0.09295 + 0.2289j, 0.09021 + 0.2085j, 0.207 + 0.5456j]]) + + def ACBN_line_z_primitive(): return array([ [1.74792626e-04+0.00085989j, @@ -209,22 +228,38 @@ def ABCN_balanced_z_primitive(): ]) -def CBN_line_geometry_phase_impedance(): - """ IEEE 13 Configuration 603 Impedance Solution """ +def CBN_line_phase_impedance(): + """ IEEE 13 Configuration 603 Impedance At 60Hz """ return OHM_PER_MILE_TO_OHM_PER_METER * array([ [0.0000 + 0.0000j, 0.0000 + 0.0000j, 0.0000 + 0.0000j], [0.0000 + 0.0000j, 1.3294 + 1.3471j, 0.2066 + 0.4591j], [0.0000 + 0.0000j, 0.2066 + 0.4591j, 1.3238 + 1.3569j]]) -def CN_line_geometry_phase_impedance(): - """ IEEE 13 Configuration 605 Impedance Solution """ +def CBN_line_phase_impedance_50Hz(): + """ IEEE 13 Configuration 603 Impedance At 50Hz """ + return OHM_PER_KILOMETER_TO_OHM_PER_METER * array([ + [0.0000 + 0.0000j, 0.0000 + 0.0000j, 0.0000 + 0.0000j], + [0.0000 + 0.0000j, 0.8128 + 0.7144j, 0.1153 + 0.2543j], + [0.0000 + 0.0000j, 0.1153 + 0.2543j, 0.8097 + 0.7189j]]) + + +def CN_line_phase_impedance(): + """ IEEE 13 Configuration 605 Impedance At 60Hz """ return OHM_PER_MILE_TO_OHM_PER_METER * array([ [0.0000 + 0.0000j, 0.0000 + 0.0000j, 0.0000 + 0.0000j], [0.0000 + 0.0000j, 0.0000 + 0.0000j, 0.0000 + 0.0000j], [0.0000 + 0.0000j, 0.0000 + 0.0000j, 1.3292 + 1.3475j]]) +def CN_line_phase_impedance_50Hz(): + """ IEEE 13 Configuration 605 Impedance Solution At 50Hz """ + return OHM_PER_KILOMETER_TO_OHM_PER_METER * array([ + [0.0000 + 0.0000j, 0.0000 + 0.0000j, 0.0000 + 0.0000j], + [0.0000 + 0.0000j, 0.0000 + 0.0000j, 0.0000 + 0.0000j], + [0.0000 + 0.0000j, 0.0000 + 0.0000j, 0.8127 + 0.7146j]]) + + def CN_line_z_primitive(): return array([ [0.0+0.j, 0.0+0.j, 0.0+0.j, 0.0+0.j], @@ -271,12 +306,16 @@ def expected_z_abc_three_neutrals(): @pytest.mark.parametrize( - "line,expected_impedance", - [(ACBN_geometry_line(), ACBN_line_geometry_phase_impedance()), - (CBN_geometry_line(), CBN_line_geometry_phase_impedance()), - (CN_geometry_line(), CN_line_geometry_phase_impedance())]) -def test_converts_geometry_to_phase_impedance(line, expected_impedance): - actual_impedance = convert_geometric_model(line) + "line,frequency,expected_impedance", + [(ACBN_geometry_line, 60, ACBN_line_phase_impedance()), + (CBN_geometry_line, 60, CBN_line_phase_impedance()), + (CN_geometry_line, 60, CN_line_phase_impedance()), + (ACBN_geometry_line, 50, ACBN_line_phase_impedance_50Hz()), + (CBN_geometry_line, 50, CBN_line_phase_impedance_50Hz()), + (CN_geometry_line, 50, CN_line_phase_impedance_50Hz())]) +def test_converts_geometry_to_phase_impedance( + line, frequency, expected_impedance): + actual_impedance = convert_geometric_model(line(ƒ=frequency)) assert_array_almost_equal(expected_impedance, actual_impedance) diff --git a/tests/test_configurable_frequency.py b/tests/test_configurable_frequency.py deleted file mode 100644 index 0d401e3..0000000 --- a/tests/test_configurable_frequency.py +++ /dev/null @@ -1,61 +0,0 @@ -from itertools import combinations_with_replacement -from math import sqrt -import numpy -from numpy.testing import assert_array_almost_equal -import pytest - -from carsons.carsons import CarsonsEquations -from tests.helpers import LineModel - - -def test_impedances_with_50hz_frequency(): - line_model = LineModel({ - # resistance gmr (x, y) - # ========================================== - "A": (0.000115575, 0.00947938, (0.762, 8.5344)), - "B": (0.000115575, 0.00947938, (0.0, 8.5344)), - "C": (0.000115575, 0.00947938, (2.1336, 8.5344)), - "N": (0.000367852, 0.00248107, (1.2192, 7.3152)), - }) - model = CarsonsEquations(line_model) - - z_primitive_60hz = model.build_z_primitive() - line_model.frequency = 50 - z_primitive_50hz = CarsonsEquations(line_model).build_z_primitive() - - # this test rests on the assumption that the real parts of the off-diagonal - # elements in z_primitive are proportional to frequency: - # where i ≠ j, R == μω / π Pᵢⱼ - # - # This holds for P approximated to just one term; additional terms - # incorporate kᵢⱼ, and kᵢⱼ ∝ √ω - - antidiagonal_mask = 1 - numpy.identity(4) - - assert_array_almost_equal( - z_primitive_50hz.real * antidiagonal_mask, - z_primitive_60hz.real * antidiagonal_mask * 50/60 - ) - - -@pytest.mark.parametrize('i, j', combinations_with_replacement("ABCN", 2)) -def test_k_for_50_vs_60hz_models(i, j): - line_model = LineModel({ - # resistance gmr (x, y) - # ========================================== - "A": (0.000115575, 0.00947938, (0.762, 8.5344)), - "B": (0.000115575, 0.00947938, (0.0, 8.5344)), - "C": (0.000115575, 0.00947938, (2.1336, 8.5344)), - "N": (0.000367852, 0.00248107, (1.2192, 7.3152)), - }) - model_60hz = CarsonsEquations(line_model) - - line_model.frequency = 50 - model_50hz = CarsonsEquations(line_model) - - # k is proportional to √ω - expected_ratio = sqrt(50) / sqrt(60) - k_50hz = model_50hz.compute_k(i, j) - k_60hz = model_60hz.compute_k(i, j) - - assert k_50hz == pytest.approx(k_60hz * expected_ratio)