From 21f340f2a24bc82454aedbf8d56903d52163cb6a Mon Sep 17 00:00:00 2001 From: Alex Kaszynski Date: Thu, 22 Jun 2023 08:11:49 -0700 Subject: [PATCH] Remove usage of _vtk (#272) * avoid usage of _vtk * use int32 * fix tests --- ansys/mapdl/reader/archive.py | 131 ++++++++++++------------- ansys/mapdl/reader/cyclic_reader.py | 4 +- ansys/mapdl/reader/cython/_archive.pyx | 57 +++++------ ansys/mapdl/reader/cython/archive.c | 21 ++-- ansys/mapdl/reader/cython/archive.h | 4 +- ansys/mapdl/reader/dis_result.py | 2 +- tests/archive/test_archive.py | 49 +++++---- 7 files changed, 134 insertions(+), 134 deletions(-) diff --git a/ansys/mapdl/reader/archive.py b/ansys/mapdl/reader/archive.py index a403a74f..2289fd9c 100644 --- a/ansys/mapdl/reader/archive.py +++ b/ansys/mapdl/reader/archive.py @@ -7,19 +7,7 @@ import numpy as np import pyvista as pv -from pyvista import _vtk as vtk -from pyvista._vtk import ( - VTK_HEXAHEDRON, - VTK_PYRAMID, - VTK_QUAD, - VTK_QUADRATIC_HEXAHEDRON, - VTK_QUADRATIC_PYRAMID, - VTK_QUADRATIC_TETRA, - VTK_QUADRATIC_WEDGE, - VTK_TETRA, - VTK_TRIANGLE, - VTK_WEDGE, -) +from pyvista import CellType VTK_VOXEL = 11 @@ -217,7 +205,7 @@ def __repr__(self): @property def grid(self): - """``vtk.UnstructuredGrid`` of the archive file. + """Return a ``pyvista.UnstructuredGrid`` of the archive file. Examples -------- @@ -258,7 +246,7 @@ def quality(self): """ if self._grid is None: # pragma: no cover raise AttributeError( - "Archive must be parsed as a vtk grid.\n" "Set `parse_vtk=True`" + "Archive must be parsed as a vtk grid.\nSet `parse_vtk=True`" ) return quality(self._grid) @@ -388,27 +376,29 @@ def save_as_archive( if hasattr(grid, "cast_to_unstructured_grid"): grid = grid.cast_to_unstructured_grid() - if not isinstance(grid, vtk.vtkUnstructuredGrid): - raise TypeError("``grid`` argument must be an UnstructuredGrid") + if not isinstance(grid, pv.UnstructuredGrid): + raise TypeError( + f"``grid`` argument must be an UnstructuredGrid, not {type(grid)}" + ) allowable = [] if include_solid_elements: allowable.extend( [ - VTK_VOXEL, - VTK_TETRA, - VTK_QUADRATIC_TETRA, - VTK_PYRAMID, - VTK_QUADRATIC_PYRAMID, - VTK_WEDGE, - VTK_QUADRATIC_WEDGE, - VTK_HEXAHEDRON, - VTK_QUADRATIC_HEXAHEDRON, + CellType.VOXEL, + CellType.TETRA, + CellType.QUADRATIC_TETRA, + CellType.PYRAMID, + CellType.QUADRATIC_PYRAMID, + CellType.WEDGE, + CellType.QUADRATIC_WEDGE, + CellType.HEXAHEDRON, + CellType.QUADRATIC_HEXAHEDRON, ] ) if include_surface_elements: - allowable.extend([VTK_TRIANGLE, VTK_QUAD]) + allowable.extend([CellType.TRIANGLE, CellType.QUAD]) # VTK_QUADRATIC_TRIANGLE, # VTK_QUADRATIC_QUAD @@ -432,7 +422,7 @@ def save_as_archive( nodenum = grid.point_data["ansys_node_num"] else: log.info("No ANSYS node numbers set in input. Adding default range") - nodenum = np.arange(1, grid.number_of_points + 1, dtype=np.int32) + nodenum = np.arange(1, grid.n_points + 1, dtype=np.int32) missing_mask = nodenum == -1 if np.any(missing_mask): @@ -457,12 +447,12 @@ def save_as_archive( nodenum[missing_mask] = np.arange(start_num, end_num, dtype=np.int32) # element block - ncells = grid.number_of_cells + ncells = grid.n_cells if "ansys_elem_num" in grid.cell_data: enum = grid.cell_data["ansys_elem_num"] else: if not allow_missing: - raise Exception('Missing node numbers. Exiting due "allow_missing=False"') + raise Exception('Missing node numbers. Exiting due "allow_missing=False"') log.info( "No ANSYS element numbers set in input. " "Adding default range starting from %d", @@ -483,7 +473,7 @@ def save_as_archive( nadd = np.sum(enum == -1) end_num = start_num + nadd log.info( - "FEM missing some cell numbers. Adding numbering " "from %d to %d", + "FEM missing some cell numbers. Adding numbering from %d to %d", start_num, end_num, ) @@ -555,26 +545,39 @@ def save_as_archive( + "Adding default range starting from %d" % etype_start ) - etype = np.empty(grid.number_of_cells, np.int32) - etype_185 = etype_start + 2 - etype[grid.celltypes == VTK_VOXEL] = etype_185 - etype[grid.celltypes == VTK_TETRA] = etype_185 - etype[grid.celltypes == VTK_HEXAHEDRON] = etype_185 - etype[grid.celltypes == VTK_WEDGE] = etype_185 - etype[grid.celltypes == VTK_PYRAMID] = etype_185 + etype = np.empty(grid.n_cells, np.int32) + # VTK to SOLID186 mapping + # TETRA delegated to SOLID187 etype_186 = etype_start - etype[grid.celltypes == VTK_QUADRATIC_HEXAHEDRON] = etype_186 - etype[grid.celltypes == VTK_QUADRATIC_WEDGE] = etype_186 - etype[grid.celltypes == VTK_QUADRATIC_PYRAMID] = etype_186 + etype_186_types = [ + CellType.QUADRATIC_HEXAHEDRON, + CellType.QUADRATIC_WEDGE, + CellType.QUADRATIC_PYRAMID, + ] + etype[np.isin(grid.celltypes, etype_186_types)] = etype_186 etype_187 = etype_start + 1 - etype[grid.celltypes == VTK_QUADRATIC_TETRA] = etype_187 + etype[grid.celltypes == CellType.QUADRATIC_TETRA] = etype_187 + + # VTK to SOLID185 mapping + etype_185 = etype_start + 2 + etype_185_types = [ + CellType.VOXEL, + CellType.TETRA, + CellType.HEXAHEDRON, + CellType.WEDGE, + CellType.PYRAMID, + ] + etype[np.isin(grid.celltypes, etype_185_types)] = etype_185 # Surface elements etype_181 = etype_start + 3 - etype[grid.celltypes == VTK_TRIANGLE] = etype_181 - etype[grid.celltypes == VTK_QUAD] = etype_181 + etype_181_types = [ + CellType.TRIANGLE, + CellType.QUAD, + ] + etype[np.isin(grid.celltypes, etype_181_types)] = etype_181 typenum = np.empty_like(etype) typenum[etype == etype_185] = 185 @@ -582,10 +585,10 @@ def save_as_archive( typenum[etype == etype_187] = 187 typenum[etype == etype_181] = 181 - header += "ET, %d, 185\n" % etype_185 - header += "ET, %d, 186\n" % etype_186 - header += "ET, %d, 187\n" % etype_187 - header += "ET, %d, 181\n" % etype_181 + header += f"ET,{etype_185},185\n" + header += f"ET,{etype_186},186\n" + header += f"ET,{etype_187},187\n" + header += f"ET,{etype_181},181\n" # number of nodes written per element elem_nnodes = np.empty(etype.size, np.int32) @@ -623,7 +626,7 @@ def save_as_archive( write_nblock(filename, nodenum, grid.points, mode="a") # write remainder of eblock - cells, offset = vtk_cell_info(grid, shift_offset=False) + cells, offset = vtk_cell_info(grid, force_int64=False, shift_offset=False) _write_eblock( filename, enum, @@ -798,26 +801,16 @@ def _write_eblock( ): """Write EBLOCK to disk""" # perform type checking here - if elem_id.dtype != np.int32: - elem_id = elem_id.astype(np.int32) - if etype.dtype != np.int32: - etype = etype.astype(np.int32) - if mtype.dtype != np.int32: - mtype = mtype.astype(np.int32) - if rcon.dtype != np.int32: - rcon = rcon.astype(np.int32) - if elem_nnodes.dtype != np.int32: - elem_nnodes = elem_nnodes.astype(np.int32) - if cells.dtype != np.int64: - cells = cells.astype(np.int64) - if offset.dtype != np.int64: - offset = offset.astype(np.int64) - if celltypes.dtype != np.uint8: - celltypes = celltypes.astype(np.uint8) - if typenum.dtype != np.int32: - typenum = typenum.astype(np.int32) - if nodenum.dtype != np.int32: - nodenum = nodenum.astype(np.int32) + elem_id = elem_id.astype(np.int32, copy=False) + etype = etype.astype(np.int32, copy=False) + mtype = mtype.astype(np.int32, copy=False) + rcon = rcon.astype(np.int32, copy=False) + elem_nnodes = elem_nnodes.astype(np.int32, copy=False) + cells = cells.astype(np.int32, copy=False) + offset = offset.astype(np.int32, copy=False) + celltypes = celltypes.astype(np.uint8, copy=False) + typenum = typenum.astype(np.int32, copy=False) + nodenum = nodenum.astype(np.int32, copy=False) _archive.py_write_eblock( filename, diff --git a/ansys/mapdl/reader/cyclic_reader.py b/ansys/mapdl/reader/cyclic_reader.py index 4191617a..cd19cb5f 100644 --- a/ansys/mapdl/reader/cyclic_reader.py +++ b/ansys/mapdl/reader/cyclic_reader.py @@ -3,7 +3,9 @@ import numpy as np import pyvista as pv -from pyvista._vtk import vtkAppendFilter, vtkMatrix4x4, vtkTransform +from vtkmodules.vtkCommonMath import vtkMatrix4x4 +from vtkmodules.vtkCommonTransforms import vtkTransform +from vtkmodules.vtkFiltersCore import vtkAppendFilter from ansys.mapdl.reader import _binary_reader from ansys.mapdl.reader.common import ( diff --git a/ansys/mapdl/reader/cython/_archive.pyx b/ansys/mapdl/reader/cython/_archive.pyx index ef3aa69e..3fafe3ba 100644 --- a/ansys/mapdl/reader/cython/_archive.pyx +++ b/ansys/mapdl/reader/cython/_archive.pyx @@ -14,8 +14,6 @@ import numpy as np cimport numpy as np ctypedef unsigned char uint8_t -from libc.stdint cimport int64_t - cdef extern from 'archive.h' nogil: int write_nblock(FILE*, const int, const int, const int*, const double*, @@ -23,8 +21,8 @@ cdef extern from 'archive.h' nogil: int write_nblock_float(FILE*, const int, const int, const int*, const float*, const float*, int) int write_eblock(FILE*, const int, const int*, const int*, const int*, - const int*, const int*, const uint8_t*, const int64_t*, - const int64_t*, const int*, const int*); + const int*, const int*, const uint8_t*, const int*, + const int*, const int*, const int*); cdef extern from "stdio.h": @@ -100,31 +98,34 @@ def py_write_nblock_float(filename, const int [::1] node_id, int max_node_id, fclose(cfile) -def py_write_eblock(filename, - const int [::1] elem_id, - const int [::1] etype, - const int [::1] mtype, - const int [::1] rcon, - const int [::1] elem_nnodes, - const int64_t [::1] cells, - const int64_t [::1] offset, - const uint8_t [::1] celltypes, - const int [::1] typenum, - const int [::1] nodenum, - mode='w'): +def py_write_eblock( + filename, + const int [::1] elem_id, + const int [::1] etype, + const int [::1] mtype, + const int [::1] rcon, + const int [::1] elem_nnodes, + const int [::1] cells, + const int [::1] offset, + const uint8_t [::1] celltypes, + const int [::1] typenum, + const int [::1] nodenum, + mode='w'): cdef FILE* cfile = fopen(filename.encode(), mode.encode()) - write_eblock(cfile, - celltypes.size, - &elem_id[0], - &etype[0], - &mtype[0], - &rcon[0], - &elem_nnodes[0], - &celltypes[0], - &offset[0], - &cells[0], - &typenum[0], - &nodenum[0]) + write_eblock( + cfile, + celltypes.size, + &elem_id[0], + &etype[0], + &mtype[0], + &rcon[0], + &elem_nnodes[0], + &celltypes[0], + &offset[0], + &cells[0], + &typenum[0], + &nodenum[0] + ) fclose(cfile) diff --git a/ansys/mapdl/reader/cython/archive.c b/ansys/mapdl/reader/cython/archive.c index ba4bb24e..06567c89 100644 --- a/ansys/mapdl/reader/cython/archive.c +++ b/ansys/mapdl/reader/cython/archive.c @@ -91,8 +91,8 @@ int write_eblock( const int *rcon, // real constant ID array const int *elem_nnodes, // number of nodes per element const uint8_t *celltypes, // VTK celltypes array - const int64_t *offset, // VTK offset array - const int64_t *cells, // VTK cells array + const int *offset, // VTK offset array + const int *cells, // VTK cell connectivity array const int *typenum, // ANSYS type number (e.g. 187 for SOLID187) const int *nodenum) { // ANSYS node numbering @@ -102,7 +102,6 @@ int write_eblock( int c; // position within offset array for (int i = 0; i < n_elem; i++) { - // Position within offset array c = offset[i]; // Write cell info @@ -124,12 +123,18 @@ int write_eblock( case VTK_QUADRATIC_TETRA: if (typenum[i] == 187) { fprintf(file, "%8d%8d%8d%8d%8d%8d%8d%8d\n%8d%8d\n", - nodenum[cells[c + 0]], nodenum[cells[c + 1]], - nodenum[cells[c + 2]], nodenum[cells[c + 3]], - nodenum[cells[c + 4]], nodenum[cells[c + 5]], - nodenum[cells[c + 6]], nodenum[cells[c + 7]], - nodenum[cells[c + 8]], nodenum[cells[c + 9]]); + nodenum[cells[c + 0]], // 0, I + nodenum[cells[c + 1]], // 1, J + nodenum[cells[c + 2]], // 2, K + nodenum[cells[c + 3]], // 3, L + nodenum[cells[c + 4]], // 4, M + nodenum[cells[c + 5]], // 5, N + nodenum[cells[c + 6]], // 6, O + nodenum[cells[c + 7]], // 7, P + nodenum[cells[c + 8]], // 8, Q + nodenum[cells[c + 9]]); // 9, R } else { + // Using SOLID186-like format fprintf( file, "%8d%8d%8d%8d%8d%8d%8d%8d\n%8d%8d%8d%8d%8d%8d%8d%8d%8d%8d%8d%8d\n", diff --git a/ansys/mapdl/reader/cython/archive.h b/ansys/mapdl/reader/cython/archive.h index 09e65852..adb568ff 100644 --- a/ansys/mapdl/reader/cython/archive.h +++ b/ansys/mapdl/reader/cython/archive.h @@ -11,5 +11,5 @@ int write_nblock(FILE*, const int, const int, const int*, const double*, int write_nblock_float(FILE*, const int, const int, const int*, const float*, const float*, int); int write_eblock(FILE*, const int, const int*, const int*, const int*, - const int*, const int*, const uint8_t*, const int64_t*, - const int64_t*, const int*, const int*); + const int*, const int*, const uint8_t*, const int*, + const int*, const int*, const int*); diff --git a/ansys/mapdl/reader/dis_result.py b/ansys/mapdl/reader/dis_result.py index ced219c2..4d964ad7 100644 --- a/ansys/mapdl/reader/dis_result.py +++ b/ansys/mapdl/reader/dis_result.py @@ -8,7 +8,7 @@ import numpy as np import pyvista as pv -from pyvista._vtk import vtkAppendFilter +from vtkmodules.vtkFiltersCore import vtkAppendFilter from ansys.mapdl.reader._binary_reader import read_nodal_values_dist from ansys.mapdl.reader._rst_keys import element_index_table_info diff --git a/tests/archive/test_archive.py b/tests/archive/test_archive.py index 09888d5d..23ba18c4 100644 --- a/tests/archive/test_archive.py +++ b/tests/archive/test_archive.py @@ -4,22 +4,24 @@ import numpy as np import pytest import pyvista as pv +from pyvista import CellType from pyvista import examples as pyvista_examples -from pyvista._vtk import ( - VTK_HEXAHEDRON, - VTK_PYRAMID, - VTK_QUADRATIC_HEXAHEDRON, - VTK_QUADRATIC_PYRAMID, - VTK_QUADRATIC_TETRA, - VTK_QUADRATIC_WEDGE, - VTK_TETRA, - VTK_WEDGE, -) from ansys.mapdl import reader as pymapdl_reader from ansys.mapdl.reader import _archive, archive, examples -LINEAR_CELL_TYPES = [VTK_TETRA, VTK_PYRAMID, VTK_WEDGE, VTK_HEXAHEDRON] +LINEAR_CELL_TYPES = [ + CellType.TETRA, + CellType.PYRAMID, + CellType.WEDGE, + CellType.HEXAHEDRON, +] +QUADRATIC_CELL_TYPES = [ + CellType.QUADRATIC_TETRA, + CellType.QUADRATIC_PYRAMID, + CellType.QUADRATIC_WEDGE, + CellType.QUADRATIC_HEXAHEDRON, +] TEST_PATH = os.path.dirname(os.path.abspath(__file__)) TESTFILES_PATH = os.path.join(TEST_PATH, "test_data") @@ -156,7 +158,7 @@ def test_missing_midside(): archive = pymapdl_reader.Archive(archive_file, allowable_types=allowable_types) assert (archive.quality > 0.0).all() - assert not np.any(archive.grid.celltypes == VTK_TETRA) + assert not np.any(archive.grid.celltypes == CellType.TETRA) def test_missing_midside_write(tmpdir): @@ -179,7 +181,10 @@ def test_writehex(tmpdir, hex_archive): pymapdl_reader.save_as_archive(filename, hex_archive.grid) archive_new = pymapdl_reader.Archive(filename) assert np.allclose(hex_archive.grid.points, archive_new.grid.points) - assert np.allclose(hex_archive.grid.cells, archive_new.grid.cells) + assert np.allclose( + hex_archive.grid.cell_connectivity, + archive_new.grid.cell_connectivity, + ) for node_component in hex_archive.node_components: assert np.allclose( @@ -321,15 +326,7 @@ def test_read_complex_archive_linear(all_solid_cells_archive_linear): assert np.all(all_solid_cells_archive_linear.quality > 0.0) -@pytest.mark.parametrize( - "celltype", - [ - VTK_QUADRATIC_TETRA, - VTK_QUADRATIC_PYRAMID, - VTK_QUADRATIC_WEDGE, - VTK_QUADRATIC_HEXAHEDRON, - ], -) +@pytest.mark.parametrize("celltype", QUADRATIC_CELL_TYPES) def test_write_quad_complex_archive(tmpdir, celltype, all_solid_cells_archive): grid = all_solid_cells_archive.grid mask = grid.celltypes == celltype @@ -487,7 +484,9 @@ def test_cython_write_eblock(hex_archive, tmpdir): nodenum = hex_archive.nnum cells, offset = pymapdl_reader.misc.vtk_cell_info( - hex_archive.grid, shift_offset=False + hex_archive.grid, + force_int64=False, + shift_offset=False, ) _archive.py_write_eblock( filename, @@ -496,8 +495,8 @@ def test_cython_write_eblock(hex_archive, tmpdir): hex_archive.material_type, np.ones(hex_archive.n_elem, np.int32), elem_nnodes, - cells, - offset, + cells.astype(np.int32, copy=False), + offset.astype(np.int32, copy=False), hex_archive.grid.celltypes, typenum, nodenum,