Skip to content

Commit eca2ef6

Browse files
Fix export to q3d (#4615)
Co-authored-by: maxcapodi78 <Shark78> Co-authored-by: Samuel Lopez <[email protected]>
1 parent 0f10b50 commit eca2ef6

File tree

4 files changed

+99
-80
lines changed

4 files changed

+99
-80
lines changed

examples/05-Q3D/Q3D_DC_IR.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
import os
1313
import pyaedt
14-
14+
from pyedb import Edb
1515
##########################################################
1616
# Set AEDT version
1717
# ~~~~~~~~~~~~~~~~
@@ -29,7 +29,7 @@
2929
coil = pyaedt.downloads.download_file('inductance_3d_component', 'air_coil.a3dcomp')
3030
res = pyaedt.downloads.download_file('resistors', 'Res_0402.a3dcomp')
3131
project_name = pyaedt.generate_unique_name("HSD")
32-
output_edb = os.path.join(project_dir, project_name + '.aedb')
32+
output_edb = os.path.join(project_dir, project_name + '_out.aedb')
3333
output_q3d = os.path.join(project_dir, project_name + '_q3d.aedt')
3434

3535
###############################################################################
@@ -38,13 +38,13 @@
3838
# Open the EDB project and create a cutout on the selected nets
3939
# before exporting to Q3D.
4040

41-
edb = pyaedt.Edb(aedb_project, edbversion=aedt_version)
41+
edb = Edb(aedb_project, edbversion=aedt_version)
4242
edb.cutout(["1.2V_AVDLL_PLL", "1.2V_AVDDL", "1.2V_DVDDL", "NetR106_1"],
4343
["GND"],
4444
output_aedb_path=output_edb,
4545
use_pyaedt_extent_computing=True,
4646
)
47-
47+
edb.layout_validation.disjoint_nets("GND", keep_only_main_net=True)
4848
###############################################################################
4949
# Identify pin positions
5050
# ~~~~~~~~~~~~~~~~~~~~~~
@@ -90,8 +90,7 @@
9090
# Save and close EDB
9191
# ~~~~~~~~~~~~~~~~~~
9292
# Save and close EDB. Then, open EDT in HFSS 3D Layout to generate the 3D model.
93-
94-
edb.save_edb()
93+
edb.save_edb_as(output_edb)
9594
edb.close_edb()
9695

9796
h3d = pyaedt.Hfss3dLayout(output_edb, specified_version=aedt_version, non_graphical=False, new_desktop_session=True)

pyaedt/modeler/cad/Primitives.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ def _parse_objs(self):
6969
self.__parent.cleanup_solids()
7070
self.__parent.logger.info_timer("3D Modeler objects parsed.")
7171
elif self.__obj_type == "p":
72-
self.__parent.logger.info("Parsing design points. This operation can take time")
73-
self.__parent.logger.reset_timer()
72+
# self.__parent.logger.info("Parsing design points. This operation can take time")
73+
# self.__parent.logger.reset_timer()
7474
self.__parent.add_new_points()
7575
self.__parent.cleanup_points()
76-
self.__parent.logger.info_timer("3D Modeler objects parsed.")
76+
# self.__parent.logger.info_timer("3D Modeler objects parsed.")
7777
elif self.__obj_type == "u":
7878
self.__parent.add_new_user_defined_component()
7979

pyaedt/modeler/modelerpcb.py

-13
Original file line numberDiff line numberDiff line change
@@ -119,20 +119,7 @@ def edb(self):
119119
isaedtowned=True,
120120
oproject=self._app.oproject,
121121
)
122-
elif not inside_desktop:
123-
if self._app.project_timestamp_changed:
124-
if self._edb:
125-
self._edb.close_edb()
126-
from pyedb import Edb
127122

128-
self._edb = Edb(
129-
self._edb_folder,
130-
self._app.design_name,
131-
True,
132-
self._app._aedt_version,
133-
isaedtowned=True,
134-
oproject=self._app.oproject,
135-
)
136123
return self._edb
137124

138125
@property

pyaedt/modules/SolveSetup.py

+91-58
Original file line numberDiff line numberDiff line change
@@ -1901,8 +1901,9 @@ def export_to_hfss(self, output_file, keep_net_name=False):
19011901
@pyaedt_function_handler()
19021902
def _get_net_names(self, app, file_fullname):
19031903
primitives_3d_pts_per_nets = self._get_primitives_points_per_net()
1904+
self.p_app.logger.info("Processing vias...")
19041905
via_per_nets = self._get_via_position_per_net()
1905-
pass
1906+
self.p_app.logger.info("Vias processing completed.")
19061907
layers_elevation = {
19071908
lay.name: lay.lower_elevation + lay.thickness / 2
19081909
for lay in list(self.p_app.modeler.edb.stackup.signal_layers.values())
@@ -1918,49 +1919,49 @@ def _get_net_names(self, app, file_fullname):
19181919
for obj in aedtapp.modeler.solid_objects
19191920
if not obj.material_name in aedtapp.modeler.materials.dielectrics
19201921
]
1921-
for net, primitives in primitives_3d_pts_per_nets.items():
1922-
obj_dict = {}
1923-
for position in primitives_3d_pts_per_nets[net]:
1922+
for net, positions in primitives_3d_pts_per_nets.items():
1923+
object_names = []
1924+
for position in positions:
19241925
aedtapp_objs = [p for p in aedtapp.modeler.get_bodynames_from_position(position) if p in metal_object]
1925-
if aedtapp_objs:
1926-
for p in aedtapp.modeler.get_bodynames_from_position(position, None, False):
1927-
if p in metal_object:
1928-
obj_ind = aedtapp.modeler.objects[p].id
1929-
if obj_ind not in obj_dict:
1930-
obj_dict[obj_ind] = aedtapp.modeler.objects[obj_ind]
1926+
object_names.extend(aedtapp_objs)
19311927
if net in via_per_nets:
19321928
for via_pos in via_per_nets[net]:
1933-
for p in aedtapp.modeler.get_bodynames_from_position(via_pos, None, False):
1934-
if p in metal_object:
1935-
obj_ind = aedtapp.modeler.objects[p].id
1936-
if obj_ind not in obj_dict:
1937-
obj_dict[obj_ind] = aedtapp.modeler.objects[obj_ind]
1938-
for lay_el in list(layers_elevation.values()):
1939-
pad_pos = via_pos[:2]
1940-
pad_pos.append(lay_el)
1941-
pad_objs = aedtapp.modeler.get_bodynames_from_position(pad_pos, None, False)
1942-
for pad_obj in pad_objs:
1943-
if pad_obj in metal_object:
1944-
pad_ind = aedtapp.modeler.objects[pad_obj].id
1945-
if pad_ind not in obj_dict:
1946-
obj_dict[pad_ind] = aedtapp.modeler.objects[pad_ind]
1947-
obj_list = list(obj_dict.values())
1929+
object_names.extend(
1930+
[
1931+
p
1932+
for p in aedtapp.modeler.get_bodynames_from_position(via_pos, None, False)
1933+
if p in metal_object
1934+
]
1935+
)
1936+
1937+
for lay_el in list(layers_elevation.values()):
1938+
pad_pos = via_pos[:2]
1939+
pad_pos.append(lay_el)
1940+
object_names.extend(
1941+
[
1942+
p
1943+
for p in aedtapp.modeler.get_bodynames_from_position(pad_pos, None, False)
1944+
if p in metal_object
1945+
]
1946+
)
1947+
19481948
net = net.replace(".", "_")
1949-
if len(obj_list) == 1:
1950-
net = net.replace("-", "m")
1951-
net = net.replace("+", "p")
1952-
net_name = re.sub("[^a-zA-Z0-9 .\n]", "_", net)
1953-
obj_list[0].name = net_name
1954-
obj_list[0].color = [randrange(255), randrange(255), randrange(255)]
1955-
elif len(obj_list) > 1:
1956-
united_object = aedtapp.modeler.unite(obj_list, purge=True)
1949+
net = net.replace("-", "m")
1950+
net = net.replace("+", "p")
1951+
net_name = re.sub("[^a-zA-Z0-9 .\n]", "_", net)
1952+
self.p_app.logger.info("Renaming primitives for net {}...".format(net_name))
1953+
object_names = list(set(object_names))
1954+
if len(object_names) == 1:
1955+
1956+
object_p = aedtapp.modeler[object_names[0]]
1957+
object_p.name = net_name
1958+
object_p.color = [randrange(255), randrange(255), randrange(255)] # nosec
1959+
elif len(object_names) > 1:
1960+
united_object = aedtapp.modeler.unite(object_names, purge=True)
19571961
obj_ind = aedtapp.modeler.objects[united_object].id
19581962
if obj_ind:
1959-
net = net.replace("-", "m")
1960-
net = net.replace("+", "p")
1961-
net_name = re.sub("[^a-zA-Z0-9 .\n]", "_", net)
19621963
aedtapp.modeler.objects[obj_ind].name = net_name
1963-
aedtapp.modeler.objects[obj_ind].color = [randrange(255), randrange(255), randrange(255)]
1964+
aedtapp.modeler.objects[obj_ind].color = [randrange(255), randrange(255), randrange(255)] # nosec
19641965

19651966
if aedtapp.design_type == "Q3D Extractor":
19661967
aedtapp.auto_identify_nets()
@@ -1973,21 +1974,61 @@ def _get_primitives_points_per_net(self):
19731974
return
19741975
net_primitives = edb.modeler.primitives_by_net
19751976
primitive_dict = {}
1977+
layers_elevation = {
1978+
lay.name: lay.lower_elevation + lay.thickness / 2
1979+
for lay in list(self.p_app.modeler.edb.stackup.signal_layers.values())
1980+
}
19761981
for net, primitives in net_primitives.items():
19771982
primitive_dict[net] = []
1978-
n = 0
1979-
while len(primitive_dict[net]) < len(net_primitives[net]):
1980-
if n > 1000: # adding 1000 as maximum value to prevent infinite loop
1981-
return
1982-
n += 20
1983-
primitive_dict[net] = []
1984-
for prim in primitives:
1985-
layer = edb.stackup.signal_layers[prim.layer_name]
1986-
z = layer.lower_elevation + layer.thickness / 2
1987-
pt = self._get_point_inside_primitive(prim, n)
1988-
if pt:
1989-
pt.append(z)
1990-
primitive_dict[net].append(pt)
1983+
self.p_app.logger.info("Processing net {}...".format(net))
1984+
for prim in primitives:
1985+
1986+
if prim.layer_name not in layers_elevation:
1987+
continue
1988+
z = layers_elevation[prim.layer_name]
1989+
if "EdbPath" in str(prim):
1990+
points = list(prim.center_line.Points)
1991+
pt = [points[0].X.ToDouble(), points[0].Y.ToDouble()]
1992+
pt.append(z)
1993+
next_p = int(len(points) / 4)
1994+
pt = [points[next_p].X.ToDouble(), points[next_p].Y.ToDouble()]
1995+
pt.append(z)
1996+
primitive_dict[net].append(pt)
1997+
1998+
elif "EdbPolygon" in str(prim):
1999+
pdata_orig = prim.polygon_data.edb_api
2000+
pdata = self.p_app.modeler.edb._edb.Geometry.PolygonData.CreateFromArcs(
2001+
pdata_orig.GetArcData(), True
2002+
)
2003+
2004+
pdata.Scale(0.99, pdata.GetBoundingCircleCenter())
2005+
points = [[], []]
2006+
for point in list(pdata.Points):
2007+
points[0].append(point.X.ToDouble())
2008+
points[1].append(point.Y.ToDouble())
2009+
# points = prim.points()
2010+
pt = [points[0][0], points[1][0]]
2011+
pt.append(z)
2012+
primitive_dict[net].append(pt)
2013+
next_p = int(len(points[0]) / 4)
2014+
pt = [points[0][next_p], points[1][next_p]]
2015+
pt.append(z)
2016+
primitive_dict[net].append(pt)
2017+
next_p = int(len(points[0]) / 2)
2018+
pt = [points[0][next_p], points[1][next_p]]
2019+
pt.append(z)
2020+
primitive_dict[net].append(pt)
2021+
2022+
else:
2023+
n = 0
2024+
while n < 1000:
2025+
n += 10
2026+
pt = self._get_point_inside_primitive(prim, n)
2027+
if pt:
2028+
pt.append(z)
2029+
primitive_dict[net].append(pt)
2030+
break
2031+
self.p_app.logger.info("Net processing completed.")
19912032
return primitive_dict
19922033

19932034
@pyaedt_function_handler()
@@ -2014,14 +2055,6 @@ def _get_point_inside_primitive(self, primitive, n):
20142055
if GeometryOperators.point_in_polygon([x, y], [primitive_x_points, primitive_y_points]) == 1:
20152056
return [x, y]
20162057

2017-
@pyaedt_function_handler()
2018-
def _get_polygon_centroid(self, arcs=None):
2019-
if arcs:
2020-
k = len(arcs[0])
2021-
x = sum(arcs[0]) / k
2022-
y = sum(arcs[1]) / k
2023-
return [x, y]
2024-
20252058
@pyaedt_function_handler()
20262059
def _convert_edb_to_aedt_units(self, input_dict=None, output_unit=0.001):
20272060
if input_dict:

0 commit comments

Comments
 (0)