Salome HOME
Update copyrights
[modules/med.git] / doc / tut / medcoupling / testmed_gendata.py
1 #!/usr/bin/env python3
2 # Copyright (C) 2011-2019  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
21 # This script illustrates the basic usage of MEDCoupling and MEDLoader
22 # to generate test data files for various cases of med operation. It
23 # illustrates also the usage of numpy to specify the values of the
24 # fields when defined on a cartesian mesh (grid).
25 # (gboulant - 11/07/2011)
26
27 import medcoupling as MC
28 import MEDLoader as ML
29
30 import numpy
31
32 #
33 # ===============================================================
34 # Helper functions to create meshes
35 # ===============================================================
36 #
37
38 def createGridMesh(meshName, nbCellsX, nbCellsY):
39     """
40     The mesh is created using MEDCoupling. The code below creates a
41     cartesian mesh as a grid with nbCellsX segments in the X direction
42     and nbCellsY in the Y direction (nb. cells = nbCellsX * nbCellsY)
43     """
44     print("Creating grid mesh of size %sx%s"%(nbCellsX, nbCellsY))
45     cmesh=MC.MEDCouplingCMesh.New();
46
47     # Create X coordinates
48     nbNodesX = nbCellsX+1
49     stepX = 0.1
50     arrX = [float(i * stepX) for i in range(nbNodesX)]
51     coordsX=MC.DataArrayDouble.New()
52     coordsX.setValues(arrX,nbNodesX,1)
53
54     # Create Y coordinates
55     nbNodesY = nbCellsY+1
56     stepY = 0.1
57     arrY=[float(i * stepY) for i in range(nbNodesY)]
58     coordsY=MC.DataArrayDouble.New()
59     coordsY.setValues(arrY,nbNodesY,1)
60
61     # Create the grid
62     cmesh.setCoords(coordsX,coordsY)
63     cmesh.setName(meshName)
64
65     return cmesh
66
67 def unstructuredMesh(cartesianMesh):
68     """
69     Convert the cartesian mesh in unstructured mesh for the need of
70     write function of MEDLoader
71     """
72     print("Creating unstructured mesh from %s"%(cartesianMesh.getName()))
73     umesh=cartesianMesh.buildUnstructured();
74     umesh.setName(cartesianMesh.getName())
75     return umesh
76
77 #
78 # ===============================================================
79 # Creating a cartesian mesh
80 # ===============================================================
81 #
82 # The size is the number of discrete values in a direction, and then
83 # corresponds to the number of cells in that direction.
84 size=80
85 #size=512
86
87
88 # >>>
89 # WARNING: remember the problem of tics and spaces. The parameter
90 # "size" is considered to be a number of cells (intervals). The number
91 # of nodes in that direction is size+1.
92 # <<<
93
94 nbCellsX = size
95 nbNodesX = nbCellsX+1
96
97 nbCellsY = size # The size could be different than the X size
98 nbNodesY = nbCellsY+1
99
100 meshName = "Grid_%sx%s"%(nbCellsX, nbCellsY)
101 cmesh = createGridMesh(meshName, nbCellsX, nbCellsY)
102 umesh = unstructuredMesh(cmesh)
103 medFileName="gendata.med"
104 ML.MEDLoader.WriteUMesh(medFileName,umesh,True);
105
106 #
107 # ===============================================================
108 # Creating a scalar field, working with numpy
109 # ===============================================================
110 #
111
112 def createField(fieldName,gridMesh,
113                 numpy2Darray,typeOfField=MC.ON_CELLS,
114                 iteration=0):
115     """
116     The number of values for the fields is deduced from the sizes of
117     the numpy array. If typeOfField is ON_CELLS, the size is considered
118     as the number of cells, otherwise it's considered as the number of
119     nodes. In any case, it must be consistent with the dimensions of
120     the numpy 2D array.
121     """
122     print("Creating field %s with iteration=%s"%(fieldName,iteration))
123
124     # The sizes are deduced from the numpy array. Note that if
125     # typeOfField is ON_CELLS, then the size should correspond to the
126     # number of cells, while if typeOfField is ON_NODES, then the size
127     # should correspond to the number of nodes
128     [sizeX,sizeY] = numpy2Darray.shape
129
130     # We first have to reshape the 2D numpy array in a 1D vector that
131     # concatenate all the rows
132     data=numpy2Darray.reshape(1,sizeX*sizeY)[0]
133     # Then, we can create a simple list as required by the MEDCoupling
134     # DataArrayDouble. Note also the usage of float type because
135     # MEDCoupling works only with real numbers
136     listdata=list(data)
137
138     # Create the field using the list obtained from the numpy array
139     field = MC.MEDCouplingFieldDouble.New(typeOfField,MC.ONE_TIME);
140     field.setName(fieldName);
141     field.setMesh(gridMesh);
142     field.setIteration(iteration)
143     field.setTimeValue(float(iteration))
144
145     nbComponents=1 # Only one single component for a scalar field
146     nbCells=sizeX*sizeY
147     dataArray=MC.DataArrayDouble.New();
148     dataArray.setValues(listdata,nbCells,nbComponents)
149     field.setArray(dataArray);
150
151     return field
152
153 def writeField(fieldName, numpy2Darray,
154                typeOfField=MC.ON_CELLS,
155                iteration=0):
156
157     field = createField(fieldName, umesh, numpy2Darray,
158                         typeOfField, iteration)
159     createFromScratch=False
160     ML.MEDLoader.WriteField(medFileName,field,createFromScratch)
161
162
163 def createTestNumpy2DArray(sizeX, sizeY):
164     """
165     This illustrates how to create a numpy 2D array for input of the
166     createField function.
167     """
168     rows=[]
169     for irow in range(sizeY):
170         row = numpy.arange(start = irow*sizeY,
171                            stop  = irow*sizeY+sizeX,
172                            step  = 1,
173                            dtype='float64')
174         rows.append(row)
175
176     numpy2Darray = numpy.vstack(rows)
177     return numpy2Darray
178
179 def createTestFieldOnCells():
180     # Test field on cells
181     numpy2Darray = createTestNumpy2DArray(sizeX=nbCellsX, sizeY=nbCellsY)
182     writeField("FieldOnCells", numpy2Darray,
183                typeOfField=MC.ON_CELLS)
184
185 def createTestFieldOnNodes():
186     # Test field on nodes
187     numpy2Darray = createTestNumpy2DArray(sizeX=nbNodesX, sizeY=nbNodesY)
188     writeField("FieldOnNodes", numpy2Darray,
189                typeOfField=MC.ON_NODES)
190
191
192 #
193 # =================================================
194 # Creating a time series
195 # =================================================
196 #
197
198 # -------------------------------------------------
199 # Simple demo of the principles
200 # -------------------------------------------------
201
202 # In these functions, (x,y) are the indexes of the element in the
203 # numpy array. Note that theses indexes maps the indexes of the
204 # cartesian mesh.
205
206 # A function can be a simple python function ...
207 def f1(x,y):
208     z = 10*x
209     print("x=%s\ny=%s\nz=%s"%(x,y,z))
210     return z
211
212 # ... but also a more sophisticated callable object, for example to
213 # defines some parameters
214 class Function:
215     def __init__(self, sizeX, sizeY, param):
216         self.sizeX = sizeX
217         self.sizeY = sizeY
218         self.param = param
219
220     def function(self, x,y):
221         z = self.param*x
222         print("x=%s\ny=%s\nz=%s"%(x,y,z))
223         return z
224
225     def __call__(self, x,y):
226         return self.function(x,y)
227
228 fOnNodes=Function(sizeX=nbNodesX, sizeY=nbNodesY, param=10)
229 fOnCells=Function(sizeX=nbCellsX, sizeY=nbCellsY, param=3)
230
231 def createFunctionField_01():
232     sizeX=nbNodesX
233     sizeY=nbNodesY
234     typeOfField=MC.ON_NODES
235     f=fOnNodes
236     numpy2Darray = numpy.fromfunction(f,(sizeX,sizeY),dtype='float64')
237     writeField("FieldOnNodesUsingFunc", numpy2Darray,typeOfField)
238
239     f=fOnCells
240     sizeX=nbCellsX
241     sizeY=nbCellsY
242     typeOfField=MC.ON_CELLS
243     numpy2Darray = numpy.fromfunction(f,(sizeX,sizeY),dtype='float64')
244     writeField("FieldOnCellsUsingFunc", numpy2Darray,typeOfField)
245
246
247 # -------------------------------------------------
248 # Using the pyfunctions package to generate data
249 # -------------------------------------------------
250
251 def createNumpy2DArrayWithFunc(sizeX, sizeY, function):
252     """
253     @function : a callable than can be used as a function of X.
254     Typically function should be an instance of Function object
255     defined in pyfunctions.functions.
256     """
257
258     # X coordinates should range between 0 and 1 to use the normalized
259     # functions. We have to generate sizeX points:
260     step=1./sizeX
261     arrX=[float(i * step) for i in range(sizeX)]
262
263     values = function(arrX)
264
265     # Then on can create the base row for the numpy 2D array
266     rowX = numpy.array(values)
267     # and replicate this row along the Y axis
268     rows=[]
269     for irow in range(sizeY):
270         rows.append(rowX)
271
272     numpy2Darray = numpy.vstack(rows)
273     return numpy2Darray
274
275 from pyfunctions.functions import FuncStiffPulse
276 def createNumpy2DArrayWithFuncStiff(sizeX, sizeY):
277     f=FuncStiffPulse(xlimit=0.3,stiffness=30,nbPeriods=10)
278     return createNumpy2DArrayWithFunc(sizeX, sizeY, f)
279
280 def createFunctionField_02():
281     sizeX=nbCellsX
282     sizeY=nbCellsY
283     typeOfField=MC.ON_CELLS
284     numpy2Darray = createNumpy2DArrayWithFuncStiff(sizeX,sizeY)
285     writeField("FieldOnCellsUsingFunc02", numpy2Darray,typeOfField)
286
287     sizeX=nbNodesX
288     sizeY=nbNodesY
289     typeOfField=MC.ON_NODES
290     numpy2Darray = createNumpy2DArrayWithFuncStiff(sizeX,sizeY)
291     writeField("FieldOnNodesUsingFunc02", numpy2Darray,typeOfField)
292
293 #
294 # =================================================
295 # Functions to create custom fields for MEDCalc tests
296 # =================================================
297 #
298 def createTimeSeries():
299     """
300     Create a single med file with a single mesh and a field defined on
301     several time steps (time series).
302     """
303     meshName = "Grid_%sx%s"%(nbCellsX, nbCellsY)
304     cmesh = createGridMesh(meshName, nbCellsX, nbCellsY)
305     umesh = unstructuredMesh(cmesh)
306     medFileName="timeseries.med"
307     ML.MEDLoader.WriteUMesh(medFileName,umesh,True);
308
309     sizeX=nbNodesX
310     sizeY=nbNodesY
311     typeOfField=MC.ON_NODES
312
313     nbIterations=10
314     pulseStiffNess = 20
315     pulseNbPeriods = 10
316     for iteration in range(nbIterations):
317         xlimit = float(iteration)/float(nbIterations)
318         f=FuncStiffPulse(xlimit,stiffness=pulseStiffNess,nbPeriods=pulseNbPeriods)
319         numpy2Darray = createNumpy2DArrayWithFunc(sizeX,sizeY,f)
320         field = createField("Pulse",umesh,numpy2Darray,typeOfField,iteration)
321         ML.MEDLoader.WriteField(medFileName,field,False)
322
323 from pyfunctions.functions import FuncStiffExp
324 def createParametrics():
325     """
326     Create 2 med files containing each a mesh (identical) and a field
327     defined on this mesh in each file.
328     """
329     meshName = "Grid_%sx%s_01"%(nbCellsX, nbCellsY)
330     cmesh = createGridMesh(meshName, nbCellsX, nbCellsY)
331     umesh = unstructuredMesh(cmesh)
332
333     sizeX=nbNodesX
334     sizeY=nbNodesY
335     typeOfField=MC.ON_NODES
336
337     medFileName="parametric_01.med"
338     ML.MEDLoader.WriteUMesh(medFileName,umesh,True);
339     f=FuncStiffExp(xlimit=0.3,stiffness=30)
340     numpy2Darray = createNumpy2DArrayWithFunc(sizeX,sizeY,f)
341     fieldName = "StiffExp_01"
342     field = createField(fieldName,umesh, numpy2Darray,typeOfField)
343     ML.MEDLoader.WriteField(medFileName,field,False)
344
345     medFileName="parametric_02.med"
346     umesh.setName("Grid_%sx%s_02"%(nbCellsX, nbCellsY))
347     ML.MEDLoader.WriteUMesh(medFileName,umesh,True);
348     f=FuncStiffExp(xlimit=0.4,stiffness=30)
349     numpy2Darray = createNumpy2DArrayWithFunc(sizeX,sizeY,f)
350     fieldName = "StiffExp_02"
351     field = createField(fieldName,umesh, numpy2Darray,typeOfField)
352     ML.MEDLoader.WriteField(medFileName,field,False)
353
354 def createParametrics_demo():
355     """
356     Create 2 med files containing each a mesh (identical) and a field
357     defined on this mesh in each file.
358     """
359     meshName = "mesh1"
360     cmesh = createGridMesh(meshName, nbCellsX, nbCellsY)
361     umesh = unstructuredMesh(cmesh)
362
363     sizeX=nbNodesX
364     sizeY=nbNodesY
365     typeOfField=MC.ON_NODES
366
367     listIteration = [0,1,2,3,4]
368
369     medFileName="parametric_01.med"
370     ML.MEDLoader.WriteUMesh(medFileName,umesh,True);
371     fieldName = "field1"
372     for iteration in listIteration:
373         #f=FuncStiffPulse(xlimit=0.3+0.1*iteration,stiffness=10,nbPeriods=5)
374         f=FuncStiffExp(xlimit=0.3+0.1*iteration,stiffness=10)
375         numpy2Darray = createNumpy2DArrayWithFunc(sizeX,sizeY,f)
376         field = createField(fieldName,umesh, numpy2Darray,typeOfField,iteration)
377         ML.MEDLoader.WriteField(medFileName,field,False)
378
379     medFileName="parametric_02.med"
380     umesh.setName("mesh2")
381     ML.MEDLoader.WriteUMesh(medFileName,umesh,True);
382     fieldName = "field2"
383     for iteration in listIteration:
384         #f=FuncStiffPulse(xlimit=0.3+0.1*iteration,stiffness=10,nbPeriods=6)
385         f=FuncStiffExp(xlimit=0.3+0.1*iteration,stiffness=15)
386         numpy2Darray = createNumpy2DArrayWithFunc(sizeX,sizeY,f)
387         field = createField(fieldName,umesh, numpy2Darray,typeOfField,iteration)
388         ML.MEDLoader.WriteField(medFileName,field,False)
389
390
391
392 #
393 # =================================================
394 # Main runner
395 # =================================================
396 #
397 if __name__ == "__main__":
398     #createTestFieldOnCells()
399     #createTestFieldOnNodes()
400     #createFunctionField_01()
401     #createFunctionField_02()
402     #createTimeSeries()
403     createParametrics_demo()