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

Plot on layers #4531

Merged
merged 6 commits into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
48 changes: 48 additions & 0 deletions _unittest/test_41_3dlayout_modeler.py
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,19 @@ def test_41_test_create_polygon(self):
@pytest.mark.skipif(config["desktopVersion"] < "2023.2", reason="Working only from 2023 R2")
def test_42_post_processing(self, add_app):
test_post1 = add_app(project_name=test_post, application=Maxwell3d, subfolder=test_subfolder)

assert test_post1.post.create_fieldplot_layers(
[],
"Mag_H",
intrinsics={"Time": "1ms"},
nets=["GND", "V3P3_S5"],
)

assert test_post1.post.create_fieldplot_layers(
["UNNAMED_006"],
"Mag_H",
intrinsics={"Time": "1ms"},
)
assert test_post1.post.create_fieldplot_layers_nets(
[["TOP", "GND", "V3P3_S5"], ["PWR", "V3P3_S5"]],
"Mag_Volume_Force_Density",
Expand All @@ -679,19 +692,54 @@ def test_42_post_processing(self, add_app):
intrinsics={"Freq": "1GHz", "Phase": "0deg"},
plot_name="Test_Layers4",
)
assert test_post2.post.create_fieldplot_layers(
["TOP", "UNNAMED_004"],
"Mag_E",
intrinsics={"Freq": "1GHz", "Phase": "0deg"},
nets=["GND", "V3P3_S5"],
)
self.aedtapp.close_project(test_post2.project_name)

@pytest.mark.skipif(config["desktopVersion"] < "2023.2", reason="Working only from 2023 R2")
def test_42_post_processing_3d_layout(self, add_app):
test = add_app(
project_name="test_post_3d_layout_solved_23R2", application=Hfss3dLayout, subfolder=test_subfolder
)
assert test.post.create_fieldplot_layers(
[],
"Mag_H",
intrinsics={"Time": "1ms"},
)

assert test.post.create_fieldplot_layers(
["UNNAMED_002", "TOP"],
"Mag_H",
intrinsics={"Time": "1ms"},
)
assert test.post.create_fieldplot_layers(
["TOP"],
"Mag_H",
intrinsics={"Time": "1ms"},
)
assert test.post.create_fieldplot_layers(
["TOP", "PWR"],
"Mag_E",
intrinsics={"Freq": "1GHz"},
nets=["GND", "V3P3_S5"],
)
assert test.post.create_fieldplot_layers(
[],
"Mag_E",
intrinsics={"Freq": "1GHz"},
nets=["GND", "V3P3_S5"],
)
pl1 = test.post.create_fieldplot_layers_nets(
[["TOP", "GND", "V3P3_S5"], ["PWR", "V3P3_S5"]],
"Mag_E",
intrinsics={"Freq": "1GHz"},
plot_name="Test_Layers",
)

assert pl1
assert pl1.export_image_from_aedtplt(tempfile.gettempdir())
self.aedtapp.close_project(test.project_name)
Expand Down
216 changes: 188 additions & 28 deletions pyaedt/modules/PostProcessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -3040,6 +3040,7 @@ def _create_fieldplot(
plot_name=None,
filter_boxes=None,
field_type=None,
create_plot=True,
):
if not list_type.startswith("Layer") and self._app.design_type != "HFSS 3D Layout Design":
assignment = self._app.modeler.convert_to_selections(assignment, True)
Expand Down Expand Up @@ -3083,14 +3084,13 @@ def _create_fieldplot(
plot.name = plot_name
plot.plot_folder = plot_name
plot.filter_boxes = filter_boxes
plt = plot.create()
if "Maxwell" in self._app.design_type and "Transient" in self.post_solution_type:
self.ofieldsreporter.SetPlotsViewSolutionContext([plot_name], setup, "Time:" + intrinsics["Time"])
if plt:
self.field_plots[plot_name] = plot
return plot
else:
return False
if create_plot:
plt = plot.create()
if plt:
return plot
else:
return False
return plot

@pyaedt_function_handler(quantityName="quantity", setup_name="setup")
def _create_fieldplot_line_traces(
Expand Down Expand Up @@ -3294,10 +3294,168 @@ def create_fieldplot_line_traces(
field_type=field_type,
)

@pyaedt_function_handler()
def _get_3dl_layers_nets(self, layers, nets, setup):
lst_faces = []
new_layers = []
if not layers:
new_layers.extend(["{}".format(i) for i in self._app.modeler.edb.stackup.dielectric_layers.keys()])
for layer in self._app.modeler.edb.stackup.signal_layers.keys():
if not nets:
nets = list(self._app.modeler.edb.nets.nets.keys())
for el in nets:
try:
get_ids = self._odesign.GetGeometryIdsForNetLayerCombination(el, layer, setup)
except:
get_ids = []
if isinstance(get_ids, (tuple, list)) and len(get_ids) > 2:
lst_faces.extend([int(i) for i in get_ids[2:]])

else:
for layer in layers:
if layer in self._app.modeler.edb.stackup.dielectric_layers:
new_layers.append("{}".format(layer))
elif layer in self._app.modeler.edb.stackup.signal_layers:
if not nets:
nets = list(self._app.modeler.edb.nets.nets.keys())
for el in nets:
try:
get_ids = self._odesign.GetGeometryIdsForNetLayerCombination(el, layer, setup)
except:
get_ids = []
if isinstance(get_ids, (tuple, list)) and len(get_ids) > 2:
lst_faces.extend([int(i) for i in get_ids[2:]])
return lst_faces, new_layers

@pyaedt_function_handler()
def _get_3d_layers_nets(self, layers, nets):
dielectrics = []
new_layers = []
for k, v in self._app.modeler.user_defined_components.items():
if v.layout_component:
if not layers and not nets:
new_layers.extend(
[
"{}:{}#t=fill".format(k, i)
for i in v.layout_component.edb_object.stackup.signal_layers.keys()
]
)
new_layers.extend(
["{}:{}".format(k, i) for i in v.layout_component.edb_object.stackup.dielectric_layers.keys()]
)
elif not nets:
for layer in layers:
if layer in v.layout_component.edb_object.stackup.signal_layers:
new_layers.append("{}:{}#t=fill".format(k, layer))
elif layer in v.layout_component.edb_object.stackup.dielectric_layers:
new_layers.append("{}:{}".format(k, layer))
elif not layers:
for v in self._app.modeler.user_defined_components.values():
new_layers.extend(
[[i] + nets for i in v.layout_component.edb_object.stackup.signal_layers.keys()]
)
else:
for layer in layers:
if layer in v.layout_component.edb_object.stackup.signal_layers:
new_layers.append([layer] + nets)
elif layer in v.layout_component.edb_object.stackup.dielectric_layers:
dielectrics.append("{}:{}".format(k, layer))
return dielectrics, new_layers

@pyaedt_function_handler()
def create_fieldplot_layers(
self, layers, quantity, setup=None, nets=None, plot_on_surface=True, intrinsics=None, name=None
):
# type: (list, str, str, list, bool, dict, str) -> FieldPlot
"""Create a field plot of stacked layer plot.
This plot is valid from AEDT 2023 R2 and later in HFSS 3D Layout.
It will also work when a layout components in 3d modeler is used.
In order to plot on signal layers use the method ``create_fieldplot_layers_nets``.

Parameters
----------
layers : list
List of layers to plot. For example:
``["Layer1","Layer2"]``. If empty list is provided
all layers will be considered.
quantity : str
Name of the quantity to plot.
setup : str, optional
Name of the setup. The default is ``None``, in which case the ``nominal_adaptive``
setup is used. Make sure to build a setup string in the form of
``"SetupName : SetupSweep"``, where ``SetupSweep`` is the sweep name to
use in the export or ``LastAdaptive``.
nets : list, optional
List of nets to filter the field plot. Optional.
intrinsics : dict, optional
Dictionary containing all intrinsic variables.
The default is ``None``.
name : str, optional
Name of the field plot to create.

Returns
-------
:class:``pyaedt.modules.solutions.FieldPlot`` or bool
Plot object.

References
----------

>>> oModule.CreateFieldPlot
"""
if not setup:
setup = self._app.existing_analysis_sweeps[0]
if nets is None:
nets = []
if not (
"APhi" in self.post_solution_type and settings.aedt_version >= "2023.2"
) and not self._app.design_type in ["HFSS", "HFSS 3D Layout Design"]:
self.logger.error("This method requires AEDT 2023 R2 and Maxwell 3D Transient APhi Formulation.")
return False
if intrinsics is None:
intrinsics = {}
if name and name in list(self.field_plots.keys()):
self.logger.info("Plot {} exists. returning the object.".format(name))
return self.field_plots[name]

if self._app.design_type in ["HFSS 3D Layout Design"]:
lst_faces, new_layers = self._get_3dl_layers_nets(layers, nets, setup)
if new_layers:
plt = self._create_fieldplot(
new_layers, quantity, setup, intrinsics, "ObjList", name, create_plot=False
)
plt.surfaces = lst_faces
out = plt.create()
if out:
return plt
return False
else:
return self._create_fieldplot(lst_faces, quantity, setup, intrinsics, "FacesList", name)
else:
dielectrics, new_layers = self._get_3d_layers_nets(layers, nets)
if nets and plot_on_surface:
plot_type = "LayerNetsExtFace"
elif nets:
plot_type = "LayerNets"
else:
plot_type = "ObjList"
if new_layers:
plt = self._create_fieldplot(
new_layers, quantity, setup, intrinsics, plot_type, name, create_plot=False
)
if dielectrics:
plt.volumes = dielectrics
out = plt.create()
if out:
return plt
elif dielectrics:
return self._create_fieldplot(dielectrics, quantity, setup, intrinsics, "ObjList", name)
return False

@pyaedt_function_handler(quantity_name="quantity", setup_name="setup")
def create_fieldplot_layers_nets(
self, layers_nets, quantity, setup=None, intrinsics=None, plot_on_surface=True, plot_name=None
): # pragma: no cover
):
# type: (list, str, str, dict, bool, str) -> FieldPlot
"""Create a field plot of stacked layer plot.
This plot is valid from AEDT 2023 R2 and later in HFSS 3D Layout
Expand Down Expand Up @@ -3335,21 +3493,7 @@ def create_fieldplot_layers_nets(

>>> oModule.CreateFieldPlot
"""
new_list = []
for layer in layers_nets:
if "no-layer" in layer[0]:
for v in self._app.modeler.user_defined_components.values():
new_list.extend(
[[i] + layer[1:] for i in v.layout_component.edb_object.stackup.stackup_layers.keys()]
)
else:
new_list.append(layer)
layers_nets = new_list
for layer in layers_nets:
if len(layer) == 1 or "no-net" in layer[1]:
for v in self._app.modeler.user_defined_components.values():
if layer[0] in v.layout_component.edb_object.stackup.stackup_layers:
layer.extend(list(v.layout_component.edb_object.nets.nets.keys()))

if not (
"APhi" in self.post_solution_type and settings.aedt_version >= "2023.2"
) and not self._app.design_type in ["HFSS", "HFSS 3D Layout Design"]:
Expand All @@ -3370,11 +3514,27 @@ def create_fieldplot_layers_nets(
if isinstance(get_ids, (tuple, list)) and len(get_ids) > 2:
lst.extend([int(i) for i in get_ids[2:]])
return self._create_fieldplot(lst, quantity, setup, intrinsics, "FacesList", plot_name)
if plot_on_surface:
plot_type = "LayerNetsExtFace"
else:
plot_type = "LayerNets"
return self._create_fieldplot(layers_nets, quantity, setup, intrinsics, plot_type, plot_name)
new_list = []
for layer in layers_nets:
if "no-layer" in layer[0]:
for v in self._app.modeler.user_defined_components.values():
new_list.extend(
[[i] + layer[1:] for i in v.layout_component.edb_object.stackup.signal_layers.keys()]
)
else:
new_list.append(layer)
layers_nets = new_list
for layer in layers_nets:
if len(layer) == 1 or "no-net" in layer[1]:
for v in self._app.modeler.user_defined_components.values():
if layer[0] in v.layout_component.edb_object.stackup.stackup_layers:
layer.extend(list(v.layout_component.edb_object.nets.nets.keys()))
if plot_on_surface:
plot_type = "LayerNetsExtFace"
else:
plot_type = "LayerNets"
return self._create_fieldplot(layers_nets, quantity, setup, intrinsics, plot_type, plot_name)

@pyaedt_function_handler(
objlist="assignment", quantityName="quantity", IntrinsincDict="intrinsics", setup_name="setup"
Expand Down
8 changes: 8 additions & 0 deletions pyaedt/modules/solutions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3113,6 +3113,14 @@ def create(self):
self.oField.CreateFieldPlot(self.surfacePlotInstructionLineTraces, "FieldLineTrace")
else:
self.oField.CreateFieldPlot(self.surfacePlotInstruction, "Field")
if (
"Maxwell" in self._postprocessor._app.design_type
and "Transient" in self._postprocessor.post_solution_type
):
self._postprocessor.ofieldsreporter.SetPlotsViewSolutionContext(
[self.name], self.solution, "Time:" + self.intrinsics["Time"]
)
self._postprocessor.field_plots[self.name] = self
return True
except Exception:
return False
Expand Down
Loading