pyedb 0.39.1__py3-none-any.whl → 0.41.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.

pyedb/__init__.py CHANGED
@@ -44,7 +44,7 @@ deprecation_warning()
44
44
  #
45
45
 
46
46
  pyedb_path = os.path.dirname(__file__)
47
- __version__ = "0.39.1"
47
+ __version__ = "0.41.0"
48
48
  version = __version__
49
49
 
50
50
  #
pyedb/common/nets.py CHANGED
@@ -22,6 +22,7 @@ class CommonNets:
22
22
  show=True,
23
23
  annotate_component_names=True,
24
24
  plot_vias=False,
25
+ title=None,
25
26
  **kwargs,
26
27
  ):
27
28
  """Plot a Net to Matplotlib 2D Chart.
@@ -57,6 +58,9 @@ class CommonNets:
57
58
  plot_vias : bool, optional
58
59
  Whether to plot vias (circular and rectangular) or not. This may impact in the plot computation time.
59
60
  Default is ``False``.
61
+ title : str, optional
62
+ Specify the default plot title. Is value is ``None`` the project name is assigned by default. Default value
63
+ is ``None``.
60
64
  show : bool, optional
61
65
  Whether to show the plot or not. Default is `True`.
62
66
 
@@ -95,7 +99,7 @@ class CommonNets:
95
99
 
96
100
  start_time = time.time()
97
101
  if not nets:
98
- nets = list(self.nets.keys())
102
+ nets = list(self._pedb.nets.nets.keys())
99
103
  if isinstance(nets, str):
100
104
  nets = [nets]
101
105
  if not layers:
@@ -395,7 +399,12 @@ class CommonNets:
395
399
  # Hide axes ticks
396
400
  ax.set_xticks([])
397
401
  ax.set_yticks([])
398
- message = "Edb Top View" if top_view else "Edb Bottom View"
402
+ if not title:
403
+ if not self._pedb.grpc:
404
+ title = self._pedb.active_cell.GetName()
405
+ else:
406
+ title = self._pedb.active_cell.name
407
+ message = f"Edb Top View {title}" if top_view else f"Edb Bottom View {title}"
399
408
  plt.title(message, size=20)
400
409
  if show_legend:
401
410
  plt.legend(loc="upper left", fontsize="x-large")
@@ -216,6 +216,7 @@ class CfgComponent(CfgBase):
216
216
  if self.pyedb_obj.type.lower() == "ic":
217
217
  self._set_ic_die_properties_to_edb()
218
218
  self._set_port_properties_to_edb()
219
+ self._set_solder_ball_properties_to_edb()
219
220
  elif self.pyedb_obj.type.lower() in ["io", "other"]:
220
221
  self._set_solder_ball_properties_to_edb()
221
222
  self._set_port_properties_to_edb()
@@ -228,6 +229,7 @@ class CfgComponent(CfgBase):
228
229
  if self.pyedb_obj.type.lower() == "ic":
229
230
  self._retrieve_ic_die_properties_from_edb()
230
231
  self._retrieve_port_properties_from_edb()
232
+ self._retrieve_solder_ball_properties_from_edb()
231
233
  elif self.pyedb_obj.type.lower() in ["io", "other"]:
232
234
  self._retrieve_solder_ball_properties_from_edb()
233
235
  self._retrieve_port_properties_from_edb()
@@ -427,7 +427,7 @@ class CfgPadstackInstance(CfgBase):
427
427
  self.api = self.DotNet(self)
428
428
 
429
429
  self.name = kwargs.get("name", None)
430
- self.net_name = kwargs.get("net_name", "")
430
+ self.net_name = kwargs.get("net_name", None)
431
431
  self.layer_range = kwargs.get("layer_range", [None, None])
432
432
  self.definition = kwargs.get("definition", None)
433
433
  self.backdrill_parameters = kwargs.get("backdrill_parameters", None)
@@ -24,6 +24,7 @@ import os
24
24
  import numpy as np
25
25
 
26
26
  from pyedb.configuration.cfg_common import CfgBase
27
+ from pyedb.dotnet.database.cell.primitive.primitive import Primitive
27
28
  from pyedb.dotnet.database.edb_data.ports import WavePort
28
29
  from pyedb.dotnet.database.general import convert_py_list_to_net_list
29
30
  from pyedb.dotnet.database.geometry.point_data import PointData
@@ -53,6 +54,7 @@ class CfgTerminalInfo(CfgBase):
53
54
  contact_radius = "0.1mm" if kwargs.get("contact_radius") is None else kwargs.get("contact_radius")
54
55
  self.contact_radius = self._pedb.edb_value(contact_radius).ToDouble()
55
56
  self.num_of_contact = kwargs.get("num_of_contact", 4)
57
+ self.contact_expansion = kwargs.get("contact_expansion", 1)
56
58
 
57
59
  def export_properties(self):
58
60
  return {self.type: self.value}
@@ -141,7 +143,7 @@ class CfgPorts:
141
143
  self.ports = []
142
144
  for p in ports_data:
143
145
  if p["type"] == "wave_port":
144
- self.ports.append(CfgWavePort(self._pedb, **p))
146
+ self.ports.append(CfgEdgePort(self._pedb, **p))
145
147
  elif p["type"] == "diff_wave_port":
146
148
  self.ports.append(CfgDiffWavePort(self._pedb, **p))
147
149
  elif p["type"] in ["coax", "circuit"]:
@@ -167,7 +169,12 @@ class CfgPorts:
167
169
 
168
170
  for _, p in ports.items():
169
171
  if not p.ref_terminal:
170
- port_type = "coax"
172
+ if p.terminal_type == "PadstackInstanceTerminal":
173
+ port_type = "coax"
174
+ elif p.hfss_type == "Wave":
175
+ port_type = "wave_port"
176
+ else:
177
+ port_type = "gap_port"
171
178
  else:
172
179
  port_type = "circuit"
173
180
 
@@ -206,7 +213,7 @@ class CfgPorts:
206
213
  positive_terminal=pos_term_info,
207
214
  negative_terminal=neg_term_info,
208
215
  )
209
- else:
216
+ elif port_type == "coax":
210
217
  cfg_port = CfgPort(
211
218
  self._pedb,
212
219
  name=p.name,
@@ -214,6 +221,22 @@ class CfgPorts:
214
221
  reference_designator=refdes,
215
222
  positive_terminal=pos_term_info,
216
223
  )
224
+ else:
225
+ _, primitive, point = p._edb_object.GetEdges()[0].GetParameters()
226
+
227
+ primitive = Primitive(self._pedb, primitive)
228
+ point = PointData(self._pedb, point)
229
+
230
+ cfg_port = CfgEdgePort(
231
+ self._pedb,
232
+ name=p.name,
233
+ type=port_type,
234
+ primitive_name=primitive.aedt_name,
235
+ point_on_edge=[point._edb_object.X.ToString(), point._edb_object.Y.ToString()],
236
+ horizontal_extent_factor=p.horizontal_extent_factor,
237
+ vertical_extent_factor=p.vertical_extent_factor,
238
+ pec_launch_width=p.pec_launch_width,
239
+ )
217
240
 
218
241
  self.ports.append(cfg_port)
219
242
  return self.export_properties()
@@ -294,7 +317,11 @@ class CfgCircuitElement(CfgBase):
294
317
  contact_type = self.positive_terminal_info.contact_type
295
318
  radius = self.positive_terminal_info.contact_radius
296
319
  num_of_contact = self.positive_terminal_info.num_of_contact
297
- virtual_pins = self._create_virtual_pins_on_pin(pin, contact_type, radius, num_of_contact)
320
+ contact_expansion = self.positive_terminal_info.contact_expansion
321
+
322
+ virtual_pins = self._create_virtual_pins_on_pin(
323
+ pin, contact_type, radius, num_of_contact, contact_expansion
324
+ )
298
325
  pos_objs.update(virtual_pins)
299
326
  self._elem_num = len(pos_objs)
300
327
  else:
@@ -309,7 +336,11 @@ class CfgCircuitElement(CfgBase):
309
336
  contact_type = self.positive_terminal_info.contact_type
310
337
  radius = self.positive_terminal_info.contact_radius
311
338
  num_of_contact = self.positive_terminal_info.num_of_contact
312
- virtual_pins = self._create_virtual_pins_on_pin(pin, contact_type, radius, num_of_contact)
339
+ contact_expansion = self.positive_terminal_info.contact_expansion
340
+
341
+ virtual_pins = self._create_virtual_pins_on_pin(
342
+ pin, contact_type, radius, num_of_contact, contact_expansion
343
+ )
313
344
  pos_objs.update(virtual_pins)
314
345
  self._elem_num = len(pos_objs)
315
346
  else:
@@ -324,7 +355,11 @@ class CfgCircuitElement(CfgBase):
324
355
  contact_type = self.positive_terminal_info.contact_type
325
356
  radius = self.positive_terminal_info.contact_radius
326
357
  num_of_contact = self.positive_terminal_info.num_of_contact
327
- virtual_pins = self._create_virtual_pins_on_pin(pin, contact_type, radius, num_of_contact)
358
+ contact_expansion = self.positive_terminal_info.contact_expansion
359
+
360
+ virtual_pins = self._create_virtual_pins_on_pin(
361
+ pin, contact_type, radius, num_of_contact, contact_expansion
362
+ )
328
363
  pos_objs.update(virtual_pins)
329
364
  self._elem_num = len(pos_objs)
330
365
  else:
@@ -400,7 +435,7 @@ class CfgCircuitElement(CfgBase):
400
435
  pins.update({f"{reference_designator}_{terminal_value[0]}_{i}": j for i, j in temp.items()})
401
436
  return pins
402
437
 
403
- def _create_virtual_pins_on_pin(self, pin, contact_type, radius, num_of_contact=4):
438
+ def _create_virtual_pins_on_pin(self, pin, contact_type, radius, num_of_contact=4, expansion=1):
404
439
  component = pin.component
405
440
  placement_layer = component.placement_layer
406
441
  pos_x, pos_y = pin.position
@@ -420,6 +455,9 @@ class CfgCircuitElement(CfgBase):
420
455
  else: # pragma no cover
421
456
  raise AttributeError(f"Unsupported pad shape {pad.shape.lower()}")
422
457
 
458
+ width = width * expansion
459
+ height = height * expansion
460
+
423
461
  positions = []
424
462
  if contact_type.lower() == "inline":
425
463
  if width > height:
@@ -624,7 +662,7 @@ class CfgProbe(CfgCircuitElement):
624
662
  self.api = self.DotNet(self)
625
663
 
626
664
 
627
- class CfgWavePort:
665
+ class CfgEdgePort:
628
666
  def __init__(self, pedb, **kwargs):
629
667
  self._pedb = pedb
630
668
  self.name = kwargs["name"]
@@ -650,10 +688,24 @@ class CfgWavePort:
650
688
  wave_port.horizontal_extent_factor = self.horizontal_extent_factor
651
689
  wave_port.vertical_extent_factor = self.vertical_extent_factor
652
690
  wave_port.pec_launch_width = self.pec_launch_width
653
- wave_port.hfss_type = "Wave"
691
+ if self.type == "wave_port":
692
+ wave_port.hfss_type = "Wave"
693
+ else:
694
+ wave_port.hfss_type = "Gap"
654
695
  wave_port.do_renormalize = True
655
696
  return wave_port
656
697
 
698
+ def export_properties(self):
699
+ return {
700
+ "name": self.name,
701
+ "type": self.type,
702
+ "primitive_name": self.primitive_name,
703
+ "point_on_edge": self.point_on_edge,
704
+ "horizontal_extent_factor": self.horizontal_extent_factor,
705
+ "vertical_extent_factor": self.vertical_extent_factor,
706
+ "pec_launch_width": self.pec_launch_width,
707
+ }
708
+
657
709
 
658
710
  class CfgDiffWavePort:
659
711
  def __init__(self, pedb, **kwargs):
@@ -666,7 +718,7 @@ class CfgDiffWavePort:
666
718
 
667
719
  kwargs["positive_terminal"]["type"] = "wave_port"
668
720
  kwargs["positive_terminal"]["name"] = self.name + ":T1"
669
- self.positive_port = CfgWavePort(
721
+ self.positive_port = CfgEdgePort(
670
722
  self._pedb,
671
723
  horizontal_extent_factor=self.horizontal_extent_factor,
672
724
  vertical_extent_factor=self.vertical_extent_factor,
@@ -675,7 +727,7 @@ class CfgDiffWavePort:
675
727
  )
676
728
  kwargs["negative_terminal"]["type"] = "wave_port"
677
729
  kwargs["negative_terminal"]["name"] = self.name + ":T2"
678
- self.negative_port = CfgWavePort(
730
+ self.negative_port = CfgEdgePort(
679
731
  self._pedb,
680
732
  horizontal_extent_factor=self.horizontal_extent_factor,
681
733
  vertical_extent_factor=self.vertical_extent_factor,
@@ -20,6 +20,7 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
+ from pyedb import Edb
23
24
  from pyedb.configuration.cfg_common import CfgBase
24
25
 
25
26
 
@@ -49,12 +50,32 @@ class CfgLayer(CfgBase):
49
50
 
50
51
 
51
52
  class CfgStackup:
52
- def __init__(self, pedb, data):
53
+ def __init__(self, pedb: Edb, data):
53
54
  self._pedb = pedb
54
55
 
55
56
  self.materials = [CfgMaterial(**mat) for mat in data.get("materials", [])]
56
57
  self.layers = [CfgLayer(**lay) for lay in data.get("layers", [])]
57
58
 
59
+ materials = [m.name for m in self.materials]
60
+ for i in self.layers:
61
+ if i.type == "signal":
62
+ if i.material not in materials:
63
+ self.materials.append(
64
+ CfgMaterial(name=i.material, **self._pedb.materials.default_conductor_property_values)
65
+ )
66
+ materials.append(i.material)
67
+ if i.fill_material not in materials:
68
+ self.materials.append(
69
+ CfgMaterial(name=i.fill_material, **self._pedb.materials.default_dielectric_property_values)
70
+ )
71
+ materials.append(i.fill_material)
72
+ elif i.type == "dielectric":
73
+ if i.material not in materials:
74
+ self.materials.append(
75
+ CfgMaterial(name=i.material, **self._pedb.materials.default_dielectric_property_values)
76
+ )
77
+ materials.append(i.material)
78
+
58
79
  def apply(self):
59
80
  """Apply configuration settings to the current design"""
60
81
  if len(self.materials):
@@ -48,3 +48,58 @@ class EdgeTerminal(Terminal):
48
48
  edb_list = convert_py_list_to_net_list(temp, self._edb.cell.terminal.Terminal)
49
49
  _edb_bundle_terminal = self._edb.cell.terminal.BundleTerminal.Create(edb_list)
50
50
  return self._pedb.ports[_edb_bundle_terminal.GetName()]
51
+
52
+ @property
53
+ def horizontal_extent_factor(self):
54
+ """Horizontal extent factor."""
55
+ return self._hfss_port_property["Horizontal Extent Factor"]
56
+
57
+ @horizontal_extent_factor.setter
58
+ def horizontal_extent_factor(self, value):
59
+ p = self._hfss_port_property
60
+ p["Horizontal Extent Factor"] = value
61
+ self._hfss_port_property = p
62
+
63
+ @property
64
+ def vertical_extent_factor(self):
65
+ """Vertical extent factor."""
66
+ return self._hfss_port_property["Vertical Extent Factor"]
67
+
68
+ @vertical_extent_factor.setter
69
+ def vertical_extent_factor(self, value):
70
+ p = self._hfss_port_property
71
+ p["Vertical Extent Factor"] = value
72
+ self._hfss_port_property = p
73
+
74
+ @property
75
+ def pec_launch_width(self):
76
+ """Launch width for the printed electronic component (PEC)."""
77
+ return self._hfss_port_property["PEC Launch Width"]
78
+
79
+ @pec_launch_width.setter
80
+ def pec_launch_width(self, value):
81
+ p = self._hfss_port_property
82
+ p["PEC Launch Width"] = value
83
+ self._hfss_port_property = p
84
+
85
+ @property
86
+ def deembed(self):
87
+ """Whether deembed is active."""
88
+ return self._edb_object.GetPortPostProcessingProp().DoDeembed
89
+
90
+ @deembed.setter
91
+ def deembed(self, value):
92
+ p = self._edb_object.GetPortPostProcessingProp()
93
+ p.DoDeembed = value
94
+ self._edb_object.SetPortPostProcessingProp(p)
95
+
96
+ @property
97
+ def deembed_length(self):
98
+ """Deembed Length."""
99
+ return self._edb_object.GetPortPostProcessingProp().DeembedLength.ToDouble()
100
+
101
+ @deembed_length.setter
102
+ def deembed_length(self, value):
103
+ p = self._edb_object.GetPortPostProcessingProp()
104
+ p.DeembedLength = self._pedb.edb_value(value)
105
+ self._edb_object.SetPortPostProcessingProp(p)
@@ -820,12 +820,13 @@ class Components(object):
820
820
  if not port_name:
821
821
  port_name = "Port_{}_{}".format(pins[0].net_name, pins[0].name)
822
822
 
823
- if len(pins) > 1 > 1 or pingroup_on_single_pin:
824
- pec_boundary = False
825
- self._logger.info(
826
- "Disabling PEC boundary creation, this feature is supported on single pin "
827
- f"ports only, {len(pins)} pins found (pingroup_on_single_pin: {pingroup_on_single_pin})."
828
- )
823
+ if len(pins) > 1 or pingroup_on_single_pin:
824
+ if pec_boundary:
825
+ pec_boundary = False
826
+ self._logger.info(
827
+ "Disabling PEC boundary creation, this feature is supported on single pin "
828
+ f"ports only, {len(pins)} pins found (pingroup_on_single_pin: {pingroup_on_single_pin})."
829
+ )
829
830
  group_name = "group_{}".format(port_name)
830
831
  pin_group = self.create_pingroup_from_pins(pins, group_name)
831
832
  term = self._create_pin_group_terminal(pingroup=pin_group, term_name=port_name)
@@ -834,12 +835,13 @@ class Components(object):
834
835
  term.SetIsCircuitPort(True)
835
836
 
836
837
  if len(reference_pins) > 1 or pingroup_on_single_pin:
837
- pec_boundary = False
838
- self._logger.info(
839
- "Disabling PEC boundary creation. This feature is supported on single pin "
840
- f"ports only, {len(reference_pins)} reference pins found "
841
- f"(pingroup_on_single_pin: {pingroup_on_single_pin})."
842
- )
838
+ if pec_boundary:
839
+ pec_boundary = False
840
+ self._logger.info(
841
+ "Disabling PEC boundary creation. This feature is supported on single pin "
842
+ f"ports only, {len(reference_pins)} reference pins found "
843
+ f"(pingroup_on_single_pin: {pingroup_on_single_pin})."
844
+ )
843
845
  ref_group_name = "group_{}_ref".format(port_name)
844
846
  ref_pin_group = self.create_pingroup_from_pins(reference_pins, ref_group_name)
845
847
  ref_term = self._create_pin_group_terminal(pingroup=ref_pin_group, term_name=port_name + "_ref")
@@ -510,7 +510,7 @@ class EDBPadstack(object):
510
510
  list
511
511
  List of layers.
512
512
  """
513
- return self._padstack_def_data.GetLayerNames()
513
+ return list(self._padstack_def_data.GetLayerNames())
514
514
 
515
515
  @property
516
516
  def via_start_layer(self):
@@ -521,7 +521,7 @@ class EDBPadstack(object):
521
521
  str
522
522
  Name of the starting layer.
523
523
  """
524
- return list(self.via_layers)[0]
524
+ return self.via_layers[0]
525
525
 
526
526
  @property
527
527
  def via_stop_layer(self):
@@ -532,7 +532,7 @@ class EDBPadstack(object):
532
532
  str
533
533
  Name of the stopping layer.
534
534
  """
535
- return list(self.via_layers)[-1]
535
+ return self.via_layers[-1]
536
536
 
537
537
  @property
538
538
  def hole_params(self):
@@ -2141,3 +2141,80 @@ class EDBPadstackInstance(Primitive):
2141
2141
  max_limit=max_limit,
2142
2142
  component_only=component_only,
2143
2143
  )
2144
+
2145
+ def split(self):
2146
+ """Split padstack instance into multiple instances. The new instances only connect adjacent layers."""
2147
+ pdef_name = self.padstack_definition
2148
+ position = self.position
2149
+ net_name = self.net_name
2150
+ name = self.name
2151
+ stackup_layer_range = list(self._pedb.stackup.signal_layers.keys())
2152
+ start_idx = stackup_layer_range.index(self.start_layer)
2153
+ stop_idx = stackup_layer_range.index(self.stop_layer)
2154
+ for idx, (l1, l2) in enumerate(
2155
+ list(zip(stackup_layer_range[start_idx:stop_idx], stackup_layer_range[start_idx + 1 : stop_idx + 1]))
2156
+ ):
2157
+ self._pedb.padstacks.place(position, pdef_name, net_name, f"{name}_{idx}", fromlayer=l1, tolayer=l2)
2158
+ self.delete()
2159
+
2160
+ def convert_hole_to_conical_shape(self, angle=75):
2161
+ """Convert actual padstack instance to microvias 3D Objects with a given aspect ratio.
2162
+
2163
+ Parameters
2164
+ ----------
2165
+ angle : float, optional
2166
+ Angle of laser penetration in degrees. The angle defines the lowest hole diameter with this formula:
2167
+ HoleDiameter -2*tan(laser_angle* Hole depth). Hole depth is the height of the via (dielectric thickness).
2168
+ The default is ``75``.
2169
+ The lowest hole is ``0.75*HoleDepth/HoleDiam``.
2170
+
2171
+ Returns
2172
+ -------
2173
+ """
2174
+ pos = self.position
2175
+ stackup_layers = self._pedb.stackup.stackup_layers
2176
+ signal_layers = self._pedb.stackup.signal_layers
2177
+ layer_idx = list(signal_layers.keys()).index(self.start_layer)
2178
+
2179
+ _layer_idx = list(stackup_layers.keys()).index(self.start_layer)
2180
+ diel_layer_idx = list(stackup_layers.keys())[_layer_idx + 1]
2181
+ diel_thickness = stackup_layers[diel_layer_idx].thickness
2182
+
2183
+ rad_large = self.definition.hole_diameter / 2
2184
+ rad_small = rad_large - diel_thickness * 1 / math.tan(math.radians(angle))
2185
+
2186
+ if layer_idx + 1 < len(signal_layers) / 2: # upper half of stack
2187
+ rad_u = rad_large
2188
+ rad_l = rad_small
2189
+ else:
2190
+ rad_u = rad_small
2191
+ rad_l = rad_large
2192
+
2193
+ layout = self._pedb.active_layout
2194
+ cloned_circle = self._edb.cell.primitive.circle.create(
2195
+ layout,
2196
+ self.start_layer,
2197
+ self._edb_padstackinstance.GetNet(),
2198
+ self._pedb.edb_value(pos[0]),
2199
+ self._pedb.edb_value(pos[1]),
2200
+ self._pedb.edb_value(rad_u),
2201
+ )
2202
+ cloned_circle2 = self._edb.cell.primitive.circle.create(
2203
+ layout,
2204
+ self.stop_layer,
2205
+ self._edb_padstackinstance.GetNet(),
2206
+ self._pedb.edb_value(pos[0]),
2207
+ self._pedb.edb_value(pos[1]),
2208
+ self._pedb.edb_value(rad_l),
2209
+ )
2210
+ s3d = self._pedb._edb.Cell.Hierarchy.Structure3D.Create(
2211
+ layout, generate_unique_name("via3d_" + self.aedt_name.replace("via_", ""), n=3)
2212
+ )
2213
+ s3d.AddMember(cloned_circle.prim_obj)
2214
+ s3d.AddMember(cloned_circle2.prim_obj)
2215
+ s3d.SetMaterial(self.definition.material)
2216
+ s3d.SetMeshClosureProp(self._pedb._edb.Cell.Hierarchy.Structure3D.TClosure.EndsClosed)
2217
+
2218
+ hole_override_enabled = True
2219
+ hole_override_diam = 0
2220
+ self._edb_object.SetHoleOverride(hole_override_enabled, self._pedb.edb_value(hole_override_diam))
@@ -117,61 +117,6 @@ class WavePort(EdgeTerminal):
117
117
  def __init__(self, pedb, edb_terminal):
118
118
  super().__init__(pedb, edb_terminal)
119
119
 
120
- @property
121
- def horizontal_extent_factor(self):
122
- """Horizontal extent factor."""
123
- return self._hfss_port_property["Horizontal Extent Factor"]
124
-
125
- @horizontal_extent_factor.setter
126
- def horizontal_extent_factor(self, value):
127
- p = self._hfss_port_property
128
- p["Horizontal Extent Factor"] = value
129
- self._hfss_port_property = p
130
-
131
- @property
132
- def vertical_extent_factor(self):
133
- """Vertical extent factor."""
134
- return self._hfss_port_property["Vertical Extent Factor"]
135
-
136
- @vertical_extent_factor.setter
137
- def vertical_extent_factor(self, value):
138
- p = self._hfss_port_property
139
- p["Vertical Extent Factor"] = value
140
- self._hfss_port_property = p
141
-
142
- @property
143
- def pec_launch_width(self):
144
- """Launch width for the printed electronic component (PEC)."""
145
- return self._hfss_port_property["PEC Launch Width"]
146
-
147
- @pec_launch_width.setter
148
- def pec_launch_width(self, value):
149
- p = self._hfss_port_property
150
- p["PEC Launch Width"] = value
151
- self._hfss_port_property = p
152
-
153
- @property
154
- def deembed(self):
155
- """Whether deembed is active."""
156
- return self._edb_object.GetPortPostProcessingProp().DoDeembed
157
-
158
- @deembed.setter
159
- def deembed(self, value):
160
- p = self._edb_object.GetPortPostProcessingProp()
161
- p.DoDeembed = value
162
- self._edb_object.SetPortPostProcessingProp(p)
163
-
164
- @property
165
- def deembed_length(self):
166
- """Deembed Length."""
167
- return self._edb_object.GetPortPostProcessingProp().DeembedLength.ToDouble()
168
-
169
- @deembed_length.setter
170
- def deembed_length(self, value):
171
- p = self._edb_object.GetPortPostProcessingProp()
172
- p.DeembedLength = self._pedb.edb_value(value)
173
- self._edb_object.SetPortPostProcessingProp(p)
174
-
175
120
 
176
121
  class ExcitationSources(Terminal):
177
122
  """Manage sources properties.
@@ -446,6 +446,33 @@ class Material(object):
446
446
  class Materials(object):
447
447
  """Manages EDB methods for material management accessible from `Edb.materials` property."""
448
448
 
449
+ default_conductor_property_values = {
450
+ "conductivity": 58000000,
451
+ "dielectric_loss_tangent": 0,
452
+ "magnetic_loss_tangent": 0,
453
+ "mass_density": 8933,
454
+ "permittivity": 1,
455
+ "permeability": 0.999991,
456
+ "poisson_ratio": 0.38,
457
+ "specific_heat": 385,
458
+ "thermal_conductivity": 400,
459
+ "youngs_modulus": 120000000000,
460
+ "thermal_expansion_coefficient": 1.77e-05,
461
+ }
462
+ default_dielectric_property_values = {
463
+ "conductivity": 0,
464
+ "dielectric_loss_tangent": 0.02,
465
+ "magnetic_loss_tangent": 0,
466
+ "mass_density": 1900,
467
+ "permittivity": 4.4,
468
+ "permeability": 1,
469
+ "poisson_ratio": 0.28,
470
+ "specific_heat": 1150,
471
+ "thermal_conductivity": 0.294,
472
+ "youngs_modulus": 11000000000,
473
+ "thermal_expansion_coefficient": 1.5e-05,
474
+ }
475
+
449
476
  def __init__(self, edb: Edb):
450
477
  self.__edb = edb
451
478
  self.__edb_definition = edb.edb_api.definition
@@ -520,14 +547,14 @@ class Materials(object):
520
547
 
521
548
  return material
522
549
 
523
- def add_conductor_material(self, name, conductivity, **kwargs):
550
+ def add_conductor_material(self, name, conductivity=58000000, **kwargs):
524
551
  """Add a new conductor material.
525
552
 
526
553
  Parameters
527
554
  ----------
528
555
  name : str
529
556
  Name of the new material.
530
- conductivity : str, float, int
557
+ conductivity : str, float, int, optional
531
558
  Conductivity of the new material.
532
559
 
533
560
  Returns
@@ -535,10 +562,11 @@ class Materials(object):
535
562
  :class:`pyedb.dotnet.database.materials.Material`
536
563
 
537
564
  """
565
+ props = self.default_conductor_property_values.copy()
566
+ props["conductivity"] = conductivity
538
567
  extended_kwargs = {key: value for (key, value) in kwargs.items()}
539
- extended_kwargs["conductivity"] = conductivity
540
- material = self.add_material(name, **extended_kwargs)
541
-
568
+ props.update(extended_kwargs)
569
+ material = self.add_material(name, **props)
542
570
  return material
543
571
 
544
572
  def add_dielectric_material(self, name, permittivity, dielectric_loss_tangent, **kwargs):
@@ -548,20 +576,21 @@ class Materials(object):
548
576
  ----------
549
577
  name : str
550
578
  Name of the new material.
551
- permittivity : str, float, int
579
+ permittivity : str, float, int, optional
552
580
  Permittivity of the new material.
553
- dielectric_loss_tangent : str, float, int
581
+ dielectric_loss_tangent : str, float, int, optional
554
582
  Dielectric loss tangent of the new material.
555
583
 
556
584
  Returns
557
585
  -------
558
586
  :class:`pyedb.dotnet.database.materials.Material`
559
587
  """
588
+ props = self.default_dielectric_property_values.copy()
589
+ props["permittivity"] = permittivity
590
+ props["dielectric_loss_tangent"] = dielectric_loss_tangent
560
591
  extended_kwargs = {key: value for (key, value) in kwargs.items()}
561
- extended_kwargs["permittivity"] = permittivity
562
- extended_kwargs["dielectric_loss_tangent"] = dielectric_loss_tangent
563
- material = self.add_material(name, **extended_kwargs)
564
-
592
+ props.update(extended_kwargs)
593
+ material = self.add_material(name, **props)
565
594
  return material
566
595
 
567
596
  def add_djordjevicsarkar_dielectric(