Skip to content

Commit

Permalink
Merge branch 'main' into port_source_enhancement
Browse files Browse the repository at this point in the history
  • Loading branch information
hui-zhou-a authored Oct 26, 2023
2 parents d4e2e31 + bb3830c commit 2f08ba9
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 103 deletions.
4 changes: 4 additions & 0 deletions _unittest/test_12_1_PostProcessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,10 @@ def test_15_export_plot(self):
show=False, export_path=os.path.join(self.local_scratch.path, "image.jpg")
)
assert os.path.exists(obj.image_file)
obj2 = self.aedtapp.post.plot_model_obj(
show=False, export_path=os.path.join(self.local_scratch.path, "image2.jpg"), plot_as_separate_objects=False
)
assert os.path.exists(obj2.image_file)

@pytest.mark.skipif(is_linux or sys.version_info < (3, 8), reason="Not running in ironpython")
def test_16_create_field_plot(self):
Expand Down
54 changes: 50 additions & 4 deletions examples/05-Q3D/Q3D_DC_IR.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@
# Use previously calculated positions to identify faces,
# select the net "1_Top" and
# assign sources and sinks on nets.

sink_f = q3d.modeler.create_circle(q3d.PLANE.XY, location_u11_scl, 0.1)
source_f1 = q3d.modeler.create_circle(q3d.PLANE.XY, location_u9_1_scl, 0.1)
source_f2 = q3d.modeler.create_circle(q3d.PLANE.XY, location_u9_2_scl, 0.1)
source_f3= q3d.modeler.create_circle(q3d.PLANE.XY, location_u11_r106, 0.1)
sources_objs = [source_f1, source_f2, source_f3]
q3d.auto_identify_nets()

identified_net = q3d.nets[0]
Expand All @@ -173,9 +173,11 @@

source2 = q3d.source(source_f2, net_name=identified_net)
source3 = q3d.source(source_f3, net_name=identified_net)
sources_bounds = [source1, source2, source3]

q3d.edit_sources(dcrl={"{}:{}".format(source1.props["Net"], source1.name): "1.0A",
"{}:{}".format(source2.props["Net"], source2.name): "1.0A"})
q3d.edit_sources(dcrl={"{}:{}".format(source1.props["Net"], source1.name): "-1.0A",
"{}:{}".format(source2.props["Net"], source2.name): "-1.0A",
"{}:{}".format(source2.props["Net"], source3.name): "-1.0A"})

###############################################################################
# Create setup
Expand All @@ -191,13 +193,27 @@
setup.props["DC"]["Cond"]["MaxPass"]=3
setup.analyze()

###############################################################################
# Field Calculator
# ~~~~~~~~~~~~~~~~
# We will create a named expression using field calculator.

drop_name = "Vdrop3_3"
fields = q3d.ofieldsreporter
q3d.ofieldsreporter.CalcStack("clear")
q3d.ofieldsreporter.EnterQty("Phidc")
q3d.ofieldsreporter.EnterScalar(3.3)
q3d.ofieldsreporter.CalcOp("+")
q3d.ofieldsreporter.AddNamedExpression(drop_name, "DC R/L Fields")

###############################################################################
# Phi plot
# ~~~~~~~~
# Compute ACL solutions and plot them.

plot1 = q3d.post.create_fieldplot_surface(q3d.modeler.get_objects_by_material("copper"), "Phidc",
plot1 = q3d.post.create_fieldplot_surface(q3d.modeler.get_objects_by_material("copper"), quantityName=drop_name,
intrinsincDict={"Freq": "1GHz"})

q3d.post.plot_field_from_fieldplot(
plot1.name,
project_path=q3d.working_directory,
Expand All @@ -209,6 +225,36 @@
log_scale=False,
)


###############################################################################
# Computing Voltage on Source Circles
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Using Field Calculator we can compute the voltage on source circles and get the value
# using get_solution_data method.

curves = []
for source_circle, source_bound in zip(sources_objs, sources_bounds):
source_sheet_name = source_circle.name

curves.append("V{}".format(source_bound.name))

q3d.ofieldsreporter.CalcStack("clear")
q3d.ofieldsreporter.CopyNamedExprToStack(drop_name)
q3d.ofieldsreporter.EnterSurf(source_sheet_name)
q3d.ofieldsreporter.CalcOp("Maximum")
q3d.ofieldsreporter.AddNamedExpression("V{}".format(source_bound.name), "DC R/L Fields")


data = q3d.post.get_solution_data(
curves,
q3d.nominal_adaptive,
variations={"Freq": "1GHz"},
report_category="DC R/L Fields",
)
for curve in curves:
print(data.data_real(curve))


###############################################################################
# Close AEDT
# ~~~~~~~~~~
Expand Down
4 changes: 2 additions & 2 deletions examples/06-Multiphysics/Hfss_Icepak_Coupling.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,8 @@
log_scale=True,
)
animated.gif_file = os.path.join(aedtapp.working_directory, "animate.gif")
animated.camera_position = [0, 0, 300]
animated.focal_point = [0, 0, 0]
# animated.camera_position = [0, 0, 300]
# animated.focal_point = [0, 0, 0]
# Set off_screen to False to visualize the animation.
# animated.off_screen = False
animated.animate()
Expand Down
48 changes: 28 additions & 20 deletions pyaedt/generic/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -1320,7 +1320,12 @@ def _read_mesh_files(self, read_frames=False):
obj_to_iterate.append(i)
for field in obj_to_iterate:
if field.path and not field._cached_polydata:
if ".aedtplt" in field.path:
if ".case" in field.path:
reader = pv.get_reader(os.path.abspath(field.path)).read()
field._cached_polydata = reader[reader.keys()[0]].extract_surface()
field.label = field._cached_polydata.point_data.active_scalars_name

elif ".aedtplt" in field.path:
vertices, faces, scalars, log1 = _parse_aedtplt(field.path)
if self.convert_fields_in_db:
scalars = [np.multiply(np.log10(i), self.log_multiplier) for i in scalars]
Expand Down Expand Up @@ -1574,6 +1579,8 @@ def plot(self, export_image_path=None):
cmap=field.color_map,
opacity=field.opacity,
show_edges=field.show_edge,
smooth_shading=True,
split_sharp_edges=True,
)

self.pv.set_scale(self.x_scale, self.y_scale, self.z_scale)
Expand All @@ -1587,9 +1594,9 @@ def plot(self, export_image_path=None):
self.pv.show_grid(color=tuple(axes_color), grid=self.show_grid, fmt="%.2e")
if self.bounding_box:
self.pv.add_bounding_box(color=tuple(axes_color))
self.pv.set_focus(self.pv.mesh.center)

if not self.isometric_view:
self.pv.set_focus(self.pv.mesh.center)
if isinstance(self.camera_position, (tuple, list)):
self.pv.camera.position = self.camera_position
self.pv.camera.focal_point = self.focal_point
Expand Down Expand Up @@ -1695,19 +1702,7 @@ def animate(self):
for m in self.fields:
labels.append([m.name, "red"])
self.pv.add_legend(labels=labels, bcolor=None, face="circle", size=[0.15, 0.15])
if not self.isometric_view:
if isinstance(self.camera_position, (tuple, list)):
self.pv.camera.position = self.camera_position
self.pv.camera.focal_point = self.focal_point
self.pv.camera.up = self.view_up
else:
self.pv.camera_position = self.camera_position
self.pv.camera.azimuth += self.azimuth_angle
self.pv.camera.roll += self.roll_angle
self.pv.camera.elevation += self.elevation_angle
else:
self.pv.isometric_view()
self.pv.zoom = self.zoom

self._animating = True

if self.gif_file:
Expand Down Expand Up @@ -1754,11 +1749,6 @@ def p_callback():
cmap=field.color_map,
opacity=field.opacity,
)
# run until q is pressed
if self.pv.mesh:
self.pv.set_focus(self.pv.mesh.center)

cpos = self.pv.show(interactive=False, auto_close=False, interactive_update=not self.off_screen)

if self.range_min is not None and self.range_max is not None:
mins = self.range_min
Expand All @@ -1785,6 +1775,24 @@ def p_callback():
name="FieldPlot",
opacity=self.frames[0].opacity,
)
# run until q is pressed
if self.pv.mesh:
self.pv.set_focus(self.pv.mesh.center)
if not self.isometric_view:
if isinstance(self.camera_position, (tuple, list)):
self.pv.camera.position = self.camera_position
self.pv.camera.focal_point = self.focal_point
self.pv.camera.up = self.view_up
else:
self.pv.camera_position = self.camera_position
self.pv.camera.azimuth += self.azimuth_angle
self.pv.camera.roll += self.roll_angle
self.pv.camera.elevation += self.elevation_angle
else:
self.pv.isometric_view()
self.pv.camera.zoom(self.zoom)
cpos = self.pv.show(interactive=False, auto_close=False, interactive_update=not self.off_screen)

start = time.time()
try:
self.pv.update(1, force_redraw=True)
Expand Down
30 changes: 23 additions & 7 deletions pyaedt/modules/AdvancedPostProcessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ def plot_field_from_fieldplot(
show_grid=False,
show_bounding=False,
show_legend=True,
plot_as_separate_objects=True,
):
"""Export a field plot to an image file (JPG or PNG) using Python PyVista.
Expand Down Expand Up @@ -367,6 +368,8 @@ def plot_field_from_fieldplot(
Whether to display the axes bounding box or not. The default is ``False``.
show_legend : bool, optional
Whether to display the legend or not. The default is ``True``.
plot_as_separate_objects : bool, optional
Plot each object separately. It may require more time to export from AEDT.
Returns
-------
Expand All @@ -381,8 +384,12 @@ def plot_field_from_fieldplot(
else:
self.ofieldsreporter.UpdateQuantityFieldsPlots(plot_folder)

file_to_add = self.export_field_plot(plotname, self._app.working_directory)
model = self.get_model_plotter_geometries(generate_mesh=False, get_objects_from_aedt=plot_cad_objs)
file_to_add = self.export_field_plot(plotname, self._app.working_directory, file_format="case")
model = self.get_model_plotter_geometries(
generate_mesh=False,
get_objects_from_aedt=plot_cad_objs,
plot_as_separate_objects=plot_as_separate_objects,
)
model.show_legend = show_legend
model.off_screen = not show
if dark_mode:
Expand All @@ -391,7 +398,10 @@ def plot_field_from_fieldplot(
model.show_grid = show_grid
if file_to_add:
model.add_field_from_file(
file_to_add, coordinate_units=self.modeler.model_units, show_edges=meshplot, log_scale=log_scale
file_to_add,
coordinate_units=self.modeler.model_units,
show_edges=meshplot,
log_scale=log_scale,
)
if plot_label:
model.fields[0].label = plot_label
Expand Down Expand Up @@ -427,7 +437,7 @@ def plot_field(
scale_min=None,
scale_max=None,
plot_cad_objs=True,
log_scale=True,
log_scale=False,
export_path="",
imageformat="jpg",
keep_plot_after_generation=False,
Expand All @@ -436,6 +446,7 @@ def plot_field(
show_grid=False,
show_legend=True,
filter_objects=[],
plot_as_separate_objects=True,
):
"""Create a field plot using Python PyVista and export to an image file (JPG or PNG).
Expand Down Expand Up @@ -471,7 +482,7 @@ def plot_field(
plot_cad_objs : bool, optional
Whether to include objects in the plot. The default is ``True``.
log_scale : bool, optional
Whether to plot fields in log scale. The default is ``True``.
Whether to plot fields in log scale. The default is ``False``.
export_path : str, optional
Image export path. Default is ``None`` to not export the image.
imageformat : str, optional
Expand All @@ -490,6 +501,8 @@ def plot_field(
Whether to display the legend or not. The default is ``True``.
filter_objects : list, optional
Objects list for filtering the ``CutPlane`` plots.
plot_as_separate_objects : bool, optional
Plot each object separately. It may require more time to export from AEDT.
Returns
-------
Expand Down Expand Up @@ -534,6 +547,7 @@ def plot_field(
show_grid=show_grid,
show_bounding=show_bounding,
show_legend=show_legend,
plot_as_separate_objects=plot_as_separate_objects,
)
if not keep_plot_after_generation:
plotf.delete()
Expand Down Expand Up @@ -652,7 +666,7 @@ def plot_animated_field(
object_list, quantity, setup_name, intrinsics, filter_objects=filter_objects
)
if plotf:
file_to_add = self.export_field_plot(plotf.name, export_path, plotf.name + str(v))
file_to_add = self.export_field_plot(plotf.name, export_path, plotf.name + str(v), file_format="case")
if file_to_add:
fields_to_add.append(file_to_add)
plotf.delete()
Expand Down Expand Up @@ -761,7 +775,9 @@ def animate_fields_from_aedtplt(
]
)
fields_to_add.append(
self.export_field_plot(plotname, project_path, plotname + variation_variable + str(el))
self.export_field_plot(
plotname, project_path, plotname + variation_variable + str(el), file_format="case"
)
)

model = self.get_model_plotter_geometries(generate_mesh=False)
Expand Down
Loading

0 comments on commit 2f08ba9

Please sign in to comment.