Source code for pymor.discretizers.builtin.grids.gmsh
# This file is part of the pyMOR project (http://www.pymor.org).
# Copyright 2013-2020 pyMOR developers and contributors. All rights reserved.
# License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
import numpy as np
import time
from pymor.core.config import config
from pymor.core.exceptions import MeshioMissing
from pymor.core.logger import getLogger
from pymor.discretizers.builtin.grids.boundaryinfos import GenericBoundaryInfo, EmptyBoundaryInfo
from pymor.discretizers.builtin.grids.unstructured import UnstructuredTriangleGrid
[docs]def load_gmsh(filename):
"""Parse a Gmsh file and create a corresponding :class:`GmshGrid` and :class:`GmshBoundaryInfo`.
Parameters
----------
filename
Path of the Gmsh MSH-file.
Returns
-------
grid
The generated :class:`GmshGrid`.
boundary_info
The generated :class:`GmshBoundaryInfo`.
"""
if not config.HAVE_MESHIO:
raise MeshioMissing('meshio (>=4) is required for reading Gmsh files.')
import meshio
logger = getLogger('pymor.discretizers.builtin.grids.gmsh.load_gmsh')
logger.info('Parsing Gmsh file ...')
tic = time.perf_counter()
data = meshio.read(filename)
toc = time.perf_counter()
t_parse = toc - tic
if data.gmsh_periodic:
raise NotImplementedError
cells_dict = data.cells_dict
if not cells_dict.keys() <= {'line', 'triangle'}:
raise NotImplementedError
if not np.all(data.points[:, 2] == 0):
raise NotImplementedError
logger.info('Create Grid ...')
tic = time.perf_counter()
vertices = data.points[:, :2]
faces = cells_dict['triangle']
grid = UnstructuredTriangleGrid.from_vertices(vertices, faces)
toc = time.perf_counter()
t_grid = toc - tic
logger.info('Create GmshBoundaryInfo ...')
tic = time.perf_counter()
boundary_types = {k: v[0] for k, v in data.field_data.items() if v[1] == 1}
cell_data_dict = data.cell_data_dict
if 'line' in cells_dict and 'gmsh:physical' in cell_data_dict and 'line' in cell_data_dict['gmsh:physical']:
superentities = grid.superentities(2, 1)
# find the edge for given vertices.
def find_edge(vertices):
edge_set = set(superentities[vertices[0]]).intersection(superentities[vertices[1]]) - {-1}
if len(edge_set) != 1:
raise ValueError
return next(iter(edge_set))
line_ids = np.array([find_edge(l) for l in cells_dict['line']])
# compute boundary masks for all boundary types.
masks = {}
for bt, bt_id in boundary_types.items():
masks[bt] = [np.zeros(grid.size(1), dtype=bool), np.zeros(grid.size(2), dtype=bool)]
masks[bt][0][line_ids] = cell_data_dict['gmsh:physical']['line'] == bt_id
vtx = np.sort(grid.subentities(1, 2)[np.where(masks[bt][0])])
masks[bt][1][vtx] = True
bi = GenericBoundaryInfo(grid, masks)
else:
logger.warning('Boundary data not found. Creating empty BoundaryInfo ...')
bi = EmptyBoundaryInfo(grid)
toc = time.perf_counter()
t_bi = toc - tic
logger.info(f'Parsing took {t_parse}s; Grid creation took {t_grid}s; BoundaryInfo creation took {t_bi}s')
return grid, bi