Skip to content

Commit

Permalink
Mesh splitting and selection (#346)
Browse files Browse the repository at this point in the history
* Add 05-mesh-exploration.py

* Comments on API

* Meeting 20/03

* Should expose MeshSelectionManager?

* Typo

* Add meshes.py

* Add Meshes.select()

* Simulation.split_mesh_by_properties() - version using scopings

* WIP

* Add Mesh.plot()

* Add Meshes.plot()

* Add Meshes.__get_item__ by dictionary of {property: value}

* Working POC with split by properties, and selection by properties, with plot

* Split mesh by list of properties

* Add test_meshes.py

* Use "import ansys.dpf.core as dpf" in test_mesh.py

* Add test_simulation_split_mesh_by_properties

* Add Mesh and Meshes imports at module init

* Add Meshes.__len__()

* Fix and test Meshes.select()

* Add selection by values in Simulation.split_mesh_by_properties()

* Update 05-mesh-exploration.py

* Inherit elemental_properties from core

* Expose elemental_properties at post level

* Simulation.split_by_property allow dict of properties and values, improve docstring and typehinting, and use elemental_properties enum

* Update test_simulation_split_by_properties accordingly

* Remove expose elemental_properties at post level due to circular imports

* Fix Simulation.split_mesh_by_properties docstring

* Add Meshes.plot docstring example

* Add Meshes docstring examples

* Update test_meshes.py

* Add Mesh.coordinates and Mesh.plot docstring example

* Update draft example with new requirements for the Mesh API

* Fix Meshes docstrings

* Completed mesh basic information querying section

* Added Elements, Nodes accessors, moved NamedSelection

* NamedSelection: composition over inheritance

* Added mock PropertyFieldsContainer for DataFrame, updated Elements

* updated Nodes list, added materials property

* split Element.type into id & info

* Added Simple ConnectivityList

* Added element types getter

* Completed doc and pre-commit checks

* Updated mesh example

* minor changes

* Apply suggestions from code review

Co-authored-by: Paul Profizi <[email protected]>

* Implemented suggestions

* Added mesh related tests

* pre-commit checks conformance

* Added string repr, ElementType composition, Node wrapper

* Fixed string rep, added docstrings

* Fixed server variable in mock class PropertyFieldFC

* Added minimal functionality for df.select on PropertyFields

* fixed mistake

* Added skin getter method

* Renamed connectivity getters, updated tests

* Revert "Added skin getter method"

This reverts commit a9316a3.

* Make PropertyFieldsContainer private

* Fix styling

* Update test ref

* Remove warning

* Fix code quality

* Fix code quality

* Fix code quality

* Add test_connectivity.py/test_connectivity_connectivity_list_idx

* Fix calls to ConnectivityListIdx and ConnectivityListIds

* Fix Mesh.element_to_node_ids_connectivity, Mesh.node_to_element_ids_connectivity, Mesh.element_to_node_connectivity, and Mesh.node_to_element_connectivity

* Fix connectivity.py/ConnectivityListById init

* Fix code quality in 05-mesh-exploration.py

* WIP

* Refactor

* Improve coverage connectivity.py

* Improve coverage connectivity.py

* Improve coverage mesh.py

* Improve coverage mesh.py

* Fix code quality

* Fix 221 retro

* Improve coverage test_connectivity.py

* Coverage elements.py/ElementType

* Coverage elements.py/Element

* Refactor and coverage of elements.py

* Coverage mesh.py

* Coverage selection.py

* Refactor NamedSelections in named_selection.py

* Refactor NamedSelections in named_selection.py

* Add test_named_selection.py

* Add test_named_selection.py

* Update CI to work with 241 dev libraries

* Make test_named_selection.py retro-compatible

* Refactor nodes.py

* Coverage nodes.py

* Move PropertyFieldsContainer to core

* Remove rogue prints from tests

* Finalize move of PropertyFieldsContainer to ansys-dpf-core

* Add examples to docstrings

* Take remarks into account

* Throw when trying to instantiate a post.Mesh with a None as MeshedRegion

* Working 05-mesh-exploration.py

* Improve notebook formatting of 05-mesh-exploration.py

---------

Co-authored-by: Antoine Karcher <[email protected]>
Co-authored-by: ansys-akarcher <[email protected]>
  • Loading branch information
3 people authored Jul 21, 2023
1 parent 7917821 commit c9b5fc9
Show file tree
Hide file tree
Showing 20 changed files with 2,149 additions and 32 deletions.
243 changes: 243 additions & 0 deletions examples/01-Detailed-Examples/05-mesh-exploration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
"""
.. _ref_mesh_exploration_example:
Explore the mesh
================
This example shows how to explore and manipulate the mesh object to query mesh data
such as connectivity tables, element IDs, element types and so on.
"""

###############################################################################
# Perform required imports
# ------------------------
# Perform required imports.
# This example uses a supplied file that you can
# get by importing the DPF ``examples`` package.

from ansys.dpf import post
from ansys.dpf.post import examples
from ansys.dpf.post.common import elemental_properties

###############################################################################
# Load the result file
# --------------------
# Load the result file in a ``Simulation`` object that allows access to the results.
# The ``Simulation`` object must be instantiated with the path for the result file.
# For example, ``"C:/Users/user/my_result.rst"`` on Windows
# or ``"/home/user/my_result.rst"`` on Linux.

example_path = examples.download_harmonic_clamped_pipe()
simulation = post.HarmonicMechanicalSimulation(example_path)

###############################################################################
# Get the mesh
# ------------
# Retrieve the mesh and print it
mesh = simulation.mesh
print(mesh)

###############################################################################
# Plot the mesh
# -------------
# Plot the mesh to view the bare mesh of the model
mesh.plot()

###############################################################################
# Query basic information about the mesh
# --------------------------------------
# The ``Mesh`` object has several properties allowing access to different information such as:

###############################################################################
# the number of nodes
print(f"This mesh contains {mesh.num_nodes} nodes")

###############################################################################
# the list of node IDs
print(f"with IDs: {mesh.node_ids}")

###############################################################################
# the number of elements
print(f"This mesh contains {mesh.num_elements} elements")

###############################################################################
# the list of element IDs
print(f"with IDs {mesh.element_ids}")

###############################################################################
# the unit of the mesh
print(f"The mesh is in '{mesh.unit}'")

###############################################################################
# Named selections
# ----------------
# The available named selections are given as a dictionary
# with the names as keys and the actual ``NamedSelection`` objects as values.
# Printing the dictionary informs you on the available names.
named_selections = mesh.named_selections
print(named_selections)

###############################################################################
# To get a specific named selection, query it using its name as key
print(named_selections["_FIXEDSU"])

###############################################################################
# Elements
# --------
# Use ``mesh.elements`` to access the list of Element objects
print(mesh.elements)

###############################################################################
# You can then query a specific element by its ID
print(mesh.elements.by_id[1])

###############################################################################
# or by its index
element_0 = mesh.elements[0]
print(element_0)

###############################################################################
# Query information about a particular element
# --------------------------------------------
# You can request the IDs of the nodes attached to an ``Element`` object
print(element_0.node_ids)

###############################################################################
# or the list of ``Node`` objects
print(element_0.nodes)

###############################################################################
# To get the number of nodes attached, use
print(element_0.num_nodes)

###############################################################################
# Get the type of the element
print(element_0.type_info)
print(element_0.type)

###############################################################################
# Get the shape of the element
print(element_0.shape)

###############################################################################
# Element types and materials
# ---------------------------
# The ``Mesh`` object provides access to properties defined on all elements,
# such as their types or their associated materials.

###############################################################################
# Get the type of all elements
print(mesh.element_types)

###############################################################################
# Get the materials of all elements
print(mesh.materials)

###############################################################################
# Elemental connectivity
# ----------------------
# The elemental connectivity maps elements to connected nodes, either using IDs or indexes.

###############################################################################
# To access the indexes of the connected nodes using an element's index, use
element_to_node_connectivity = mesh.element_to_node_connectivity
print(element_to_node_connectivity[0])

###############################################################################
# To access the IDs of the connected nodes using an element's index, use
element_to_node_ids_connectivity = mesh.element_to_node_ids_connectivity
print(element_to_node_ids_connectivity[0])

###############################################################################
# Each connectivity object has a ``by_id`` property which changes the input from index to ID, thus:

###############################################################################
# To access the indexes of the connected nodes using an element's ID, use
element_to_node_connectivity_by_id = mesh.element_to_node_connectivity.by_id
print(element_to_node_connectivity_by_id[3487])

###############################################################################
# To access the IDs of the connected nodes using an element's ID, use
element_to_node_ids_connectivity_by_id = mesh.element_to_node_ids_connectivity.by_id
print(element_to_node_ids_connectivity_by_id[3487])

###############################################################################
# Nodes
# -----
# Get a node by its ID
node_1 = mesh.nodes.by_id[1]
print(node_1)

###############################################################################
# Get a node by its index
print(mesh.nodes[0])

###############################################################################
# Get the coordinates of all nodes
print(mesh.coordinates)

###############################################################################
# Query information about one particular node
# -------------------------------------------
# Get the coordinates of a node
print(node_1.coordinates)

###############################################################################
# Nodal connectivity
# ------------------
# The nodal connectivity maps nodes to connected elements, either using IDs or indexes.

###############################################################################
# To access the indexes of the connected elements using a node's index, use
node_to_element_connectivity = mesh.node_to_element_connectivity
print(node_to_element_connectivity[0])

###############################################################################
# To access the IDs of the connected elements using a node's index, use
node_to_element_ids_connectivity = mesh.node_to_element_ids_connectivity
print(node_to_element_ids_connectivity[0])

###############################################################################
# Each connectivity object has a ``by_id`` property which changes the input from index to ID, thus:

###############################################################################
# To access the indexes of the connected elements using a node's ID, use
node_to_element_connectivity_by_id = mesh.node_to_element_connectivity.by_id
print(node_to_element_connectivity_by_id[1])

###############################################################################
# To access the IDs of the connected elements using a node's ID, use
node_to_element_ids_connectivity_by_id = mesh.node_to_element_ids_connectivity.by_id
print(node_to_element_ids_connectivity_by_id[1])

###############################################################################
# Splitting into meshes
# ---------------------
# You can split the global mesh according to mesh properties to work on specific parts of the mesh
meshes = simulation.split_mesh_by_properties(
properties=[elemental_properties.material, elemental_properties.element_shape]
)
###############################################################################
# The object obtained is a ``Meshes``
print(meshes)

###############################################################################
# Plotting a ``Meshes`` object plots a combination of all the ``Mesh`` objects within
meshes.plot(text="Mesh split")

###############################################################################
# Select a specific ``Mesh`` in the ``Meshes``, by index
meshes[0].plot(text="First mesh in the split mesh")

###############################################################################
# You can split the global mesh and select meshes based on specific property values
meshes_filtered = simulation.split_mesh_by_properties(
properties={
elemental_properties.material: [2, 3, 4],
elemental_properties.element_shape: 1,
}
)
meshes_filtered.plot(text="Mesh split and filtered")

###############################################################################
# or with a unique combination of property values
meshes[{"mat": 5, "elshape": 0}].plot(text="Mesh for mat=5 and elshape=0")
2 changes: 2 additions & 0 deletions src/ansys/dpf/post/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
from ansys.dpf.post.harmonic_mechanical_simulation import ( # noqa: F401
HarmonicMechanicalSimulation,
)
from ansys.dpf.post.mesh import Mesh # noqa: F401
from ansys.dpf.post.meshes import Meshes # noqa: F401
from ansys.dpf.post.misc import Report
from ansys.dpf.post.modal_mechanical_simulation import ( # noqa: F401
ModalMechanicalSimulation,
Expand Down
3 changes: 3 additions & 0 deletions src/ansys/dpf/post/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
------
"""
from ansys.dpf.core.common import ( # noqa: F401 # pylint: disable=W0611
elemental_properties,
)

from ansys.dpf.post.fluid_simulation import FluidSimulation
from ansys.dpf.post.harmonic_mechanical_simulation import HarmonicMechanicalSimulation
Expand Down
Loading

0 comments on commit c9b5fc9

Please sign in to comment.