From bcbfe2dac15f2773aa3692bd64a9b334d63b7e10 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Fri, 11 Aug 2023 15:28:39 +0200 Subject: [PATCH] [EDF27988] : Add MEDFileUMesh.reduceToCells method and test on it --- src/MEDLoader/MEDFileMesh.cxx | 2 +- src/MEDLoader/MEDFileMesh.hxx | 1 + src/MEDLoader/Swig/CMakeLists.txt | 2 +- src/MEDLoader/Swig/MEDLoaderFinalize.i | 3 ++ src/MEDLoader/Swig/MEDLoaderFinalize.py | 66 +++++++++++++++++++++++++ src/MEDLoader/Swig/MEDLoaderTest3.py | 59 ++++++++++++++++++++++ 6 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 src/MEDLoader/Swig/MEDLoaderFinalize.py diff --git a/src/MEDLoader/MEDFileMesh.cxx b/src/MEDLoader/MEDFileMesh.cxx index d00f5ba7a..4de31cc17 100644 --- a/src/MEDLoader/MEDFileMesh.cxx +++ b/src/MEDLoader/MEDFileMesh.cxx @@ -4534,7 +4534,7 @@ DataArrayIdType *MEDFileUMesh::deduceNodeSubPartFromCellSubPart(const std::map >& extractDef) const { diff --git a/src/MEDLoader/MEDFileMesh.hxx b/src/MEDLoader/MEDFileMesh.hxx index 993625e66..2cdbaa0f7 100644 --- a/src/MEDLoader/MEDFileMesh.hxx +++ b/src/MEDLoader/MEDFileMesh.hxx @@ -368,6 +368,7 @@ MCAuto& coords, MCAuto& partCoords, MCAuto >& extractDef) const; MEDLOADER_EXPORT MEDFileUMesh *extractPart(const std::map >& extractDef) const; + // MCAuto extractPart(int level, DataArrayIdType *keepCells, bool removeOrphanNodes = true) const; // implemented in python MEDLOADER_EXPORT MEDFileUMesh *buildExtrudedMesh(const MEDCouplingUMesh *m1D, int policy) const; MEDLOADER_EXPORT MEDFileUMesh *linearToQuadratic(int conversionType=0, double eps=1e-12) const; MEDLOADER_EXPORT MEDFileUMesh *quadraticToLinear(double eps=1e-12) const; diff --git a/src/MEDLoader/Swig/CMakeLists.txt b/src/MEDLoader/Swig/CMakeLists.txt index d718bafb0..0cb6bc26d 100644 --- a/src/MEDLoader/Swig/CMakeLists.txt +++ b/src/MEDLoader/Swig/CMakeLists.txt @@ -96,7 +96,7 @@ INSTALL(FILES MEDLoader.i MEDLoaderTypemaps.i MEDLoaderCommon.i MEDLoaderFinaliz SALOME_INSTALL_SCRIPTS(${CMAKE_CURRENT_BINARY_DIR}/MEDLoader.py ${MEDCOUPLING_INSTALL_PYTHON} EXTRA_DPYS "${SWIG_MODULE_MEDLoader_REAL_NAME}") -INSTALL(FILES MEDLoaderSplitter.py DESTINATION ${MEDCOUPLING_INSTALL_PYTHON}) +INSTALL(FILES MEDLoaderSplitter.py MEDLoaderFinalize.py DESTINATION ${MEDCOUPLING_INSTALL_PYTHON}) INSTALL(FILES ${ALL_TESTS} MEDLoaderDataForTest.py MEDLoaderTest1.py MEDLoaderTest2.py MEDLoaderTest3.py DESTINATION ${MEDCOUPLING_INSTALL_SCRIPT_SCRIPTS}) diff --git a/src/MEDLoader/Swig/MEDLoaderFinalize.i b/src/MEDLoader/Swig/MEDLoaderFinalize.i index c8fab8b86..84eecd379 100644 --- a/src/MEDLoader/Swig/MEDLoaderFinalize.i +++ b/src/MEDLoader/Swig/MEDLoaderFinalize.i @@ -19,6 +19,9 @@ // Author : Anthony Geay (EDF R&D) %pythoncode %{ +import MEDLoaderFinalize +MEDFileUMesh.reduceToCells = MEDLoaderFinalize.MEDFileUMeshReduceToCells +del MEDLoaderFinalize MEDFileMeshesIterator.__next__ = MEDFileMeshesIterator.next MEDFileAnyTypeFieldMultiTSIterator.__next__ = MEDFileAnyTypeFieldMultiTSIterator.next MEDFileFieldsIterator.__next__ = MEDFileFieldsIterator.next diff --git a/src/MEDLoader/Swig/MEDLoaderFinalize.py b/src/MEDLoader/Swig/MEDLoaderFinalize.py new file mode 100644 index 000000000..c5689dbbd --- /dev/null +++ b/src/MEDLoader/Swig/MEDLoaderFinalize.py @@ -0,0 +1,66 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2023 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 +# + +def MEDFileUMeshReduceToCells(self, level, keepCells, removeOrphanNodes=True): + """ + Method returning a new MEDFileUMesh, restriction of self to level and keepCell cells at this level. + This method also + + :param level: Specifies the top level of the returned MEDFileUMesh expected + :param keepCells: A DataArrayInt specifying cell ids at level level of self + :param removeOrphanNodes: Specifies if orphan nodes should be removed at the end + + see also MEDFileUMesh.extractPart + """ + import MEDLoader as ml + subLevs = [l for l in self.getNonEmptyLevels() if l<=level] + subMeshes = [self[lev] for lev in subLevs] + allFamilyFields = [self.getFamilyFieldAtLevel(lev) for lev in subLevs] + allRefMesh = subMeshes[0] + refMesh = allRefMesh[keepCells] + + mmOut = ml.MEDFileUMesh() + # level 0 + mmOut[0] = refMesh + mmOut.setFamilyFieldArr(0,allFamilyFields[0][keepCells]) + + # subLevels + for curLev,meshLev,famFieldLev in zip(subLevs[1:],subMeshes[1:],allFamilyFields[1:]): + allMeshLev,d,di, rd,rdi = allRefMesh.explodeMeshTo( curLev-level ) + a,b = allMeshLev.areCellsIncludedIn(meshLev,2) + if not a: + raise RuntimeError("Error in mesh {}") + dlev,dlevi = ml.DataArrayInt.ExtractFromIndexedArrays( keepCells, d,di ) + dlev2 = dlev.buildUniqueNotSorted() + cellsToKeepLev = ml.DataArrayInt.BuildIntersection([dlev2,b]) + cellsToKeepLev = b.indicesOfSubPart(cellsToKeepLev) + cellsToKeepLev.sort() + mmOut[curLev] = meshLev[cellsToKeepLev] + mmOut.setFamilyFieldArr(curLev,famFieldLev[cellsToKeepLev]) + + allFamNodes = mmOut.getFamilyFieldAtLevel(1) + if allFamNodes: + mmOut.setFamilyFieldArr(1,allFamNodes[:]) + + if removeOrphanNodes: + mmOut.zipCoords() + + mmOut.copyFamGrpMapsFrom(self) + return mmOut diff --git a/src/MEDLoader/Swig/MEDLoaderTest3.py b/src/MEDLoader/Swig/MEDLoaderTest3.py index d8afdb960..80a1b87ab 100644 --- a/src/MEDLoader/Swig/MEDLoaderTest3.py +++ b/src/MEDLoader/Swig/MEDLoaderTest3.py @@ -7132,6 +7132,65 @@ class MEDLoaderTest3(unittest.TestCase): pass + def testUMeshReduceToCells(self): + """ + [EDF27988] : test of MEDFileUMesh.reduceToCells method + """ + arr = DataArrayDouble(4) ; arr.iota() + arrZ = DataArrayDouble(2) ; arrZ.iota() + m = MEDCouplingCMesh() ; m.setCoords(arr,arr,arrZ) + m = m.buildUnstructured() + mm = MEDFileUMesh() + mm[0] = m + m1 = m.buildDescendingConnectivity()[0] + bas1 = DataArrayInt([0,6,11,16,21,25,29,34,38]) + haut1 = DataArrayInt([1,7,12,17,22,26,30,35,39]) + lat1 = DataArrayInt([8,9,23,36]) + allcellsInMM = DataArrayInt.Aggregate([bas1,haut1,lat1]) + allcellsInMM.sort() + m1InMM = m1[allcellsInMM] + mm[-1] = m1InMM + bas1 = allcellsInMM.findIdForEach(bas1) ; bas1.setName("bas1") + haut1 = allcellsInMM.findIdForEach(haut1) ; haut1.setName("haut1") + lat1 = allcellsInMM.findIdForEach(lat1) ; lat1.setName("lat1") + m2 = m1InMM.buildDescendingConnectivity()[0] + lat2 = DataArrayInt( [ 14, 15, 16, 17, 34, 35, 50, 51] ) + allCellsInMM2 = DataArrayInt( [4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 21, 22, 23, 27, 28, 29, 32, 33, 34, 35, 38, 39, 43, 44, 45, 48, 49, 50, 51, 54, 55] ) + lat2 = allCellsInMM2.findIdForEach(lat2) ; lat2.setName("lat2") + m2InMM = m2[allCellsInMM2] + mm[-2] = m2InMM + mm.setName("mesh") + ## + bas1_id = -1 ; haut1_id = -2 ; lat1_id = -3 ; lat2_id = -4 + fam0 = DataArrayInt( m.getNumberOfCells() ) ; fam0.iota() + mm.setFamilyFieldArr(0,fam0) + fam1 = DataArrayInt( m1InMM.getNumberOfCells() ) ; fam1[:] = 0 ; fam1[bas1] = bas1_id ; fam1[haut1] = haut1_id ; fam1[lat1] = lat1_id + mm.setFamilyFieldArr(-1,fam1) + fam2 = DataArrayInt( m2InMM.getNumberOfCells() ) ; fam2[:] = 0 ; fam2[lat2] = lat2_id + mm.setFamilyFieldArr(-2,fam2) + for grp,famid in [(bas1,bas1_id),(haut1,haut1_id),(lat1,lat1_id),(lat2,lat2_id)]: + mm.addFamily(grp.getName(),famid) + mm.setFamiliesIdsOnGroup(grp.getName(),[famid]) + # ze heart of the test + mmr = mm.reduceToCells(0,DataArrayInt([4])) + # assert section + tmp = m[4] ; tmp.zipCoords() + self.assertTrue( mmr[0].isEqual(tmp,1e-12) ) + tmp = MEDCoupling1SGTUMesh( mmr[-1] ) + self.assertTrue( tmp.getCellModelEnum() == NORM_QUAD4 ) + self.assertTrue( tmp.getNodalConnectivity().isEqual( DataArrayInt([0, 4, 5, 1, 1, 0, 2, 3, 5, 7, 6, 4, 2, 6, 7, 3]) ) ) + tmp = MEDCoupling1SGTUMesh( mmr[-2] ) + self.assertTrue( tmp.getCellModelEnum() == NORM_SEG2 ) + self.assertTrue( tmp.getNodalConnectivity().isEqual( DataArrayInt([5, 4, 0, 4, 5, 1, 4, 6, 5, 7, 7, 6, 2, 6, 7, 3]) ) ) + # + self.assertTrue( mmr.getFamilyFieldAtLevel(0).isEqual(DataArrayInt([4])) ) + self.assertTrue( mmr.getFamilyFieldAtLevel(-1).isEqual(DataArrayInt([-3, -1, -2, -3])) ) + self.assertTrue( mmr.getFamilyFieldAtLevel(-2).isEqual(DataArrayInt([0, -4, -4, 0, 0, 0, -4, -4])) ) + # + self.assertTrue( set( mm.getGroupsNames() ) == set( mmr.getGroupsNames() ) ) + for grp in mm.getGroupsNames(): + self.assertTrue( set(mm.getFamiliesIdsOnGroup(grp)) == set(mmr.getFamiliesIdsOnGroup(grp)) ) + pass if __name__ == "__main__": -- 2.39.2