]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/ParaMEDMEM_Swig/test_OverlapDEC.py
Salome HOME
[ParaMEDMEM] Adding SWIG interface for OverlapDEC + py tests of DEC
[tools/medcoupling.git] / src / ParaMEDMEM_Swig / test_OverlapDEC.py
1 #!/usr/bin/env python
2
3 from medcoupling import *
4 from ParaMEDMEMTestTools import WriteInTmpDir
5 import sys, os
6 import unittest
7 import math
8 from mpi4py import MPI
9
10 class ParaMEDMEM_O_DEC_Tests(unittest.TestCase):
11     """ This test illustrates a basic use of the OverlapDEC and shows notably that not all 
12     processors must possess a piece of the source and/or target mesh. 
13     Look at the C++ documentation of the class for more informations.
14     In this case, the source mesh is only stored on 2 procs, whereas the target is on 4.
15     Since only a single group of processor is defined in the setup, the 2 idle procs on the source side are just providing an empty mesh,
16     thus indicating that they don't participate in the source definition. 
17     
18     Main method is testOverlapDEC_2D_py_1()
19     """
20
21     def generateFullSource(self):
22         """ The complete source mesh: 4 squares each divided in 2 diagonaly (so 8 cells in total) """
23         msh  = self.generateFullTarget()
24         msh.simplexize(0)
25         msh.setName("src_mesh")
26         fld = MEDCouplingFieldDouble(ON_CELLS, ONE_TIME)
27         fld.setMesh(msh); fld.setName("source_F");
28         da = DataArrayDouble(msh.getNumberOfCells())
29         da.iota()
30         da *= 2
31         fld.setArray(da)
32         return msh, fld
33
34     def generateFullTarget(self):
35         """ The complete target mesh: 4 squares """
36         m1 = MEDCouplingCMesh("tgt_msh")
37         da = DataArrayDouble([0,1,2])
38         m1.setCoords(da, da)
39         msh = m1.buildUnstructured()
40         return msh
41
42     #
43     # Below, the two functions emulating the set up of a piece of the source and target mesh
44     # on each proc. Obviously in real world problems, this comes from your code and is certainly
45     # not computed by cuting again from scratch the full-size mesh!!
46     #
47     def getPartialSource(self, rank):
48         """ Will return an empty mesh piece for rank=2 and 3 """
49         msh, f = self.generateFullSource()
50         if rank in [2,3]:
51             sub_m, sub_f = msh[[]], f[[]]  # Little trick to select nothing in the mesh, thus producing an empty mesh
52         elif rank == 0:
53             sub_m, sub_f = msh[0:4], f[0:4]
54         elif rank == 1:
55             sub_m, sub_f = msh[4:8], f[4:8]
56         sub_m.zipCoords()
57         return sub_m, sub_f
58
59     def getPartialTarget(self, rank):
60         """ One square for each rank """
61         msh = self.generateFullTarget()
62         sub_m = msh[rank]
63         sub_m.zipCoords()
64         # Receiving side must prepare an empty field that will be filled by DEC:
65         fld = MEDCouplingFieldDouble(ON_CELLS, ONE_TIME)
66         da = DataArrayDouble(sub_m.getNumberOfCells())
67         fld.setArray(da)
68         fld.setName("tgt_F")
69         fld.setMesh(sub_m)
70         return sub_m, fld
71
72     @WriteInTmpDir
73     def testOverlapDEC_2D_py_1(self):
74         """ The main method of the test """
75         size = MPI.COMM_WORLD.size
76         rank = MPI.COMM_WORLD.rank
77         if size != 4:
78             raise RuntimeError("Should be run on 4 procs!")
79
80         # Define (single) processor group - note the difference with InterpKernelDEC which needs two groups.
81         proc_group = list(range(size))   # No need for ProcessorGroup object here.
82         odec = OverlapDEC(proc_group)
83
84         # Write out full size meshes/fields for inspection
85         if rank == 0:
86             _, fld = self.generateFullSource()
87             mshT = self.generateFullTarget()
88             WriteField("./source_field_FULL.med", fld, True)
89             WriteUMesh("./target_mesh_FULL.med", mshT, True)
90
91         MPI.COMM_WORLD.Barrier()  # really necessary??
92
93         #
94         # OK, let's go DEC !!
95         #
96         _, fieldS = self.getPartialSource(rank)
97         fieldS.setNature(IntensiveMaximum)   # The only policy supported for now ...
98         mshT, fieldT = self.getPartialTarget(rank)
99         fieldT.setNature(IntensiveMaximum)
100         if rank not in [2,3]:
101             WriteField("./source_field_part_%d.med" % rank, fieldS, True)
102         WriteUMesh("./target_mesh_part_%d.med" % rank, mshT, True)
103
104         odec.attachSourceLocalField(fieldS)
105         odec.attachTargetLocalField(fieldT)
106         odec.synchronize()
107         odec.sendRecvData()
108
109         # Now the actual checks:
110         if rank == 0:
111             self.assertEqual(fieldT.getArray().getValues(), [1.0])
112         elif rank == 1:
113             self.assertEqual(fieldT.getArray().getValues(), [5.0])
114         elif rank == 2:
115             self.assertEqual(fieldT.getArray().getValues(), [9.0])
116         elif rank == 3:
117             self.assertEqual(fieldT.getArray().getValues(), [13.0])
118
119         # Release DEC (this involves MPI exchanges -- notably the release of the communicator -- so better be done before MPI.Finalize()
120         odec.release()
121
122         MPI.COMM_WORLD.Barrier()
123
124 if __name__ == "__main__":
125     unittest.main()
126     MPI.Finalize()