33# covers detailed check of API states, etc.
44import sys , os , itertools , threading
55from time import perf_counter
6+ from math import sqrt , pi
67try :
78 from ._settings import BASE_DIR , ZIP_FN , WIN32
89except ImportError :
1718else :
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
2122import numpy as np
2223import 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
3436def 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+
623735def test_patch_comtypes ():
624736 if WIN32 :
625737 import comtypes .client
@@ -634,5 +746,6 @@ def test_patch_win32com():
634746 test_essentials (DSS_COM )
635747
636748if __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