medcoupling 9.13.0__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- CaseIO.py +31 -0
- CaseReader.py +424 -0
- CaseWriter.py +349 -0
- MEDCouplingCompat.py +15020 -0
- MEDCouplingRemapper.py +15491 -0
- MEDLoader.py +21994 -0
- MEDLoaderFinalize.py +66 -0
- MEDLoaderSplitter.py +199 -0
- MEDPartitioner.py +163 -0
- MEDRenumber.py +14946 -0
- VTKReader.py +306 -0
- _MEDCouplingCompat.pyd +0 -0
- _MEDCouplingRemapper.pyd +0 -0
- _MEDLoader.pyd +0 -0
- _MEDPartitioner.pyd +0 -0
- _MEDRenumber.pyd +0 -0
- _medcoupling.pyd +0 -0
- geom2medcoupling.py +99 -0
- hdf5.dll +0 -0
- interpkernel.dll +0 -0
- libxml2.dll +0 -0
- medC.dll +0 -0
- medcoupling-9.13.0.dist-info/METADATA +45 -0
- medcoupling-9.13.0.dist-info/RECORD +30 -0
- medcoupling-9.13.0.dist-info/WHEEL +4 -0
- medcoupling.dll +0 -0
- medcoupling.py +22874 -0
- medcouplingremapper.dll +0 -0
- medicoco.dll +0 -0
- medloader.dll +0 -0
- medpartitionercpp.dll +0 -0
- renumbercpp.dll +0 -0
- vtk2medcoupling.py +72 -0
CaseWriter.py
ADDED
@@ -0,0 +1,349 @@
|
|
1
|
+
# -*- coding: iso-8859-1 -*-
|
2
|
+
# Copyright (C) 2007-2024 CEA, EDF
|
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
|
+
import numpy as np
|
23
|
+
from CaseIO import CaseIO
|
24
|
+
from MEDLoader import *
|
25
|
+
import sys,re,os,mmap
|
26
|
+
|
27
|
+
### www-vis.lbl.gov/NERSC/Software/ensight/doc/OnlineHelp/UM-C11.pdf
|
28
|
+
|
29
|
+
class CaseWriter(CaseIO):
|
30
|
+
""" Converting MED file format in memory to a the Case file format (Ensight).
|
31
|
+
A new file with the same base name and the .case extension is created with its dependencies (.geo ...).
|
32
|
+
"""
|
33
|
+
|
34
|
+
header="""FORMAT
|
35
|
+
type: ensight gold
|
36
|
+
GEOMETRY
|
37
|
+
model: %(geofilewithoutpath)s
|
38
|
+
"""
|
39
|
+
header_varpart="""VARIABLE"""
|
40
|
+
header_timepart="""TIME
|
41
|
+
time set: 1
|
42
|
+
number of steps: %(NbTimeSteps)i
|
43
|
+
filename start number: 0
|
44
|
+
filename increment: 1
|
45
|
+
time values:
|
46
|
+
%(TimeValues)s
|
47
|
+
"""
|
48
|
+
|
49
|
+
@classmethod
|
50
|
+
def New(cls):
|
51
|
+
""" Static constructor. """
|
52
|
+
return CaseWriter()
|
53
|
+
pass
|
54
|
+
|
55
|
+
def __init__(self):
|
56
|
+
""" Constructor """
|
57
|
+
self.__export_groups=False
|
58
|
+
pass
|
59
|
+
|
60
|
+
def setMEDFileDS(self,medData):
|
61
|
+
""" Input should be MEDFileData instance """
|
62
|
+
self._med_data=medData
|
63
|
+
pass
|
64
|
+
|
65
|
+
def isExportingGroups(self):
|
66
|
+
""" return the status of exporting groups policy """
|
67
|
+
return self.__export_groups
|
68
|
+
|
69
|
+
def setExportingGroups(self,status):
|
70
|
+
assert(isinstance(status,bool))
|
71
|
+
self.__export_groups=status
|
72
|
+
pass
|
73
|
+
|
74
|
+
|
75
|
+
def write(self,fileName):
|
76
|
+
""" Write into the specified fileName series the result """
|
77
|
+
self._file_name=fileName
|
78
|
+
self._base_name_without_dir=os.path.splitext(os.path.basename(self._file_name))[0]
|
79
|
+
self._l=self._file_name.split(os.path.sep) ; self._l[-1]=os.path.splitext(self._l[-1])[0]
|
80
|
+
self._base_name_with_dir=os.path.sep.join(self._l)
|
81
|
+
self._real_written_file_name=[]
|
82
|
+
self._dico={}
|
83
|
+
for mesh in self._med_data.getMeshes():
|
84
|
+
additionnalFileNamePart=""
|
85
|
+
if len(self._med_data.getMeshes())!=1:
|
86
|
+
additionnalFileNamePart="_%s"%(mesh.getName())
|
87
|
+
pass
|
88
|
+
self._dico["geofilewithoutpath"]="%s%s.geo"%(self._base_name_without_dir,additionnalFileNamePart)
|
89
|
+
h0=self.header%self._dico
|
90
|
+
self.__writeMeshesPart(mesh,"%s%s.geo"%(self._base_name_with_dir,additionnalFileNamePart))
|
91
|
+
#
|
92
|
+
h2=self.__writeFieldsPart(self._med_data.getFields().partOfThisLyingOnSpecifiedMeshName(mesh.getName()))
|
93
|
+
realWrittenCaseFileNameForCurMesh="%s%s.case"%(self._base_name_with_dir,additionnalFileNamePart)
|
94
|
+
fheader=open(realWrittenCaseFileNameForCurMesh,"w") ; fheader.write((h0+h2)%self._dico)
|
95
|
+
self._real_written_file_name.append(realWrittenCaseFileNameForCurMesh)
|
96
|
+
pass
|
97
|
+
return self._real_written_file_name
|
98
|
+
|
99
|
+
def __writeMeshesPart(self,mdm,meshfn):
|
100
|
+
try:
|
101
|
+
os.remove(meshfn)
|
102
|
+
except:
|
103
|
+
pass
|
104
|
+
f=open(meshfn,"w+b")
|
105
|
+
sz=5*80
|
106
|
+
#
|
107
|
+
assert(isinstance(mdm,MEDFileUMesh))
|
108
|
+
ms2=[[mdm.getMeshAtLevel(lev) for lev in mdm.getNonEmptyLevels()[:1]]]
|
109
|
+
if self.__export_groups:
|
110
|
+
for grpnm in mdm.getGroupsNames():
|
111
|
+
ms3=[]
|
112
|
+
for lev in mdm.getGrpNonEmptyLevels(grpnm)[:1]:
|
113
|
+
m=mdm.getGroup(lev,grpnm) ; m.zipCoords()
|
114
|
+
ms3.append(m)
|
115
|
+
pass
|
116
|
+
ms2.append(ms3)
|
117
|
+
pass
|
118
|
+
pass
|
119
|
+
for ms in ms2:
|
120
|
+
nn=ms[0].getNumberOfNodes()
|
121
|
+
sz+=self.__computeSizeOfGeoFile(ms,nn)
|
122
|
+
pass
|
123
|
+
pass
|
124
|
+
a=np.memmap(f,dtype='byte',mode='w+',offset=0,shape=(sz,)) ; a.flush() # truncate to set the size of the file
|
125
|
+
mm=mmap.mmap(f.fileno(),offset=0,length=0)
|
126
|
+
mm.write(self.__str80("C Binary"))
|
127
|
+
mm.write(self.__str80("Exported from MEDCoupling/MEDLoader version %s"%(MEDCouplingVersionStr())))
|
128
|
+
mm.write(self.__str80("Conversion using CaseWriter class"))
|
129
|
+
mm.write(self.__str80("node id off"))
|
130
|
+
mm.write(self.__str80("element id off"))
|
131
|
+
for iii,ms in enumerate(ms2):
|
132
|
+
nn=ms[0].getNumberOfNodes()
|
133
|
+
mm.write(self.__str80("part"))
|
134
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(1,))
|
135
|
+
a[0]=iii+1 ; a.flush() ; mm.seek(mm.tell()+4) # part number maybe to change ?
|
136
|
+
name=ms[0].getName()
|
137
|
+
if iii>0:
|
138
|
+
name="%s_%s"%(ms2[0][0].getName(),name)
|
139
|
+
pass
|
140
|
+
mm.write(self.__str80(name))
|
141
|
+
mm.write(self.__str80("coordinates"))
|
142
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(1,))
|
143
|
+
a[0]=nn ; a.flush() # number of nodes
|
144
|
+
mm.seek(mm.tell()+4)
|
145
|
+
coo=ms[0].getCoords()
|
146
|
+
spaceDim=coo.getNumberOfComponents()
|
147
|
+
if spaceDim!=3:
|
148
|
+
coo=coo.changeNbOfComponents(3,0.)
|
149
|
+
pass
|
150
|
+
a=np.memmap(f,dtype='float32',mode='w+',offset=mm.tell(),shape=(3,nn))
|
151
|
+
c=coo.toNoInterlace() ; c.rearrange(1) ; cnp=c.toNumPyArray() ; cnp=cnp.reshape(3,nn)
|
152
|
+
a[:]=cnp ; a.flush() ; mm.seek(mm.tell()+3*nn*4)
|
153
|
+
for m in ms:
|
154
|
+
i=0
|
155
|
+
for typ2,nbelem,dummy in m.getDistributionOfTypes():
|
156
|
+
typ=typ2
|
157
|
+
if typ not in self.dictMCTyp:
|
158
|
+
typ=MEDCouplingMesh.GetCorrespondingPolyType(typ)
|
159
|
+
pass
|
160
|
+
mp=m[i:i+nbelem]
|
161
|
+
mm.write(self.__str80(self.dictMCTyp_str[typ]))
|
162
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(1,))
|
163
|
+
a[0]=nbelem ; a.flush() ; mm.seek(mm.tell()+4)
|
164
|
+
if typ!=NORM_POLYHED and typ!=NORM_POLYGON:
|
165
|
+
nbNodesPerElem=MEDCouplingMesh.GetNumberOfNodesOfGeometricType(typ)
|
166
|
+
c=mp.getNodalConnectivity() ; c.rearrange(nbNodesPerElem+1) ; c=c[:,1:] ; c.rearrange(1) ; c+=1
|
167
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(nbNodesPerElem*nbelem,))
|
168
|
+
a[:]=c.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+nbNodesPerElem*nbelem*4)
|
169
|
+
pass
|
170
|
+
elif typ==NORM_POLYHED:
|
171
|
+
mp.orientCorrectlyPolyhedrons()
|
172
|
+
c=mp.computeNbOfFacesPerCell()
|
173
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(nbelem,))
|
174
|
+
a[:]=c.toNumPyArray(); a.flush() ; mm.seek(mm.tell()+nbelem*4)
|
175
|
+
c=mp.getNodalConnectivity()[:] ; c.pushBackSilent(-1) ; c[mp.getNodalConnectivityIndex()[:-1]]=-1 ; ids=c.findIdsEqual(-1) ; nbOfNodesPerFace=ids.deltaShiftIndex()-1
|
176
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(len(nbOfNodesPerFace),))
|
177
|
+
a[:]=nbOfNodesPerFace.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+len(nbOfNodesPerFace)*4)
|
178
|
+
ids2=ids.buildComplement(ids.back()+1)
|
179
|
+
c2=mp.getNodalConnectivity()[ids2]+1
|
180
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(len(c2),))
|
181
|
+
a[:]=c2.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+len(c2)*4)
|
182
|
+
pass
|
183
|
+
else:
|
184
|
+
nbOfNodesPerCell=mp.getNodalConnectivityIndex().deltaShiftIndex()-1
|
185
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(len(nbOfNodesPerCell),))
|
186
|
+
a[:]=nbOfNodesPerCell.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+len(nbOfNodesPerCell)*4)
|
187
|
+
ids2=mp.getNodalConnectivityIndex().buildComplement(mp.getNodalConnectivityIndex().back()+1)
|
188
|
+
c2=mp.getNodalConnectivity()[ids2]+1
|
189
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(len(c2),))
|
190
|
+
a[:]=c2.toNumPyArray() ; a.flush() ; mm.seek(mm.tell()+len(c2)*4)
|
191
|
+
pass
|
192
|
+
i+=nbelem
|
193
|
+
pass
|
194
|
+
pass
|
195
|
+
pass
|
196
|
+
pass
|
197
|
+
|
198
|
+
def __writeFieldsPart(self,mdfs):
|
199
|
+
if not mdfs:
|
200
|
+
return ""
|
201
|
+
self._ze_top_dict={}
|
202
|
+
its,areForgottenTS=mdfs.getCommonIterations()
|
203
|
+
if areForgottenTS:
|
204
|
+
print(("WARNING : some iterations are NOT present in all fields ! Kept iterations are : %s !"%(str(its))))
|
205
|
+
pass
|
206
|
+
TimeValues=""
|
207
|
+
for it in its:
|
208
|
+
TimeValues+="%s\n"%(str(mdfs[0][it].getTime()[-1]))
|
209
|
+
pass
|
210
|
+
dictVars={}
|
211
|
+
for mdf in mdfs:
|
212
|
+
nbCompo=mdf.getNumberOfComponents()
|
213
|
+
if nbCompo not in self.dictCompo:
|
214
|
+
l = [x for x in self.dictCompo if x - nbCompo > 0]
|
215
|
+
if len(l)==0:
|
216
|
+
print(("Field \"%s\" will be ignored because number of components (%i) is too big to be %s supported by case files !"%(mdf.getName(),nbCompo,str(list(self.dictCompo.keys())))))
|
217
|
+
continue
|
218
|
+
pass
|
219
|
+
print(("WARNING : Field \"%s\" will have its number of components (%i) set to %i, in order to be supported by case files (must be in %s) !"%(mdf.getName(),nbCompo,l[0],str(list(self.dictCompo.keys())))))
|
220
|
+
nbCompo=l[0]
|
221
|
+
pass
|
222
|
+
if nbCompo in dictVars:
|
223
|
+
dictVars[nbCompo].append(mdf)
|
224
|
+
pass
|
225
|
+
else:
|
226
|
+
dictVars[nbCompo]=[mdf]
|
227
|
+
pass
|
228
|
+
pass
|
229
|
+
for mdf in mdfs:
|
230
|
+
nbCompo=mdf.getNumberOfComponents()
|
231
|
+
if nbCompo not in self.dictCompo:
|
232
|
+
l = [x for x in self.dictCompo if x - nbCompo > 0]
|
233
|
+
if len(l)==0:
|
234
|
+
continue;
|
235
|
+
nbCompo=l[0]
|
236
|
+
pass
|
237
|
+
for iii,it in enumerate(its):
|
238
|
+
ff=mdf[it]
|
239
|
+
isMultiDisc=len(ff.getTypesOfFieldAvailable())>1
|
240
|
+
for typ in ff.getTypesOfFieldAvailable():
|
241
|
+
l=self._l[:] ; l[-1]="%s%s.%s"%(self._base_name_without_dir,str(iii).rjust(4,"0"),ff.getName())
|
242
|
+
if isMultiDisc:
|
243
|
+
l[-1]="%s_%s"(l[-1],MEDCouplingFieldDiscretization.New(typ).getStringRepr())
|
244
|
+
pass
|
245
|
+
fffn=l[-1]
|
246
|
+
try:
|
247
|
+
os.remove(os.path.sep.join(l))
|
248
|
+
except:
|
249
|
+
pass
|
250
|
+
f=open(os.path.sep.join(l),"w+b")
|
251
|
+
summ=0
|
252
|
+
for geo,[(curTyp,(bg,end),pfl,loc)] in ff.getFieldSplitedByType():
|
253
|
+
if typ==curTyp:
|
254
|
+
summ+=4*nbCompo*(end-bg)+80
|
255
|
+
pass
|
256
|
+
pass
|
257
|
+
a=np.memmap(f,dtype='byte',mode='w+',offset=0,shape=(2*80+4+summ,)) ; a.flush() # truncate to set the size of the file
|
258
|
+
mm=mmap.mmap(f.fileno(),offset=0,length=0)
|
259
|
+
k1=ff.getName()
|
260
|
+
if isMultiDisc:
|
261
|
+
k1="%s_%s"%(k1,MEDCouplingFieldDiscretization.New(typ).getStringRepr())
|
262
|
+
pass
|
263
|
+
mm.write(self.__str80(k1))
|
264
|
+
mm.write(self.__str80("part"))
|
265
|
+
a=np.memmap(f,dtype='int32',mode='w+',offset=mm.tell(),shape=(1,))
|
266
|
+
a[0]=1 ; a.flush() ; mm.seek(mm.tell()+4) # part number maybe to change ?
|
267
|
+
for geo,[(curTyp,(bg,end),pfl,loc)] in ff.getFieldSplitedByType():
|
268
|
+
if pfl!="":
|
269
|
+
raise Exception("Field \"%s\" contains profiles ! Profiles are not supported yet !"%(mdf.getName()))
|
270
|
+
if typ==curTyp:
|
271
|
+
arr=ff.getUndergroundDataArray()[bg:end].changeNbOfComponents(nbCompo,0.) ; arr=arr.toNoInterlace()
|
272
|
+
if typ==ON_CELLS:
|
273
|
+
mm.write(self.__str80(self.dictMCTyp_str[geo]))
|
274
|
+
pass
|
275
|
+
elif typ==ON_NODES:
|
276
|
+
mm.write(self.__str80("coordinates"))
|
277
|
+
pass
|
278
|
+
else:
|
279
|
+
print(("UnManaged type of field for field \"%s\" !"%(mdf.getName())))
|
280
|
+
pass
|
281
|
+
a=np.memmap(f,dtype='float32',mode='w+',offset=mm.tell(),shape=(nbCompo,end-bg))
|
282
|
+
b=arr.toNumPyArray() ; b=b.reshape(nbCompo,end-bg)
|
283
|
+
a[:]=b
|
284
|
+
a.flush() ; mm.seek(mm.tell()+nbCompo*(end-bg)*4)
|
285
|
+
pass
|
286
|
+
pass
|
287
|
+
k="%s per %s"%(self.dictCompo[nbCompo],self.discSpatial[typ])
|
288
|
+
if k in self._ze_top_dict:
|
289
|
+
if k1 in self._ze_top_dict[k]:
|
290
|
+
self._ze_top_dict[k][k1].append(fffn)
|
291
|
+
pass
|
292
|
+
else:
|
293
|
+
self._ze_top_dict[k][k1]=[fffn]
|
294
|
+
pass
|
295
|
+
else:
|
296
|
+
self._ze_top_dict[k]={k1:[fffn]}
|
297
|
+
pass
|
298
|
+
pass
|
299
|
+
pass
|
300
|
+
pass
|
301
|
+
headerPart=""
|
302
|
+
if len(self._ze_top_dict)!=0:
|
303
|
+
hvp=self.header_varpart[:]
|
304
|
+
for k in self._ze_top_dict:
|
305
|
+
for k1 in self._ze_top_dict[k]:
|
306
|
+
hvp+="\n%s: %s %s"%(k,k1,re.sub("([\d]{4})",4*"*",self._ze_top_dict[k][k1][0]))
|
307
|
+
pass
|
308
|
+
pass
|
309
|
+
hvp+="\n"
|
310
|
+
headerPart+=hvp
|
311
|
+
#
|
312
|
+
ddd={"NbTimeSteps":len(its),"TimeValues":TimeValues}
|
313
|
+
htp=self.header_timepart%ddd
|
314
|
+
headerPart+=htp
|
315
|
+
pass
|
316
|
+
return headerPart
|
317
|
+
|
318
|
+
@classmethod
|
319
|
+
def __str80(cls,st):
|
320
|
+
if len(st)>79:
|
321
|
+
raise Exception("String \"%s\" is too long (>79) !"%(st))
|
322
|
+
return bytes(str(st).ljust(79)+"\n", "ascii")
|
323
|
+
|
324
|
+
def __computeSizeOfGeoFile(self,listOfMeshes,nn):
|
325
|
+
sz=0
|
326
|
+
for m in listOfMeshes:
|
327
|
+
distribTypes=m.getDistributionOfTypes()
|
328
|
+
sz+=80+4+2*80+4+nn*3*4
|
329
|
+
i=0
|
330
|
+
for typ2,nbelem,dummy in distribTypes:
|
331
|
+
typ=typ2
|
332
|
+
if typ not in self.dictMCTyp:
|
333
|
+
typ=MEDCouplingMesh.GetCorrespondingPolyType()
|
334
|
+
pass
|
335
|
+
if typ!=NORM_POLYHED and typ!=NORM_POLYGON:
|
336
|
+
sz+=80+4+MEDCouplingMesh.GetNumberOfNodesOfGeometricType(typ)*nbelem*4
|
337
|
+
pass
|
338
|
+
elif typ==NORM_POLYHED:
|
339
|
+
mplh=m[i:i+nbelem] ; delta=len(mplh.getNodalConnectivity())+nbelem
|
340
|
+
sz+=80+4+delta*4
|
341
|
+
pass
|
342
|
+
else:
|
343
|
+
mplh=m[i:i+nbelem] ; delta=len(mplh.getNodalConnectivity())
|
344
|
+
sz+=80+4+delta*4
|
345
|
+
pass
|
346
|
+
i+=nbelem
|
347
|
+
pass
|
348
|
+
pass
|
349
|
+
return sz
|