Salome HOME
Add test for .mesh file format master spns_40523_family_cells_test
authorChristophe Bourcier <christophe.bourcier@cea.fr>
Tue, 4 Jun 2024 13:41:46 +0000 (15:41 +0200)
committerChristophe Bourcier <christophe.bourcier@cea.fr>
Tue, 4 Jun 2024 13:41:46 +0000 (15:41 +0200)
src/MEDLoader/Swig/MeshFormatWriterTest1.py [new file with mode: 0644]
src/MEDLoader/Swig/tests.set

diff --git a/src/MEDLoader/Swig/MeshFormatWriterTest1.py b/src/MEDLoader/Swig/MeshFormatWriterTest1.py
new file mode 100644 (file)
index 0000000..ec7cb63
--- /dev/null
@@ -0,0 +1,304 @@
+# Copyright (C) 2007-2024  CEA, EDF
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+
+from MEDLoader import *
+import unittest
+from MEDLoaderDataForTest import MEDLoaderDataForTest,WriteInTmpDir
+
+class MeshFormatWriterTest2(unittest.TestCase):
+
+  def createMesh(self, nb_seg):
+
+    # Create mesh
+    mesh_dim = 3
+    self.bounding_box_coords = [(0, 100)]*mesh_dim
+    # with 25 segs per side, time of test run
+    # 9.12: 7.8 s
+    # 9.13: 0.1 s
+
+    # with 100 nb_segs per side:
+    # 9.12: more than 3 h
+    # 9.13: 8.14 s
+
+    nb_segs = [nb_seg]*mesh_dim
+    box_sizes = [size_coords[1]-size_coords[0] for size_coords in self.bounding_box_coords]
+    print("box_sizes: ", box_sizes)
+    box_steps = [box_sizes[i]/nb_segs[i] for i in range(mesh_dim)]
+    l_nb_nodes = [nb_segs_i+1 for nb_segs_i in nb_segs]
+    l_start = [size_coords[0] for size_coords in self.bounding_box_coords]
+    l_end = [size_coords[1] for size_coords in self.bounding_box_coords]
+
+    mesh = MEDCouplingIMesh("Mesh", mesh_dim, l_nb_nodes, l_start, box_steps)
+    self.mesh = mesh.buildUnstructured()
+    pass
+
+  def createVolumeGroups(self):
+    nb_cells = self.mesh.getNumberOfCells()
+    nb_half_cells = int(round(nb_cells/2))
+    grp0 = DataArrayInt(list(range(nb_half_cells)))
+    grp0.setName("half1")
+    grp1 = DataArrayInt(list(range(nb_half_cells, nb_cells)))
+    grp1.setName("half2")
+    self.volumeGroups = [grp0, grp1]
+    pass
+
+  def createSkinGroups(self):
+    # create groups on each side of skin mesh
+    nb_faces = self.skinMesh.getNumberOfCells()
+    #xMin, xMax, yMin, yMax, zMin, zMax
+    xMin, xMax = self.bounding_box_coords[0]
+    yMin, yMax = self.bounding_box_coords[1]
+    zMin, zMax = self.bounding_box_coords[2]
+    tol = 1e-10
+    barycenters = self.skinMesh.computeIsoBarycenterOfNodesPerCell()
+    left = []
+    right = []
+    bottom = []
+    top = []
+    back = []
+    front = []
+    for i in range(nb_faces):
+      coord = barycenters[i]
+      x, y, z = coord.getValues()
+      if abs(x-xMin) < tol:
+        left.append(i)
+      elif abs(x-xMax) < tol:
+        right.append(i)
+      elif abs(y-yMin) < tol:
+        back.append(i)
+      elif abs(y-yMax) < tol:
+        front.append(i)
+      elif abs(z-zMin) < tol:
+        bottom.append(i)
+      elif abs(z-zMax) < tol:
+        top.append(i)
+
+    grp_left = DataArrayInt(left)
+    grp_left.setName("left")
+    grp_right = DataArrayInt(right)
+    grp_right.setName("right")
+    grp_back = DataArrayInt(back)
+    grp_back.setName("back")
+    grp_front = DataArrayInt(front)
+    grp_front.setName("front")
+    grp_bottom = DataArrayInt(bottom)
+    grp_bottom.setName("bottom")
+    grp_top = DataArrayInt(top)
+    grp_top.setName("top")
+    self.skinGroups = [grp_left, grp_right, grp_back, grp_front, grp_bottom, grp_top]
+    pass
+
+  def createField(self):
+    # create a field on nodes with 1 component
+    coords = self.mesh.getCoords()
+    coords_z = coords[:,2]
+    zMin, zMax = self.bounding_box_coords[2]
+    coords_z_normed = coords_z/(zMax-zMin)
+    size_min = 1e-4
+    size_max = 1e-3
+    coords_z_normed.applyFuncOnThis('(%f-%f)*tanh(x)/tanh(1)+%f'%(size_max, size_min, size_min))
+
+    # Create the field with this array
+    self.field = MEDCouplingFieldDouble(ON_NODES,ONE_TIME)
+    self.field.setName("Elevation")
+    self.field.setMesh(self.mesh)
+    self.field.setTime(0,1,1)
+    self.field.setArray(coords_z_normed)
+    pass
+
+  def createMEDMeshFile(self):
+    self.meshMEDFile = MEDFileUMesh()
+    self.meshMEDFile.setMeshAtLevel(0, self.mesh)
+    self.meshMEDFile.setGroupsAtLevel(0, self.volumeGroups)
+    self.meshMEDFile.setMeshAtLevel(-1, self.skinMesh)
+    self.meshMEDFile.setGroupsAtLevel(-1, self.skinGroups)
+    pass
+
+  def setMeshInMEDFileData(self):
+    # Set mesh in file data structure
+    ms=MEDFileMeshes()
+    ms.pushMesh(self.meshMEDFile)
+    self.medFileData = MEDFileData()
+    self.medFileData.setMeshes(ms)
+    pass
+
+  def setFieldInMEDFileData(self):
+    mf=MEDFileFields()
+    fmts0=MEDFileFieldMultiTS()
+    mf.pushField(fmts0)
+    f1ts=MEDFileField1TS()
+    f1ts.setFieldNoProfileSBT(self.field)
+    fmts0.pushBackTimeStep(f1ts)
+    self.medFileData.setFields(mf)
+    pass
+
+  def writeToMeshFile(self, meshFileName):
+    tmpMeshWriter = MeshFormatWriter()
+    tmpMeshWriter.setMeshFileName(meshFileName)
+    tmpMeshWriter.setMEDFileDS(self.medFileData)
+    tmpMeshWriter.write()
+    pass
+
+  def readMeshFile(self, meshFileName):
+    meshFormatReader = MeshFormatReader()
+    meshFormatReader.setFile(meshFileName)
+    medFileData = meshFormatReader.loadInMedFileDS()
+    meshes = medFileData.getMeshes()
+    meshNames = meshes.getMeshesNames()
+    assert len(meshNames) == 1
+    self.meshMEDFileOut = meshes.getMeshWithName(meshNames[0])
+
+  def compareFamilies(self, levels):
+    meshRef = self.meshMEDFile
+    meshRead = self.meshMEDFileOut
+    # compare families on levels
+    for level in levels:
+      print("level: ", level)
+      # ids of families at this level
+      referenceFamilyIds = meshRef.getFamilyFieldAtLevel(level).getDifferentValues().getValues()
+      print("referenceFamilyIds; ", referenceFamilyIds)
+      readFamilyIds      = meshRead.getFamilyFieldAtLevel(level).getDifferentValues().getValues()
+      print("readFamilyIds: ", readFamilyIds)
+      assert len(readFamilyIds) == len(readFamilyIds)
+
+      for ref_id in referenceFamilyIds:
+        # by convention, the id in the .mesh file is the abs of the family
+        read_id = abs(ref_id)
+        referenceName = meshRef.getFamilyNameGivenId(ref_id)
+        readName = meshRead.getFamilyNameGivenId(read_id)
+
+        referenceFamilyArr = meshRef.getFamilyArr(level, referenceName)
+        readFamilyArr = meshRead.getFamilyArr(level, readName)
+
+        # compare family arrays
+        referenceFamilyArr = meshRef.getFamilyArr(level, referenceName)
+        readFamilyArr = meshRead.getFamilyArr(level, readName)
+        referenceFamilyArr.isEqualWithoutConsideringStr(readFamilyArr)
+        #print(readFamilyArr_i)
+
+        # compare family meshes
+        referenceFamily = meshRef.getFamily(level, referenceName)
+        readFamily = meshRead.getFamily(level, readName)
+
+        assert referenceFamily.isEqualWithoutConsideringStr(readFamily, 1e-12)
+
+  @WriteInTmpDir
+  def testMeshHexaWithoutField(self):
+    """
+    Test writing .mesh without field does not crash (as it did before 9.13)
+    """
+
+    nb_seg = 3
+    self.createMesh(nb_seg)
+
+    # Create groups
+    self.createVolumeGroups()
+    # Build 1D mesh and create groups of faces
+    self.skinMesh = self.mesh.computeSkin()
+    self.createSkinGroups()
+    self.createField()
+    self.createMEDMeshFile()
+
+    self.setMeshInMEDFileData()
+
+    # write to med (to debug if needed)
+    #medFileData.write("Mesh3D_hexa.med", 2)
+
+    # write to .mesh
+    self.writeToMeshFile("Mesh3D_hexa_%i.mesh"%nb_seg)
+    # test succeeds if there is no crash
+    pass
+
+  @WriteInTmpDir
+  def testMeshHexaWithField(self):
+    """
+    Test writing .mesh is not too slow (more than 9 seconds before 9.13)
+    """
+
+    nb_seg = 25
+    self.createMesh(nb_seg)
+
+    # Create groups
+    self.createVolumeGroups()
+    # Build 1D mesh and create groups of faces
+    self.skinMesh = self.mesh.computeSkin()
+    self.createSkinGroups()
+    self.createField()
+    self.createMEDMeshFile()
+
+    # Set mesh in file data structure
+    self.setMeshInMEDFileData()
+    # Set field in file data structure
+    self.setFieldInMEDFileData()
+
+    # Write to med (to debug if needed)
+    #medFileData.write("Mesh3D_hexa.med", 2)
+
+    # Write to .mesh
+    meshFileName = "Mesh3D_hexa_%i.mesh"%nb_seg
+    self.writeToMeshFile(meshFileName)
+
+    # Read Mesh File
+    self.readMeshFile(meshFileName)
+
+    # Compare families at levels
+    self.compareFamilies([0, -1])
+
+    pass
+
+  @WriteInTmpDir
+  def testMeshTetraWithField(self):
+    """
+    Test writing .mesh tetra
+    """
+
+    nb_seg = 3
+    self.createMesh(nb_seg)
+
+    self.mesh = self.mesh.tetrahedrize(PLANAR_FACE_5)[0].buildUnstructured()
+
+    # Create groups
+    self.createVolumeGroups()
+    # Build 1D mesh and create groups of faces
+    self.skinMesh = self.mesh.computeSkin()
+    self.createSkinGroups()
+    self.createField()
+    self.createMEDMeshFile()
+
+    # Set mesh in file data structure
+    self.setMeshInMEDFileData()
+    # Set field in file data structure
+    self.setFieldInMEDFileData()
+
+    # Write to med (to debug if needed)
+    #medFileData.write("Mesh3D_tetra.med", 2)
+
+    # Write to .mesh
+    meshFileName = "Mesh3D_hexa_%i.mesh"%nb_seg
+    self.writeToMeshFile(meshFileName)
+
+    # Read Mesh File
+    self.readMeshFile(meshFileName)
+
+    # Compare families at levels
+    self.compareFamilies([0, -1])
+
+    pass
+
+if __name__ == '__main__':
+  unittest.main()
index fb403aa4e52b6aad035ef7a413142a6c37ed41fd..2e58e373954f9a2d2ec2ca56c608c2296e81ad5b 100644 (file)
@@ -22,6 +22,7 @@ SET(BASE_TESTS
   MEDLoaderTest4.py
   MEDLoaderExamplesTest.py
   UsersGuideExamplesTest_ML.py
+  MeshFormatWriterTest1.py
 )
 
 # if numpy is used