pyedb 0.16.0__py3-none-any.whl → 0.17.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 (32) hide show
  1. pyedb/__init__.py +1 -1
  2. pyedb/configuration/cfg_components.py +47 -1
  3. pyedb/configuration/configuration.py +2 -0
  4. pyedb/dotnet/edb.py +43 -37
  5. pyedb/dotnet/edb_core/cell/hierarchy/component.py +12 -17
  6. pyedb/dotnet/edb_core/cell/hierarchy/hierarchy_obj.py +50 -0
  7. pyedb/dotnet/edb_core/cell/layout.py +0 -6
  8. pyedb/dotnet/edb_core/cell/voltage_regulator.py +0 -5
  9. pyedb/dotnet/edb_core/components.py +2 -2
  10. pyedb/dotnet/edb_core/dotnet/primitive.py +129 -3
  11. pyedb/dotnet/edb_core/edb_data/hfss_pi_simulation_setup_data.py +0 -460
  12. pyedb/dotnet/edb_core/edb_data/primitives_data.py +38 -38
  13. pyedb/dotnet/edb_core/edb_data/raptor_x_simulation_setup_data.py +1 -1
  14. pyedb/dotnet/edb_core/layout.py +21 -0
  15. pyedb/dotnet/edb_core/layout_validation.py +26 -0
  16. pyedb/dotnet/edb_core/nets.py +1 -1
  17. pyedb/dotnet/edb_core/sim_setup_data/data/sim_setup_info.py +1 -1
  18. pyedb/dotnet/edb_core/sim_setup_data/data/simulation_settings.py +357 -0
  19. pyedb/dotnet/edb_core/siwave.py +14 -0
  20. pyedb/dotnet/edb_core/utilities/hfss_simulation_setup.py +83 -0
  21. pyedb/dotnet/edb_core/utilities/simulation_setup.py +7 -4
  22. pyedb/misc/siw_feature_config/xtalk_scan/fd_xtalk_scan_config.py +91 -0
  23. pyedb/misc/siw_feature_config/xtalk_scan/impedance_scan_config.py +70 -0
  24. pyedb/misc/siw_feature_config/xtalk_scan/net.py +69 -0
  25. pyedb/misc/siw_feature_config/xtalk_scan/pins.py +60 -0
  26. pyedb/misc/siw_feature_config/xtalk_scan/scan_config.py +88 -0
  27. pyedb/misc/siw_feature_config/xtalk_scan/td_xtalk_config.py +104 -0
  28. pyedb/workflow.py +32 -0
  29. {pyedb-0.16.0.dist-info → pyedb-0.17.0.dist-info}/METADATA +1 -1
  30. {pyedb-0.16.0.dist-info → pyedb-0.17.0.dist-info}/RECORD +32 -24
  31. {pyedb-0.16.0.dist-info → pyedb-0.17.0.dist-info}/LICENSE +0 -0
  32. {pyedb-0.16.0.dist-info → pyedb-0.17.0.dist-info}/WHEEL +0 -0
@@ -558,6 +558,15 @@ class EDBPrimitives(Primitive):
558
558
  dist = GeometryOperators.points_distance(mid_point, point)
559
559
  return [out.X.ToDouble(), out.Y.ToDouble()]
560
560
 
561
+ @property
562
+ def voids(self):
563
+ """:obj:`list` of :class:`Primitive <ansys.edb.primitive.Primitive>`: List of void\
564
+ primitive objects inside the primitive.
565
+
566
+ Read-Only.
567
+ """
568
+ return [cast(void, self._app) for void in self.prim_obj.Voids]
569
+
561
570
  @property
562
571
  def arcs(self):
563
572
  """Get the Primitive Arc Data."""
@@ -896,6 +905,35 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
896
905
  return cloned_poly
897
906
  return False
898
907
 
908
+ @property
909
+ def has_self_intersections(self):
910
+ """Check if Polygon has self intersections.
911
+
912
+ Returns
913
+ -------
914
+ bool
915
+ """
916
+ return self.polygon_data.edb_api.HasSelfIntersections()
917
+
918
+ def fix_self_intersections(self):
919
+ """Remove self intersections if they exists.
920
+
921
+ Returns
922
+ -------
923
+ list
924
+ All new polygons created from the removal operation.
925
+ """
926
+ new_polys = []
927
+ if self.has_self_intersections:
928
+ new_polygons = list(self.polygon_data.edb_api.RemoveSelfIntersections())
929
+ self.polygon_data = new_polygons[0]
930
+ for p in new_polygons[1:]:
931
+ cloned_poly = self._app.edb_api.cell.primitive.polygon.create(
932
+ self._app.active_layout, self.layer_name, self.net, p
933
+ )
934
+ new_polys.append(cloned_poly)
935
+ return new_polys
936
+
899
937
  def duplicate_across_layers(self, layers):
900
938
  """Duplicate across layer a primitive object.
901
939
 
@@ -989,44 +1027,6 @@ class EdbPolygon(EDBPrimitives, PolygonDotNet):
989
1027
  return self.api_object.SetPolygonData(polygon_data)
990
1028
  return False
991
1029
 
992
- def scale(self, factor, center=None):
993
- """Scales the polygon relative to a center point by a factor.
994
-
995
- Parameters
996
- ----------
997
- factor : float
998
- Scaling factor.
999
- center : List of float or str [x,y], optional
1000
- If None scaling is done from polygon center.
1001
-
1002
- Returns
1003
- -------
1004
- bool
1005
- ``True`` when successful, ``False`` when failed.
1006
-
1007
- Examples
1008
- --------
1009
- >>> edbapp = pyaedt.Edb("myproject.aedb")
1010
- >>> top_layer_polygon = [poly for poly in edbapp.modeler.polygons if poly.layer_name == "Top Layer"]
1011
- >>> for polygon in top_layer_polygon:
1012
- >>> polygon.scale(factor=2)
1013
- """
1014
- if not isinstance(factor, str):
1015
- factor = float(factor)
1016
- polygon_data = self._edb.Geometry.PolygonData.CreateFromArcs(self.polygon_data.edb_api.GetArcData(), True)
1017
- if not center:
1018
- center = polygon_data.GetBoundingCircleCenter()
1019
- if center:
1020
- polygon_data.Scale(factor, center)
1021
- return self.api_object.SetPolygonData(polygon_data)
1022
- elif isinstance(center, list) and len(center) == 2:
1023
- center = self._edb.Geometry.PointData(
1024
- self._edb.Utility.Value(center[0]), self._edb.Utility.Value(center[1])
1025
- )
1026
- polygon_data.Scale(factor, center)
1027
- return self.api_object.SetPolygonData(polygon_data)
1028
- return False
1029
-
1030
1030
  def move_layer(self, layer):
1031
1031
  """Move polygon to given layer.
1032
1032
 
@@ -38,7 +38,7 @@ class RaptorXSimulationSetup(SimulationSetup):
38
38
  def create(self, name=None):
39
39
  """Create an HFSS setup."""
40
40
  self._name = name
41
- self._create(name)
41
+ self._create(name, simulation_setup_type=self._setup_type)
42
42
  return self
43
43
 
44
44
  @property
@@ -94,6 +94,27 @@ class EdbLayout(object):
94
94
  """
95
95
  return self._pedb.stackup.layers
96
96
 
97
+ def get_primitive(self, primitive_id):
98
+ """Retrieve primitive from give id.
99
+
100
+ Parameters
101
+ ----------
102
+ primitive_id : int
103
+ Primitive id.
104
+
105
+ Returns
106
+ -------
107
+ list of :class:`pyedb.dotnet.edb_core.edb_data.primitives_data.EDBPrimitives`
108
+ List of primitives.
109
+ """
110
+ for p in self._layout.primitives:
111
+ if p.id == primitive_id:
112
+ return p
113
+ for p in self._layout.primitives:
114
+ for v in p.voids:
115
+ if v.id == primitive_id:
116
+ return v
117
+
97
118
  @property
98
119
  def primitives(self):
99
120
  """Primitives.
@@ -258,6 +258,32 @@ class LayoutValidation:
258
258
 
259
259
  return new_nets
260
260
 
261
+ def fix_self_intersections(self, net_list=None):
262
+ """Find and fix self intersections from a given netlist.
263
+
264
+ Parameters
265
+ ----------
266
+ net_list : str, list, optional
267
+ List of nets on which check disjoints. If `None` is provided then the algorithm will loop on all nets.
268
+
269
+ Returns
270
+ -------
271
+ bool
272
+ """
273
+ if not net_list:
274
+ net_list = list(self._pedb.nets.keys())
275
+ elif isinstance(net_list, str):
276
+ net_list = [net_list]
277
+ new_prims = []
278
+ for prim in self._pedb.modeler.polygons:
279
+ if prim.net_name in net_list:
280
+ new_prims.extend(prim.fix_self_intersections())
281
+ if new_prims:
282
+ self._pedb._logger.info("Self-intersections detected and removed.")
283
+ else:
284
+ self._pedb._logger.info("Self-intersection not found.")
285
+ return True
286
+
261
287
  def illegal_net_names(self, fix=False):
262
288
  """Find and fix illegal net names."""
263
289
  pattern = r"[\(\)\\\/:;*?<>\'\"|`~$]"
@@ -38,7 +38,7 @@ class EdbNets(object):
38
38
 
39
39
  Examples
40
40
  --------
41
- >>> from pyedb.dotnet.edb import Edb
41
+ >>> from pyedb import Edb
42
42
  >>> edbapp = Edb("myaedbfolder", edbversion="2021.2")
43
43
  >>> edb_nets = edbapp.nets
44
44
  """
@@ -46,7 +46,7 @@ class SimSetupInfo:
46
46
  "kAnalysisOption": None,
47
47
  "kSIwaveDCIR": self._pedb.simsetupdata.SIwave.SIWDCIRSimulationSettings,
48
48
  "kSIwaveEMI": None,
49
- "kHFSSPI": None,
49
+ "kHFSSPI": self._pedb.simsetupdata.HFSSPISimulationSettings,
50
50
  "kDDRwizard": None,
51
51
  "kQ3D": None,
52
52
  "kNumSetupTypes": None,
@@ -65,3 +65,360 @@ class HFSSSimulationSettings(SimulationSettings):
65
65
  @property
66
66
  def mesh_operations(self):
67
67
  return self._edb_object.MeshOperations
68
+
69
+
70
+ class HFSSPISimulationSettings(SimulationSettings):
71
+ def __init__(self, edb_setup_info, pedb, edb_object):
72
+ super().__init__(pedb, edb_setup_info, edb_object)
73
+ self._pedb = pedb
74
+ self.logger = self._pedb.logger
75
+ self._edb_setup_info = edb_setup_info
76
+ self._simulation_settings = edb_setup_info.SimulationSettings
77
+
78
+ @property
79
+ def auto_select_nets_for_simulation(self):
80
+ """Auto select nets for simulation.
81
+
82
+ Returns
83
+ -------
84
+ bool
85
+ """
86
+ return self._simulation_settings.AutoSelectNetsForSimulation
87
+
88
+ @auto_select_nets_for_simulation.setter
89
+ def auto_select_nets_for_simulation(self, value):
90
+ if isinstance(value, bool):
91
+ self._simulation_settings.AutoSelectNetsForSimulation = value
92
+ else:
93
+ self.logger.error(
94
+ "Property auto_select_nets_for_simulation expects a boolean "
95
+ f"value while the provided value is {value}."
96
+ )
97
+
98
+ @property
99
+ def enabled(self):
100
+ return self._simulation_settings.Enabled
101
+
102
+ @enabled.setter
103
+ def enabled(self, value):
104
+ if isinstance(value, bool):
105
+ self._simulation_settings.Enabled = value
106
+ else:
107
+ self.logger.error(f"Property enabled expects a boolean value while the provided value is {value}.")
108
+
109
+ @property
110
+ def ignore_dummy_nets_for_selected_nets(self):
111
+ """Auto select Nets for simulation
112
+
113
+ Returns
114
+ -------
115
+ bool
116
+ """
117
+ return self._simulation_settings.IgnoreDummyNetsForSelectedNets
118
+
119
+ @ignore_dummy_nets_for_selected_nets.setter
120
+ def ignore_dummy_nets_for_selected_nets(self, value):
121
+ if isinstance(value, bool):
122
+ self._simulation_settings.IgnoreDummyNetsForSelectedNets = value
123
+ else:
124
+ self.logger.error(
125
+ "Property ignore_dummy_nets_for_selected_nets expects a boolean "
126
+ f"value while the provided value is {value}."
127
+ )
128
+
129
+ @property
130
+ def ignore_small_holes(self):
131
+ """Ignore small holes choice.
132
+
133
+ Returns
134
+ -------
135
+ bool
136
+ """
137
+ return self._simulation_settings.IgnoreSmallHoles
138
+
139
+ @ignore_small_holes.setter
140
+ def ignore_small_holes(self, value):
141
+ if isinstance(value, bool):
142
+ self._simulation_settings.IgnoreSmallHoles = value
143
+ else:
144
+ self.logger.error(
145
+ f"Property ignore_small_holes expects a boolean value while the provided value is {value}."
146
+ )
147
+
148
+ @property
149
+ def ignore_small_holes_min_diameter(self):
150
+ """Min diameter to ignore small holes.
151
+
152
+ Returns
153
+ -------
154
+ str
155
+ """
156
+ return self._simulation_settings.IgnoreSmallHolesMinDiameter
157
+
158
+ @ignore_small_holes_min_diameter.setter
159
+ def ignore_small_holes_min_diameter(self, value):
160
+ self._simulation_settings.IgnoreSmallHolesMinDiameter = self._pedb.edb_value(value).ToString()
161
+
162
+ @property
163
+ def improved_loss_model(self):
164
+ """Improved Loss Model on power ground nets option.
165
+
166
+ Returns
167
+ -------
168
+ str
169
+ ``Level1``, ``Level2``, ``Level3``
170
+ """
171
+ return self._simulation_settings.ImprovedLossModel
172
+
173
+ @improved_loss_model.setter
174
+ def improved_loss_model(self, value):
175
+ expected_values = ["Level1", "Level2", "Level3"]
176
+ if isinstance(value, str) and value in expected_values:
177
+ self._simulation_settings.ImprovedLossModel = value
178
+ else:
179
+ self.logger.error(
180
+ "Property improved_loss_model expects a string value among "
181
+ f"'Level1', 'Level2' or 'Level3' while the provided value is {value}."
182
+ )
183
+
184
+ @property
185
+ def include_enhanced_bond_wire_modeling(self):
186
+ """Enhance Bond wire modeling.
187
+
188
+ Returns
189
+ -------
190
+ bool
191
+ """
192
+ return self._simulation_settings.IncludeEnhancedBondWireModeling
193
+
194
+ @include_enhanced_bond_wire_modeling.setter
195
+ def include_enhanced_bond_wire_modeling(self, value):
196
+ if isinstance(value, bool):
197
+ self._simulation_settings.IncludeEnhancedBondWireModeling = value
198
+ else:
199
+ self.logger.error(
200
+ "Property include_enhanced_bond_wire_modeling expects a "
201
+ f"boolean value while the provided value is {value}."
202
+ )
203
+
204
+ @property
205
+ def include_nets(self):
206
+ """Add Additional Nets for simulation.
207
+
208
+ Returns
209
+ -------
210
+ [str]
211
+ List of net name.
212
+ """
213
+ return list(self._simulation_settings.IncludeNets)
214
+
215
+ @include_nets.setter
216
+ def include_nets(self, value):
217
+ if isinstance(value, str):
218
+ value = [value]
219
+ if isinstance(value, list):
220
+ self._simulation_settings.IncludeNets = convert_py_list_to_net_list(value)
221
+ else:
222
+ self.logger.error(
223
+ f"Property include_nets expects a string or list of string while the provided value is {value}."
224
+ )
225
+
226
+ @property
227
+ def min_plane_area_to_mesh(self):
228
+ """The minimum area below which geometry is ignored.
229
+
230
+ Returns
231
+ -------
232
+ str
233
+ """
234
+ return self._simulation_settings.MinPlaneAreaToMesh
235
+
236
+ @min_plane_area_to_mesh.setter
237
+ def min_plane_area_to_mesh(self, value):
238
+ self._simulation_settings.MinPlaneAreaToMesh = self._pedb.edb_value(value).ToString()
239
+
240
+ @property
241
+ def min_void_area_to_mesh(self):
242
+ """The minimum area below which voids are ignored.
243
+
244
+ Returns
245
+ -------
246
+ str
247
+ """
248
+ return self._simulation_settings.MinVoidAreaToMesh
249
+
250
+ @min_void_area_to_mesh.setter
251
+ def min_void_area_to_mesh(self, value):
252
+ self._simulation_settings.MinVoidAreaToMesh = self._pedb.edb_value(value).ToString()
253
+
254
+ @property
255
+ def model_type(self):
256
+ """Model Type setting.
257
+
258
+ Returns
259
+ -------
260
+ int
261
+ Model type: ``0``=RDL, ``1``=Package, ``2``=PCB
262
+ """
263
+ return self._simulation_settings.ModelType
264
+
265
+ @model_type.setter
266
+ def model_type(self, value):
267
+ if isinstance(value, int) and value in range(3):
268
+ self._simulation_settings.ModelType = value
269
+ else:
270
+ self.logger.error(
271
+ f"Property model_type expects an integer value among 0, 1 or 2 while the provided value is {value}."
272
+ )
273
+
274
+ @property
275
+ def perform_erc(self):
276
+ """Perform ERC
277
+
278
+ Returns
279
+ -------
280
+ bool
281
+ """
282
+ return self._simulation_settings.PerformERC
283
+
284
+ @perform_erc.setter
285
+ def perform_erc(self, value):
286
+ if isinstance(value, bool):
287
+ self._simulation_settings.PerformERC = value
288
+ else:
289
+ self.logger.error(f"Property perform_erc expects a boolean value while the provided value is {value}.")
290
+
291
+ @property
292
+ def pi_slider_pos(self):
293
+ """The Simulation Preference Slider setting
294
+
295
+ Returns
296
+ -------
297
+ int
298
+ Model type: ``0``= balanced, ``1``=Accuracy.
299
+ """
300
+ return self._simulation_settings.PISliderPos
301
+
302
+ @pi_slider_pos.setter
303
+ def pi_slider_pos(self, value):
304
+ if isinstance(value, int) and value in range(2):
305
+ self._simulation_settings.PISliderPos = value
306
+ else:
307
+ self.logger.error(
308
+ f"Property pi_slider_pos expects an integer value among 0 or 1 while the provided value is {value}."
309
+ )
310
+
311
+ @property
312
+ def rms_surface_roughness(self):
313
+ """RMS Surface Roughness setting
314
+
315
+ Returns
316
+ -------
317
+ str
318
+ """
319
+ return self._simulation_settings.RMSSurfaceRoughness
320
+
321
+ @rms_surface_roughness.setter
322
+ def rms_surface_roughness(self, value):
323
+ self._simulation_settings.RMSSurfaceRoughness = self._pedb.edb_value(value).ToString()
324
+
325
+ @property
326
+ def signal_nets_conductor_modeling(self):
327
+ """Conductor Modeling
328
+
329
+ Returns
330
+ -------
331
+ str
332
+ Value: ``"MeshInside"`` or ``"ImpedanceBoundary"``.
333
+ """
334
+ return self._simulation_settings.SignalNetsConductorModeling
335
+
336
+ @signal_nets_conductor_modeling.setter
337
+ def signal_nets_conductor_modeling(self, value):
338
+ expected_values = ["MeshInside", "ImpedanceBoundary"]
339
+ if isinstance(value, str) and value in expected_values:
340
+ self._simulation_settings.SignalNetsConductorModeling = value
341
+ else:
342
+ self.logger.error(
343
+ "Property signal_nets_conductor_modeling expects a string value among "
344
+ f"'MeshInside' or 'ImpedanceBoundary' while the provided value is {value}."
345
+ )
346
+
347
+ @property
348
+ def signal_nets_error_tolerance(self):
349
+ """Error Tolerance
350
+
351
+ Returns
352
+ -------
353
+ str
354
+ Value between 0.02 and 1.
355
+ """
356
+ return self._simulation_settings.SignalNetsErrorTolerance
357
+
358
+ @signal_nets_error_tolerance.setter
359
+ def signal_nets_error_tolerance(self, value):
360
+ self._simulation_settings.SignalNetsErrorTolerance = self._pedb.edb_value(value).ToString()
361
+
362
+ @property
363
+ def signal_nets_include_improved_dielectric_fill_refinement(self):
364
+ return self._simulation_settings.SignalNetsIncludeImprovedDielectricFillRefinement
365
+
366
+ @signal_nets_include_improved_dielectric_fill_refinement.setter
367
+ def signal_nets_include_improved_dielectric_fill_refinement(self, value):
368
+ if isinstance(value, bool):
369
+ self._simulation_settings.SignalNetsIncludeImprovedDielectricFillRefinement = value
370
+ else:
371
+ self.logger.error(
372
+ "Property signal_nets_include_improved_dielectric_fill_refinement "
373
+ f"expects a boolean value while the provided value is {value}."
374
+ )
375
+
376
+ @property
377
+ def signal_nets_include_improved_loss_handling(self):
378
+ """Improved Dielectric Fill Refinement choice.
379
+
380
+ Returns
381
+ -------
382
+ bool
383
+ """
384
+ return self._simulation_settings.SignalNetsIncludeImprovedLossHandling
385
+
386
+ @signal_nets_include_improved_loss_handling.setter
387
+ def signal_nets_include_improved_loss_handling(self, value):
388
+ if isinstance(value, bool):
389
+ self._simulation_settings.SignalNetsIncludeImprovedLossHandling = value
390
+ else:
391
+ self.logger.error(
392
+ "Property signal_nets_include_improved_loss_handling "
393
+ f"expects a boolean value while the provided value is {value}."
394
+ )
395
+
396
+ @property
397
+ def snap_length_threshold(self):
398
+ return self._simulation_settings.SnapLengthThreshold
399
+
400
+ @snap_length_threshold.setter
401
+ def snap_length_threshold(self, value):
402
+ self._simulation_settings.SnapLengthThreshold = self._pedb.edb_value(value).ToString()
403
+
404
+ @property
405
+ def surface_roughness_model(self):
406
+ """Chosen Model setting
407
+
408
+ Returns
409
+ -------
410
+ str
411
+ Model allowed, ``"None"``, ``"Exponential"`` or ``"Hammerstad"``.
412
+ """
413
+ return self._simulation_settings.SurfaceRoughnessModel
414
+
415
+ @surface_roughness_model.setter
416
+ def surface_roughness_model(self, value):
417
+ expected_values = ["None", "Exponential", "Hammerstad"]
418
+ if isinstance(value, str) and value in expected_values:
419
+ self._simulation_settings.SurfaceRoughnessModel = value
420
+ else:
421
+ self.logger.error(
422
+ "Property surface_roughness_model expects a string value among "
423
+ f"'None', 'Exponential' or 'Hammerstad' while the provided value is {value}."
424
+ )
@@ -43,6 +43,7 @@ from pyedb.dotnet.edb_core.edb_data.sources import (
43
43
  from pyedb.dotnet.edb_core.general import convert_py_list_to_net_list
44
44
  from pyedb.generic.constants import SolverType, SweepType
45
45
  from pyedb.generic.general_methods import _retry_ntimes, generate_unique_name
46
+ from pyedb.misc.siw_feature_config.xtalk_scan.scan_config import SiwaveScanConfig
46
47
  from pyedb.modeler.geometry_operators import GeometryOperators
47
48
 
48
49
 
@@ -1488,6 +1489,19 @@ class EdbSiwave(object):
1488
1489
  _, value = cell.GetProductProperty(siwave_id, 422, "")
1489
1490
  return bool(value)
1490
1491
 
1492
+ def create_impedance_crosstalk_scan(self, scan_type="impedance"):
1493
+ """Create Siwave crosstalk scan object
1494
+
1495
+ Parameters
1496
+ ----------
1497
+ scan_type : str
1498
+ Scan type to be analyzed. 3 options are available, ``impedance`` for frequency impedance scan,
1499
+ ``frequency_xtalk`` for frequency domain crosstalk and ``time_xtalk`` for time domain crosstalk.
1500
+ Default value is ``frequency``.
1501
+
1502
+ """
1503
+ return SiwaveScanConfig(self._pedb, scan_type)
1504
+
1491
1505
  @icepak_use_minimal_comp_defaults.setter
1492
1506
  def icepak_use_minimal_comp_defaults(self, value):
1493
1507
  value = "True" if bool(value) else ""
@@ -37,6 +37,10 @@ from pyedb.dotnet.edb_core.sim_setup_data.data.settings import (
37
37
  ViaSettings,
38
38
  )
39
39
  from pyedb.dotnet.edb_core.sim_setup_data.data.sim_setup_info import SimSetupInfo
40
+ from pyedb.dotnet.edb_core.sim_setup_data.data.simulation_settings import (
41
+ HFSSPISimulationSettings,
42
+ )
43
+ from pyedb.dotnet.edb_core.sim_setup_data.data.sweep_data import SweepData
40
44
  from pyedb.dotnet.edb_core.utilities.simulation_setup import SimulationSetup
41
45
  from pyedb.generic.general_methods import generate_unique_name
42
46
 
@@ -384,3 +388,82 @@ class HfssSimulationSetup(SimulationSetup):
384
388
  ): # pragma no cover
385
389
  return False
386
390
  return True
391
+
392
+
393
+ class HFSSPISimulationSetup(SimulationSetup):
394
+ """Manages EDB methods for HFSSPI simulation setup."""
395
+
396
+ def __init__(self, pedb, edb_object=None):
397
+ super().__init__(pedb, edb_object)
398
+ self._edb_object = edb_object
399
+ self._pedb = pedb
400
+ self._setup_type = "kHFSSPI"
401
+ self._edb_setup_info = None
402
+ self.logger = self._pedb.logger
403
+
404
+ def create(self, name=None):
405
+ """Create an HFSS setup."""
406
+ self._name = name
407
+ self._create(name=name, simulation_setup_type=self._setup_type)
408
+ return self
409
+
410
+ @property
411
+ def setup_type(self):
412
+ return self._setup_type
413
+
414
+ @property
415
+ def settings(self):
416
+ return HFSSPISimulationSettings(self._edb_setup_info, self._pedb, self._edb_object)
417
+
418
+ @property
419
+ def enabled(self):
420
+ return self.settings.enabled
421
+
422
+ @enabled.setter
423
+ def enabled(self, value):
424
+ if isinstance(value, bool):
425
+ self.settings.enabled = value
426
+ else:
427
+ self.logger.error(f"Property enabled expects a boolean value while the provided value is {value}.")
428
+
429
+ @property
430
+ def position(self):
431
+ return self._edb_setup_info.Position
432
+
433
+ @position.setter
434
+ def position(self, value):
435
+ if isinstance(value, int):
436
+ self._edb_setup_info.Position = value
437
+ else:
438
+ self.logger.error(f"Property position expects an integer value while the provided value is {value}.")
439
+
440
+ def add_frequency_sweep(self, name=None, frequency_sweep=None):
441
+ """Add frequency sweep.
442
+
443
+ Parameters
444
+ ----------
445
+ name : str, optional
446
+ Name of the frequency sweep.
447
+ frequency_sweep : list, optional
448
+ List of frequency points.
449
+
450
+ Returns
451
+ -------
452
+ :class:`pyedb.dotnet.edb_core.edb_data.hfss_simulation_setup_data.EdbFrequencySweep`wheen succeeded, ``False``
453
+ when failed.
454
+
455
+ Examples
456
+ --------
457
+ >>> setup1 = edbapp.create_hfss_setup("setup1")
458
+ >>> setup1.add_frequency_sweep(frequency_sweep=[
459
+ ... ["linear count", "0", "1kHz", 1],
460
+ ... ["log scale", "1kHz", "0.1GHz", 10],
461
+ ... ["linear scale", "0.1GHz", "10GHz", "0.1GHz"],
462
+ ... ])
463
+ """
464
+ if name in self.frequency_sweeps:
465
+ self.logger.error("Frequency sweep with same name already defined.")
466
+ return False
467
+ if not name:
468
+ name = generate_unique_name("sweep")
469
+ return SweepData(self, frequency_sweep, name)