Skip to content

Commit 6869d13

Browse files
committed
Tweak AdvancedTypes: use per instance variable to toggle complex
This may allow mixing old and new code more easily. We can tweak it more if there's user feedback or issues.
1 parent abbc0e2 commit 6869d13

File tree

2 files changed

+19
-24
lines changed

2 files changed

+19
-24
lines changed

dss/IDSS.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ def NewContext(self) -> Self:
324324
lib = self._api_util.lib_unpatched
325325
new_ctx = ffi.gc(lib.ctx_New(), lib.ctx_Dispose)
326326
new_api_util = CffiApiUtil(ffi, lib, new_ctx)
327+
new_api_util._allow_complex = self._api_util._allow_complex
327328
return IDSS(new_api_util)
328329

329330
def __call__(self, single:Union[AnyStr, List[AnyStr]]=None, block : AnyStr = None): #TODO: benchmark and simplify (single argument)
@@ -388,10 +389,10 @@ def Plotting(self):
388389
@property
389390
def AdvancedTypes(self) -> bool:
390391
'''
391-
When enabled, there are **two global side-effects**:
392+
When enabled, there are **two side-effects**:
392393
393-
- Complex arrays and complex numbers can be returned and consumed by the Python API.
394-
- The low-level API provides matrix dimensions when available (`EnableArrayDimensions` is enabled).
394+
- **Per DSS Context:** Complex arrays and complex numbers can be returned and consumed by the Python API.
395+
- **Global effect:** The low-level API provides matrix dimensions when available (`EnableArrayDimensions` is enabled).
395396
396397
As a result, for example, `DSS.ActiveCircuit.ActiveCktElement.Yprim` is returned as a complex matrix instead
397398
of a plain array.
@@ -404,16 +405,13 @@ def AdvancedTypes(self) -> bool:
404405
'''
405406

406407
arr_dim = self.CheckForError(self._lib.DSS_Get_EnableArrayDimensions()) != 0
407-
allow_complex = CffiApiUtil._ADV_TYPES
408-
if arr_dim != allow_complex:
409-
raise RuntimeError('Invalid state detected.')
410-
411-
return arr_dim
408+
allow_complex = self._api_util._allow_complex
409+
return arr_dim and allow_complex
412410

413411
@AdvancedTypes.setter
414412
def AdvancedTypes(self, Value: bool):
415413
self.CheckForError(self._lib.DSS_Set_EnableArrayDimensions(Value))
416-
CffiApiUtil._ADV_TYPES = bool(Value)
414+
self._api_util._allow_complex = bool(Value)
417415

418416
@property
419417
def CompatFlags(self) -> int:

dss/_cffi_api_util.py

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,6 @@ def _decode_and_free_string(self, s) -> str:
186186

187187

188188
class CffiApiUtil(object):
189-
_ADV_TYPES = False # class variable, changed globally
190-
191189
def __init__(self, ffi, lib, ctx=None):
192190
self.owns_ctx = True
193191
self.codec = codec
@@ -199,10 +197,9 @@ def __init__(self, ffi, lib, ctx=None):
199197
else:
200198
self.lib = CtxLib(ctx, lib)
201199

200+
self._allow_complex = False
202201
self.init_buffers()
203202

204-
# Just in case the user has set the env var DSS_CAPI_ARRAY_DIMS=1
205-
CffiApiUtil._ADV_TYPES = self.lib.DSS_Get_EnableArrayDimensions()
206203

207204

208205
# def __delete__(self):
@@ -252,7 +249,7 @@ def get_float64_array(self, func, *args) -> Float64Array:
252249
res = np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 8), dtype=np.float64).copy()
253250
self.lib.DSS_Dispose_PDouble(ptr)
254251

255-
if self._ADV_TYPES and cnt[3]:
252+
if self._allow_complex and cnt[3]:
256253
# If the last element is filled, we have a matrix. Otherwise, the
257254
# matrix feature is disabled or the result is indeed a vector
258255
return res.reshape((cnt[2], cnt[3]), order='F')
@@ -261,7 +258,7 @@ def get_float64_array(self, func, *args) -> Float64Array:
261258

262259

263260
def get_complex128_array(self, func, *args) -> Float64ArrayOrComplexArray:
264-
if not self._ADV_TYPES:
261+
if not self._allow_complex:
265262
return self.get_float64_array(func, *args)
266263

267264
# Currently we use the same as API as get_float64_array, may change later
@@ -280,7 +277,7 @@ def get_complex128_array(self, func, *args) -> Float64ArrayOrComplexArray:
280277

281278

282279
def get_complex128_simple(self, func, *args) -> Float64ArrayOrSimpleComplex:
283-
if not self._ADV_TYPES:
280+
if not self._allow_complex:
284281
return self.get_float64_array(func, *args)
285282

286283
# Currently we use the same as API as get_float64_array, may change later
@@ -296,26 +293,26 @@ def get_complex128_simple(self, func, *args) -> Float64ArrayOrSimpleComplex:
296293

297294
def get_float64_gr_array(self) -> Float64Array:
298295
ptr, cnt = self.gr_float64_pointers
299-
if self._ADV_TYPES and cnt[3]:
296+
if self._allow_complex and cnt[3]:
300297
return np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 8), dtype=np.float64).copy().reshape((cnt[2], cnt[3]), order='F')
301298

302299
return np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 8), dtype=np.float64).copy()
303300

304301

305302
def get_complex128_gr_array(self) -> ComplexArray:
306-
if not self._ADV_TYPES:
303+
if not self._allow_complex:
307304
return self.get_float64_gr_array()
308305

309306
# Currently we use the same as API as get_float64_array, may change later
310307
ptr, cnt = self.gr_float64_pointers
311-
if self._ADV_TYPES and cnt[3]:
308+
if self._allow_complex and cnt[3]:
312309
return np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 8), dtype=complex).copy().reshape((cnt[2], cnt[3]), order='F')
313310

314311
return np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 8), dtype=complex).copy()
315312

316313

317314
def get_complex128_gr_simple(self) -> Float64ArrayOrSimpleComplex:
318-
if not self._ADV_TYPES:
315+
if not self._allow_complex:
319316
return self.get_float64_gr_array()
320317

321318
# Currently we use the same as API as get_float64_array, may change later
@@ -331,7 +328,7 @@ def get_int32_array(self, func: Callable, *args) -> Int32Array:
331328
res = np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 4), dtype=np.int32).copy()
332329
self.lib.DSS_Dispose_PInteger(ptr)
333330

334-
if self._ADV_TYPES and cnt[3]:
331+
if self._allow_complex and cnt[3]:
335332
# If the last element is filled, we have a matrix. Otherwise, the
336333
# matrix feature is disabled or the result is indeed a vector
337334
return res.reshape((cnt[2], cnt[3]))
@@ -349,7 +346,7 @@ def get_ptr_array(self, func: Callable, *args):
349346

350347
def get_int32_gr_array(self) -> Int32Array:
351348
ptr, cnt = self.gr_int32_pointers
352-
if self._ADV_TYPES and cnt[3]:
349+
if self._allow_complex and cnt[3]:
353350
return np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 4), dtype=np.int32).copy().reshape((cnt[2], cnt[3]))
354351

355352
return np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 4), dtype=np.int32).copy()
@@ -362,7 +359,7 @@ def get_int8_array(self, func: Callable, *args: Any) -> Int8Array:
362359
res = np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 1), dtype=np.int8).copy()
363360
self.lib.DSS_Dispose_PByte(ptr)
364361

365-
if self._ADV_TYPES and cnt[3]:
362+
if self._allow_complex and cnt[3]:
366363
# If the last element is filled, we have a matrix. Otherwise, the
367364
# matrix feature is disabled or the result is indeed a vector
368365
return res.reshape((cnt[2], cnt[3]))
@@ -371,7 +368,7 @@ def get_int8_array(self, func: Callable, *args: Any) -> Int8Array:
371368

372369
def get_int8_gr_array(self) -> Int8Array:
373370
ptr, cnt = self.gr_int8_pointers
374-
if self._ADV_TYPES and cnt[3]:
371+
if self._allow_complex and cnt[3]:
375372
return np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 1), dtype=np.int8).copy().reshape((cnt[2], cnt[3]), order='F')
376373

377374
return np.frombuffer(self.ffi.buffer(ptr[0], cnt[0] * 1), dtype=np.int8).copy()

0 commit comments

Comments
 (0)