Skip to content

Commit c7351f1

Browse files
committed
Tests: add a few reactor and capacitor checks, and cross-validation files.
1 parent edbe6aa commit c7351f1

File tree

2 files changed

+118
-3
lines changed

2 files changed

+118
-3
lines changed

tests/_settings.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#"L!Distrib/IEEETestCases/4wire-Delta/Kersting4wireIndMotor.dss",
2626

2727
test_filenames = '''
28+
Test/CapacitorConfigs.dss
29+
Test/ReactorConfigs.dss
2830
L!Version8/Distrib/Examples/Dynamic_Expressions/Dynamic_KundurDynExp.dss
2931
L!Test/AutoTrans/Auto1bus.dss
3032
L!Test/AutoTrans/Auto3bus.dss

tests/test_general.py

Lines changed: 116 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# covers detailed check of API states, etc.
44
import sys, os, itertools, threading
55
from time import perf_counter
6+
from math import sqrt, pi
67
try:
78
from ._settings import BASE_DIR, ZIP_FN, WIN32
89
except ImportError:
@@ -17,7 +18,7 @@
1718
else:
1819
import dss
1920

20-
from dss import DSS, IDSS, DSSException, SparseSolverOptions, SolveModes, set_case_insensitive_attributes, DSSCompatFlags
21+
from dss import DSS, IDSS, DSSException, SparseSolverOptions, SolveModes, set_case_insensitive_attributes, DSSCompatFlags, LoadModels
2122
import numpy as np
2223
import pytest
2324

@@ -30,6 +31,7 @@ def setup_function():
3031
DSS.COMErrorResults = True # TODO: change to False
3132
DSS.CompatFlags = 0
3233
DSS.Error.UseExceptions = True
34+
DSS.Text.Command = 'set DefaultBaseFreq=60'
3335

3436
def test_zip_redirect():
3537
with pytest.raises(DSSException):
@@ -620,6 +622,116 @@ def test_exception_control(DSS: IDSS = DSS):
620622
assert DSS.Error.Number == 0
621623

622624

625+
def debug_print(s):
626+
# print(s)
627+
pass
628+
629+
def test_capacitor_reactor(DSS: IDSS = DSS):
630+
from itertools import product
631+
kVA = 1329.53
632+
kV = 2.222
633+
DSS.AdvancedTypes = True
634+
635+
for component, f in product(('Capacitor', 'Reactor'), (50, 60)):
636+
bus = 1
637+
sign = 1 if component[0] == 'C' else -1
638+
DSS.Text.Command = 'clear'
639+
debug_print('clear')
640+
DSS.Text.Command = f'set DefaultBaseFreq={f}'
641+
debug_print(DSS.Text.Command)
642+
DSS.Text.Command = f'new circuit.test{f} bus1={bus}'
643+
debug_print(DSS.Text.Command)
644+
for conn in ('delta', 'wye'):
645+
for phases0 in (1, 2, 3):
646+
phases = phases0
647+
if conn == 'wye':
648+
V_eff_ln = kV * 1000
649+
if phases == 1:
650+
kV_eff = kV
651+
else:
652+
kV_eff = kV * sqrt(3)
653+
else:
654+
V_eff_ll = kV * sqrt(3) * 1000
655+
kV_eff = kV * sqrt(3)
656+
657+
DSS.Text.Command = f'new Line.{bus}-{bus + 1} bus1={bus} bus2={bus + 1}'
658+
debug_print(DSS.Text.Command)
659+
bus += 1
660+
DSS.Text.Command = f'new {component}.{conn}_{phases} bus1={bus} phases={phases} conn={conn} kva={kVA} kV={kV_eff}'
661+
debug_print(DSS.Text.Command)
662+
DSS.Text.Command = 'solve'
663+
# debug_print(DSS.Text.Command)
664+
assert DSS.ActiveCircuit.ActiveCktElement.Name == f'{component}.{conn}_{phases}'
665+
Y_dss = DSS.ActiveCircuit.ActiveCktElement.Yprim
666+
667+
DSS.Text.Command = f'new {component}.{conn}_{phases}_alt bus1={bus} phases=1 conn={conn} phases={phases} kva={kVA} kV={kV_eff}'
668+
# debug_print(DSS.Text.Command)
669+
DSS.Text.Command = 'solve'
670+
# debug_print(DSS.Text.Command)
671+
assert DSS.ActiveCircuit.ActiveCktElement.Name == f'{component}.{conn}_{phases}_alt'
672+
Y_dss2 = DSS.ActiveCircuit.ActiveCktElement.Yprim
673+
674+
np.testing.assert_allclose(Y_dss, Y_dss2)
675+
676+
if conn == 'wye':
677+
VA_branch = 1000 * kVA / phases
678+
y = sign * 1j * VA_branch / (V_eff_ln**2)
679+
Y_py = np.zeros(shape=(phases * 2, phases * 2), dtype=complex)
680+
for ph1 in range(phases):
681+
ph2 = ph1 + phases
682+
Y_py[ph1, ph1] += y
683+
Y_py[ph2, ph2] += y
684+
Y_py[ph2, ph1] += -y
685+
Y_py[ph1, ph2] += -y
686+
687+
np.testing.assert_allclose(Y_py, Y_dss)
688+
elif conn == 'delta':
689+
VA_branch = 1000 * kVA / phases
690+
y = sign * 1j * VA_branch / (V_eff_ll**2)
691+
if phases0 == 1:
692+
branches = [(0, 1)]
693+
phases = 2
694+
elif phases0 == 2:
695+
branches = [(0, 1), (1, 2)]
696+
phases = 3
697+
elif phases0 == 3:
698+
branches = [(0, 1), (1, 2), (2, 0)]
699+
phases = 3
700+
701+
Y_py = np.zeros(shape=(phases, phases), dtype=complex)
702+
for ph1, ph2 in branches:
703+
Y_py[ph1, ph1] += y
704+
Y_py[ph2, ph2] += y
705+
Y_py[ph2, ph1] += -y
706+
Y_py[ph1, ph2] += -y
707+
708+
np.testing.assert_allclose(Y_py, Y_dss)
709+
710+
phases = phases0
711+
model = int(LoadModels.ConstZ)
712+
DSS.Text.Command = f'new Line.{bus}-{bus + 1} bus1={bus} bus2={bus + 1}'
713+
debug_print(DSS.Text.Command)
714+
bus += 1
715+
DSS.Text.Command = f'new Load.{conn}_{phases} bus1={bus} phases={phases} conn={conn} kw=0 kvar={-sign * kVA} kV={kV_eff} model={model} Xneut=0 Rneut=0'
716+
debug_print(DSS.Text.Command)
717+
DSS.Text.Command = 'solve'
718+
# debug_print(DSS.Text.Command)
719+
assert DSS.ActiveCircuit.ActiveCktElement.Name == f'Load.{conn}_{phases}'
720+
Y_load = DSS.ActiveCircuit.ActiveCktElement.Yprim
721+
Y_load -= Y_load.real
722+
if conn == 'wye':
723+
n = Y_load.shape[0] # wye load is 1 terminal
724+
Y_py2 = np.copy(Y_py[:n, :n])
725+
Y_py2[:, n - 1] += np.sum(Y_py[:n, n:], axis=1)
726+
Y_py2[n - 1, :] += np.sum(Y_py[n:, :n], axis=0)
727+
Y_py2[n - 1, n - 1] += np.sum(np.diag(Y_py)[n:])
728+
Y_py = Y_py2
729+
else:
730+
n = Y_load.shape[0]
731+
732+
np.testing.assert_allclose(Y_py[:n, :n], Y_load[:n, :n], atol=1e-6)
733+
734+
623735
def test_patch_comtypes():
624736
if WIN32:
625737
import comtypes.client
@@ -634,5 +746,6 @@ def test_patch_win32com():
634746
test_essentials(DSS_COM)
635747

636748
if __name__ == '__main__':
637-
for _ in range(250):
638-
test_pm_threads()
749+
# for _ in range(250):
750+
# test_pm_threads()
751+
test_capacitor_reactor()

0 commit comments

Comments
 (0)