Skip to content
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
16 changes: 7 additions & 9 deletions src/ansys/dpf/core/meshed_region.py
Original file line number Diff line number Diff line change
Expand Up @@ -446,22 +446,14 @@ def deform_by(self, deform_by, scale_factor=1.0):

def _as_vtk(self, coordinates=None, as_linear=True, include_ids=False):
"""Convert DPF mesh to a PyVista unstructured grid."""
if coordinates is None:
coordinates_field = self.nodes.coordinates_field
coordinates = self.nodes.coordinates_field.data
else:
coordinates_field = coordinates
coordinates = coordinates.data
etypes = self.elements.element_types_field.data
conn = self.elements.connectivities_field
try:
from ansys.dpf.core.vtk_helper import dpf_mesh_to_vtk
except ModuleNotFoundError:
raise ModuleNotFoundError(
"To use plotting capabilities, please install pyvista "
"with :\n pip install pyvista>=0.24.0"
)
grid = dpf_mesh_to_vtk(coordinates, etypes, conn, as_linear, self)
grid = dpf_mesh_to_vtk(self, coordinates, as_linear)

# consider adding this when scoping request is faster
if include_ids:
Expand All @@ -472,6 +464,12 @@ def _as_vtk(self, coordinates=None, as_linear=True, include_ids=False):

# Quick fix required to hold onto the data as PyVista does not make a copy.
# All of those now return DPFArrays
if coordinates is None:
coordinates_field = self.nodes.coordinates_field
coordinates = self.nodes.coordinates_field.data
else:
coordinates_field = coordinates
coordinates = coordinates.data
setattr(grid, "_dpf_cache", [coordinates, coordinates_field])

return grid
Expand Down
4 changes: 4 additions & 0 deletions src/ansys/dpf/core/outputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ def get_data(self):
type_output = types.meshes_container
elif type_output == "streams_container":
type_output = types.streams_container
elif type_output == "vector<double>":
type_output = types.vec_double
elif type_output == "vector<int32>":
type_output = types.vec_int

return self._operator.get_output(self._pin, type_output)

Expand Down
131 changes: 81 additions & 50 deletions src/ansys/dpf/core/vtk_helper.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import numpy as np
import pyvista as pv
import ansys.dpf.core as dpf
from ansys.dpf.core import errors
from vtk import (
VTK_HEXAHEDRON,
VTK_LINE,
Expand All @@ -24,47 +26,6 @@

VTK9 = vtkVersion().GetVTKMajorVersion() >= 9

# Maps dpf cell sizes (based on array order) to the number of nodes per cell
SIZE_MAPPING = np.array(
[
10, # kAnsTet10
20, # kAnsHex20
15, # kAnsWedge15
13, # kAnsPyramid13
6, # kAnsTri6
6, # kAnsTriShell6
8, # kAnsQuad8
8, # kAnsQuadShell8
3, # kAnsLine3
1, # kAnsPoint1
4, # kAnsTet4
8, # kAnsHex8
6, # kAnsWedge6
5, # kAnsPyramid5
3, # kAnsTri3
3, # kAnsTriShell3
4, # kAnsQuad4
4, # kAnsQuadShell4
2, # kAnsLine2
0, # kAnsNumElementTypes
0, # kAnsUnknown
0, # kAnsEMagLine
0, # kAnsEMagArc
0, # kAnsEMagCircle
3, # kAnsSurface3
4, # kAnsSurface4
6, # kAnsSurface6
8, # kAnsSurface8
2, # kAnsEdge2
3, # kAnsEdge3
3, # kAnsBeam3
4, # kAnsBeam4
0, # kAnsGeneralPlaceholder
-1, # kAnsPolygon
-2, # kAnsPolyhedron
]
) # kAnsBeam4


# DPF --> VTK mapping
# any cells not mapped will be empty cells
Expand Down Expand Up @@ -163,26 +124,70 @@ def __init__(
ModuleNotFoundError.__init__(self, msg)


def dpf_mesh_to_vtk(nodes, etypes, connectivity, as_linear=True, mesh=None):
def dpf_mesh_to_vtk_op(mesh, nodes, as_linear):
"""Return a pyvista unstructured grid given DPF node and element
definitions.
definitions from operators (server > 6.2)

Parameters
----------
nodes : np.ndarray
Numpy array containing the nodes of the mesh.
mesh : dpf.MeshedRegion
Meshed Region to export to pyVista format

etypes : np.ndarray
ANSYS DPF element types.
nodes : dpf.Field
Field containing the nodes of the mesh.

connectivity : np.ndarray
Array containing the nodes used by each element.
as_linear : bool
Export quadratic surface elements as linear.

Returns
-------
grid : pyvista.UnstructuredGrid
Unstructured grid of the DPF mesh.
"""
mesh_to_pyvista = dpf.operators.mesh.mesh_to_pyvista(server=mesh._server)
mesh_to_pyvista.inputs.mesh.connect(mesh)
mesh_to_pyvista.inputs.as_linear.connect(as_linear)
mesh_to_pyvista.inputs.vtk_updated.connect(VTK9)
if nodes is not None:
mesh_to_pyvista.inputs.coordinates.connect(nodes)

nodes_pv = mesh_to_pyvista.outputs.nodes()
cells_pv = mesh_to_pyvista.outputs.cells()
celltypes_pv = mesh_to_pyvista.outputs.cell_types()
if VTK9:
return pv.UnstructuredGrid(cells_pv, celltypes_pv, nodes_pv)
else:
offsets_pv = mesh_to_pyvista.outputs.offsets()
return pv.UnstructuredGrid(offsets_pv, cells_pv, celltypes_pv, nodes_pv)


def dpf_mesh_to_vtk_py(mesh, nodes, as_linear):
"""Return a pyvista unstructured grid given DPF node and element
definitions in pure Python (server <= 6.2)

Parameters
----------
mesh : dpf.MeshedRegion
Meshed Region to export to pyVista format

nodes : dpf.Field
Field containing the nodes of the mesh.

as_linear : bool
Export quadratic surface elements as linear.

Returns
-------
grid : pyvista.UnstructuredGrid
Unstructured grid of the DPF mesh.
"""
etypes = mesh.elements.element_types_field.data
connectivity = mesh.elements.connectivities_field
if nodes is None:
nodes = mesh.nodes.coordinates_field.data
else:
nodes = nodes.data

elem_size = np.ediff1d(np.append(connectivity._data_pointer, connectivity.shape))

faces_nodes_connectivity = mesh.property_field("faces_nodes_connectivity")
Expand All @@ -197,7 +202,7 @@ def dpf_mesh_to_vtk(nodes, etypes, connectivity, as_linear=True, mesh=None):
insert_ind = np.cumsum(elem_size)
insert_ind = np.hstack(([0], insert_ind))[:-1]

# TODO: Investigate why connectivity can be -1
# Handle semiparabolic elements
nullmask = connectivity.data == -1
connectivity.data[nullmask] = 0
if nullmask.any():
Expand Down Expand Up @@ -283,6 +288,32 @@ def compute_offset():
return pv.UnstructuredGrid(offset, cells, vtk_cell_type, nodes)


def dpf_mesh_to_vtk(mesh, nodes=None, as_linear=True):
"""Return a pyvista unstructured grid given DPF node and element
definitions.

Parameters
----------
mesh : dpf.MeshedRegion
Meshed Region to export to pyVista format

nodes : dpf.Field, optional
Field containing the nodes of the mesh.

as_linear : bool, optional
Export quadratic surface elements as linear.

Returns
-------
grid : pyvista.UnstructuredGrid
Unstructured grid of the DPF mesh.
"""
try:
return dpf_mesh_to_vtk_op(mesh, nodes, as_linear)
except (AttributeError, KeyError, errors.DPFServerException):
return dpf_mesh_to_vtk_py(mesh, nodes, as_linear)


def vtk_update_coordinates(vtk_grid, coordinates_array):
from copy import copy

Expand Down