Source code for simudo.mesh.pygmsh
import numpy as np
from numpy import nan
__all__ = ['PygmshMakeRegions']
# FIXME: clean this up
[docs]class PygmshMakeRegions(object):
'''We want overlapping regions. gmsh and pygmsh make that
difficult. gmsh supports overlapping physical surfaces/volumes, but it
returns duplicate mesh cells (see `meshio issue 175`_). We can fix
this by postprocessing pygmsh's output, which thankfully contains all
the necessarily info. *At least for now.*
.. _`meshio issue 175`: https://github.com/nschloe/meshio/issues/175
'''
[docs] def process(self, cells, cell_data, field_data, dim):
'''Note: In-place modifies ``cells`` and ``cell_data``.'''
cells_key, = cells.keys()
xcell_data = cell_data[cells_key]
xcell_data_key = 'gmsh:physical'
for k in list(xcell_data.keys()):
if k != xcell_data_key:
del xcell_data[k]
r = self.unduplicate_msh3_cells(
cells[cells_key],
xcell_data[xcell_data_key])
cells[cells_key] = r['cells']
xcell_data[xcell_data_key] = r['cell_data']
tagid_to_tagname = {tagid: tagname for tagname, (tagid, dimension)
in field_data.items()
if dimension == dim}
tag_to_cell_values = {
tagid_to_tagname[k]: v
for k, v in r['tag_to_cell_values'].items()}
return dict(tag_to_cell_values=tag_to_cell_values)
[docs] def unduplicate_msh3_cells(self, cells, cell_data):
previous_row = None
new_cells_rowindices = []
cell_to_tags = []
last_cell_to_tags = None
for old_index, row in enumerate(cells):
if previous_row is not None and np.array_equal(row, previous_row):
pass # duplicate cell
else:
previous_row = row
new_cells_rowindices.append(old_index)
last_cell_to_tags = set()
cell_to_tags.append(last_cell_to_tags)
last_cell_to_tags.add(cell_data[old_index])
new_cells = cells[new_cells_rowindices]
### alternate code
#
# the code below messes up the cell ordering (because
# np.unique sorts the array), and is quite inefficient because
# gmsh seems to produce contiguous blocks of duplicate cells.
#
### BEGIN OLD CODE
#
# new_cells, unique_inverse = np.unique(
# cells, axis=0, return_inverse=True)
#
# cell_to_tags = [set() for i in range(len(new_cells))]
# for old_index, new_index in enumerate(unique_inverse):
# cell_to_tags[new_index].add(cell_data[old_index])
#
### END OLD CODE
cell_to_tagtuple = [tuple(sorted(v)) for v in cell_to_tags]
tagtuples = list(sorted(frozenset(cell_to_tagtuple)))
tagtuple_to_cellvalue = {
k: i for i, k in enumerate(tagtuples, 1)}
tag_to_cell_values = {}
for tt, cv in tagtuple_to_cellvalue.items():
for tag in tt:
cvs = tag_to_cell_values.get(tag, None)
if cvs is None:
tag_to_cell_values[tag] = cvs = set()
cvs.add(cv)
cell_to_cellvalue = [
tagtuple_to_cellvalue[tt] for tt in cell_to_tagtuple]
new_cell_data = np.array(cell_to_cellvalue, dtype='uintp')
return dict(cells=new_cells,
cell_data=new_cell_data,
tag_to_cell_values=tag_to_cell_values)