-
Notifications
You must be signed in to change notification settings - Fork 135
Reducing pymapdl-reader
dependency on the mesh
module
#1299
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
Merged
Merged
Changes from 39 commits
Commits
Show all changes
40 commits
Select commit
Hold shift + click to select a range
7a953e1
Replacing default value for chunk size.
germa89 d773c97
First attemp
germa89 dc45712
Merge branch 'main' into feat/replacing-mesh
germa89 3279887
Merge branch 'main' into feat/replacing-mesh
germa89 9662cae
Initial commit.
germa89 1d42302
Adding dpf to test requirements.
germa89 c3784e6
Missing import
germa89 18e1006
Renaming class.
germa89 2f43419
Merge branch 'main' into feat/replacing-mesh
germa89 7a08c35
Moving contact solve fixture to conftest
germa89 4aa9e8a
fixing some coverage.
germa89 b3f4870
Adding unit tests
germa89 37d5887
removing extra file
germa89 f330e77
Removing dpf
germa89 f459e0d
Fixing tests
germa89 3f2a6a5
Adding test to not implemented methods.
germa89 cc01ec2
Removing needs from unit tests in CICD
germa89 af559b3
Merge branch 'ci/make-unit-test-independent-' into feat/replacing-mesh
germa89 da50d25
Fixing unit tests and removing overwritting of ``node_angles``
germa89 9b1f1a7
Undoing the node_angles
germa89 c1e26da
Merging both classes and changing folder name.
germa89 2ab7a9b
emptying the mesh file.
germa89 b8e44cb
emptying the mesh file.
germa89 3415677
Big refactoring.
germa89 57235a0
Adding unit tests.
germa89 06c2222
Fixing tests
germa89 35e25ed
Improving tests.
germa89 e4a0194
Improving coverage
germa89 69f246e
Calling parse_vtk from mesh folder (centralizing)
germa89 a925e29
Adding mesh.py
germa89 4856654
Removing duplicated function
germa89 d9f9efc
Trying to fix the docs.
germa89 dccc09f
Fixing tech demo example
germa89 70fe5aa
Merge branch 'main' into feat/replacing-mesh
germa89 4db3b14
Fixing mesh plotting in tech demo
germa89 8ce0f94
Ading more clean options to make file
germa89 a6d8fbb
Reset cache
germa89 fd5efa2
Merge branch 'main' into feat/replacing-mesh
germa89 14287b7
fixing cache.
germa89 983eca9
Removing useless if condition.
germa89 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
"""Module for common class between Archive, and result mesh.""" | ||
from ansys.mapdl.reader import _reader, _relaxmidside | ||
from ansys.mapdl.reader.elements import ETYPE_MAP | ||
from ansys.mapdl.reader.misc import unique_rows | ||
import numpy as np | ||
import pyvista as pv | ||
from pyvista._vtk import VTK9 | ||
|
||
INVALID_ALLOWABLE_TYPES = TypeError( | ||
"`allowable_types` must be an array " "of ANSYS element types from 1 and 300" | ||
) | ||
|
||
# map MESH200 elements to a pymapdl_reader/VTK element type (see elements.py) | ||
MESH200_MAP = { | ||
0: 2, # line | ||
1: 2, # line | ||
2: 2, # line | ||
3: 2, # line | ||
4: 3, # triangle | ||
5: 3, # triangle | ||
6: 3, # quadrilateral | ||
7: 3, # quadrilateral | ||
8: 5, # tetrahedron with 4 nodes | ||
9: 5, # tetrahedron with 10 nodes | ||
10: 4, # hex with 8 nodes | ||
11: 4, | ||
} # hex with 8 nodes | ||
|
||
SHAPE_MAP = { # from ELIST definition | ||
0: "", | ||
1: "LINE", | ||
2: "PARA", | ||
3: "ARC ", | ||
4: "CARC", | ||
5: "", | ||
6: "TRIA", | ||
7: "QUAD", | ||
8: "TRI6", | ||
9: "QUA8", | ||
10: "POIN", | ||
11: "CIRC", | ||
12: "", | ||
13: "", | ||
14: "CYLI", | ||
15: "CONE", | ||
16: "SPHE", | ||
17: "", | ||
18: "", | ||
19: "PILO", | ||
} | ||
# element type to VTK conversion function call map | ||
# 0: skip | ||
# 1: Point | ||
# 2: Line (linear or quadratic) | ||
# 3: Shell | ||
# 4: 3D Solid (Hexahedral, wedge, pyramid, tetrahedral) | ||
# 5: Tetrahedral | ||
# 6: Line (always linear) | ||
TARGE170_MAP = { | ||
"TRI": 3, # 3-Node Triangle | ||
"QUAD": 3, # 4-Node Quadrilateral | ||
"CYLI": 0, # Not supported (NS) # Cylinder | ||
"CONE": 0, # NS # Cone | ||
"TRI6": 3, # 6-Node triangle | ||
"SPHE": 0, # NS # Sphere | ||
"PILO": 1, # Pilot Node | ||
"QUAD8": 3, # 8-Node Quadrilateral | ||
"LINE": 2, # Line | ||
"PARA": 2, # Parabola | ||
"POINT": 1, # Point | ||
} | ||
|
||
|
||
def _parse_vtk( | ||
mesh, | ||
allowable_types=None, | ||
force_linear=False, | ||
null_unallowed=False, | ||
fix_midside=True, | ||
additional_checking=False, | ||
): | ||
"""Convert raw ANSYS nodes and elements to a VTK UnstructuredGrid | ||
|
||
Parameters | ||
---------- | ||
fix_midside : bool, optional | ||
Adds additional midside nodes when ``True``. When | ||
``False``, missing ANSYS cells will simply point to the | ||
first node. | ||
|
||
""" | ||
if not mesh._has_nodes or not mesh._has_elements: | ||
# warnings.warn('Missing nodes or elements. Unable to parse to vtk') | ||
return | ||
|
||
etype_map = ETYPE_MAP | ||
if allowable_types is not None: | ||
try: | ||
allowable_types = np.asarray(allowable_types) | ||
except: | ||
raise INVALID_ALLOWABLE_TYPES | ||
|
||
if not issubclass(allowable_types.dtype.type, np.integer): | ||
raise TypeError("Element types must be an integer array-like") | ||
|
||
if allowable_types.min() < 1 or allowable_types.max() > 300: | ||
raise INVALID_ALLOWABLE_TYPES | ||
|
||
etype_map = np.zeros_like(ETYPE_MAP) | ||
etype_map[allowable_types] = ETYPE_MAP[allowable_types] | ||
|
||
# ANSYS element type to VTK map | ||
type_ref = np.empty(2 << 16, np.int32) # 131072 | ||
type_ref[mesh._ekey[:, 0]] = etype_map[mesh._ekey[:, 1]] | ||
|
||
if allowable_types is None or 200 in allowable_types: | ||
for etype_ind, etype in mesh._ekey: | ||
|
||
# MESH200 | ||
if etype == 200 and etype_ind in mesh.key_option: | ||
# keyoption 1 contains various cell types | ||
# map them to the corresponding type (see elements.py) | ||
mapped = MESH200_MAP[mesh.key_option[etype_ind][0][1]] | ||
type_ref[etype_ind] = mapped | ||
|
||
# TARGE170 specifics | ||
if etype == 170: | ||
# edge case where missing element within the tshape_key | ||
if etype_ind not in mesh.tshape_key: # pragma: no cover | ||
continue | ||
tshape_num = mesh.tshape_key[etype_ind] | ||
if tshape_num >= 19: # weird bug when 'PILO' can be 99 instead of 19. | ||
tshape_num = 19 | ||
tshape_label = SHAPE_MAP[tshape_num] | ||
type_ref[etype_ind] = TARGE170_MAP.get(tshape_label, 0) | ||
|
||
offset, celltypes, cells = _reader.ans_vtk_convert( | ||
mesh._elem, mesh._elem_off, type_ref, mesh.nnum, True | ||
) # for reset_midside | ||
|
||
nodes, angles, nnum = mesh.nodes, mesh.node_angles, mesh.nnum | ||
|
||
# fix missing midside | ||
if np.any(cells == -1): | ||
if fix_midside: | ||
nodes, angles, nnum = fix_missing_midside( | ||
cells, nodes, celltypes, offset, angles, nnum | ||
) | ||
else: | ||
cells[cells == -1] = 0 | ||
|
||
if additional_checking: | ||
cells[cells < 0] = 0 | ||
# cells[cells >= nodes.shape[0]] = 0 # fails when n_nodes < 20 | ||
|
||
if VTK9: | ||
grid = pv.UnstructuredGrid(cells, celltypes, nodes, deep=True) | ||
else: | ||
grid = pv.UnstructuredGrid(offset, cells, celltypes, nodes, deep=True) | ||
|
||
# Store original ANSYS element and node information | ||
grid.point_data["ansys_node_num"] = nnum | ||
grid.cell_data["ansys_elem_num"] = mesh.enum | ||
grid.cell_data["ansys_real_constant"] = mesh.elem_real_constant | ||
grid.cell_data["ansys_material_type"] = mesh.material_type | ||
grid.cell_data["ansys_etype"] = mesh._ans_etype | ||
grid.cell_data["ansys_elem_type_num"] = mesh.etype | ||
|
||
# add components | ||
# Add element components to unstructured grid | ||
for key, item in mesh.element_components.items(): | ||
mask = np.in1d(mesh.enum, item, assume_unique=True) | ||
grid.cell_data[key] = mask | ||
|
||
# Add node components to unstructured grid | ||
for key, item in mesh.node_components.items(): | ||
mask = np.in1d(nnum, item, assume_unique=True) | ||
grid.point_data[key] = mask | ||
|
||
# store node angles | ||
if angles is not None: | ||
if angles.shape[1] == 3: | ||
grid.point_data["angles"] = angles | ||
|
||
if not null_unallowed: | ||
grid = grid.extract_cells(grid.celltypes != 0) | ||
|
||
if force_linear: | ||
# only run if the grid has points or cells | ||
if grid.n_points: | ||
grid = grid.linear_copy() | ||
|
||
# map over element types | ||
# Add tracker for original node numbering | ||
ind = np.arange(grid.n_points) | ||
grid.point_data["origid"] = ind | ||
grid.point_data["VTKorigID"] = ind | ||
return grid | ||
|
||
|
||
def fix_missing_midside(cells, nodes, celltypes, offset, angles, nnum): | ||
"""Adds missing midside nodes to cells. | ||
|
||
ANSYS sometimes does not add midside nodes, and this is denoted in | ||
the element array with a ``0``. When translated to VTK, this is | ||
saved as a ``-1``. If this is not corrected, VTK will segfault. | ||
|
||
This function creates missing midside nodes for the quadratic | ||
elements. | ||
""" | ||
# Check for missing midside nodes | ||
mask = cells == -1 | ||
nnodes = nodes.shape[0] | ||
|
||
nextra = mask.sum() | ||
cells[mask] = np.arange(nnodes, nnodes + nextra) | ||
|
||
nodes_new = np.empty((nnodes + nextra, 3)) | ||
nodes_new[:nnodes] = nodes | ||
nodes_new[nnodes:] = 0 # otherwise, segfault disaster | ||
|
||
# Set new midside nodes directly between their edge nodes | ||
temp_nodes = nodes_new.copy() | ||
_relaxmidside.reset_midside(cells, celltypes, offset, temp_nodes) | ||
|
||
# merge midside nodes | ||
unique_nodes, idx_a, idx_b = unique_rows(temp_nodes[nnodes:]) | ||
|
||
# rewrite node numbers | ||
cells[mask] = idx_b + nnodes | ||
nextra = idx_a.shape[0] # extra unique nodes | ||
nodes_new = nodes_new[: nnodes + nextra] | ||
nodes_new[nnodes:] = unique_nodes | ||
|
||
if angles is not None: | ||
new_angles = np.empty((nnodes + nextra, 3)) | ||
new_angles[:nnodes] = angles | ||
new_angles[nnodes:] = 0 | ||
else: | ||
new_angles = None | ||
|
||
# Add extra node numbers | ||
nnum_new = np.empty(nnodes + nextra) | ||
nnum_new[:nnodes] = nnum | ||
nnum_new[nnodes:] = -1 | ||
return nodes_new, new_angles, nnum_new |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.