# -*- coding: utf-8 -*-
#
# This file is subject to the terms and conditions defined in
# file 'LICENSE.txt', which is part of this source code package.
#
"""Gmsh File Writer (gmesh mesh files)
"""
from Muscat.IO.IOFactory import RegisterWriterClass
from itertools import combinations
import numpy as np
import Muscat.Containers.ElementsDescription as ED
from Muscat.IO.WriterBase import WriterBase as WriterBase
from Muscat.Types import MuscatFloat, MuscatIndex
from Muscat.IO.GmshTools import gmshName, PermutationGmshToMuscat
from Muscat.Containers.Tags import Tag as Tag
from Muscat.Containers.Mesh import Mesh
PermutationMuscatToGmsh = {key: np.argsort(value) for key, value in PermutationGmshToMuscat.items()}
[docs]class OverlappingTagException(Exception):
pass
[docs]def WriteMeshToGmsh(filename, mesh, useOriginalId=False, tagMapping=None):
"""Function API for writing data into a gmsh file
Parameters
----------
fileName : str
name of the file to be written
mesh : Mesh
the mesh to be written
useOriginalId : bool, optional
If True, Original Id for the number of nodes and elements are used
(the user is responsible of the consistency of this data), by default False
tagMapping : dict, optional
tags of geometric objects defined in the mesh, by default None
"""
OW = GmshWriter()
if tagMapping is not None:
OW.tagMapping = tagMapping
OW.Open(filename)
OW.Write(mesh, useOriginalId=useOriginalId)
OW.Close()
[docs]class GmshWriter(WriterBase):
"""Class to writes a gmsh file on disk"""
def __init__(self):
super().__init__()
self.SetBinary(False)
self.canHandleBinaryChange = False
self.tagMapping = dict()
self.userRequiredTags = []
def __str__(self):
res = "GmshWriter : \n"
res += " FileName : " + str(self.fileName) + "\n"
return res
[docs] def SetFileName(self, fileName):
"""Sets the fileName parameter of the class
Parameters
----------
string : str
fileName to set
"""
self.fileName = fileName
[docs] def Write(self, meshObject: Mesh, useOriginalId=False, PointFieldsNames=None, PointFields=None, CellFieldsNames=None, CellFields=None):
"""Function to writes a gmsh file on disk
Parameters
----------
meshObject : Mesh
support of the data to be written
useOriginalId : bool, optional
If True original ids of vertices and elements, by default False
PointFieldsNames : _type_, optional
Not Used, by default None
PointFields : _type_, optional
Not Used, by default None
CellFieldsNames : _type_, optional
Not Used, by default None
CellFields : _type_, optional
Not Used, by default None
Raises
------
OverlappingTagException
when at least 2 tags are overlapping
"""
self.filePointer.write("$MeshFormat\n")
self.filePointer.write("2.2 0 8\n")
self.filePointer.write("$EndMeshFormat\n")
self.filePointer.write("$Nodes\n")
numberofpoints = meshObject.GetNumberOfNodes()
self.filePointer.write(f"{numberofpoints}\n")
posn = meshObject.GetPosOfNodes()
if useOriginalId:
for n in range(numberofpoints):
self.filePointer.write("{} ".format(int(meshObject.originalIDNodes[n])))
posn[np.newaxis, n, :].tofile(self.filePointer, sep=" ")
self.filePointer.write("\n")
else:
for n in range(numberofpoints):
self.filePointer.write(f"{n+1} ")
posn[np.newaxis, n, :].tofile(self.filePointer, sep=" ")
self.filePointer.write("\n")
self.filePointer.write("$EndNodes\n")
self.filePointer.write("$Elements\n")
self.filePointer.write(f"{meshObject.GetNumberOfElements()}\n")
cpt = 1
celltags = meshObject.GetNamesOfElementTags()
elements = meshObject.elements
if self.tagMapping:
self.userRequiredTags = self.tagMapping.keys()
minTagVal = max(self.tagMapping.values()) + 1
notMappedTagNames = sorted(list(set(celltags) - set(self.tagMapping.keys())))
notMappedTagsValue = np.arange(minTagVal, minTagVal + len(notMappedTagNames), dtype=int)
notMappedTagsMapping = dict(zip(notMappedTagNames, notMappedTagsValue))
self.tagMapping = {**notMappedTagsMapping, **self.tagMapping}
# tagcounter = 2
# for tagname in celtags:
for elementContainer in elements.keys():
elemtype = gmshName[elementContainer]
# try:
data = meshObject.elements[elementContainer]
phyGeoTags = np.ones(data.GetNumberOfElements(), MuscatIndex)
elemIdsInTags = {tagName: data.tags[tagName].GetIds() for tagName in self.userRequiredTags if tagName in data.tags}
if elemIdsInTags.keys():
tagPairs = list(combinations(elemIdsInTags.keys(), 2))
for tag1, tag2 in tagPairs:
idsTag1, idsTag2 = elemIdsInTags[tag1], elemIdsInTags[tag2]
commonIds = np.intersect1d(idsTag1, idsTag2)
if commonIds.size > 0:
print("Common element ids for pair " + str(tag1) + "," + str(tag2) + " are: ", str(commonIds))
raise OverlappingTagException("At least 2 tags are overlapping, cannot be handled properly naturally in .msh 2.2 format")
for tagName in self.tagMapping.keys():
if tagName in data.tags:
elemIds = data.tags[tagName].GetIds()
phyGeoTags[elemIds] = self.tagMapping[tagName]
if useOriginalId:
for i in range(data.GetNumberOfElements()):
self.filePointer.write(f"{data.originalIds[i]} {elemtype} 2 {phyGeoTags[i]} {phyGeoTags[i]} ")
self.filePointer.write(" ".join([str(meshObject.originalIDNodes[x]) for x in data.connectivity[i, :].ravel()]))
cpt += 1
self.filePointer.write("\n")
else:
# for connectivity in meshObject.elements[elementContainer].connectivity[meshObject.elements[elementContainer].tags[tagname].id-1]:
if elementContainer in PermutationMuscatToGmsh:# pragma: no cover
connectivity = data.connectivity[:, PermutationMuscatToGmsh[elementContainer]]
else:
connectivity = data.connectivity
for i in range(data.GetNumberOfElements()):
lconnectivity = connectivity[i, :]
self.filePointer.write(f"{cpt} {elemtype} 2 {phyGeoTags[i]} {phyGeoTags[i]} ")
self.filePointer.write(" ".join([str(x + 1) for x in lconnectivity]))
cpt += 1
self.filePointer.write("\n")
# except KeyError:
# continue
# tagcounter += 1
self.filePointer.write("$EndElements\n")
RegisterWriterClass(".msh", GmshWriter)
[docs]def CheckIntegrity(GUI: bool = False):
from Muscat.Helpers.CheckTools import RunListOfCheckIntegrities
toTest = [CheckIntegrity_SeparatedTags, CheckIntegrity_OriginalIdsForTags, CheckIntegrity_OverlappingTags]
return RunListOfCheckIntegrities(toTest, GUI=GUI)
if __name__ == "__main__":
print(CheckIntegrity()) # pragma: no cover