From 0161379f99fb1d205acd44877f5f5e064bce45fd Mon Sep 17 00:00:00 2001 From: maxcapodi78 Date: Tue, 30 Apr 2024 15:22:43 +0200 Subject: [PATCH 1/4] fixed method export_to_q3d and export_to_hfss --- examples/05-Q3D/Q3D_DC_IR.py | 11 +-- pyaedt/modeler/cad/Primitives.py | 6 +- pyaedt/modules/SolveSetup.py | 154 +++++++++++++++++++++---------- 3 files changed, 111 insertions(+), 60 deletions(-) diff --git a/examples/05-Q3D/Q3D_DC_IR.py b/examples/05-Q3D/Q3D_DC_IR.py index 20c7e451384..1b2979d1b9e 100644 --- a/examples/05-Q3D/Q3D_DC_IR.py +++ b/examples/05-Q3D/Q3D_DC_IR.py @@ -11,7 +11,7 @@ import os import pyaedt - +from pyedb import Edb ########################################################## # Set AEDT version # ~~~~~~~~~~~~~~~~ @@ -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') ############################################################################### @@ -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 # ~~~~~~~~~~~~~~~~~~~~~~ @@ -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) diff --git a/pyaedt/modeler/cad/Primitives.py b/pyaedt/modeler/cad/Primitives.py index c34dde58a0b..590df3010d3 100644 --- a/pyaedt/modeler/cad/Primitives.py +++ b/pyaedt/modeler/cad/Primitives.py @@ -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() diff --git a/pyaedt/modules/SolveSetup.py b/pyaedt/modules/SolveSetup.py index 5597f9ff439..90065b0e403 100644 --- a/pyaedt/modules/SolveSetup.py +++ b/pyaedt/modules/SolveSetup.py @@ -1902,7 +1902,6 @@ def export_to_hfss(self, output_file, keep_net_name=False): def _get_net_names(self, app, file_fullname): primitives_3d_pts_per_nets = self._get_primitives_points_per_net() via_per_nets = self._get_via_position_per_net() - pass layers_elevation = { lay.name: lay.lower_elevation + lay.thickness / 2 for lay in list(self.p_app.modeler.edb.stackup.signal_layers.values()) @@ -1918,42 +1917,61 @@ 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) + # for name in aedtapp_objs: + # prim = aedtapp.modeler.objects[name] + # obj_dict[prim.id] = prim + # 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] 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 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) + object_names.extend( + [ + p + for p in aedtapp.modeler.get_bodynames_from_position(pad_pos, None, False) + if p in metal_object + ] + ) + # 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()) net = net.replace(".", "_") - if len(obj_list) == 1: + object_names = list(set(object_names)) + if len(object_names) == 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) + 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") @@ -1973,21 +1991,63 @@ 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 += 10 - 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: + # layer = edb.stackup.signal_layers[prim.layer_name] + # z = layer.lower_elevation + layer.thickness / 2 + 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) + 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.97, 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) + # pts = [[x,y,0] for x,y in zip(points[0], points[1])] + # pt = GeometryOperators.get_polygon_centroid(pts) + # if pt: + # pt[2] = 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() @@ -2014,14 +2074,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: From 8a05aec2bb4b97af07a371930a0bba7285940e53 Mon Sep 17 00:00:00 2001 From: maxcapodi78 Date: Tue, 30 Apr 2024 16:48:57 +0200 Subject: [PATCH 2/4] fixed method export_to_q3d and export_to_hfss --- pyaedt/modeler/modelerpcb.py | 28 ++++++++++++------------- pyaedt/modules/SolveSetup.py | 40 ++++++++++++++---------------------- 2 files changed, 29 insertions(+), 39 deletions(-) diff --git a/pyaedt/modeler/modelerpcb.py b/pyaedt/modeler/modelerpcb.py index 413cdc7856f..6f8049efc89 100644 --- a/pyaedt/modeler/modelerpcb.py +++ b/pyaedt/modeler/modelerpcb.py @@ -119,20 +119,20 @@ 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, - ) + # 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 diff --git a/pyaedt/modules/SolveSetup.py b/pyaedt/modules/SolveSetup.py index 90065b0e403..ef46dcbfd62 100644 --- a/pyaedt/modules/SolveSetup.py +++ b/pyaedt/modules/SolveSetup.py @@ -1901,7 +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() + 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()) @@ -1940,11 +1942,7 @@ def _get_net_names(self, app, file_fullname): if p in metal_object ] ) - # 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) @@ -1955,18 +1953,15 @@ def _get_net_names(self, app, file_fullname): if p in metal_object ] ) - # 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()) + net = net.replace(".", "_") + 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: - net = net.replace("-", "m") - net = net.replace("+", "p") - net_name = re.sub("[^a-zA-Z0-9 .\n]", "_", net) + object_p = aedtapp.modeler[object_names[0]] object_p.name = net_name object_p.color = [randrange(255), randrange(255), randrange(255)] @@ -1974,9 +1969,6 @@ def _get_net_names(self, app, file_fullname): 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)] @@ -1999,8 +1991,7 @@ def _get_primitives_points_per_net(self): primitive_dict[net] = [] self.p_app.logger.info("Processing net {}...".format(net)) for prim in primitives: - # layer = edb.stackup.signal_layers[prim.layer_name] - # z = layer.lower_elevation + layer.thickness / 2 + if prim.layer_name not in layers_elevation: continue z = layers_elevation[prim.layer_name] @@ -2008,6 +1999,9 @@ def _get_primitives_points_per_net(self): 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): @@ -2016,7 +2010,7 @@ def _get_primitives_points_per_net(self): pdata_orig.GetArcData(), True ) - pdata.Scale(0.97, pdata.GetBoundingCircleCenter()) + pdata.Scale(0.99, pdata.GetBoundingCircleCenter()) points = [[], []] for point in list(pdata.Points): points[0].append(point.X.ToDouble()) @@ -2033,11 +2027,7 @@ def _get_primitives_points_per_net(self): pt = [points[0][next_p], points[1][next_p]] pt.append(z) primitive_dict[net].append(pt) - # pts = [[x,y,0] for x,y in zip(points[0], points[1])] - # pt = GeometryOperators.get_polygon_centroid(pts) - # if pt: - # pt[2] = z - # primitive_dict[net].append(pt) + else: n = 0 while n < 1000: From b7763adfcfa7149830495e741a96390f4f694035 Mon Sep 17 00:00:00 2001 From: maxcapodi78 Date: Tue, 30 Apr 2024 16:49:15 +0200 Subject: [PATCH 3/4] fixed method export_to_q3d and export_to_hfss --- pyaedt/modeler/modelerpcb.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/pyaedt/modeler/modelerpcb.py b/pyaedt/modeler/modelerpcb.py index 6f8049efc89..5732b2875b7 100644 --- a/pyaedt/modeler/modelerpcb.py +++ b/pyaedt/modeler/modelerpcb.py @@ -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 From 0d19fa96fd5e4dc12f8256e2c20abb3d81b9d9b0 Mon Sep 17 00:00:00 2001 From: Samuel Lopez <85613111+Samuelopez-ansys@users.noreply.github.com> Date: Fri, 3 May 2024 16:35:25 +0200 Subject: [PATCH 4/4] Codacy skip --- pyaedt/modules/SolveSetup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyaedt/modules/SolveSetup.py b/pyaedt/modules/SolveSetup.py index 8151284c8d9..a482f804813 100644 --- a/pyaedt/modules/SolveSetup.py +++ b/pyaedt/modules/SolveSetup.py @@ -1955,13 +1955,13 @@ def _get_net_names(self, app, file_fullname): object_p = aedtapp.modeler[object_names[0]] object_p.name = net_name - object_p.color = [randrange(255), randrange(255), randrange(255)] + 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: 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()