Source code for ensight2vtk

#!/usr/bin/env python

"""
ensight2vtk script
==================

This script converts parts from EnSight Gold case into
files in VTK legacy ASCII format.

Demonstrates reading steady-state geometry, node coordinates,
connectivity, per-node and per-element variable data
using memory-mapped I/O.

For commandline usage, run the script with ``--help``.

"""

import argparse
import os.path as op
import re
import sys
from typing import Optional

from ensightreader import ElementType, EnsightCaseFile, VariableType, read_case


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("ensight_case", metavar="*.case", help="input EnSight Gold case (C Binary)")
    parser.add_argument("output_vtk", metavar="*.vtk", help="output VTK file (text)")
    parser.add_argument("--only-parts", metavar="regex", help="only export parts matching given "
                                                              "regular expression (Python re.search)")

    args = parser.parse_args()
    ensight_case_path = args.ensight_case
    output_vtk_path_given = args.output_vtk
    part_name_regex = args.only_parts

    return ensight2vtk(ensight_case_path, output_vtk_path_given, part_name_regex)


[docs] def ensight2vtk(ensight_case_path: str, output_vtk_path_given: str, part_name_regex: Optional[str] = None) -> int: """Main function of ensight2vtk.py""" output_vtk_prefix, _ = op.splitext(output_vtk_path_given) print("Reading input EnSight case", ensight_case_path) case = read_case(ensight_case_path) geofile = case.get_geometry_model() print("I see", len(geofile.get_part_names()), "parts in case") part_ids = [] for part_id, part in geofile.parts.items(): if part_name_regex and not re.search(part_name_regex, part.part_name): print("Skipping part", part.part_name, "(name doesn't match)") else: part_ids.append(part_id) for part_id in part_ids: part = geofile.parts[part_id] part_name = part.part_name vtk_output_path = f"{output_vtk_prefix}_{part_name}.vtk" print("Writing part", part_name) write_vtk_part(case, part_id, vtk_output_path) print("\nAll done.") return 0
VTK_ELEMENT_TYPES = { ElementType.POINT: 1, # VTK_VERTEX ElementType.BAR2: 2, # VTK_LINE ElementType.TRIA3: 5, # VTK_TRIANGLE ElementType.QUAD4: 9, # VTK_QUAD ElementType.TETRA4: 10, # VTK_TETRA ElementType.PYRAMID5: 14, # VTK_PYRAMID ElementType.PENTA6: 13, # VTK_WEDGE ElementType.HEXA8: 12, # VTK_HEXAHEDRON ElementType.NSIDED: 7, # VTK_POLYGON }
[docs] def write_vtk_part(case: EnsightCaseFile, part_id: int, vtk_output_path: str) -> None: """ Write part from EnSight Gold case with given ID as VTK legacy ASCII format file See also: https://kitware.github.io/vtk-examples/site/VTKFileFormats/#simple-legacy-formats """ geofile = case.get_geometry_model() part = geofile.parts[part_id] with open(vtk_output_path, "w") as fp_vtk, geofile.mmap() as mm_geo: print("# vtk DataFile Version 2.0", file=fp_vtk) print("ensight2vtk output file", file=fp_vtk) print("ASCII", file=fp_vtk) print("DATASET UNSTRUCTURED_GRID", file=fp_vtk) print("POINTS", part.number_of_nodes, "float", file=fp_vtk) nodes = part.read_nodes(mm_geo) for i in range(len(nodes)): print(*nodes[i], file=fp_vtk) cell_list_size = 0 for block in part.element_blocks: if block.element_type not in VTK_ELEMENT_TYPES: raise NotImplementedError(f"Exporting element type {block.element_type} is not supported") if block.element_type != ElementType.NSIDED: cell_list_size += block.number_of_elements * (1 + block.element_type.nodes_per_element) else: polygon_node_counts, _ = block.read_connectivity_nsided(mm_geo) cell_list_size += block.number_of_elements + polygon_node_counts.sum() print("CELLS", part.number_of_elements, cell_list_size, file=fp_vtk) for block in part.element_blocks: if block.element_type != ElementType.NSIDED: connectivity = block.read_connectivity(mm_geo) n, k = connectivity.shape for i in range(n): # VTK numbers from 0, EnSight numbers from 1 # the connectivity array is memory-mapped from the file, so we need to change it via copy element_connectivity = connectivity[i] - 1 print(k, *element_connectivity, file=fp_vtk) else: polygon_node_counts, polygon_connectivity = block.read_connectivity_nsided(mm_geo) polygon_connectivity -= 1 n = polygon_node_counts.shape[0] k = 0 for i in range(n): node_count = polygon_node_counts[i] element_connectivity = polygon_connectivity[k:k + node_count] - 1 print(node_count, *element_connectivity, file=fp_vtk) k += node_count print("CELL_TYPES", part.number_of_elements, file=fp_vtk) for block in part.element_blocks: vtk_element_type = VTK_ELEMENT_TYPES[block.element_type] for i in range(block.number_of_elements): print(vtk_element_type, file=fp_vtk) point_variables = case.get_node_variables() cell_variables = case.get_element_variables() if point_variables: print("POINT_DATA", part.number_of_nodes, file=fp_vtk) for variable_name in point_variables: variable = case.get_variable(variable_name) if not variable.is_defined_for_part_id(part_id): continue with variable.mmap() as mm_var: data = variable.read_node_data(mm_var, part_id) assert data is not None if variable.variable_type == VariableType.SCALAR: print("SCALARS", variable_name.replace(" ", "_"), "float 1", file=fp_vtk) print("LOOKUP_TABLE default", file=fp_vtk) for i in range(part.number_of_nodes): print(data[i], file=fp_vtk) elif variable.variable_type == VariableType.VECTOR: print("VECTORS", variable_name.replace(" ", "_"), "float", file=fp_vtk) for i in range(part.number_of_nodes): print(*data[i], file=fp_vtk) else: raise NotImplementedError(f"Exporting variable type {variable.variable_type} is not supported") if cell_variables: print("CELL_DATA", part.number_of_elements, file=fp_vtk) for variable_name in cell_variables: variable = case.get_variable(variable_name) if not variable.is_defined_for_part_id(part_id): continue with variable.mmap() as mm_var: all_data = [] for block in part.element_blocks: data = variable.read_element_data(mm_var, part_id, block.element_type) if data is None: raise RuntimeError("Variable must be either undefined or defined for all elements") all_data.append(data) if variable.variable_type == VariableType.SCALAR: print("SCALARS", variable_name.replace(" ", "_"), "float 1", file=fp_vtk) print("LOOKUP_TABLE default", file=fp_vtk) for data in all_data: for i in range(data.shape[0]): print(data[i], file=fp_vtk) elif variable.variable_type == VariableType.VECTOR: print("VECTORS", variable_name.replace(" ", "_"), "float", file=fp_vtk) for data in all_data: for i in range(data.shape[0]): print(*data[i], file=fp_vtk) else: raise NotImplementedError(f"Exporting variable type {variable.variable_type} is not supported")
if __name__ == "__main__": sys.exit(main())