Skip to content

Commit

Permalink
Fix export to q3d (#4615)
Browse files Browse the repository at this point in the history
Co-authored-by: maxcapodi78 <Shark78>
Co-authored-by: Samuel Lopez <[email protected]>
  • Loading branch information
maxcapodi78 and Samuelopez-ansys authored May 3, 2024
1 parent 0f10b50 commit eca2ef6
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 80 deletions.
11 changes: 5 additions & 6 deletions examples/05-Q3D/Q3D_DC_IR.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import os
import pyaedt

from pyedb import Edb
##########################################################
# Set AEDT version
# ~~~~~~~~~~~~~~~~
Expand All @@ -29,7 +29,7 @@
coil = pyaedt.downloads.download_file('inductance_3d_component', 'air_coil.a3dcomp')
res = pyaedt.downloads.download_file('resistors', 'Res_0402.a3dcomp')
project_name = pyaedt.generate_unique_name("HSD")
output_edb = os.path.join(project_dir, project_name + '.aedb')
output_edb = os.path.join(project_dir, project_name + '_out.aedb')
output_q3d = os.path.join(project_dir, project_name + '_q3d.aedt')

###############################################################################
Expand All @@ -38,13 +38,13 @@
# Open the EDB project and create a cutout on the selected nets
# before exporting to Q3D.

edb = pyaedt.Edb(aedb_project, edbversion=aedt_version)
edb = Edb(aedb_project, edbversion=aedt_version)
edb.cutout(["1.2V_AVDLL_PLL", "1.2V_AVDDL", "1.2V_DVDDL", "NetR106_1"],
["GND"],
output_aedb_path=output_edb,
use_pyaedt_extent_computing=True,
)

edb.layout_validation.disjoint_nets("GND", keep_only_main_net=True)
###############################################################################
# Identify pin positions
# ~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -90,8 +90,7 @@
# Save and close EDB
# ~~~~~~~~~~~~~~~~~~
# Save and close EDB. Then, open EDT in HFSS 3D Layout to generate the 3D model.

edb.save_edb()
edb.save_edb_as(output_edb)
edb.close_edb()

h3d = pyaedt.Hfss3dLayout(output_edb, specified_version=aedt_version, non_graphical=False, new_desktop_session=True)
Expand Down
6 changes: 3 additions & 3 deletions pyaedt/modeler/cad/Primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ def _parse_objs(self):
self.__parent.cleanup_solids()
self.__parent.logger.info_timer("3D Modeler objects parsed.")
elif self.__obj_type == "p":
self.__parent.logger.info("Parsing design points. This operation can take time")
self.__parent.logger.reset_timer()
# self.__parent.logger.info("Parsing design points. This operation can take time")
# self.__parent.logger.reset_timer()
self.__parent.add_new_points()
self.__parent.cleanup_points()
self.__parent.logger.info_timer("3D Modeler objects parsed.")
# self.__parent.logger.info_timer("3D Modeler objects parsed.")
elif self.__obj_type == "u":
self.__parent.add_new_user_defined_component()

Expand Down
13 changes: 0 additions & 13 deletions pyaedt/modeler/modelerpcb.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,20 +119,7 @@ def edb(self):
isaedtowned=True,
oproject=self._app.oproject,
)
elif not inside_desktop:
if self._app.project_timestamp_changed:
if self._edb:
self._edb.close_edb()
from pyedb import Edb

self._edb = Edb(
self._edb_folder,
self._app.design_name,
True,
self._app._aedt_version,
isaedtowned=True,
oproject=self._app.oproject,
)
return self._edb

@property
Expand Down
149 changes: 91 additions & 58 deletions pyaedt/modules/SolveSetup.py
Original file line number Diff line number Diff line change
Expand Up @@ -1901,8 +1901,9 @@ def export_to_hfss(self, output_file, keep_net_name=False):
@pyaedt_function_handler()
def _get_net_names(self, app, file_fullname):
primitives_3d_pts_per_nets = self._get_primitives_points_per_net()
self.p_app.logger.info("Processing vias...")
via_per_nets = self._get_via_position_per_net()
pass
self.p_app.logger.info("Vias processing completed.")
layers_elevation = {
lay.name: lay.lower_elevation + lay.thickness / 2
for lay in list(self.p_app.modeler.edb.stackup.signal_layers.values())
Expand All @@ -1918,49 +1919,49 @@ def _get_net_names(self, app, file_fullname):
for obj in aedtapp.modeler.solid_objects
if not obj.material_name in aedtapp.modeler.materials.dielectrics
]
for net, primitives in primitives_3d_pts_per_nets.items():
obj_dict = {}
for position in primitives_3d_pts_per_nets[net]:
for net, positions in primitives_3d_pts_per_nets.items():
object_names = []
for position in positions:
aedtapp_objs = [p for p in aedtapp.modeler.get_bodynames_from_position(position) if p in metal_object]
if aedtapp_objs:
for p in aedtapp.modeler.get_bodynames_from_position(position, None, False):
if p in metal_object:
obj_ind = aedtapp.modeler.objects[p].id
if obj_ind not in obj_dict:
obj_dict[obj_ind] = aedtapp.modeler.objects[obj_ind]
object_names.extend(aedtapp_objs)
if net in via_per_nets:
for via_pos in via_per_nets[net]:
for p in aedtapp.modeler.get_bodynames_from_position(via_pos, None, False):
if p in metal_object:
obj_ind = aedtapp.modeler.objects[p].id
if obj_ind not in obj_dict:
obj_dict[obj_ind] = aedtapp.modeler.objects[obj_ind]
for lay_el in list(layers_elevation.values()):
pad_pos = via_pos[:2]
pad_pos.append(lay_el)
pad_objs = aedtapp.modeler.get_bodynames_from_position(pad_pos, None, False)
for pad_obj in pad_objs:
if pad_obj in metal_object:
pad_ind = aedtapp.modeler.objects[pad_obj].id
if pad_ind not in obj_dict:
obj_dict[pad_ind] = aedtapp.modeler.objects[pad_ind]
obj_list = list(obj_dict.values())
object_names.extend(
[
p
for p in aedtapp.modeler.get_bodynames_from_position(via_pos, None, False)
if p in metal_object
]
)

for lay_el in list(layers_elevation.values()):
pad_pos = via_pos[:2]
pad_pos.append(lay_el)
object_names.extend(
[
p
for p in aedtapp.modeler.get_bodynames_from_position(pad_pos, None, False)
if p in metal_object
]
)

net = net.replace(".", "_")
if len(obj_list) == 1:
net = net.replace("-", "m")
net = net.replace("+", "p")
net_name = re.sub("[^a-zA-Z0-9 .\n]", "_", net)
obj_list[0].name = net_name
obj_list[0].color = [randrange(255), randrange(255), randrange(255)]
elif len(obj_list) > 1:
united_object = aedtapp.modeler.unite(obj_list, purge=True)
net = net.replace("-", "m")
net = net.replace("+", "p")
net_name = re.sub("[^a-zA-Z0-9 .\n]", "_", net)
self.p_app.logger.info("Renaming primitives for net {}...".format(net_name))
object_names = list(set(object_names))
if len(object_names) == 1:

object_p = aedtapp.modeler[object_names[0]]
object_p.name = net_name
object_p.color = [randrange(255), randrange(255), randrange(255)] # nosec
elif len(object_names) > 1:
united_object = aedtapp.modeler.unite(object_names, purge=True)
obj_ind = aedtapp.modeler.objects[united_object].id
if obj_ind:
net = net.replace("-", "m")
net = net.replace("+", "p")
net_name = re.sub("[^a-zA-Z0-9 .\n]", "_", net)
aedtapp.modeler.objects[obj_ind].name = net_name
aedtapp.modeler.objects[obj_ind].color = [randrange(255), randrange(255), randrange(255)]
aedtapp.modeler.objects[obj_ind].color = [randrange(255), randrange(255), randrange(255)] # nosec

if aedtapp.design_type == "Q3D Extractor":
aedtapp.auto_identify_nets()
Expand All @@ -1973,21 +1974,61 @@ def _get_primitives_points_per_net(self):
return
net_primitives = edb.modeler.primitives_by_net
primitive_dict = {}
layers_elevation = {
lay.name: lay.lower_elevation + lay.thickness / 2
for lay in list(self.p_app.modeler.edb.stackup.signal_layers.values())
}
for net, primitives in net_primitives.items():
primitive_dict[net] = []
n = 0
while len(primitive_dict[net]) < len(net_primitives[net]):
if n > 1000: # adding 1000 as maximum value to prevent infinite loop
return
n += 20
primitive_dict[net] = []
for prim in primitives:
layer = edb.stackup.signal_layers[prim.layer_name]
z = layer.lower_elevation + layer.thickness / 2
pt = self._get_point_inside_primitive(prim, n)
if pt:
pt.append(z)
primitive_dict[net].append(pt)
self.p_app.logger.info("Processing net {}...".format(net))
for prim in primitives:

if prim.layer_name not in layers_elevation:
continue
z = layers_elevation[prim.layer_name]
if "EdbPath" in str(prim):
points = list(prim.center_line.Points)
pt = [points[0].X.ToDouble(), points[0].Y.ToDouble()]
pt.append(z)
next_p = int(len(points) / 4)
pt = [points[next_p].X.ToDouble(), points[next_p].Y.ToDouble()]
pt.append(z)
primitive_dict[net].append(pt)

elif "EdbPolygon" in str(prim):
pdata_orig = prim.polygon_data.edb_api
pdata = self.p_app.modeler.edb._edb.Geometry.PolygonData.CreateFromArcs(
pdata_orig.GetArcData(), True
)

pdata.Scale(0.99, pdata.GetBoundingCircleCenter())
points = [[], []]
for point in list(pdata.Points):
points[0].append(point.X.ToDouble())
points[1].append(point.Y.ToDouble())
# points = prim.points()
pt = [points[0][0], points[1][0]]
pt.append(z)
primitive_dict[net].append(pt)
next_p = int(len(points[0]) / 4)
pt = [points[0][next_p], points[1][next_p]]
pt.append(z)
primitive_dict[net].append(pt)
next_p = int(len(points[0]) / 2)
pt = [points[0][next_p], points[1][next_p]]
pt.append(z)
primitive_dict[net].append(pt)

else:
n = 0
while n < 1000:
n += 10
pt = self._get_point_inside_primitive(prim, n)
if pt:
pt.append(z)
primitive_dict[net].append(pt)
break
self.p_app.logger.info("Net processing completed.")
return primitive_dict

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

@pyaedt_function_handler()
def _get_polygon_centroid(self, arcs=None):
if arcs:
k = len(arcs[0])
x = sum(arcs[0]) / k
y = sum(arcs[1]) / k
return [x, y]

@pyaedt_function_handler()
def _convert_edb_to_aedt_units(self, input_dict=None, output_unit=0.001):
if input_dict:
Expand Down

0 comments on commit eca2ef6

Please sign in to comment.