Skip to content

Commit a950a7d

Browse files
committed
Adds missing ActiveCircuit.CktElements[index] (or ...CktElements(index)) and ActiveCircuit.Buses[index] (or ...Buses(index)).
1 parent 9696fea commit a950a7d

File tree

9 files changed

+136
-18
lines changed

9 files changed

+136
-18
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Python bindings and misc tools for using OpenDSS (EPRI Distribution System Simul
66

77
If you are looking for the C API library, see [`dss_capi`](http://github.com/PMeira/dss_capi/).
88

9-
Version 0.9.4, based on [OpenDSS revision 2152](https://sourceforge.net/p/electricdss/code/2152/tree/).
9+
Version 0.9.5, based on [OpenDSS revision 2152](https://sourceforge.net/p/electricdss/code/2152/tree/).
1010
This is a work-in-progress but it's deemed stable enough to be made public.
1111
*Note that, while the interface with OpenDSS is stable (classic version), the OpenDSS-PM (actor-based parallel machine version) interface was integrated recently and is experimental.*
1212

@@ -17,8 +17,9 @@ This module depends on CFFI, NumPy and, optionally, SciPy.Sparse for reading the
1717

1818
Recent changes
1919
==============
20+
- 2018-04-05 / version 0.9.5: Adds missing `ActiveCircuit.CktElements[index]` (or `...CktElements(index)`) and `ActiveCircuit.Buses[index]` (or `...Buses(index)`).
2021
- 2018-03-07 / version 0.9.4: Allows using `len` on several classes, fixes DSSProperty, and includes COM helpstrings as docstrings. Contains changes up to OpenDSS revision 2152.
21-
- 2018-02-16 / version 0.9.3: Integrate COM interface fixes from revision 2136 (`First` `Next` iteration on some elements)
22+
- 2018-02-16 / version 0.9.3: Integrates COM interface fixes from revision 2136 (`First` `Next` iteration on some elements)
2223
- 2018-02-12 / version 0.9.2: Experimental support for OpenDSS-PM (at the moment, a custom patch is provided for FreePascal support) and port COM interface fixes (OpenDSS revision 2134)
2324
- 2018-02-08 / version 0.9.1: First public release (OpenDSS revision 2123)
2425

README.pdf

-32 Bytes
Binary file not shown.

cffi/dss_capi_cffi.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ void Circuit_EndOfTimeStepUpdate(void);
145145
void Circuit_Get_YNodeOrder(char*** ResultPtr, int32_t* ResultCount);
146146
void Circuit_Get_YCurrents(double** ResultPtr, int32_t* ResultCount);
147147
void Circuit_Get_YNodeVarray(double** ResultPtr, int32_t* ResultCount);
148+
void Circuit_SetCktElementIndex(int32_t Value);
149+
void Circuit_SetCktElementName(char* Value);
148150
void CktElement_Get_BusNames(char*** ResultPtr, int32_t* ResultCount);
149151
char* CktElement_Get_Name(void);
150152
int32_t CktElement_Get_NumConductors(void);
@@ -1034,4 +1036,4 @@ uint16_t YMatrix_Get_UseAuxCurrents(void);
10341036
void decompress_complex_csc_matrix(int32_t nrows, int32_t ncols, int32_t *col_ptrs, int32_t *col_indices, double* complex_vals, double* complex_output);
10351037
void dss_custom_update_loads(int *idx, double *kw, size_t count);
10361038
void dss_custom_enable_loads(int *idx, int enabled, size_t count);
1037-
void dss_custom_line_currents(double *line_norm_amps, int *line_nodes, double* Ia, double* Ib, double* Ic, double* In);
1039+
void dss_custom_line_currents(double *line_norm_amps, int *line_nodes, double* Ia, double* Ib, double* Ic, double* In);

cffi/dsspm_capi_cffi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ void Circuit_EndOfTimeStepUpdate(void);
145145
void Circuit_Get_YNodeOrder(char*** ResultPtr, int32_t* ResultCount);
146146
void Circuit_Get_YCurrents(double** ResultPtr, int32_t* ResultCount);
147147
void Circuit_Get_YNodeVarray(double** ResultPtr, int32_t* ResultCount);
148+
void Circuit_SetCktElementIndex(int32_t Value);
149+
void Circuit_SetCktElementName(char* Value);
148150
void CktElement_Get_BusNames(char*** ResultPtr, int32_t* ResultCount);
149151
char* CktElement_Get_Name(void);
150152
int32_t CktElement_Get_NumConductors(void);

dss/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
from .enums import *
88
from . import enums
99

10-
__version__ = '0.9.4'
10+
__version__ = '0.9.5'

dss/dss_capi.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,23 @@ def y(self):
251251
def y(self, Value):
252252
lib.Bus_Set_y(Value)
253253

254+
def __getitem__(self, index):
255+
if isinstance(index, int):
256+
# bus index is zero based, pass it directly
257+
lib.Circuit_SetActiveBusi(index)
258+
else:
259+
if type(index) is not bytes:
260+
index = index.encode(codec)
261+
262+
lib.Circuit_SetActiveBus(index)
263+
264+
return self
265+
266+
def __call__(self, index):
267+
return self.__getitem__(index)
268+
269+
270+
254271

255272
class ICapacitors(FrozenClass):
256273
_isfrozen = freeze
@@ -4959,6 +4976,23 @@ def Yprim(self):
49594976
'''(read-only) YPrim matrix, column order, complex numbers (paired)'''
49604977
return get_float64_array(lib.CktElement_Get_Yprim)
49614978

4979+
def __getitem__(self, index):
4980+
if isinstance(index, int):
4981+
# index is zero based, pass it directly
4982+
lib.Circuit_SetCktElementIndex(index)
4983+
else:
4984+
if type(index) is not bytes:
4985+
index = index.encode(codec)
4986+
4987+
lib.Circuit_SetCktElementName(index)
4988+
4989+
return self
4990+
4991+
def __call__(self, index):
4992+
return self.__getitem__(index)
4993+
4994+
4995+
49624996

49634997
class IDSSElement(FrozenClass):
49644998
_isfrozen = freeze

dss/pm/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@
77
from ..enums import *
88
from .. import enums
99

10-
__version__ = '0.9.4'
10+
__version__ = '0.9.5'

dss/pm/dsspm_capi.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,23 @@ def y(self):
251251
def y(self, Value):
252252
lib.Bus_Set_y(Value)
253253

254+
def __getitem__(self, index):
255+
if isinstance(index, int):
256+
# bus index is zero based, pass it directly
257+
lib.Circuit_SetActiveBusi(index)
258+
else:
259+
if type(index) is not bytes:
260+
index = index.encode(codec)
261+
262+
lib.Circuit_SetActiveBus(index)
263+
264+
return self
265+
266+
def __call__(self, index):
267+
return self.__getitem__(index)
268+
269+
270+
254271

255272
class ICapacitors(FrozenClass):
256273
_isfrozen = freeze
@@ -5045,6 +5062,23 @@ def Yprim(self):
50455062
'''(read-only) YPrim matrix, column order, complex numbers (paired)'''
50465063
return get_float64_array(lib.CktElement_Get_Yprim)
50475064

5065+
def __getitem__(self, index):
5066+
if isinstance(index, int):
5067+
# index is zero based, pass it directly
5068+
lib.Circuit_SetCktElementIndex(index)
5069+
else:
5070+
if type(index) is not bytes:
5071+
index = index.encode(codec)
5072+
5073+
lib.Circuit_SetCktElementName(index)
5074+
5075+
return self
5076+
5077+
def __call__(self, index):
5078+
return self.__getitem__(index)
5079+
5080+
5081+
50485082

50495083
class IDSSElement(FrozenClass):
50505084
_isfrozen = freeze

tests/validate.py

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,9 @@ def validate_CktElement(self):
151151
all_props = list(A.AllPropertyNames)
152152
for prop_name in all_props:
153153
is_equal = False
154-
if A.Properties(prop_name).val != B.Properties(prop_name).val:
155-
val_A = A.Properties(prop_name).val
156-
val_B = B.Properties(prop_name).val
154+
if A.Properties(prop_name).Val != B.Properties(prop_name).Val:
155+
val_A = A.Properties(prop_name).Val
156+
val_B = B.Properties(prop_name).Val
157157
# Try as floats
158158
try:
159159
val_A = float(val_A)
@@ -164,8 +164,8 @@ def validate_CktElement(self):
164164
val_B = 1
165165

166166
if val_A != val_B:
167-
val_A = A.Properties(prop_name).val
168-
val_B = B.Properties(prop_name).val
167+
val_A = A.Properties(prop_name).Val
168+
val_B = B.Properties(prop_name).Val
169169

170170
# Try as matrices of floats
171171
if val_A.startswith('[') and val_A.endswith(']'):
@@ -179,18 +179,29 @@ def validate_CktElement(self):
179179
break
180180

181181

182-
if not (is_equal or val_A == val_B or A.Properties(prop_name).val == B.Properties(prop_name).val):
183-
print('ERROR: CktElement.Properties({}).val'.format(prop_name), A.Properties(prop_name).val, B.Properties(prop_name).val)
182+
if not (is_equal or val_A == val_B or A.Properties(prop_name).Val == B.Properties(prop_name).Val):
183+
print('ERROR: CktElement.Properties({}).Val'.format(prop_name), A.Properties(prop_name).Val, B.Properties(prop_name).Val)
184184

185-
assert (A.Properties(prop_name).description == B.Properties(prop_name).description), ('Properties({}).description'.format(prop_name), A.Properties(prop_name).description, B.Properties(prop_name).description)
185+
assert (A.Properties(prop_name).Description == B.Properties(prop_name).Description), ('Properties({}).Description'.format(prop_name), A.Properties(prop_name).Description, B.Properties(prop_name).Description)
186186
assert (A.Properties(prop_name).name == B.Properties(prop_name).name), ('Properties({}).name'.format(prop_name), A.Properties(prop_name).name, B.Properties(prop_name).name)
187187

188-
assert (B.Properties(prop_name).val == B.Properties[prop_name].val)
189-
assert (B.Properties(prop_name).description == B.Properties[prop_name].description)
188+
assert (B.Properties(prop_name).Val == B.Properties[prop_name].Val)
189+
assert (B.Properties(prop_name).Description == B.Properties[prop_name].Description)
190190
assert (B.Properties(prop_name).name == B.Properties[prop_name].name)
191191

192192

193193
def validate_Buses(self):
194+
for idx in range(len(self.AllBusNames)):
195+
A = self.com.ActiveCircuit.Buses(idx)
196+
B = self.capi.ActiveCircuit.Buses(idx)
197+
assert A.Name == B.Name
198+
199+
for name in self.AllBusNames[-1]:
200+
A = self.com.ActiveCircuit.Buses(name)
201+
B = self.capi.ActiveCircuit.Buses(name)
202+
assert A.Name == B.Name
203+
204+
194205
A = self.com.ActiveCircuit.ActiveBus
195206
B = self.capi.ActiveCircuit.ActiveBus
196207
for name in self.AllBusNames[-1]:
@@ -693,6 +704,37 @@ def validate_Circuit(self):
693704
"YNodeVarray" : self.YNodeVarray,
694705
}
695706

707+
# Get all line names
708+
lines_names = []
709+
LA = self.com.ActiveCircuit.Lines
710+
nA = LA.First
711+
while nA != 0:
712+
lines_names.append(LA.Name)
713+
nA = LA.Next
714+
715+
# Test Circuit_SetCktElementName with line names
716+
for name in lines_names:
717+
A = self.capi.ActiveCircuit.CktElements('Line.' + name)
718+
B = self.com.ActiveCircuit.CktElements('Line.' + name)
719+
assert A.Name == B.Name
720+
721+
# Test Circuit_SetCktElementIndex
722+
for idx in range(len(self.AllBusNames[-1])):
723+
# Note: idx is not the bus index but it is a valid CktElement index
724+
A = self.capi.ActiveCircuit.CktElements(idx)
725+
B = self.com.ActiveCircuit.CktElements(idx)
726+
assert A.Name == B.Name
727+
728+
# Try to use an invalid index
729+
A = self.capi.ActiveCircuit.CktElements(999999)
730+
B = self.com.ActiveCircuit.CktElements(999999)
731+
assert A.Name == B.Name
732+
733+
# Try to use an invalid name
734+
A = self.capi.ActiveCircuit.CktElements('NONEXISTENT_123456789')
735+
B = self.com.ActiveCircuit.CktElements('NONEXISTENT_123456789')
736+
assert A.Name == B.Name
737+
696738
for k, v in all_fields.items():
697739
if type(v[1]) == np.ndarray:
698740
print(k, max(abs(v[1] - v[0])))
@@ -755,6 +797,7 @@ def run_tests(fns):
755797

756798
import win32com.client
757799
com = win32com.client.Dispatch("OpenDSSEngine.DSS")
800+
#com = win32com.client.gencache.EnsureDispatch("OpenDSSEngine.DSS")
758801

759802
#import comtypes.client
760803
#com = comtypes.client.CreateObject("OpenDSSEngine.DSS")
@@ -783,12 +826,11 @@ def run_tests(fns):
783826

784827
if __name__ == '__main__':
785828
fns = [
786-
829+
"../../electricdss/Distrib/IEEETestCases/IEEE 30 Bus/Master.dss",
787830
"../../electricdss/Distrib/EPRITestCircuits/ckt5/Master_ckt5.dss",
788831
"../../electricdss/Distrib/EPRITestCircuits/ckt7/Master_ckt7.dss",
789832
"../../electricdss/Distrib/EPRITestCircuits/ckt24/Master_ckt24.dss",
790833
"../../electricdss/Distrib/IEEETestCases/8500-Node/Master-unbal.dss",
791-
"../../electricdss/Distrib/IEEETestCases/IEEE 30 Bus/Master.dss",
792834
"../../electricdss/Distrib/IEEETestCases/NEVTestCase/NEVMASTER.DSS",
793835
"../../electricdss/Distrib/IEEETestCases/37Bus/ieee37.dss",
794836
"../../electricdss/Distrib/IEEETestCases/4Bus-DY-Bal/4Bus-DY-Bal.DSS",
@@ -840,4 +882,7 @@ def run_tests(fns):
840882

841883
]
842884

843-
run_tests(fns)
885+
from time import time
886+
t0_global = time()
887+
run_tests(fns)
888+
print(time() - t0_global, 'seconds')

0 commit comments

Comments
 (0)