Salome HOME
Copyright update 2020
[tools/medcoupling.git] / src / MEDLoader / Swig / MEDLoaderSplitter.py
1 #  -*- coding: iso-8859-1 -*-
2 # Copyright (C) 2007-2020  CEA/DEN, EDF R&D
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2.1 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 #
18 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #
20 # Author : Anthony GEAY (CEA/DEN/DM2S/STMF/LGLS)
21
22 from medcoupling import *
23 import os
24
25 class MEDLoaderSplitter:
26     @classmethod
27     def New(cls,mfd,idsLst):
28         """ mfd is a MEDFileData instance containing only one mesh. idsLst is a list of DataArrayInt containing each the ids per processor """
29         return MEDLoaderSplitter(mfd,idsLst)
30         pass
31
32     def __init__(self,mfd,idsLst):
33         """ mfd is a MEDFileData instance containing only one mesh. idsLst is a list of DataArrayInt containing each the ids per processor """
34         mfmsh=mfd.getMeshes()
35         mfflds=mfd.getFields()
36         if len(mfmsh)!=1:
37             raise InterpKernelException("Works only with one mesh !")
38         mfflds=mfflds.partOfThisLyingOnSpecifiedMeshName(mfmsh[0].getName())
39         retm=self.__splitMesh(mfmsh[0],idsLst)
40         retf=self.__splitFields(mfmsh[0],retm,mfflds,idsLst)
41         self._mfd_splitted=[MEDFileData() for i in range(len(idsLst))]
42         for a,b,c in zip(self._mfd_splitted,retf,retm):
43             a.setFields(b) ; a.setMeshes(c)
44             pass
45         pass
46
47     def getSplittedInstances(self):
48         return self._mfd_splitted
49     
50     @classmethod
51     def __splitMEDFileField1TSNodePfl(cls,mm,fieldName,pfl,ids,cache,procID):
52         zeLev = None
53         for lev in reversed(mm.getNonEmptyLevels()):
54             cellIds = mm[lev].getCellIdsLyingOnNodes(pfl,True)
55             if mm[lev][cellIds].computeFetchedNodeIds().isEqualWithoutConsideringStr(pfl):
56                 zeLev = lev
57                 break
58         assert(zeLev is not None)
59         cache[(fieldName,procID)]["zeLev"]=zeLev
60         #
61         m0Part=mm[0][ids]
62         mLev=mm[zeLev]
63         #
64         trado2n=m0Part.zipCoordsTraducer() # 3D part of nodes o2n
65         trad=trado2n.invertArrayO2N2N2O(m0Part.getNumberOfNodes()) # 3D part of nodes n2o
66         part=mLev.getCellIdsFullyIncludedInNodeIds(trad)
67         mSubPart=mLev[part] # 2D part lying on 3D part
68         mSubPartReducedNode=mSubPart.deepCopy() ; mSubPartReducedNode.renumberNodesInConn(trado2n) ; mSubPartReducedNode.setCoords(m0Part.getCoords()) # 2D part lying on 3D part node zipped 
69         #
70         if mSubPart.getNumberOfCells()==0:
71             cache[(fieldName,procID)]["res"] = None
72             cache[(fieldName,procID)]["subProfileInProcReducedNode"] = None
73             return
74         cellsInSubPartFetchedByProfile = mSubPart.getCellIdsFullyIncludedInNodeIds(pfl)
75         mSubPartFetchedByPfl=mSubPart[cellsInSubPartFetchedByProfile]
76         subProfileInProc=mSubPartFetchedByPfl.computeFetchedNodeIds()
77         mSubPartFetchedByPfl.zipCoords()
78         #
79         res=pfl.findIdForEach(subProfileInProc)
80         subProfileInProcReducedNode=subProfileInProc.deepCopy() ; subProfileInProcReducedNode.transformWithIndArr(trado2n)
81         subProfileInProcReducedNode.setName(pfl.getName())
82         #
83         cache[(fieldName,procID)]["res"] = res
84         cache[(fieldName,procID)]["subProfileInProcReducedNode"] = subProfileInProcReducedNode
85         pass
86
87     
88     @classmethod
89     def __splitMEDFileField1TSNode(cls,t,mm,mmOut,f1tsIn,f1tsOut,ids,cache,procID):
90         if len(f1tsIn.getPflsReallyUsed())!=0:
91             arr,pfl=f1tsIn.getFieldWithProfile(ON_NODES,0,mm)
92             #
93             if (f1tsIn.getName(),procID) not in cache:
94                 cls.__splitMEDFileField1TSNodePfl(mm,f1tsIn.getName(),pfl,ids,cache,procID)
95                 pass
96             zeLev = cache[(f1tsIn.getName(),procID)]["zeLev"]
97             res = cache[(f1tsIn.getName(),procID)]["res"]
98             subProfileInProcReducedNode = cache[(f1tsIn.getName(),procID)]["subProfileInProcReducedNode"]
99             if (zeLev is None) or (res is None) or (subProfileInProcReducedNode is None):
100                 return
101             if len(res)>0:
102                 fRes=MEDCouplingFieldDouble(ON_NODES)
103                 fRes.setArray(arr[res])
104                 fRes.setName(f1tsIn.getName())
105                 #fRes.setMesh(mSubPartFetchedByPfl)
106                 #fRes.copyAllTinyAttrFrom(f_medcoupling)
107                 a,b,c=f1tsIn.getTime(); fRes.setTime(c,a,b)
108                 f1tsOut.setFieldProfile(fRes,mmOut,zeLev,subProfileInProcReducedNode)
109                 pass
110             #raise RuntimeError("Field \"%s\" contains profiles ! Not supported yet ! This field will be ignored !" % (f1tsIn.getName()))
111         else:
112             f=f1tsIn.getFieldOnMeshAtLevel(t,0,mm)
113             fRet=f[ids]
114             f1tsOut.setFieldNoProfileSBT(fRet)
115             pass
116         pass
117     
118     @classmethod
119     def __splitMEDFileField1TSCell(cls,t,mm,mmOut,f1tsIn,f1tsOut,ids,cache,procID):
120         f=f1tsIn.getFieldOnMeshAtLevel(t,0,mm)
121         fRet=f[ids]
122         m=fRet.getMesh() ; m.zipCoords()
123         o2n=m.getRenumArrForMEDFileFrmt() ; fRet.renumberCells(o2n,False)
124         f1tsOut.setFieldNoProfileSBT(fRet)
125         pass
126     
127     def __splitMEDFileField1TS(self,mm,mmOutList,f1ts,idsLst,cache):
128         """
129            Split input f1ts into parts defined by idsLst.
130
131            :param mm: The underlying mesh of f1ts
132            :param f1ts: The field to be split
133            :param idsLst: For each proc the cell ids at level 0
134            :return: A list of fields.
135         """
136         ret=[f1ts.__class__() for i in range(len(idsLst))]
137         dico={ON_CELLS:MEDLoaderSplitter.__splitMEDFileField1TSCell,
138               ON_NODES:MEDLoaderSplitter.__splitMEDFileField1TSNode,
139               ON_GAUSS_PT:MEDLoaderSplitter.__splitMEDFileField1TSCell,
140               ON_GAUSS_NE:MEDLoaderSplitter.__splitMEDFileField1TSCell}
141         for t in f1ts.getTypesOfFieldAvailable():
142             for procID,f0 in enumerate(ret):
143                 dico[t](t,mm,mmOutList[procID][0],f1ts,f0,idsLst[procID],cache,procID)
144                 pass
145             pass
146         return ret
147     
148     def __splitFields(self,mm,mmOutList,mfflds,idsLst):
149         ret0 = [MEDFileFields() for i in range(len(idsLst))]
150         from collections import defaultdict
151         cache = defaultdict(dict)
152         for fmts in mfflds:
153             ret1=[fmts.__class__() for i in range(len(idsLst))]
154             for f1ts in fmts:
155                 for fmtsPart,f1tsPart in zip(ret1,self.__splitMEDFileField1TS(mm,mmOutList,f1ts,idsLst,cache)):
156                     if f1tsPart.getUndergroundDataArray():
157                         if len(f1tsPart.getUndergroundDataArray())!=0 :
158                             fmtsPart.pushBackTimeStep(f1tsPart)
159                     pass
160                 pass
161             for fieldsPart,fmtsPart in zip(ret0,ret1):
162                 if len(fmtsPart) != 0 :
163                     fieldsPart.pushField(fmtsPart);
164                 pass
165             pass
166         return ret0
167
168     def __splitMesh(self,mfm,idsLst):
169         ret0 = [MEDFileMeshes() for i in range(len(idsLst))]
170         m=mfm[0]
171         addlevs=list(mfm.getNonEmptyLevels())[1:]
172         dAddlevs={k:mfm[k] for k in addlevs}
173         for ret,ids in zip(ret0,idsLst):
174             mlPart=mfm.createNewEmpty()
175             mPart=m[ids] ; trado2n=mPart.zipCoordsTraducer()
176             trad=trado2n.invertArrayO2N2N2O(mPart.getNumberOfNodes())
177             mlPart[0]=mPart
178             if 0 in mfm.getFamArrNonEmptyLevelsExt():
179                 mlPart.setFamilyFieldArr(0,mfm.getFamilyFieldAtLevel(0)[ids])
180                 pass
181             if 0 in mfm.getNameArrNonEmptyLevelsExt():
182                 mlPart.setNameFieldAtLevel(0, mfm.getNameFieldAtLevel(0)[ids])
183             if 1 in mfm.getFamArrNonEmptyLevelsExt():
184                 mlPart.setFamilyFieldArr(1,mfm.getFamilyFieldAtLevel(1)[trad])
185                 pass
186             if 1 in mfm.getNameArrNonEmptyLevelsExt():
187                 mlPart.setNameFieldAtLevel(1, mfm.getNameFieldAtLevel(1)[trad])
188             for k,v in dAddlevs.items():
189                 part=v.getCellIdsFullyIncludedInNodeIds(trad)
190                 mSubPart=v[part] ; mSubPart.renumberNodesInConn(trado2n) ; mSubPart.setCoords(mPart.getCoords())
191                 mlPart[k]=mSubPart
192                 mlPart.setFamilyFieldArr(k,mfm.getFamilyFieldAtLevel(k)[part])
193                 if k in mfm.getNameArrNonEmptyLevelsExt():
194                     mlPart.setNameFieldAtLevel(k, mfm.getNameFieldAtLevel(k)[part])
195             mlPart.copyFamGrpMapsFrom(mfm)
196             ret.pushMesh(mlPart)
197             pass
198         return ret0
199     pass