# -*- 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.
#
"""Geof file writer (Zset mesh files)
"""
from typing import Optional
import numpy as np
from Muscat.Helpers.Logger import Info
import Muscat.Containers.ElementsDescription as ED
from Muscat.IO.WriterBase import WriterBase
from Muscat.Types import MuscatFloat, MuscatIndex
from Muscat.Containers.Mesh import Mesh
from Muscat.IO.GeofReader import PermutationZSetToMuscat
PermutationMuscatToZSet = {key:np.argsort(value) for key, value in PermutationZSetToMuscat.items() }
GeofName = {}
GeofSetName= {}
#0d
GeofName[ED.Point_1] = "l2d1"
#1d
GeofName[ED.Bar_2] = "l2d2"
GeofSetName[ED.Bar_2] = "line"
GeofSetName[ED.Bar_3] = "quad"
#2d
GeofName[ED.Triangle_3] = "c2d3"
GeofSetName[ED.Triangle_3] = "t3"
GeofName[ED.Triangle_6] = "c2d6"
GeofSetName[ED.Triangle_6] = "t6"
GeofSetName[ED.Quadrangle_4] = "q4"
GeofName[ED.Quadrangle_8] = "c3d8"
GeofSetName[ED.Quadrangle_8] = "q8"
#3d
GeofName[ED.Tetrahedron_4] = "c3d4"
GeofName[ED.Tetrahedron_10] = "c3d10"
GeofName[ED.Quadrangle_4] = "c2d4"
GeofName[ED.Hexahedron_8] = "c3d8"
GeofName[ED.Hexahedron_20] = "c3d20"
GeofName[ED.Wedge_6] = "c3d6"
GeofName[ED.Pyramid_13] = "c3d13"
GeofName[ED.Wedge_15] = "c3d15"
[docs]def WriteMeshToGeof(fileName :str , mesh:Mesh, useOriginalId:Optional[bool]=False,lowerDimElementsAsElsets:bool=False)-> None:
"""Function API for writing mesh in the geof format file.
A file is created using the path and name of fileName
Parameters
----------
fileName : str
name with path to the file to be created (relative or absolute)
mesh : Mesh
the mesh to be exported
useOriginalId : Optional[bool], optional
use the Original Id for the number of nodes and elements
(the user is responsible of the consistency of this data), by default False
lowerDimElementsAsElsets : Optional[bool], optional
refert to GeofWriter.SetWriteLowerDimElementsAsSets for the documentations
"""
geofWriter = GeofWriter()
geofWriter.Open(fileName)
geofWriter.SetWriteLowerDimElementsAsSets(lowerDimElementsAsElsets)
geofWriter.Write(mesh,useOriginalId = useOriginalId)
geofWriter.Close()
[docs]class GeofWriter(WriterBase):
"""Class to write Unstructured mesh on disk in the geof format file
"""
def __init__(self) -> None:
super().__init__()
self.lowerDimElementsAsElsets= False
self.canHandleBinaryChange = False
def __str__(self):
res = 'GeofWriter : \n'
res += ' FileName : '+ str(self.fileName) +'\n'
return res
[docs] def SetWriteLowerDimElementsAsSets(self,val:bool) -> None:
""" Set the type of export for element of lower dimensionality
(1D and 2D element on a 3D mesh)
Parameters
----------
val : bool
if True all the elements of lower dimensionality are exported in the mesh
if False all the element of lower dimensionality are exported as bsets,
by default False
"""
if val is not None:
self.lowerDimElementsAsElsets= bool(val)
[docs] def Write(self,meshObject: Mesh, useOriginalId:Optional[bool]=False, lowerDimElementsAsElsets:bool=False, PointFieldsNames=None, PointFields=None, CellFieldsNames=None, CellFields=None):
"""Write mesh to file in Geof format
Parameters
----------
meshObject : Mesh
the mesh to be written
useOriginalId : Optional[bool], optional
use the Original Id for the number of nodes and elements
(the user is responsible of the consistency of this data),
by default False
lowerDimElementsAsElsets : Optional[bool], optional
refert to GeofWriter.SetWriteLowerDimElementsAsSets for the documentations
PointFieldsNames : None
Not Used, by default None
PointFields : None
Not Used, by default None
CellFieldsNames : None
Not Used, by default None
CellFields : None
Not Used, by default None
Raises
------
Exception
in the case 1D element are presents in the mesh (doset)
"""
if PointFieldsNames is not None or PointFields is not None or \
CellFieldsNames is not None or CellFields is not None:
print("warning GeofWriter only can write the mesh, fields are ignored")
self.SetWriteLowerDimElementsAsSets(lowerDimElementsAsElsets)
meshObject.PrepareForOutput()
self.filePointer.write("% Written by Muscat package\n")
self.filePointer.write("***geometry\n")
self.filePointer.write(" **node\n")
numberOfPoints = meshObject.GetNumberOfNodes()
self.filePointer.write(f"{numberOfPoints} {meshObject.GetPointsDimensionality()} \n" )
#
posn = meshObject.GetPosOfNodes()
if useOriginalId:
for n in range(numberOfPoints):
self.filePointer.write(f"{int(meshObject.originalIDNodes[n])} ")
posn[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")
#
nbElements = 0
maxDimensionalityOfElements = 0
for ntype,elems in meshObject.elements.items():
maxDimensionalityOfElements = max(ED.dimensionality[ntype],maxDimensionalityOfElements)
for ntype,elems in meshObject.elements.items():
if ED.dimensionality[ntype] == maxDimensionalityOfElements or self.lowerDimElementsAsElsets is True:
nbElements += elems.GetNumberOfElements()
self.filePointer.write(" **element\n")
self.filePointer.write(f"{nbElements}\n")
cpt =0
for ntype, data in meshObject.elements.items():
elemtype = GeofName[ntype]
if ED.dimensionality[ntype] != maxDimensionalityOfElements and self.lowerDimElementsAsElsets is False:
continue
#npe = data.GetNumberOfNodesPerElement()
#if elemtype!="c2d3":
for i in range(data.GetNumberOfElements() ):
conn = data.connectivity[i,:].ravel()
if elemtype in PermutationMuscatToZSet:
conn = [conn[x] for x in PermutationMuscatToZSet[elemtype]]
if useOriginalId:
self.filePointer.write(f"{data.originalIds[i]} {elemtype} " )
self.filePointer.write(" ".join([str(int(meshObject.originalIDNodes[x])) for x in conn]))
else:
self.filePointer.write(f"{cpt+1} {elemtype} ")
self.filePointer.write(" ".join([str(x+1) for x in conn]))
cpt += 1
self.filePointer.write("\n")
self.filePointer.write(" ***group \n")
for tag in meshObject.nodesTags:
if len(tag) == 0:
continue
self.filePointer.write(f" **nset {tag.name} \n")
data = np.zeros((meshObject.GetNumberOfNodes(),1),dtype=MuscatIndex)
if useOriginalId:
self.filePointer.write(" ".join([str(int(meshObject.originalIDNodes[x])) for x in tag.GetIds()]))
else:
self.filePointer.write(" ".join([str(x+1) for x in tag.GetIds()]))
self.filePointer.write("\n")
meshObject.PrepareForOutput()
if self.lowerDimElementsAsElsets is False :
celtags = meshObject.GetNamesOfElementTags()
for tagname in celtags:
idInTag = 0
flag = False
for ntype,elems in meshObject.elements.items():
if ED.dimensionality[ntype] == maxDimensionalityOfElements:
if tagname in elems.tags:
flag = True
idInTag += elems.tags[tagname].cpt
Info(f"Tag {tagname} has {idInTag} elements")
# no output if no elements in tag
if flag is False :
continue
#empty tags
if idInTag == 0 :
continue
self.filePointer.write(f" **elset {tagname} \n")
cpt =0
for ntype,elems in meshObject.elements.items():
if ED.dimensionality[ntype] != maxDimensionalityOfElements:
continue
if tagname in elems.tags:
tag = elems.tags[tagname]
if tag.cpt :
if useOriginalId:
self.filePointer.write(" ".join([str(elems.originalIds[x]) for x in tag.GetIds()]))
else:
self.filePointer.write(" ".join([str(x+1+cpt) for x in tag.GetIds()]))
self.filePointer.write(" ")
cpt += elems.GetNumberOfElements()
self.filePointer.write("\n")
else:
celtags = meshObject.GetNamesOfElemTags()
for tagname in celtags:
self.filePointer.write(f" **elset {tagname} \n")
data = meshObject.GetElementsInTag(tagname,useOriginalId=useOriginalId)
if useOriginalId :
self.filePointer.write(" ".join([str(x) for x in data]))
self.filePointer.write(" ")
else:
self.filePointer.write(" ".join([str(x+1) for x in data]))
self.filePointer.write(" ")
self.filePointer.write("\n")
# Dotsets, lisets, facets
if self.lowerDimElementsAsElsets is False:
for dimToTreat in range(maxDimensionalityOfElements):
celtags = meshObject.GetNamesOfElementTags()
for tagname in celtags:
idInTag = 0
flag = False
for ntype,elems in meshObject.elements.items():
if ED.dimensionality[ntype] == dimToTreat:
if tagname in elems.tags:
flag = True
idInTag += elems.tags[tagname].cpt
Info("Set " + str(tagname) + " has "+ str(idInTag) + " elements")
# no output if no elements in tag
if flag is False :
continue
#empty tags
if idInTag == 0 :
continue
if dimToTreat == 0:# pragma: no cover
raise Exception("Don't know how to treat the doset, please code me")
# self.filePointer.write(" **doset {} \n".format(tagname))
elif dimToTreat == 1:
self.filePointer.write(f" **liset {tagname} \n")
elif dimToTreat == 2:
self.filePointer.write(f" **faset {tagname} \n")
for ntype,elems in meshObject.elements.items():
if ED.dimensionality[ntype] != dimToTreat:
continue
if tagname in elems.tags:
tag = elems.tags[tagname]
name = GeofSetName[ntype]
ids = tag.GetIds()
for e in range(len(tag)):
conn = elems.connectivity[ids[e],:]
if name in PermutationMuscatToZSet:
conn = [conn[x] for x in PermutationMuscatToZSet[name]]
self.filePointer.write(f" {name} ")
self.filePointer.write(" ".join([str(x+1) for x in conn ]))
self.filePointer.write(" \n")
self.filePointer.write("***return \n")
from Muscat.IO.IOFactory import RegisterWriterClass
RegisterWriterClass(".geof",GeofWriter)
[docs]def CheckIntegrity():
import Muscat.Containers.Mesh as UM
from Muscat.Helpers.IO.TemporaryDirectory import TemporaryDirectory
tempdir = TemporaryDirectory.GetTempPath()
print(tempdir)
mymesh = UM.Mesh()
mymesh.nodes = np.array([[0.00000000001,0,0],
[1,0,0],
[0,1,0],
[1,1,0],
[0.5,0,0.1],
[0,0.5,0.1],
[0.5,0.5,0.1],
],dtype=MuscatFloat)
mymesh.originalIDNodes = np.array([1, 3, 4, 5, 6, 7, 8],dtype=MuscatIndex)
mymesh.nodesTags.CreateTag("coucou").AddToTag(0)
mymesh.nodesTags.CreateTag("empty tag")
tet = mymesh.GetElementsOfType(ED.Tetrahedron_4)
tet.AddNewElement([0,1,2,3],0)
tet.tags.CreateTag("TheOnlyTet").AddToTag(0)
triangles = mymesh.GetElementsOfType(ED.Triangle_3)
triangles.AddNewElement([0,1,2],0)
triangles.AddNewElement([2,1,3],3)
triangles.originalIds = np.array([3, 5],dtype=MuscatIndex)
bars = mymesh.GetElementsOfType(ED.Bar_2)
bars.AddNewElement([0,1],0)
bars.AddNewElement([1,3],1)
bars.tags.CreateTag("firstBar").AddToTag(0)
bars3 = mymesh.GetElementsOfType(ED.Triangle_6)
bars3.AddNewElement([0,1,2,4,6,5],0)
bars3.tags.CreateTag("Tri6").AddToTag(0)
#point = mymesh.GetElementsOfType(ED.Point_1)
#point.AddNewElement([0],0)
#point.tags.CreateTag("onlyPoint").AddToTag(0)
mymesh.AddElementToTagUsingOriginalId(3,"Tag1")
mymesh.AddElementToTagUsingOriginalId(5,"Tag3")
geofWriter = GeofWriter()
print(geofWriter)
geofWriter.Open(tempdir+"Test_GeoWriter.geof")
geofWriter.Write(mymesh, useOriginalId=True, PointFieldsNames=[], PointFields=[])
geofWriter.Close()
WriteMeshToGeof(tempdir+"Test_GeoWriter_II.geof", mymesh,useOriginalId=False )
WriteMeshToGeof(tempdir+"Test_GeoWriter_III.geof", mymesh,useOriginalId=False,lowerDimElementsAsElsets=True )
WriteMeshToGeof(tempdir+"Test_GeoWriter_III.geof", mymesh,useOriginalId=True,lowerDimElementsAsElsets=True )
return "ok"
if __name__ == '__main__':
print(CheckIntegrity())# pragma: no cover