]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/ParaMEDMEM/MxN_Mapping.cxx
Salome HOME
Merge from BR_V5_DEV 16Feb09
[tools/medcoupling.git] / src / ParaMEDMEM / MxN_Mapping.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D
2 //
3 //  This library is free software; you can redistribute it and/or
4 //  modify it under the terms of the GNU Lesser General Public
5 //  License as published by the Free Software Foundation; either
6 //  version 2.1 of the License.
7 //
8 //  This library is distributed in the hope that it will be useful,
9 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 //  Lesser General Public License for more details.
12 //
13 //  You should have received a copy of the GNU Lesser General Public
14 //  License along with this library; if not, write to the Free Software
15 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include "CommInterface.hxx" 
20 #include "ProcessorGroup.hxx"
21 #include "MPIProcessorGroup.hxx"
22 #include "MPIAccessDEC.hxx"
23 #include "MxN_Mapping.hxx"
24
25 using namespace std;
26
27 namespace ParaMEDMEM
28 {
29
30   MxN_Mapping::MxN_Mapping(const ProcessorGroup& source_group, const ProcessorGroup& target_group,const DECOptions& dec_options)
31     : _union_group(source_group.fuse(target_group)),
32       DECOptions(dec_options)
33   {
34     _access_DEC = new MPIAccessDEC(source_group,target_group,getAsynchronous());
35     _access_DEC->setTimeInterpolator(getTimeInterpolationMethod());
36     _send_proc_offsets.resize(_union_group->size()+1,0);
37     _recv_proc_offsets.resize(_union_group->size()+1,0);
38   
39   }
40
41   MxN_Mapping::~MxN_Mapping()
42   {
43     delete _union_group;
44     delete _access_DEC;
45   }
46
47
48   /*!
49     Method registering a new element for correspondence with a distant element
50     \param distant_proc proc rank of the distant processor (in terms of the union group)
51     \param distant_element id of the element on the distant processor
52   */
53   void MxN_Mapping::addElementFromSource(int distant_proc, int distant_element)
54   {
55     _sending_ids.push_back(make_pair(distant_proc,distant_element));
56     for (int i=distant_proc; i<_union_group->size(); i++)
57       _send_proc_offsets[i+1]++;
58   }
59
60   void MxN_Mapping::prepareSendRecv()
61   {
62     CommInterface comm_interface=_union_group->getCommInterface();
63     // sending count pattern
64     int* nbsend=new int[_union_group->size()];
65     int* nbrecv=new int[_union_group->size()];
66     for (int i=0; i<_union_group->size(); i++)
67       {
68         nbsend[i]=_send_proc_offsets[i+1]-_send_proc_offsets[i];
69       }
70   
71     MPIProcessorGroup* group = static_cast<MPIProcessorGroup*>(_union_group);
72     const MPI_Comm* comm=group->getComm();
73     comm_interface.allToAll(nbsend, 1, MPI_INT,
74                             nbrecv, 1, MPI_INT,
75                             *comm);
76          
77     for (int i=0; i<_union_group->size(); i++)
78       {
79         for (int j=i+1;j<_union_group->size()+1; j++)
80           _recv_proc_offsets[j]+=nbrecv[i];
81     
82       } 
83
84     delete[] nbsend;
85     delete[] nbrecv;
86
87     _recv_ids.resize(_recv_proc_offsets[_union_group->size()]);
88     int* isendbuf=0;
89     int* irecvbuf=0;
90     if (_sending_ids.size()>0)
91       isendbuf = new int[_sending_ids.size()];
92     if (_recv_ids.size()>0)  
93       irecvbuf = new int[_recv_ids.size()];
94     int* sendcounts = new int[_union_group->size()];
95     int* senddispls=new int[_union_group->size()];
96     int* recvcounts=new int[_union_group->size()];
97     int* recvdispls=new int[_union_group->size()];
98     for (int i=0; i< _union_group->size(); i++)
99       {
100         sendcounts[i]=_send_proc_offsets[i+1]-_send_proc_offsets[i];
101         senddispls[i]=_send_proc_offsets[i];
102         recvcounts[i]=_recv_proc_offsets[i+1]-_recv_proc_offsets[i];
103         recvdispls[i]=_recv_proc_offsets[i];
104       }
105     vector<int> offsets = _send_proc_offsets;
106     for (int i=0; i<_sending_ids.size();i++)
107       {
108         int iproc = _sending_ids[i].first;
109         isendbuf[offsets[iproc]]=_sending_ids[i].second;
110         offsets[iproc]++;
111       }
112     comm_interface.allToAllV(isendbuf, sendcounts, senddispls, MPI_INT,
113                              irecvbuf, recvcounts, recvdispls, MPI_INT,
114                              *comm);
115                            
116     for (int i=0; i< _recv_proc_offsets[_union_group->size()]; i++)
117       _recv_ids[i]=irecvbuf[i];                           
118  
119     if (_sending_ids.size()>0)
120       delete[] isendbuf;
121     if (_recv_ids.size()>0)  
122       delete[] irecvbuf;
123     delete[] sendcounts;
124     delete[]recvcounts;
125     delete[]senddispls;
126     delete[] recvdispls;
127   }
128
129   /*! Exchanging field data between two groups of processes
130    * 
131    * \param field MEDCoupling field containing the values to be sent
132    * 
133    * The ids that were defined by addElementFromSource method
134    * are sent.
135    */ 
136   void MxN_Mapping::sendRecv(double* sendfield, MEDCouplingFieldDouble& field) const 
137   {
138     CommInterface comm_interface=_union_group->getCommInterface();
139     const MPIProcessorGroup* group = static_cast<const MPIProcessorGroup*>(_union_group);
140  
141     int nbcomp=field.getArray()->getNumberOfComponents();
142     double* sendbuf=0;
143     double* recvbuf=0;
144     if (_sending_ids.size() >0)
145       sendbuf = new double[_sending_ids.size()*nbcomp];
146     if (_recv_ids.size()>0)
147       recvbuf = new double[_recv_ids.size()*nbcomp];
148     
149     int* sendcounts = new int[_union_group->size()];
150     int* senddispls=new int[_union_group->size()];
151     int* recvcounts=new int[_union_group->size()];
152     int* recvdispls=new int[_union_group->size()];
153   
154     for (int i=0; i< _union_group->size(); i++)
155       {
156         sendcounts[i]=nbcomp*(_send_proc_offsets[i+1]-_send_proc_offsets[i]);
157         senddispls[i]=nbcomp*(_send_proc_offsets[i]);
158         recvcounts[i]=nbcomp*(_recv_proc_offsets[i+1]-_recv_proc_offsets[i]);
159         recvdispls[i]=nbcomp*(_recv_proc_offsets[i]);
160       }
161     //building the buffer of the elements to be sent
162     vector<int> offsets = _send_proc_offsets;
163
164     for (int i=0; i<_sending_ids.size();i++)
165       { 
166         int iproc = _sending_ids[i].first;
167         for (int icomp=0; icomp<nbcomp; icomp++)
168           sendbuf[offsets[iproc]*nbcomp+icomp]=sendfield[i*nbcomp+icomp];
169         offsets[iproc]++;
170       }
171   
172     //communication phase
173     switch (getAllToAllMethod())
174       {
175       case Native:
176         {
177           const MPI_Comm* comm = group->getComm();
178           comm_interface.allToAllV(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
179                                    recvbuf, recvcounts, recvdispls, MPI_DOUBLE,
180                                    *comm);
181         }
182         break;
183       case PointToPoint:
184         _access_DEC->allToAllv(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
185                               recvbuf, recvcounts, recvdispls, MPI_DOUBLE);
186         break;
187       }
188   
189     //setting the received values in the field
190     DataArrayDouble *fieldArr=field.getArray();
191     double* recvptr=recvbuf;                         
192     for (int i=0; i< _recv_proc_offsets[_union_group->size()]; i++)
193       {
194         for (int icomp=0; icomp<nbcomp; icomp++)
195           {
196             double temp = fieldArr->getIJ(_recv_ids[i],icomp);
197             fieldArr->setIJ(_recv_ids[i],icomp,temp+*recvptr);
198             recvptr++;
199           }
200       }   
201     if (sendbuf!=0 && getAllToAllMethod()== Native)
202       delete[] sendbuf;
203     if (recvbuf !=0)
204       delete[] recvbuf;
205     delete[] sendcounts;
206     delete[] recvcounts;
207     delete[] senddispls; 
208     delete[] recvdispls;
209   
210   }
211
212   /*! Exchanging field data between two groups of processes
213    * 
214    * \param field MEDCoupling field containing the values to be sent
215    * 
216    * The ids that were defined by addElementFromSource method
217    * are sent.
218    */ 
219   void MxN_Mapping::reverseSendRecv(double* recvfield, MEDCouplingFieldDouble& field) const 
220   {
221     CommInterface comm_interface=_union_group->getCommInterface();
222     const MPIProcessorGroup* group = static_cast<const MPIProcessorGroup*>(_union_group);
223
224     int nbcomp=field.getArray()->getNumberOfComponents();
225     double* sendbuf=0;
226     double* recvbuf=0;
227     if (_recv_ids.size() >0)
228       sendbuf = new double[_recv_ids.size()*nbcomp];
229     if (_sending_ids.size()>0)
230       recvbuf = new double[_sending_ids.size()*nbcomp];
231
232     int* sendcounts = new int[_union_group->size()];
233     int* senddispls=new int[_union_group->size()];
234     int* recvcounts=new int[_union_group->size()];
235     int* recvdispls=new int[_union_group->size()];
236
237     for (int i=0; i< _union_group->size(); i++)
238       {
239         sendcounts[i]=nbcomp*(_recv_proc_offsets[i+1]-_recv_proc_offsets[i]);
240         senddispls[i]=nbcomp*(_recv_proc_offsets[i]);
241         recvcounts[i]=nbcomp*(_send_proc_offsets[i+1]-_send_proc_offsets[i]);
242         recvdispls[i]=nbcomp*(_send_proc_offsets[i]);
243       }
244     //building the buffer of the elements to be sent
245     vector<int> offsets = _recv_proc_offsets;
246     DataArrayDouble *fieldArr=field.getArray();
247     for (int iproc=0; iproc<_union_group->size();iproc++)
248       for (int i=_recv_proc_offsets[iproc]; i<_recv_proc_offsets[iproc+1]; i++)
249         {
250           for (int icomp=0; icomp<nbcomp; icomp++)
251             sendbuf[i*nbcomp+icomp]=fieldArr->getIJ(_recv_ids[i],icomp);
252         }
253
254     //communication phase
255     switch (getAllToAllMethod())
256       {
257       case Native:
258         {
259           const MPI_Comm* comm = group->getComm();
260           comm_interface.allToAllV(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
261                                    recvbuf, recvcounts, recvdispls, MPI_DOUBLE,
262                                    *comm);
263         }
264         break;
265       case PointToPoint:
266         _access_DEC->allToAllv(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
267                                recvbuf, recvcounts, recvdispls, MPI_DOUBLE);
268         break;
269       }
270
271     //setting the received values in the field
272     double* recvptr=recvbuf;                         
273     for (int i=0; i< _send_proc_offsets[_union_group->size()]; i++)
274       {
275         for (int icomp=0; icomp<nbcomp; icomp++)
276           {
277             recvfield[i*nbcomp+icomp]=*recvptr;
278             recvptr++;
279           }
280       }
281     if (sendbuf!=0 && getAllToAllMethod() == Native)
282       delete[] sendbuf;
283     if (recvbuf!=0)
284       delete[] recvbuf;
285     delete[] sendcounts;
286     delete[] recvcounts;
287     delete[] senddispls; 
288     delete[] recvdispls;
289   }
290
291
292   ostream & operator<< (ostream & f ,const AllToAllMethod & alltoallmethod )
293   {
294     switch (alltoallmethod)
295       {
296       case Native :
297         f << " Native ";
298         break;
299       case PointToPoint :
300         f << " PointToPoint ";
301         break;
302       default :
303         f << " UnknownAllToAllMethod ";
304         break;
305       }
306     return f;
307   }
308 }