pyedb 0.53.0__py3-none-any.whl → 0.55.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pyedb might be problematic. Click here for more details.

Files changed (119) hide show
  1. pyedb/__init__.py +1 -8
  2. pyedb/configuration/cfg_boundaries.py +69 -151
  3. pyedb/configuration/cfg_components.py +201 -460
  4. pyedb/configuration/cfg_data.py +4 -2
  5. pyedb/configuration/cfg_general.py +13 -36
  6. pyedb/configuration/cfg_modeler.py +2 -1
  7. pyedb/configuration/cfg_nets.py +21 -35
  8. pyedb/configuration/cfg_operations.py +22 -151
  9. pyedb/configuration/cfg_package_definition.py +56 -112
  10. pyedb/configuration/cfg_padstacks.py +292 -688
  11. pyedb/configuration/cfg_pin_groups.py +32 -79
  12. pyedb/configuration/cfg_ports_sources.py +20 -9
  13. pyedb/configuration/cfg_s_parameter_models.py +67 -172
  14. pyedb/configuration/cfg_setup.py +102 -295
  15. pyedb/configuration/configuration.py +66 -6
  16. pyedb/dotnet/database/cell/connectable.py +38 -9
  17. pyedb/dotnet/database/cell/hierarchy/component.py +28 -28
  18. pyedb/dotnet/database/cell/hierarchy/model.py +1 -1
  19. pyedb/dotnet/database/cell/layout.py +64 -3
  20. pyedb/dotnet/database/cell/layout_obj.py +3 -3
  21. pyedb/dotnet/database/cell/primitive/path.py +6 -8
  22. pyedb/dotnet/database/cell/primitive/primitive.py +10 -31
  23. pyedb/dotnet/database/cell/terminal/edge_terminal.py +2 -2
  24. pyedb/dotnet/database/cell/terminal/padstack_instance_terminal.py +1 -1
  25. pyedb/dotnet/database/cell/terminal/pingroup_terminal.py +1 -1
  26. pyedb/dotnet/database/cell/terminal/point_terminal.py +1 -1
  27. pyedb/dotnet/database/cell/terminal/terminal.py +26 -28
  28. pyedb/dotnet/database/cell/voltage_regulator.py +0 -21
  29. pyedb/dotnet/database/components.py +99 -91
  30. pyedb/dotnet/database/definition/component_def.py +4 -4
  31. pyedb/dotnet/database/definition/component_model.py +1 -1
  32. pyedb/dotnet/database/definition/package_def.py +2 -3
  33. pyedb/dotnet/database/dotnet/database.py +27 -218
  34. pyedb/dotnet/database/dotnet/primitive.py +16 -16
  35. pyedb/dotnet/database/edb_data/control_file.py +5 -5
  36. pyedb/dotnet/database/edb_data/hfss_extent_info.py +6 -6
  37. pyedb/dotnet/database/edb_data/layer_data.py +35 -35
  38. pyedb/dotnet/database/edb_data/padstacks_data.py +65 -90
  39. pyedb/dotnet/database/edb_data/primitives_data.py +5 -5
  40. pyedb/dotnet/database/edb_data/sources.py +6 -6
  41. pyedb/dotnet/database/edb_data/variables.py +8 -4
  42. pyedb/dotnet/database/geometry/point_data.py +14 -10
  43. pyedb/dotnet/database/geometry/polygon_data.py +3 -5
  44. pyedb/dotnet/database/hfss.py +50 -52
  45. pyedb/dotnet/database/layout_validation.py +14 -11
  46. pyedb/dotnet/database/materials.py +10 -11
  47. pyedb/dotnet/database/modeler.py +104 -101
  48. pyedb/dotnet/database/nets.py +20 -23
  49. pyedb/dotnet/database/padstack.py +156 -84
  50. pyedb/dotnet/database/sim_setup_data/data/settings.py +24 -0
  51. pyedb/dotnet/database/sim_setup_data/io/siwave.py +26 -1
  52. pyedb/dotnet/database/siwave.py +47 -47
  53. pyedb/dotnet/database/stackup.py +152 -87
  54. pyedb/dotnet/database/utilities/heatsink.py +4 -4
  55. pyedb/dotnet/database/utilities/obj_base.py +3 -3
  56. pyedb/dotnet/database/utilities/simulation_setup.py +2 -2
  57. pyedb/dotnet/database/utilities/value.py +116 -0
  58. pyedb/dotnet/edb.py +248 -170
  59. pyedb/edb_logger.py +12 -27
  60. pyedb/extensions/via_design_backend.py +6 -3
  61. pyedb/generic/design_types.py +68 -21
  62. pyedb/generic/general_methods.py +0 -120
  63. pyedb/generic/process.py +44 -108
  64. pyedb/generic/settings.py +75 -19
  65. pyedb/grpc/__init__.py +0 -0
  66. pyedb/grpc/database/components.py +55 -17
  67. pyedb/grpc/database/control_file.py +5 -5
  68. pyedb/grpc/database/definition/materials.py +24 -31
  69. pyedb/grpc/database/definition/package_def.py +18 -18
  70. pyedb/grpc/database/definition/padstack_def.py +104 -51
  71. pyedb/grpc/database/geometry/arc_data.py +7 -5
  72. pyedb/grpc/database/geometry/point_3d_data.py +8 -7
  73. pyedb/grpc/database/geometry/polygon_data.py +4 -3
  74. pyedb/grpc/database/hierarchy/component.py +43 -38
  75. pyedb/grpc/database/hierarchy/pin_pair_model.py +15 -14
  76. pyedb/grpc/database/hierarchy/pingroup.py +9 -9
  77. pyedb/grpc/database/layers/stackup_layer.py +45 -44
  78. pyedb/grpc/database/layout/layout.py +17 -13
  79. pyedb/grpc/database/layout/voltage_regulator.py +7 -7
  80. pyedb/grpc/database/layout_validation.py +16 -15
  81. pyedb/grpc/database/modeler.py +60 -58
  82. pyedb/grpc/database/net/net.py +15 -14
  83. pyedb/grpc/database/nets.py +112 -31
  84. pyedb/grpc/database/padstacks.py +303 -190
  85. pyedb/grpc/database/ports/ports.py +5 -6
  86. pyedb/grpc/database/primitive/bondwire.py +8 -7
  87. pyedb/grpc/database/primitive/circle.py +4 -4
  88. pyedb/grpc/database/primitive/padstack_instance.py +191 -23
  89. pyedb/grpc/database/primitive/path.py +7 -7
  90. pyedb/grpc/database/primitive/polygon.py +3 -3
  91. pyedb/grpc/database/primitive/primitive.py +13 -17
  92. pyedb/grpc/database/primitive/rectangle.py +13 -13
  93. pyedb/grpc/database/simulation_setup/hfss_general_settings.py +1 -1
  94. pyedb/grpc/database/simulation_setup/hfss_simulation_setup.py +10 -0
  95. pyedb/grpc/database/simulation_setup/siwave_simulation_setup.py +17 -1
  96. pyedb/grpc/database/siwave.py +31 -25
  97. pyedb/grpc/database/source_excitations.py +335 -233
  98. pyedb/grpc/database/stackup.py +165 -148
  99. pyedb/grpc/database/terminal/bundle_terminal.py +18 -8
  100. pyedb/grpc/database/terminal/edge_terminal.py +10 -0
  101. pyedb/grpc/database/terminal/padstack_instance_terminal.py +16 -5
  102. pyedb/grpc/database/terminal/pingroup_terminal.py +12 -11
  103. pyedb/grpc/database/terminal/point_terminal.py +4 -3
  104. pyedb/grpc/database/terminal/terminal.py +9 -9
  105. pyedb/grpc/database/utility/value.py +109 -0
  106. pyedb/grpc/database/utility/xml_control_file.py +5 -5
  107. pyedb/grpc/edb.py +130 -63
  108. pyedb/grpc/edb_init.py +3 -10
  109. pyedb/grpc/rpc_session.py +10 -10
  110. pyedb/libraries/common.py +366 -0
  111. pyedb/libraries/rf_libraries/base_functions.py +1358 -0
  112. pyedb/libraries/rf_libraries/planar_antennas.py +628 -0
  113. pyedb/misc/decorators.py +61 -0
  114. pyedb/misc/misc.py +0 -13
  115. pyedb/siwave.py +2 -2
  116. {pyedb-0.53.0.dist-info → pyedb-0.55.0.dist-info}/METADATA +2 -3
  117. {pyedb-0.53.0.dist-info → pyedb-0.55.0.dist-info}/RECORD +119 -112
  118. {pyedb-0.53.0.dist-info → pyedb-0.55.0.dist-info}/WHEEL +0 -0
  119. {pyedb-0.53.0.dist-info → pyedb-0.55.0.dist-info}/licenses/LICENSE +0 -0
pyedb/edb_logger.py CHANGED
@@ -29,8 +29,6 @@ import sys
29
29
  import tempfile
30
30
  import time
31
31
 
32
- from pyedb.generic.settings import settings
33
-
34
32
 
35
33
  class Msg:
36
34
  (INFO, WARNING, ERROR, FATAL) = range(4)
@@ -91,14 +89,17 @@ class EdbLogger(object):
91
89
  Whether to write log messages to stdout. The default is ``False``.
92
90
  """
93
91
 
94
- def __init__(self, level=logging.DEBUG, filename=None, to_stdout=False):
92
+ log_file = ""
93
+
94
+ def __init__(self, level=logging.DEBUG, filename=None, to_stdout=False, settings=None):
95
+ self.settings = settings
95
96
  self._std_out_handler = None
96
97
  self._files_handlers = []
97
98
  self.level = level
98
99
  self.filename = filename or settings.logger_file_path
99
100
  settings.logger_file_path = self.filename
100
101
 
101
- self._global = logging.getLogger("Global")
102
+ self._global = logging.getLogger("Edb")
102
103
  if not settings.enable_logger:
103
104
  self._global.addHandler(logging.NullHandler())
104
105
  return
@@ -123,6 +124,7 @@ class EdbLogger(object):
123
124
  encoding="utf-8",
124
125
  delay=0,
125
126
  )
127
+ self.log_file = log_file
126
128
  my_handler.setFormatter(self.formatter)
127
129
  my_handler.setLevel(self.level)
128
130
  if not global_handler and settings.global_log_file_name:
@@ -171,11 +173,11 @@ class EdbLogger(object):
171
173
 
172
174
  @property
173
175
  def _log_on_file(self):
174
- return settings.enable_file_logs
176
+ return self.settings.enable_file_logs
175
177
 
176
178
  @_log_on_file.setter
177
179
  def _log_on_file(self, val):
178
- settings.enable_file_logs = val
180
+ self.settings.enable_file_logs = val
179
181
 
180
182
  @property
181
183
  def logger(self):
@@ -334,7 +336,7 @@ class EdbLogger(object):
334
336
 
335
337
  def info(self, msg, *args, **kwargs):
336
338
  """Write an info message to the global logger."""
337
- if not settings.enable_logger:
339
+ if not self.settings.enable_logger:
338
340
  return
339
341
  if args:
340
342
  try:
@@ -348,7 +350,7 @@ class EdbLogger(object):
348
350
  def info_timer(self, msg, start_time=None, *args, **kwargs):
349
351
  """Write an info message to the global logger with elapsed time.
350
352
  Message will have an appendix of type Elapsed time: time."""
351
- if not settings.enable_logger:
353
+ if not self.settings.enable_logger:
352
354
  return
353
355
  if not start_time:
354
356
  start_time = self._timer
@@ -373,7 +375,7 @@ class EdbLogger(object):
373
375
 
374
376
  def warning(self, msg, *args, **kwargs):
375
377
  """Write a warning message to the global logger."""
376
- if not settings.enable_logger:
378
+ if not self.settings.enable_logger:
377
379
  return
378
380
  if args:
379
381
  try:
@@ -397,7 +399,7 @@ class EdbLogger(object):
397
399
 
398
400
  def debug(self, msg, *args, **kwargs):
399
401
  """Write a debug message to the global logger."""
400
- if not settings.enable_debug_logger or not settings.enable_logger:
402
+ if not self.settings.enable_debug_logger or not self.settings.enable_logger:
401
403
  return
402
404
  if args:
403
405
  try:
@@ -413,20 +415,3 @@ class EdbLogger(object):
413
415
  """Global logger."""
414
416
  self._global = logging.getLogger("Global")
415
417
  return self._global
416
-
417
-
418
- logger = logging.getLogger("Global")
419
- if any("aedt_logger" in str(i) for i in logger.filters):
420
- from ansys.aedt.core.generic.settings import settings as pyaedt_settings
421
-
422
- from pyedb.generic.settings import settings as pyaedb_settings
423
-
424
- pyedb_logger = pyaedt_settings.logger
425
- pyaedb_settings.use_pyaedt_log = True
426
- pyaedb_settings.logger = pyedb_logger
427
-
428
- else:
429
- pyedb_logger = EdbLogger(to_stdout=settings.enable_screen_logs)
430
- from pyedb.generic.settings import settings as pyaedb_settings
431
-
432
- pyaedb_settings.logger = pyedb_logger
@@ -663,7 +663,7 @@ class ViaDesignBackend:
663
663
  pitch = self.cfg["general"]["pitch"]
664
664
 
665
665
  board = Board(
666
- stackup=self.cfg["stackup"],
666
+ stackup=self.cfg["stackup"] if isinstance(self.cfg["stackup"], list) else self.cfg["stackup"]["layers"],
667
667
  padstack_defs=self.cfg["padstack_defs"],
668
668
  outline_extent=outline_extent,
669
669
  pitch=pitch,
@@ -673,9 +673,12 @@ class ViaDesignBackend:
673
673
  )
674
674
  board.populate_config(cfg_json)
675
675
 
676
+ self.output_dir.mkdir(parents=True, exist_ok=True)
677
+ with open(self.output_dir / "config.json", "w") as f:
678
+ json.dump(cfg_json, f, indent=4)
676
679
  self.app = Edb(
677
680
  edbpath=str((Path(self.output_dir) / self.cfg["title"]).with_suffix(".aedb")), edbversion=self.version
678
681
  )
679
682
  self.app.configuration.load(cfg_json, apply_file=True)
680
- self.app.save_edb()
681
- self.app.close_edb()
683
+ self.app.save()
684
+ self.app.close()
@@ -23,6 +23,8 @@ from typing import TYPE_CHECKING, Literal, Union, overload
23
23
  import warnings
24
24
 
25
25
  from pyedb.generic.grpc_warnings import GRPC_GENERAL_WARNING
26
+ from pyedb.generic.settings import settings
27
+ from pyedb.misc.decorators import deprecate_argument_name
26
28
 
27
29
  if TYPE_CHECKING:
28
30
  from pyedb.dotnet.edb import Edb as EdbDotnet
@@ -45,11 +47,12 @@ def Edb(*, grpc: bool, **kwargs) -> Union["EdbGrpc", "EdbDotnet"]:
45
47
 
46
48
 
47
49
  # lazy imports
50
+ @deprecate_argument_name({"edbversion": "version"})
48
51
  def Edb(
49
52
  edbpath=None,
50
53
  cellname=None,
51
54
  isreadonly=False,
52
- edbversion=None,
55
+ version=None,
53
56
  isaedtowned=False,
54
57
  oproject=None,
55
58
  student_version=False,
@@ -256,30 +259,74 @@ def Edb(
256
259
  >>> workflow.run()
257
260
 
258
261
  """
259
-
260
- # Use EDB legacy (default choice)
261
- if float(edbversion) >= 2025.2:
262
- if not grpc:
263
- warnings.warn(GRPC_GENERAL_WARNING, UserWarning)
262
+ settings.is_student_version = student_version
263
+ if grpc is False and settings.edb_dll_path is not None:
264
+ # Check if the user specified a .dll path
265
+ settings.logger.info(f"Force to use .dll from {settings.edb_dll_path} defined in settings.")
266
+ settings.specified_version = "unknown"
267
+ elif version is None:
268
+ if settings.specified_version is not None:
269
+ settings.logger.info(f"Use {settings.specified_version} defined in settings.")
270
+ # Use the latest version
271
+ elif student_version:
272
+ if settings.LATEST_STUDENT_VERSION is None:
273
+ raise RuntimeWarning("AEDT is not properly installed.")
274
+ else:
275
+ settings.specified_version = settings.LATEST_STUDENT_VERSION
276
+ else:
277
+ if settings.LATEST_VERSION is None:
278
+ raise RuntimeWarning("AEDT is not properly installed.")
279
+ else:
280
+ settings.specified_version = settings.LATEST_VERSION
264
281
  else:
265
- if grpc:
266
- raise ValueError(f"gRPC flag was enabled however your ANSYS AEDT version {edbversion} is not compatible")
282
+ # Version is specified
283
+ version = str(version)
284
+ if student_version:
285
+ if version not in settings.INSTALLED_STUDENT_VERSIONS:
286
+ raise RuntimeWarning(f"AEDT student version {version} is not properly installed.")
287
+ else:
288
+ settings.specified_version = version
289
+ else:
290
+ if version not in settings.INSTALLED_VERSIONS:
291
+ raise RuntimeWarning(f"AEDT version {version} is not properly installed.")
292
+ else:
293
+ settings.specified_version = version
294
+
267
295
  if grpc:
296
+ if float(settings.specified_version) < 2025.2:
297
+ raise ValueError(
298
+ f"gRPC flag was enabled however your ANSYS AEDT version {settings.specified_version} is not compatible"
299
+ )
300
+
268
301
  from pyedb.grpc.edb import Edb as app
302
+
303
+ return app(
304
+ edbpath=edbpath,
305
+ cellname=cellname,
306
+ isreadonly=isreadonly,
307
+ edbversion=version,
308
+ isaedtowned=isaedtowned,
309
+ oproject=oproject,
310
+ use_ppe=use_ppe,
311
+ technology_file=technology_file,
312
+ control_file=control_file,
313
+ )
269
314
  else:
270
- from pyedb.dotnet.edb import Edb as app
271
- return app(
272
- edbpath=edbpath,
273
- cellname=cellname,
274
- isreadonly=isreadonly,
275
- edbversion=edbversion,
276
- isaedtowned=isaedtowned,
277
- oproject=oproject,
278
- student_version=student_version,
279
- use_ppe=use_ppe,
280
- technology_file=technology_file,
281
- control_file=control_file,
282
- )
315
+ if float(settings.specified_version) >= 2025.2:
316
+ warnings.warn(GRPC_GENERAL_WARNING, UserWarning)
317
+
318
+ from pyedb.dotnet.edb import Edb
319
+
320
+ return Edb(
321
+ edbpath=edbpath,
322
+ cellname=cellname,
323
+ isreadonly=isreadonly,
324
+ isaedtowned=isaedtowned,
325
+ oproject=oproject,
326
+ use_ppe=use_ppe,
327
+ technology_file=technology_file,
328
+ control_file=control_file,
329
+ )
283
330
 
284
331
 
285
332
  def Siwave(
@@ -43,7 +43,6 @@ import tempfile
43
43
  import time
44
44
  import traceback
45
45
 
46
- from pyedb.exceptions import MaterialModelException
47
46
  from pyedb.generic.constants import CSS4_COLORS
48
47
  from pyedb.generic.settings import settings
49
48
 
@@ -141,82 +140,6 @@ def _exception(ex_info, func, args, kwargs, message="Type Error"):
141
140
  )
142
141
 
143
142
 
144
- def _function_handler_wrapper(user_function): # pragma: no cover
145
- def wrapper(*args, **kwargs): # pragma: no cover
146
- if not settings.enable_error_handler:
147
- result = user_function(*args, **kwargs)
148
- return result
149
- else:
150
- try:
151
- settings.time_tick = time.time()
152
- out = user_function(*args, **kwargs)
153
- if settings.enable_debug_logger or settings.enable_debug_edb_logger:
154
- _log_method(user_function, args, kwargs)
155
- return out
156
- except TypeError:
157
- _exception(sys.exc_info(), user_function, args, kwargs, "Type Error")
158
- return False
159
- except ValueError:
160
- _exception(sys.exc_info(), user_function, args, kwargs, "Value Error")
161
- return False
162
- except AttributeError:
163
- _exception(sys.exc_info(), user_function, args, kwargs, "Attribute Error")
164
- return False
165
- except KeyError:
166
- _exception(sys.exc_info(), user_function, args, kwargs, "Key Error")
167
- return False
168
- except IndexError:
169
- _exception(sys.exc_info(), user_function, args, kwargs, "Index Error")
170
- return False
171
- except AssertionError:
172
- _exception(sys.exc_info(), user_function, args, kwargs, "Assertion Error")
173
- return False
174
- except NameError:
175
- _exception(sys.exc_info(), user_function, args, kwargs, "Name Error")
176
- return False
177
- except IOError:
178
- _exception(sys.exc_info(), user_function, args, kwargs, "IO Error")
179
- return False
180
- except MaterialModelException:
181
- _exception(sys.exc_info(), user_function, args, kwargs, "Material Model")
182
- return False
183
-
184
- return wrapper
185
-
186
-
187
- import functools
188
- import warnings
189
-
190
-
191
- def deprecate_argument_name(argument_map):
192
- """Decorator to deprecate certain argument names in favor of new ones."""
193
-
194
- def decorator(func):
195
- """Decorator that wraps the function to handle deprecated arguments."""
196
-
197
- @functools.wraps(func)
198
- def wrapper(*args, **kwargs):
199
- """Wrapper function that checks for deprecated arguments."""
200
- func_name = func.__name__
201
- for old_arg, new_arg in argument_map.items():
202
- if old_arg in kwargs:
203
- warnings.warn(
204
- f"Argument `{old_arg}` is deprecated for method `{func_name}`; use `{new_arg}` instead.",
205
- DeprecationWarning,
206
- stacklevel=2,
207
- )
208
- # NOTE: Use old argument if new argument is not provided
209
- if new_arg not in kwargs:
210
- kwargs[new_arg] = kwargs.pop(old_arg)
211
- else:
212
- kwargs.pop(old_arg)
213
- return func(*args, **kwargs)
214
-
215
- return wrapper
216
-
217
- return decorator
218
-
219
-
220
143
  def get_filename_without_extension(path):
221
144
  """Get the filename without its extension.
222
145
 
@@ -242,49 +165,6 @@ def _write_mes(mes_text):
242
165
  settings.logger.error(el)
243
166
 
244
167
 
245
- def _log_method(func, new_args, new_kwargs): # pragma: no cover
246
- if not settings.enable_debug_internal_methods_logger and str(func.__name__)[0] == "_":
247
- return
248
- if not settings.enable_debug_geometry_operator_logger and "GeometryOperators" in str(func):
249
- return
250
- if (
251
- not settings.enable_debug_edb_logger
252
- and "Edb" in str(func) + str(new_args)
253
- or "database" in str(func) + str(new_args)
254
- ):
255
- return
256
- line_begin = "ARGUMENTS: "
257
- message = []
258
- delta = time.time() - settings.time_tick
259
- m, s = divmod(delta, 60)
260
- h, m = divmod(m, 60)
261
- d, h = divmod(h, 24)
262
- msec = (s - int(s)) * 1000
263
- if d > 0:
264
- time_msg = " {}days {}h {}m {}sec.".format(d, h, m, int(s))
265
- elif h > 0:
266
- time_msg = " {}h {}m {}sec.".format(h, m, int(s))
267
- else:
268
- time_msg = " {}m {}sec {}msec.".format(m, int(s), int(msec))
269
- if settings.enable_debug_methods_argument_logger:
270
- args_dict = _get_args_dicts(func, new_args, new_kwargs)
271
- id = 0
272
- if new_args:
273
- object_name = str([new_args[0]])[1:-1]
274
- id = object_name.find(" object at ")
275
- if id > 0:
276
- object_name = object_name[1:id]
277
- message.append("'{}' was run in {}".format(object_name + "." + str(func.__name__), time_msg))
278
- else:
279
- message.append("'{}' was run in {}".format(str(func.__name__), time_msg))
280
- message.append(line_begin)
281
- for k, v in args_dict.items():
282
- if k != "self":
283
- message.append(" {} = {}".format(k, v))
284
- for m in message:
285
- settings.logger.debug(m)
286
-
287
-
288
168
  def _get_args_dicts(func, args, kwargs):
289
169
  if int(sys.version[0]) > 2:
290
170
  args_name = list(OrderedDict.fromkeys(inspect.getfullargspec(func)[0] + list(kwargs.keys())))
pyedb/generic/process.py CHANGED
@@ -1,104 +1,51 @@
1
1
  import os.path
2
+ from pathlib import Path
2
3
  import subprocess
3
4
 
4
- from pyedb.generic.general_methods import env_path, is_linux, is_windows
5
+ from pyedb.generic.general_methods import is_linux
5
6
 
6
7
 
7
8
  class SiwaveSolve(object):
8
- def __init__(self, aedb_path="", aedt_version="2021.2", aedt_installer_path=None):
9
- self._project_path = aedb_path
10
- self._exec_path = ""
11
- self._nbcores = 4
12
- self._ng = True
13
- if aedt_installer_path:
14
- self.installer_path = aedt_installer_path
15
- else:
16
- try:
17
- self.installer_path = env_path(aedt_version)
18
- except:
19
- raise Exception("Either a valid aedt version or full path has to be provided")
20
- if self._ng:
21
- executable = "siwave_ng"
22
- else:
23
- executable = "siwave"
24
- if is_linux:
25
- self._exe = os.path.join(self.installer_path, executable)
26
- else:
27
- self._exe = os.path.join(self.installer_path, executable + ".exe")
9
+ def __init__(self, pedb):
10
+ self._pedb = pedb
28
11
 
29
12
  @property
30
- def siwave_exe(self):
31
- return self._exe
32
-
33
- @siwave_exe.setter
34
- def siwave_exe(self, value):
35
- self._exe = value
36
-
37
- @property
38
- def projectpath(self):
39
- return self._project_path
40
-
41
- @projectpath.setter
42
- def projectpath(self, value):
43
- self._project_path = value
13
+ def __siwave_exe_path(self):
14
+ executable = "siwave"
15
+ executable = executable if is_linux else executable + ".exe"
16
+ full_path = Path(self._pedb.ansys_em_path) / executable
17
+ return str(full_path)
44
18
 
45
19
  @property
46
- def execfile(self):
47
- return self._exec_path
48
-
49
- @execfile.setter
50
- def execfile(self, value):
51
- self._exec_path = value
52
-
53
- @property
54
- def nbcores(self):
55
- return self._nbcores
56
-
57
- @nbcores.setter
58
- def nbcores(self, value):
59
- self._nbcores = value
60
-
61
- @property
62
- def nongraphical(self):
63
- return self._ng
64
-
65
- @nongraphical.setter
66
- def nongraphical(self, value):
67
- self._ng = value
68
-
69
- def solve(self):
70
- # supporting non graphical solve only
71
- if self.nongraphical:
72
- if is_linux:
73
- exe_path = os.path.join(self.installer_path, "siwave_ng")
74
- else:
75
- exe_path = os.path.join(self.installer_path, "siwave_ng.exe")
76
- exec_file = os.path.splitext(self._project_path)[0] + ".exec"
77
- if os.path.exists(exec_file):
78
- with open(exec_file, "r+") as f:
79
- content = f.readlines()
80
- if "SetNumCpus" not in content:
81
- f.writelines(str.format("SetNumCpus {}", str(self.nbcores)) + "\n")
82
- f.writelines("SaveSiw")
83
- else:
84
- fstarts = [i for i in range(len(content)) if content[i].startswith("SetNumCpus")]
85
- content[fstarts[0]] = str.format("SetNumCpus {}", str(self.nbcores))
86
- f.close()
87
- os.remove(exec_file)
88
- f = open(exec_file, "w")
89
- f.writelines(content)
90
- command = [exe_path]
91
- command.append(self._project_path)
92
- command.append(exec_file)
93
- command.append("-formatOutput -useSubdir")
94
- if os.name == "posix":
95
- p = subprocess.Popen(command)
96
- else:
97
- p = subprocess.Popen(" ".join(command))
98
- p.wait()
20
+ def __siwave_ng_exe_path(self):
21
+ executable = "siwave_ng"
22
+ executable = executable if is_linux else executable + ".exe"
23
+ full_path = Path(self._pedb.ansys_em_path) / executable
24
+ return str(full_path)
25
+
26
+ def solve(self, num_of_cores=4):
27
+ exec_file = os.path.splitext(self._pedb.edbpath)[0] + ".exec"
28
+ if os.path.exists(exec_file):
29
+ with open(exec_file, "r+") as f:
30
+ content = f.readlines()
31
+ if "SetNumCpus" not in content:
32
+ f.writelines(str.format("SetNumCpus {}", str(num_of_cores)) + "\n")
33
+ f.writelines("SaveSiw")
34
+ else:
35
+ fstarts = [i for i in range(len(content)) if content[i].startswith("SetNumCpus")]
36
+ content[fstarts[0]] = str.format("SetNumCpus {}", str(num_of_cores))
37
+ f.close()
38
+ os.remove(exec_file)
39
+ f = open(exec_file, "w")
40
+ f.writelines(content)
41
+ command = [self.__siwave_ng_exe_path, self._pedb.edbpath, exec_file, "-formatOutput -useSubdir"]
42
+ command_ = command if os.name == "posix" else " ".join(command)
43
+ # p = subprocess.Popen(command_)
44
+ p = subprocess.Popen(command)
45
+ p.wait()
99
46
 
100
47
  def export_3d_cad(
101
- self, format_3d="Q3D", output_folder=None, net_list=None, num_cores=None, aedt_file_name=None, hidden=False
48
+ self, format_3d="Q3D", output_folder=None, net_list=None, num_cores=4, aedt_file_name=None, hidden=False
102
49
  ): # pragma: no cover
103
50
  """Export edb to Q3D or HFSS
104
51
 
@@ -119,11 +66,11 @@ class SiwaveSolve(object):
119
66
  path to aedt file
120
67
  """
121
68
  if not output_folder:
122
- output_folder = os.path.dirname(self.projectpath)
69
+ output_folder = os.path.dirname(self._pedb.edbpath)
123
70
  scriptname = os.path.join(output_folder, "export_cad.py")
124
71
  with open(scriptname, "w") as f:
125
72
  f.write("import os\n")
126
- f.write("edbpath = r'{}'\n".format(self.projectpath))
73
+ f.write("edbpath = r'{}'\n".format(self._pedb.edbpath))
127
74
  f.write("exportOptions = os.path.join(r'{}', 'options.config')\n".format(output_folder))
128
75
  f.write("oDoc.ScrImportEDB(edbpath)\n")
129
76
  f.write("oDoc.ScrSaveProjectAs(os.path.join(r'{}','{}'))\n".format(output_folder, "test.siw"))
@@ -140,14 +87,11 @@ class SiwaveSolve(object):
140
87
  f.write("q3d_filename = os.path.join(r'{}', '{}')\n".format(output_folder, aedt_file_name))
141
88
  if num_cores:
142
89
  f.write("oDoc.ScrSetNumCpusToUse('{}')\n".format(num_cores))
143
- self.nbcores = num_cores
144
90
  f.write("oDoc.ScrExport3DModel('{}', q3d_filename)\n".format(format_3d))
145
91
  f.write("oDoc.ScrCloseProject()\n")
146
92
  f.write("oApp.Quit()\n")
147
- _exe = os.path.join(self.installer_path, "siwave")
148
- if is_windows:
149
- _exe += ".exe"
150
- command = [_exe]
93
+
94
+ command = [self.__siwave_exe_path]
151
95
  if hidden:
152
96
  command.append("-embedding")
153
97
  command += ["-RunScriptAndExit", scriptname]
@@ -204,7 +148,7 @@ class SiwaveSolve(object):
204
148
  list of files generated.
205
149
  """
206
150
  if not output_folder:
207
- output_folder = os.path.dirname(self.projectpath)
151
+ output_folder = os.path.dirname(self._pedb.edbpath)
208
152
  output_list = []
209
153
  scriptname = os.path.normpath(os.path.join(os.path.normpath(output_folder), "export_results.py"))
210
154
  with open(scriptname, "w") as f:
@@ -265,20 +209,12 @@ class SiwaveSolve(object):
265
209
  f.write("proj.ScrCloseProject()\n")
266
210
 
267
211
  f.write("oApp.Quit()\n")
268
- if is_linux:
269
- _exe = '"' + os.path.join(self.installer_path, "siwave") + '"'
270
- else:
271
- _exe = '"' + os.path.join(self.installer_path, "siwave.exe") + '"'
272
- command = [_exe]
212
+ command = [self.__siwave_exe_path]
273
213
  if hidden:
274
214
  command.append("-embedding")
275
215
  command.append("-RunScriptAndExit")
276
- command.append('"' + scriptname + '"')
216
+ command.append(scriptname)
277
217
  print(command)
278
- if os.name == "posix":
279
- p = subprocess.Popen(command)
280
-
281
- else:
282
- p = subprocess.Popen(" ".join(command))
218
+ p = subprocess.Popen(command)
283
219
  p.wait()
284
220
  return output_list