Skip to content

Commit adae66d

Browse files
authored
Merge branch 'main' into create_circuit_schematics
2 parents 808db3f + 3012455 commit adae66d

11 files changed

+251
-69
lines changed

_unittest/test_01_3dlayout_edb.py

+13-1
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ def test_15_3dplacement(self):
307307

308308
def test_16_differential_ports(self):
309309
self.aedtapp.set_active_design(self.design_name)
310-
pins = self.aedtapp.modeler.components["R3"].pins
310+
pins = list(self.aedtapp.modeler.components["R3"].pins.keys())
311311
assert self.aedtapp.create_differential_port(pins[0], pins[1], "test_differential", deembed=True)
312312
assert "test_differential" in self.aedtapp.port_list
313313

@@ -376,3 +376,15 @@ def test_22_change_design_settings(self):
376376
assert (
377377
self.aedtapp.get_oo_property_value(self.aedtapp.odesign, "Design Settings", "DCExtrapolation") == "Advanced"
378378
)
379+
380+
def test_23_dissolve_element(self):
381+
comp = self.aedtapp.modeler.components["D1"]
382+
pins = {name: pin for name, pin in comp.pins.items() if name in ["D1-1", "D1-2", "D1-7"]}
383+
self.aedtapp.dissolve_component("D1")
384+
comp = self.aedtapp.modeler.create_components_on_pins(list(pins.keys()))
385+
nets = [
386+
list(pins.values())[0].net_name,
387+
list(pins.values())[1].net_name,
388+
]
389+
assert self.aedtapp.create_ports_on_component_by_nets(comp.name, nets)
390+
assert self.aedtapp.create_pec_on_component_by_nets(comp.name, "GND")

_unittest/test_03_Materials.py

+10-6
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,18 @@ def test_02_create_material(self):
9292
assert mat1.get_curve_coreloss_type() == "Power Ferrite"
9393
assert isinstance(mat1.material_appearance, list)
9494

95-
mat1.material_appearance = [11, 22, 0]
96-
assert mat1.material_appearance == [11, 22, 0]
97-
mat1.material_appearance = ["11", "22", "10"]
98-
assert mat1.material_appearance == [11, 22, 10]
95+
mat1.material_appearance = [11, 22, 0, 0.5]
96+
assert mat1.material_appearance == [11, 22, 0, 0.5]
97+
mat1.material_appearance = ["11", "22", "10", "0.5"]
98+
assert mat1.material_appearance == [11, 22, 10, 0.5]
9999
with pytest.raises(ValueError):
100-
mat1.material_appearance = [11, 22, 300]
100+
mat1.material_appearance = [11, 22, 300, 0.5]
101101
with pytest.raises(ValueError):
102-
mat1.material_appearance = [11, -22, 0]
102+
mat1.material_appearance = [11, 22, 100, 1.5]
103+
with pytest.raises(ValueError):
104+
mat1.material_appearance = [11, -22, 0, 0.5]
105+
with pytest.raises(ValueError):
106+
mat1.material_appearance = [11, 22, 0, -1]
103107
with pytest.raises(ValueError):
104108
mat1.material_appearance = [11, 22]
105109

examples/02-HFSS/HFSS_Choke.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import os
1313
import pyaedt
1414

15-
project_name = pyaedt.generate_unique_project_name(project_name="choke")
15+
project_name = pyaedt.generate_unique_project_name(rootname=r"C:\Data\Support\Test", folder_name="choke", project_name="choke")
1616

1717
##########################################################
1818
# Set AEDT version

examples/02-HFSS/Probe_Fed_Patch.py

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
solution_type="Terminal",
6565
designname="patch",
6666
non_graphical=non_graphical,
67+
new_desktop_session=True,
6768
specified_version=aedt_version)
6869

6970
hfss.modeler.model_units = length_units

pyaedt/hfss3dlayout.py

+54-1
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,25 @@ def create_wave_port_from_two_conductors(self, primivitivenames=[""], edgenumber
363363
else:
364364
return False
365365

366+
@pyaedt_function_handler()
367+
def dissolve_component(self, component_name):
368+
"""Dissolve a component and remove it from 3D Layout.
369+
370+
Parameters
371+
----------
372+
component_name : str
373+
Name of the component.
374+
375+
Returns
376+
-------
377+
bool
378+
``True`` when successful, ``False`` when failed.
379+
380+
381+
"""
382+
self.oeditor.DissolveComponents(["NAME:elements", component_name])
383+
return True
384+
366385
@pyaedt_function_handler()
367386
def create_ports_on_component_by_nets(
368387
self,
@@ -407,9 +426,43 @@ def create_ports_on_component_by_nets(
407426
ports.append(bound)
408427
return ports
409428

429+
@pyaedt_function_handler()
430+
def create_pec_on_component_by_nets(
431+
self,
432+
component_name,
433+
nets,
434+
):
435+
"""Create a PEC connection on a component for a list of nets.
436+
437+
Parameters
438+
----------
439+
component_name : str
440+
Component name.
441+
nets : str, list
442+
Nets to include.
443+
444+
445+
Returns
446+
-------
447+
bool
448+
``True`` when successful, ``False`` when failed.
449+
450+
References
451+
----------
452+
453+
>>> oEditor.CreateEdgePort
454+
"""
455+
if isinstance(nets, list):
456+
pass
457+
else:
458+
nets = [nets]
459+
net_array = ["NAME:Nets"] + nets
460+
self.oeditor.CreatePortsOnComponentsByNet(["NAME:Components", component_name], net_array, "PEC", "0", "0", "0")
461+
return True
462+
410463
@pyaedt_function_handler()
411464
def create_differential_port(self, via_signal, via_reference, port_name, deembed=True):
412-
"""Create a new differential port.
465+
"""Create a differential port.
413466
414467
Parameters
415468
----------

pyaedt/modeler/cad/Primitives.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -6233,10 +6233,8 @@ def create_region(self, pad_value=300, pad_type="Percentage Offset", region_name
62336233
is_percentage = True
62346234
if kwarg.get("pad_percent", False):
62356235
pad_percent = kwarg["pad_percent"]
6236-
else:
6237-
pad_percent = 300
6238-
pad_value = pad_percent
6239-
if isinstance(pad_value, list):
6236+
pad_value = pad_percent
6237+
if isinstance(pad_value, list) and len(pad_value) < 6:
62406238
pad_value = [pad_value[i // 2 + 3 * (i % 2)] for i in range(6)]
62416239
pad_type = ["Absolute Offset", "Percentage Offset"][int(is_percentage)]
62426240

pyaedt/modeler/cad/Primitives2D.py

+39-14
Original file line numberDiff line numberDiff line change
@@ -281,17 +281,26 @@ def create_regular_polygon(
281281
return self._create_object(new_object_name, **kwargs)
282282

283283
@pyaedt_function_handler()
284-
def create_region(self, pad_percent=300, is_percentage=True):
284+
def create_region(self, pad_value=300, pad_type="Percentage Offset", region_name="Region", **kwarg):
285285
"""Create an air region.
286286
287287
Parameters
288288
----------
289-
pad_percent : float, str, list of floats or list of str, optional
290-
Same padding is applied if not a list. The default is ``300``.
291-
If a list of floats or strings, interpret as adding ``["+X", "+Y", "-X", "-Y"]`` for XY geometry mode,
292-
and ``["+R", "+Z", "-Z"]`` for RZ geometry mode.
293-
is_percentage : bool, optional
294-
Whether the region definition is a percentage or absolute value. The default is `True``.
289+
pad_value : float, str, list of floats or list of str, optional
290+
Padding values to apply. If a list is not provided, the same
291+
value is applied to all padding directions. If a list of floats
292+
or strings is provided, the values are
293+
interpreted as padding for ``["+X", "-X", "+Y", "-Y", "+Z", "-Z"]``.
294+
pad_type : str, optional
295+
Padding definition. The default is ``"Percentage Offset"``.
296+
Options are ``"Absolute Offset"``,
297+
``"Absolute Position"``, ``"Percentage Offset"``, and
298+
``"Transverse Percentage Offset"``. When using a list,
299+
different padding types can be provided for different
300+
directions.
301+
region_name : str, optional
302+
Region name. The default is ``None``, in which case the name
303+
is generated automatically.
295304
296305
Returns
297306
-------
@@ -303,19 +312,35 @@ def create_region(self, pad_percent=300, is_percentage=True):
303312
304313
>>> oEditor.CreateRegion
305314
"""
306-
if not isinstance(pad_percent, list):
307-
pad_percent = [pad_percent] * 4
315+
# backward compatibility
316+
if kwarg:
317+
if "is_percentage" in kwarg.keys():
318+
is_percentage = kwarg["is_percentage"]
319+
else:
320+
is_percentage = True
321+
if kwarg.get("pad_percent", False):
322+
pad_percent = kwarg["pad_percent"]
323+
pad_value = pad_percent
324+
if isinstance(pad_value, list) and len(pad_value) < 6:
325+
pad_value = [pad_value[i // 2 + 3 * (i % 2)] for i in range(6)]
326+
pad_type = ["Absolute Offset", "Percentage Offset"][int(is_percentage)]
327+
328+
if isinstance(pad_type, bool):
329+
pad_type = ["Absolute Offset", "Percentage Offset"][int(pad_type)]
330+
331+
if not isinstance(pad_value, list):
332+
pad_value = [pad_value] * 4
308333
if self._app.design_type == "2D Extractor" or (
309334
self._app.design_type == "Maxwell 2D" and self._app.odesign.GetGeometryMode() == "XY"
310335
):
311-
if len(pad_percent) != 4:
336+
if len(pad_value) != 4:
312337
self.logger.error("Wrong padding list provided. Four values have to be provided.")
313338
return False
314-
pad_percent = [pad_percent[0], pad_percent[2], pad_percent[1], pad_percent[3], 0, 0]
339+
pad_value = [pad_value[0], pad_value[2], pad_value[1], pad_value[3], 0, 0]
315340
else:
316-
if len(pad_percent) < 3:
341+
if len(pad_value) < 3:
317342
self.logger.error("Wrong padding list provided. Three values have to be provided for RZ geometry.")
318343
return False
319-
pad_percent = [pad_percent[0], 0, 0, 0, pad_percent[1], pad_percent[2]]
344+
pad_value = [pad_value[0], 0, 0, 0, pad_value[1], pad_value[2]]
320345

321-
return self._create_region(pad_percent, ["Absolute Offset", "Percentage Offset"][int(is_percentage)])
346+
return self._create_region(pad_value, pad_type, region_name, region_type="Region")

pyaedt/modeler/modelerpcb.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -914,7 +914,7 @@ def set_spice_model(self, component_name, model_path, model_name=None, subcircui
914914
pinNames.remove(pinNames[0])
915915
pinNames.remove(pinNames[0])
916916
break
917-
componentPins = self.components[component_name].pins
917+
componentPins = list(self.components[component_name].pins.keys())
918918
componentPins.reverse()
919919
if not pin_map:
920920
pin_map = []

pyaedt/modeler/pcb/Primitives3DLayout.py

+54
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,60 @@ def place_3d_component(
14891489
self.oeditor.CreatePortsOnComponentsByNet(["NAME:Components", comp.name], [], "Port", "0", "0", "0")
14901490
return comp #
14911491

1492+
@pyaedt_function_handler()
1493+
def create_components_on_pins(
1494+
self,
1495+
pins,
1496+
definition_name=None,
1497+
component_type="Other",
1498+
ref_des="U100",
1499+
):
1500+
"""Create a component based on a pin list.
1501+
1502+
Parameters
1503+
----------
1504+
pins : list
1505+
Pins to include in the new component.
1506+
definition_name : str, optional
1507+
Name of the component definition. If no name is provided, a
1508+
name is automatically assigned.
1509+
component_type : str, optional
1510+
Component type. The default is ``"Other"``.
1511+
ref_des : str, optional
1512+
Reference designator. The default is ``"U100"``.
1513+
1514+
Returns
1515+
-------
1516+
:class:`pyaedt.modeler.cad.object3dlayout.Components3DLayout`
1517+
1518+
"""
1519+
if not definition_name:
1520+
definition_name = generate_unique_name("COMP")
1521+
placement_layer = list(self.layers.signals.keys())[0]
1522+
for pin in self.pins.items():
1523+
if pin[0] == pins[0]:
1524+
placement_layer = pin[1].start_layer
1525+
break
1526+
comp_name = self.modeler.oeditor.CreateComponent(
1527+
[
1528+
"NAME:Contents",
1529+
"isRCS:=",
1530+
True,
1531+
"definition_name:=",
1532+
definition_name,
1533+
"type:=",
1534+
component_type,
1535+
"ref_des:=",
1536+
ref_des,
1537+
"placement_layer:=",
1538+
placement_layer,
1539+
"elements:=",
1540+
pins,
1541+
]
1542+
)
1543+
comp = Components3DLayout(self, comp_name.split(";")[-1])
1544+
return comp
1545+
14921546
def create_text(self, text, position, placement_layer="PostProcessing", angle=0, font_size=12):
14931547
"""Create a text primitive object.
14941548

0 commit comments

Comments
 (0)