From e8d8579af1bac47ff9fdf03d87771103c5c86cea Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Mon, 24 Jul 2023 10:28:30 +0200 Subject: [PATCH 01/11] Create examples for isosurfaces using fluid files --- examples/12-fluids/03-fluids_isosurface.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 examples/12-fluids/03-fluids_isosurface.py diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py new file mode 100644 index 00000000000..262a28d847c --- /dev/null +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -0,0 +1,10 @@ +""" +.. _ref_fluids_isosurface: + +Compute iso-surfaces on fluid models +------------------------------------------------------ + +This example shows how to compute iso-surfaces on fluid models with and without +polygons and polyhedrons. +""" + From 30ab67b5e4bc4d10259b591633778c63b244260c Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Mon, 24 Jul 2023 12:04:41 +0200 Subject: [PATCH 02/11] Complete example for iso-surfaces with elbow file --- examples/12-fluids/03-fluids_isosurface.py | 81 +++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index 262a28d847c..f474083bf5c 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -4,7 +4,86 @@ Compute iso-surfaces on fluid models ------------------------------------------------------ -This example shows how to compute iso-surfaces on fluid models with and without +This example shows how to compute iso-surfaces on fluid models without polygons and polyhedrons. """ +############################################################################### +# Import the ``dpf-core`` module and its examples files. +# ------------------------------ + +import ansys.dpf.core as dpf +from ansys.dpf.core import examples +from ansys.dpf.core.plotter import DpfPlotter + +############################################################################### +# Specify the file path. +# We first work on a cas/dat.h5 file with only elemental variable. +# ------------------------------ + +path = examples.download_fluent_multi_phase() +ds = dpf.DataSources(path) +ds.set_result_file_path(path["cas"], "cas") +ds.add_file_path(path["dat"], "dat") +streams = dpf.operators.metadata.streams_provider(data_sources=ds) + +############################################################################### +# Explore elemental (cell) results +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# We split the work in those steps +# -> Evaluate the mesh and store it +# -> Extract from the mesh the node and element scoping +# -> Evaluate on variable (for example the pressure) and store it +# -> Average the results on nodes in order to cut iso-surfaces +# -> Cut the mesh for a specific value + +############################################################################### +# Evaluate the mesh through mesh_provider operator + +mesh_whole = dpf.operators.mesh.mesh_provider(streams_container=streams).eval() +print(mesh_whole) +mesh_whole.plot() + +############################################################################### +# Element and node scoping + +element_scop = dpf.operators.scoping.elemental_from_mesh(mesh=mesh_whole).eval() +node_scop = dpf.operators.scoping.nodal_from_mesh(mesh=mesh_whole).eval() + +print("elements in whole mesh : ", element_scop, "\n") +print("nodes in whole mesh : ", node_scop) + +############################################################################### +# Here we choose to work with the static pressure by default which is a scalar and +# elemental variable without multi-species. With a multi-species case, we should have +# select one specific using qualifiers ellipsis pins and connecting a LabelSpace "phase". + +P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=mesh_whole).eval() +print(P_S) + +############################################################################### +# In order to extract the iso-surfaces for this specific variable, we have first to average +# the elemental values to the nodes. The mesh_cut operator only works for nodal variables. + +to_nodal = dpf.operators.averaging.elemental_to_nodal(field=P_S, mesh_scoping=node_scop).eval() +print(to_nodal) + +############################################################################### +# We can finally use the mesh_cut operator on this specific variable for a specific iso-value +# arbitrary chosen. We have to specify also the mesh scoping. By default, we choose to take +# into account shell and skin elements. + +iso_surface = dpf.operators.mesh.mesh_cut( + field=to_nodal, iso_value=1.0, closed_surface=0, mesh=mesh_whole, slice_surfaces=True +).eval() + +c_pos = [(0.04, 0.03, 0.05), (0.0, 0.0, 0.0), (0.1, 0.2, 0.1)] + +pl = DpfPlotter() +pl.add_mesh( + mesh_whole, style="surface", show_edges=True, show_axes=True, color="w", opacity=0.3 +) +pl.add_mesh( + iso_surface, style="surface", show_edges=True, show_axes=True, color="w" +) +pl.show_figure(show_axes=True, cpos=c_pos, return_cpos=True) From f9bde3230a76b3478ca19e860d1e0955a6274f38 Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Mon, 24 Jul 2023 14:44:00 +0200 Subject: [PATCH 03/11] Complete the example --- examples/12-fluids/03-fluids_isosurface.py | 47 ++++++++++++++-------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index f474083bf5c..1d14cbd8dc9 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -28,24 +28,24 @@ streams = dpf.operators.metadata.streams_provider(data_sources=ds) ############################################################################### -# Explore elemental (cell) results -# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# We split the work in those steps -# -> Evaluate the mesh and store it -# -> Extract from the mesh the node and element scoping -# -> Evaluate on variable (for example the pressure) and store it -# -> Average the results on nodes in order to cut iso-surfaces -# -> Cut the mesh for a specific value - -############################################################################### -# Evaluate the mesh through mesh_provider operator +# Evaluate the mesh with mesh_provider operator in order to scope the mesh_cut operator +# with the mesh. mesh_whole = dpf.operators.mesh.mesh_provider(streams_container=streams).eval() print(mesh_whole) -mesh_whole.plot() + +pl = DpfPlotter() +pl.add_mesh(mesh_whole) +cpos_mesh_whole = [ + (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), + (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), + (-0.84269816220442720, 0.39520703007216523, -0.3656107367116286), +] +pl.show_figure(cpos=cpos_mesh_whole, show_axes=True) ############################################################################### -# Element and node scoping +# Element and node scoping in order to scope first the result ont the element +# and then the mesh_cut operator on the node. element_scop = dpf.operators.scoping.elemental_from_mesh(mesh=mesh_whole).eval() node_scop = dpf.operators.scoping.nodal_from_mesh(mesh=mesh_whole).eval() @@ -58,9 +58,18 @@ # elemental variable without multi-species. With a multi-species case, we should have # select one specific using qualifiers ellipsis pins and connecting a LabelSpace "phase". -P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=mesh_whole).eval() +P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=mesh_whole, mesh_scoping=element_scop).eval() print(P_S) +pl = DpfPlotter() +pl.add_field(P_S) +cpos_mesh_variable = [ + (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), + (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), + (-0.84269816220442720, 0.39520703007216523, -0.3656107367116286), +] +pl.show_figure(cpos=cpos_mesh_variable, show_axes=True) + ############################################################################### # In order to extract the iso-surfaces for this specific variable, we have first to average # the elemental values to the nodes. The mesh_cut operator only works for nodal variables. @@ -77,13 +86,17 @@ field=to_nodal, iso_value=1.0, closed_surface=0, mesh=mesh_whole, slice_surfaces=True ).eval() -c_pos = [(0.04, 0.03, 0.05), (0.0, 0.0, 0.0), (0.1, 0.2, 0.1)] +c_pos_iso = [ + (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), + (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), + (-0.84269816220442720, 0.39520703007216523, -0.3656107367116286), +] pl = DpfPlotter() pl.add_mesh( mesh_whole, style="surface", show_edges=True, show_axes=True, color="w", opacity=0.3 ) pl.add_mesh( - iso_surface, style="surface", show_edges=True, show_axes=True, color="w" + iso_surface, style="surface", show_edges=True, show_axes=True, color="r" ) -pl.show_figure(show_axes=True, cpos=c_pos, return_cpos=True) +pl.show_figure(show_axes=True, cpos=c_pos_iso, return_cpos=True) From 119d98cbcce1d78b508cee7127543f28d9285927 Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Mon, 24 Jul 2023 15:02:19 +0200 Subject: [PATCH 04/11] Complete isosurface example for fluids --- examples/12-fluids/03-fluids_isosurface.py | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index 1d14cbd8dc9..2d53f10ba9e 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -21,36 +21,34 @@ # We first work on a cas/dat.h5 file with only elemental variable. # ------------------------------ -path = examples.download_fluent_multi_phase() -ds = dpf.DataSources(path) -ds.set_result_file_path(path["cas"], "cas") -ds.add_file_path(path["dat"], "dat") +paths = examples.download_fluent_multi_phase() +ds = dpf.DataSources() +ds.set_result_file_path(paths["cas"], "cas") +ds.add_file_path(paths["dat"], "dat") streams = dpf.operators.metadata.streams_provider(data_sources=ds) ############################################################################### # Evaluate the mesh with mesh_provider operator in order to scope the mesh_cut operator # with the mesh. -mesh_whole = dpf.operators.mesh.mesh_provider(streams_container=streams).eval() -print(mesh_whole) +whole_mesh = dpf.operators.mesh.mesh_provider(streams_container=streams).eval() +print(whole_mesh) pl = DpfPlotter() -pl.add_mesh(mesh_whole) -cpos_mesh_whole = [ +pl.add_mesh(whole_mesh) +cpos_whole_mesh = [ (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), (-0.84269816220442720, 0.39520703007216523, -0.3656107367116286), ] -pl.show_figure(cpos=cpos_mesh_whole, show_axes=True) +pl.show_figure(cpos=cpos_whole_mesh, show_axes=True) ############################################################################### # Element and node scoping in order to scope first the result ont the element # and then the mesh_cut operator on the node. -element_scop = dpf.operators.scoping.elemental_from_mesh(mesh=mesh_whole).eval() -node_scop = dpf.operators.scoping.nodal_from_mesh(mesh=mesh_whole).eval() +node_scop = dpf.operators.scoping.nodal_from_mesh(mesh=whole_mesh).eval() -print("elements in whole mesh : ", element_scop, "\n") print("nodes in whole mesh : ", node_scop) ############################################################################### @@ -58,11 +56,11 @@ # elemental variable without multi-species. With a multi-species case, we should have # select one specific using qualifiers ellipsis pins and connecting a LabelSpace "phase". -P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=mesh_whole, mesh_scoping=element_scop).eval() +P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=whole_mesh).eval() print(P_S) pl = DpfPlotter() -pl.add_field(P_S) +pl.add_field(P_S[0]) cpos_mesh_variable = [ (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), @@ -83,9 +81,11 @@ # into account shell and skin elements. iso_surface = dpf.operators.mesh.mesh_cut( - field=to_nodal, iso_value=1.0, closed_surface=0, mesh=mesh_whole, slice_surfaces=True + field=to_nodal, iso_value=1.0, closed_surface=0, mesh=whole_mesh, slice_surfaces=True ).eval() +print(iso_surface) + c_pos_iso = [ (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), @@ -94,7 +94,10 @@ pl = DpfPlotter() pl.add_mesh( - mesh_whole, style="surface", show_edges=True, show_axes=True, color="w", opacity=0.3 + whole_mesh, style="surface", show_edges=True, show_axes=True, color="w", opacity=0.6 +) +pl.add_field( + P_S[0], style="surface", show_edges=True, show_axes=True, color="w", opacity=0.6 ) pl.add_mesh( iso_surface, style="surface", show_edges=True, show_axes=True, color="r" From 2f14dc24130fcd4fc0a76ee775bde0b8a742d908 Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Mon, 24 Jul 2023 18:19:43 +0200 Subject: [PATCH 05/11] Update the PR : Enable to implement a field with overall location Plot iso surface as overall location field --- examples/12-fluids/03-fluids_isosurface.py | 61 +++++++++++----------- src/ansys/dpf/core/plotter.py | 10 ++-- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index 2d53f10ba9e..0bf6da8fe43 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -21,10 +21,8 @@ # We first work on a cas/dat.h5 file with only elemental variable. # ------------------------------ -paths = examples.download_fluent_multi_phase() -ds = dpf.DataSources() -ds.set_result_file_path(paths["cas"], "cas") -ds.add_file_path(paths["dat"], "dat") +path = examples.download_fluent_axial_comp()["flprj"] +ds = dpf.DataSources(path) streams = dpf.operators.metadata.streams_provider(data_sources=ds) ############################################################################### @@ -37,11 +35,12 @@ pl = DpfPlotter() pl.add_mesh(whole_mesh) cpos_whole_mesh = [ - (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), - (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), - (-0.84269816220442720, 0.39520703007216523, -0.3656107367116286), + (-0.15891996848242032, -0.26917748231475785, -0.02581671258881637), + (-0.012145186906044624, -0.07864627423068209, -0.022515001706779003), + (-0.7907463709555519, 0.6100286761144966, -0.050844774939214174), ] -pl.show_figure(cpos=cpos_whole_mesh, show_axes=True) +# pl.show_figure(cpos=cpos_whole_mesh, show_axes=True, return_cpos=True) + ############################################################################### # Element and node scoping in order to scope first the result ont the element @@ -57,16 +56,16 @@ # select one specific using qualifiers ellipsis pins and connecting a LabelSpace "phase". P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=whole_mesh).eval() -print(P_S) +print(P_S[0]) pl = DpfPlotter() pl.add_field(P_S[0]) cpos_mesh_variable = [ - (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), - (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), - (-0.84269816220442720, 0.39520703007216523, -0.3656107367116286), + (-0.15891996848242032, -0.26917748231475785, -0.02581671258881637), + (-0.012145186906044624, -0.07864627423068209, -0.022515001706779003), + (-0.7907463709555519, 0.6100286761144966, -0.050844774939214174), ] -pl.show_figure(cpos=cpos_mesh_variable, show_axes=True) +# pl.show_figure(cpos=cpos_mesh_variable, show_axes=True) ############################################################################### # In order to extract the iso-surfaces for this specific variable, we have first to average @@ -80,26 +79,26 @@ # arbitrary chosen. We have to specify also the mesh scoping. By default, we choose to take # into account shell and skin elements. -iso_surface = dpf.operators.mesh.mesh_cut( - field=to_nodal, iso_value=1.0, closed_surface=0, mesh=whole_mesh, slice_surfaces=True -).eval() - -print(iso_surface) +max_pressure = 136877.2 #Pa +min_pressure = 24554.91 #Pa +number_of_iso_surface = 5 +step = (max_pressure - min_pressure)/number_of_iso_surface +pl = DpfPlotter() c_pos_iso = [ - (-0.17022616684387018, -0.20190398787025482, 0.1948471407823707), - (0.00670901800318915, 0.00674082901283412, 0.0125629516499091), - (-0.84269816220442720, 0.39520703007216523, -0.3656107367116286), + (-0.15891996848242032, -0.26917748231475785, -0.02581671258881637), + (-0.012145186906044624, -0.07864627423068209, -0.022515001706779003), + (-0.7907463709555519, 0.6100286761144966, -0.050844774939214174), ] +pl.add_mesh(meshed_region=whole_mesh, style="wireframe", show_edges=True, show_axes=True, color="w", opacity=0.3) + +for i in range(number_of_iso_surface): + iso_surface = dpf.operators.mesh.mesh_cut( + field=to_nodal, iso_value=min_pressure, closed_surface=0, mesh=whole_mesh, slice_surfaces=True + ).eval() + P_S_step = dpf.Field(location=dpf.locations.overall, nature=dpf.common.natures.scalar) + P_S_step.append([min_pressure], i) + pl.add_field(field=P_S_step, meshed_region=iso_surface, style="surface", show_edges=False, show_axes=True) + min_pressure += step -pl = DpfPlotter() -pl.add_mesh( - whole_mesh, style="surface", show_edges=True, show_axes=True, color="w", opacity=0.6 -) -pl.add_field( - P_S[0], style="surface", show_edges=True, show_axes=True, color="w", opacity=0.6 -) -pl.add_mesh( - iso_surface, style="surface", show_edges=True, show_axes=True, color="r" -) pl.show_figure(show_axes=True, cpos=c_pos_iso, return_cpos=True) diff --git a/src/ansys/dpf/core/plotter.py b/src/ansys/dpf/core/plotter.py index 08db6c0cfdb..ed37d621e50 100644 --- a/src/ansys/dpf/core/plotter.py +++ b/src/ansys/dpf/core/plotter.py @@ -273,6 +273,8 @@ def add_field( warnings.warn("`show_max` and `show_min` is only supported for Nodal results.") show_max = False show_min = False + elif location == locations.overall: + mesh_location = meshed_region.elements else: raise ValueError("Only elemental, nodal or faces location are supported for plotting.") component_count = field.component_count @@ -280,9 +282,11 @@ def add_field( overall_data = np.full((len(mesh_location), component_count), np.nan) else: overall_data = np.full(len(mesh_location), np.nan) - ind, mask = mesh_location.map_scoping(field.scoping) - overall_data[ind] = field.data[mask] - + if location != locations.overall: + ind, mask = mesh_location.map_scoping(field.scoping) + overall_data[ind] = field.data[mask] + else: + overall_data[:] = field.data[0] # Filter kwargs for add_mesh kwargs_in = _sort_supported_kwargs(bound_method=self._plotter.add_mesh, **kwargs) # Have to remove any active scalar field from the pre-existing grid object, From cbc4624d6fd1c68b497b7549c22aaa11ca970cde Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Mon, 24 Jul 2023 19:25:19 +0200 Subject: [PATCH 06/11] Update the PR : Implement a setter for field's name Complete iso-surface example to make it more readable --- examples/12-fluids/03-fluids_isosurface.py | 85 ++++++++++++---------- src/ansys/dpf/core/field.py | 23 +++++- 2 files changed, 67 insertions(+), 41 deletions(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index 0bf6da8fe43..f44b7be47f5 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -4,8 +4,7 @@ Compute iso-surfaces on fluid models ------------------------------------------------------ -This example shows how to compute iso-surfaces on fluid models without -polygons and polyhedrons. +This example shows how to compute iso-surfaces on fluid models. """ ############################################################################### @@ -18,16 +17,19 @@ ############################################################################### # Specify the file path. -# We first work on a cas/dat.h5 file with only elemental variable. +# We first work on a cas/dat.h5 file with only nodal variable. # ------------------------------ -path = examples.download_fluent_axial_comp()["flprj"] -ds = dpf.DataSources(path) +path = examples.download_cfx_heating_coil() +ds = dpf.DataSources() +ds.set_result_file_path(path["cas"], "cas") +ds.add_file_path(path["dat"], "dat") streams = dpf.operators.metadata.streams_provider(data_sources=ds) ############################################################################### # Evaluate the mesh with mesh_provider operator in order to scope the mesh_cut operator # with the mesh. +# ------------------------------ whole_mesh = dpf.operators.mesh.mesh_provider(streams_container=streams).eval() print(whole_mesh) @@ -35,25 +37,17 @@ pl = DpfPlotter() pl.add_mesh(whole_mesh) cpos_whole_mesh = [ - (-0.15891996848242032, -0.26917748231475785, -0.02581671258881637), - (-0.012145186906044624, -0.07864627423068209, -0.022515001706779003), - (-0.7907463709555519, 0.6100286761144966, -0.050844774939214174), + (4.256160478475664, 4.73662111240005, 4.00410065817644), + (-0.0011924505233764648, 1.8596649169921875e-05, 1.125), + (-0.2738679385987956, -0.30771426079547065, 0.9112125360807675), ] -# pl.show_figure(cpos=cpos_whole_mesh, show_axes=True, return_cpos=True) - - -############################################################################### -# Element and node scoping in order to scope first the result ont the element -# and then the mesh_cut operator on the node. - -node_scop = dpf.operators.scoping.nodal_from_mesh(mesh=whole_mesh).eval() - -print("nodes in whole mesh : ", node_scop) +pl.show_figure(cpos=cpos_whole_mesh, show_axes=True, return_cpos=True) ############################################################################### # Here we choose to work with the static pressure by default which is a scalar and -# elemental variable without multi-species. With a multi-species case, we should have -# select one specific using qualifiers ellipsis pins and connecting a LabelSpace "phase". +# nodal variable without multi-species/phases. With a multi-species case, we should have +# select one specific using qualifiers ellipsis pins and connecting a LabelSpace "specie"/"phase". +# ------------------------------ P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=whole_mesh).eval() print(P_S[0]) @@ -61,44 +55,55 @@ pl = DpfPlotter() pl.add_field(P_S[0]) cpos_mesh_variable = [ - (-0.15891996848242032, -0.26917748231475785, -0.02581671258881637), - (-0.012145186906044624, -0.07864627423068209, -0.022515001706779003), - (-0.7907463709555519, 0.6100286761144966, -0.050844774939214174), + (4.256160478475664, 4.73662111240005, 4.00410065817644), + (-0.0011924505233764648, 1.8596649169921875e-05, 1.125), + (-0.2738679385987956, -0.30771426079547065, 0.9112125360807675), ] -# pl.show_figure(cpos=cpos_mesh_variable, show_axes=True) - -############################################################################### -# In order to extract the iso-surfaces for this specific variable, we have first to average -# the elemental values to the nodes. The mesh_cut operator only works for nodal variables. - -to_nodal = dpf.operators.averaging.elemental_to_nodal(field=P_S, mesh_scoping=node_scop).eval() -print(to_nodal) +pl.show_figure(cpos=cpos_mesh_variable, show_axes=True) ############################################################################### # We can finally use the mesh_cut operator on this specific variable for a specific iso-value # arbitrary chosen. We have to specify also the mesh scoping. By default, we choose to take # into account shell and skin elements. +# ------------------------------ + +max_pressure = 361.8170 # Pa +min_pressure = -153.5356 # Pa -max_pressure = 136877.2 #Pa -min_pressure = 24554.91 #Pa number_of_iso_surface = 5 -step = (max_pressure - min_pressure)/number_of_iso_surface +step = (max_pressure - min_pressure) / number_of_iso_surface pl = DpfPlotter() c_pos_iso = [ - (-0.15891996848242032, -0.26917748231475785, -0.02581671258881637), - (-0.012145186906044624, -0.07864627423068209, -0.022515001706779003), - (-0.7907463709555519, 0.6100286761144966, -0.050844774939214174), + (4.256160478475664, 4.73662111240005, 4.00410065817644), + (-0.0011924505233764648, 1.8596649169921875e-05, 1.125), + (-0.2738679385987956, -0.30771426079547065, 0.9112125360807675), ] -pl.add_mesh(meshed_region=whole_mesh, style="wireframe", show_edges=True, show_axes=True, color="w", opacity=0.3) +pl.add_mesh( + meshed_region=whole_mesh, + style="wireframe", + show_edges=True, + show_axes=True, + color="black", + opacity=0.3, +) for i in range(number_of_iso_surface): iso_surface = dpf.operators.mesh.mesh_cut( - field=to_nodal, iso_value=min_pressure, closed_surface=0, mesh=whole_mesh, slice_surfaces=True + field=P_S[0], iso_value=min_pressure, closed_surface=0, mesh=whole_mesh, slice_surfaces=True ).eval() P_S_step = dpf.Field(location=dpf.locations.overall, nature=dpf.common.natures.scalar) P_S_step.append([min_pressure], i) - pl.add_field(field=P_S_step, meshed_region=iso_surface, style="surface", show_edges=False, show_axes=True) + P_S_step.name = "static pressure" + P_S_step.unit = "Pa" + pl.add_field( + field=P_S_step, meshed_region=iso_surface, style="surface", show_edges=False, show_axes=True + ) min_pressure += step pl.show_figure(show_axes=True, cpos=c_pos_iso, return_cpos=True) + +############################################################################### +# For elemental or face variables we should have done an averaging on node +# by using elemental_to_node operator and set as an input of the +# mesh_cut operator the node scoping \ No newline at end of file diff --git a/src/ansys/dpf/core/field.py b/src/ansys/dpf/core/field.py index 1a938f52404..8ed2d23f3df 100644 --- a/src/ansys/dpf/core/field.py +++ b/src/ansys/dpf/core/field.py @@ -575,7 +575,6 @@ def dimensionality(self, value): @property def name(self): """Name of the field.""" - # return self._api.csfield_get_name(self) from ansys.dpf.gate import integral_types size = integral_types.MutableInt32() @@ -585,6 +584,28 @@ def name(self): ) return str(name) + @name.setter + def name(self, value): + """Change the name of the field + + Parameters + ---------- + value : str + Name of the field. + + Examples + -------- + Units for a displacement field. + + >>> from ansys.dpf import core as dpf + >>> my_field = dpf.Field(10, dpf.natures.vector,dpf.locations.nodal) + >>> my_field.name = "my-field" + >>> my_field.name + 'my-field' + + """ + self._field_definition._api.csfield_definition_set_name(self._field_definition, name=value) + def _set_field_definition(self, field_definition): """Set the field definition. From bd35bd8091a02153d73a09a83baa48532a9ca2a8 Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Tue, 25 Jul 2023 08:38:03 +0200 Subject: [PATCH 07/11] Update the PR : Give the possibility through fields_factory to create an overall location field Reformat the example Add ValueError message for faces location in plotter --- examples/12-fluids/03-fluids_isosurface.py | 2 +- src/ansys/dpf/core/fields_factory.py | 51 ++++++++++++++++++++++ src/ansys/dpf/core/plotter.py | 2 + 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index f44b7be47f5..ab473b390c9 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -106,4 +106,4 @@ ############################################################################### # For elemental or face variables we should have done an averaging on node # by using elemental_to_node operator and set as an input of the -# mesh_cut operator the node scoping \ No newline at end of file +# mesh_cut operator the node scoping diff --git a/src/ansys/dpf/core/fields_factory.py b/src/ansys/dpf/core/fields_factory.py index 01afbae1d56..32a2849ab08 100644 --- a/src/ansys/dpf/core/fields_factory.py +++ b/src/ansys/dpf/core/fields_factory.py @@ -254,6 +254,57 @@ def create_vector_field(num_entities, num_comp, location=locations.nodal, server return _create_field(server, natures.vector, num_entities, location, ncomp_n=num_comp) +def create_overall_field( + value, nature, num_entities, num_comp, location=locations.overall, server=None +): + """Create a specific `:class:`ansys.dpf.core.Field` with entities that have an + overall location. + + Regarding the nature of the entity contained in the field, we set the same value + for all element. + + Parameters + ---------- + value : float + Value of the entity + nature : str + Nature of the field entity data. For example: + + - :class:`ansys.dpf.core.natures.matrix` + - :class:`ansys.dpf.core.natures.scalar` + num_entities : int + Number of entities to reserve. + num_comp : int + Number of vector components. + location : str, optional + Location of the field. Options are in :class:`locations `. + The default is ``dpf.locations.nodal``. + + server : ansys.dpf.core.server, optional + Server with the channel connected to the remote or local instance. + The default is ``None``, in which case an attempt is made to use the + global server. + + Returns + ------- + field : Field + DPF field in the requested format. + + Examples + -------- + Create a field containing 10 scalar entities of 1 component each with an + overall location (default). Same value (1.0) is set for all element of the field. + + >>> from ansys.dpf.core import fields_factory + >>> field = fields_factory.create_overall_field(1.0, natures.scalar, 10, 1) + + """ + overall_field = _create_field(server, nature, num_entities, location, ncomp_n=num_comp) + for i in range(num_entities): + overall_field.append(value, i) + return overall_field + + def _create_field(server, nature, nentities, location=locations.nodal, ncomp_n=0, ncomp_m=0): """Create a specific :class:`ansys.dpf.core.Field`. diff --git a/src/ansys/dpf/core/plotter.py b/src/ansys/dpf/core/plotter.py index ed37d621e50..bf59f7da6c7 100644 --- a/src/ansys/dpf/core/plotter.py +++ b/src/ansys/dpf/core/plotter.py @@ -269,6 +269,8 @@ def add_field( show_min = False elif location == locations.faces: mesh_location = meshed_region.faces + if len(mesh_location) == 0: + raise ValueError("No faces found to plot on") if show_max or show_min: warnings.warn("`show_max` and `show_min` is only supported for Nodal results.") show_max = False From ddb5a69fd9be97158ce9bd8cf24cc80cb33fd808 Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Tue, 25 Jul 2023 09:39:41 +0200 Subject: [PATCH 08/11] Update the PR : fix doc display --- examples/12-fluids/03-fluids_isosurface.py | 33 ++++++++++++---------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index ab473b390c9..a3c5546e668 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -9,7 +9,7 @@ ############################################################################### # Import the ``dpf-core`` module and its examples files. -# ------------------------------ +# # ~~~~~~~~~~~~~~~~~~ import ansys.dpf.core as dpf from ansys.dpf.core import examples @@ -17,8 +17,8 @@ ############################################################################### # Specify the file path. -# We first work on a cas/dat.h5 file with only nodal variable. -# ------------------------------ +# ~~~~~~~~~~~~~~~~~~ +# We work on a cas/dat.h5 file with only nodal variable. path = examples.download_cfx_heating_coil() ds = dpf.DataSources() @@ -27,9 +27,10 @@ streams = dpf.operators.metadata.streams_provider(data_sources=ds) ############################################################################### -# Evaluate the mesh with mesh_provider operator in order to scope the mesh_cut operator -# with the mesh. -# ------------------------------ +# Whole mesh scoping. +# ~~~~~~~~~~~~~~~~~~ +# We evaluate the mesh with mesh_provider operator in order to scope the mesh_cut operator +# with the whole mesh. whole_mesh = dpf.operators.mesh.mesh_provider(streams_container=streams).eval() print(whole_mesh) @@ -41,13 +42,14 @@ (-0.0011924505233764648, 1.8596649169921875e-05, 1.125), (-0.2738679385987956, -0.30771426079547065, 0.9112125360807675), ] -pl.show_figure(cpos=cpos_whole_mesh, show_axes=True, return_cpos=True) +pl.show_figure(cpos=cpos_whole_mesh, show_axes=True) ############################################################################### +# Extract the physic variable. +# ~~~~~~~~~~~~~~~~~~ # Here we choose to work with the static pressure by default which is a scalar and # nodal variable without multi-species/phases. With a multi-species case, we should have # select one specific using qualifiers ellipsis pins and connecting a LabelSpace "specie"/"phase". -# ------------------------------ P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=whole_mesh).eval() print(P_S[0]) @@ -62,14 +64,13 @@ pl.show_figure(cpos=cpos_mesh_variable, show_axes=True) ############################################################################### -# We can finally use the mesh_cut operator on this specific variable for a specific iso-value -# arbitrary chosen. We have to specify also the mesh scoping. By default, we choose to take -# into account shell and skin elements. -# ------------------------------ +# Evaluate iso-surfaces. +# ~~~~~~~~~~~~~~~~~~ +# We can finally use the mesh_cut operator on this specific variable. +# We choose to cut the whole with 5 iso-surface equally spaced between min and max. max_pressure = 361.8170 # Pa min_pressure = -153.5356 # Pa - number_of_iso_surface = 5 step = (max_pressure - min_pressure) / number_of_iso_surface @@ -101,9 +102,11 @@ ) min_pressure += step -pl.show_figure(show_axes=True, cpos=c_pos_iso, return_cpos=True) +pl.show_figure(show_axes=True, cpos=c_pos_iso) ############################################################################### +# Important note +# ------------------------------ # For elemental or face variables we should have done an averaging on node # by using elemental_to_node operator and set as an input of the -# mesh_cut operator the node scoping +# mesh_cut operator the node scoping. From 863b815456267e0664f37ff15aae421fbe6d6803 Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Tue, 25 Jul 2023 09:53:55 +0200 Subject: [PATCH 09/11] Update the PR : fix format --- examples/12-fluids/03-fluids_isosurface.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index a3c5546e668..49899372cfb 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -9,7 +9,7 @@ ############################################################################### # Import the ``dpf-core`` module and its examples files. -# # ~~~~~~~~~~~~~~~~~~ +# ~~~~~~~~~~~~~~~~~~ import ansys.dpf.core as dpf from ansys.dpf.core import examples From 4e2c026d321551acc6c8f06cc3acd8a8de369d2d Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Tue, 25 Jul 2023 09:58:52 +0200 Subject: [PATCH 10/11] Update the PR : enhance the doc --- examples/12-fluids/03-fluids_isosurface.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index 49899372cfb..4226720d82f 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -107,6 +107,7 @@ ############################################################################### # Important note # ------------------------------ -# For elemental or face variables we should have done an averaging on node -# by using elemental_to_node operator and set as an input of the -# mesh_cut operator the node scoping. +# Isosurfaces computation through the `mesh_cut` operator are only supported for Nodal Fields. +# Thus, for Elemental variables an averaging operation to the Nodes needs to be performed before +# running the `mesh_cut` operator. This can be done by chaining the `elemental_to_nodal` operator +# output with the `mesh_cut` operator input. From e2d905e488d12f76663582d4ddd1fa98acffbcd3 Mon Sep 17 00:00:00 2001 From: Michael Nale Date: Tue, 25 Jul 2023 21:00:31 +0200 Subject: [PATCH 11/11] Update the PR : correct docstrings and reformat code --- examples/12-fluids/03-fluids_isosurface.py | 24 +++++++++++----------- src/ansys/dpf/core/fields_factory.py | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/12-fluids/03-fluids_isosurface.py b/examples/12-fluids/03-fluids_isosurface.py index 4226720d82f..34e3f2a9619 100644 --- a/examples/12-fluids/03-fluids_isosurface.py +++ b/examples/12-fluids/03-fluids_isosurface.py @@ -2,9 +2,9 @@ .. _ref_fluids_isosurface: Compute iso-surfaces on fluid models ------------------------------------------------------- +------------------------------------------ -This example shows how to compute iso-surfaces on fluid models. +This example demonstrates how to compute iso-surfaces on fluid models. """ ############################################################################### @@ -18,7 +18,7 @@ ############################################################################### # Specify the file path. # ~~~~~~~~~~~~~~~~~~ -# We work on a cas/dat.h5 file with only nodal variable. +# We work on a cas/dat.h5 file with only nodal variables. path = examples.download_cfx_heating_coil() ds = dpf.DataSources() @@ -29,7 +29,7 @@ ############################################################################### # Whole mesh scoping. # ~~~~~~~~~~~~~~~~~~ -# We evaluate the mesh with mesh_provider operator in order to scope the mesh_cut operator +# We evaluate the mesh with the mesh_provider operator to scope the mesh_cut operator # with the whole mesh. whole_mesh = dpf.operators.mesh.mesh_provider(streams_container=streams).eval() @@ -45,11 +45,11 @@ pl.show_figure(cpos=cpos_whole_mesh, show_axes=True) ############################################################################### -# Extract the physic variable. -# ~~~~~~~~~~~~~~~~~~ +# Extract the physics variable +# ~~~~~~~~~~~~~~~~~ # Here we choose to work with the static pressure by default which is a scalar and -# nodal variable without multi-species/phases. With a multi-species case, we should have -# select one specific using qualifiers ellipsis pins and connecting a LabelSpace "specie"/"phase". +# nodal variable without multi-species/phases. With a multi-species case, +# select one using qualifier ellipsis pins and connecting a LabelSpace "species"/"phase". P_S = dpf.operators.result.static_pressure(streams_container=streams, mesh=whole_mesh).eval() print(P_S[0]) @@ -64,8 +64,8 @@ pl.show_figure(cpos=cpos_mesh_variable, show_axes=True) ############################################################################### -# Evaluate iso-surfaces. -# ~~~~~~~~~~~~~~~~~~ +# Evaluate iso-surfaces +# ~~~~~~~~~~~~~~ # We can finally use the mesh_cut operator on this specific variable. # We choose to cut the whole with 5 iso-surface equally spaced between min and max. @@ -107,7 +107,7 @@ ############################################################################### # Important note # ------------------------------ -# Isosurfaces computation through the `mesh_cut` operator are only supported for Nodal Fields. -# Thus, for Elemental variables an averaging operation to the Nodes needs to be performed before +# Iso-surfaces computation through the `mesh_cut` operator are only supported for Nodal Fields. +# For Elemental variables, you must perform an averaging operation on the Nodes before # running the `mesh_cut` operator. This can be done by chaining the `elemental_to_nodal` operator # output with the `mesh_cut` operator input. diff --git a/src/ansys/dpf/core/fields_factory.py b/src/ansys/dpf/core/fields_factory.py index 32a2849ab08..3eb113a10e6 100644 --- a/src/ansys/dpf/core/fields_factory.py +++ b/src/ansys/dpf/core/fields_factory.py @@ -261,7 +261,7 @@ def create_overall_field( overall location. Regarding the nature of the entity contained in the field, we set the same value - for all element. + for all elements. Parameters ----------