Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix export to q3d #4615

Merged
merged 6 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
maxcapodi78 marked this conversation as resolved.
Show resolved Hide resolved
##########################################################
# 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
147 changes: 90 additions & 57 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,47 +1919,47 @@ 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)]
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)]

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
SMoraisAnsys marked this conversation as resolved.
Show resolved Hide resolved
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
Loading