1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include "CommInterface.hxx"
20 #include "ProcessorGroup.hxx"
21 #include "MPIProcessorGroup.hxx"
22 #include "MPIAccessDEC.hxx"
23 #include "MxN_Mapping.hxx"
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)
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);
41 MxN_Mapping::~MxN_Mapping()
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
53 void MxN_Mapping::addElementFromSource(int distant_proc, int distant_element)
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]++;
60 void MxN_Mapping::prepareSendRecv()
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++)
68 nbsend[i]=_send_proc_offsets[i+1]-_send_proc_offsets[i];
71 MPIProcessorGroup* group = static_cast<MPIProcessorGroup*>(_union_group);
72 const MPI_Comm* comm=group->getComm();
73 comm_interface.allToAll(nbsend, 1, MPI_INT,
77 for (int i=0; i<_union_group->size(); i++)
79 for (int j=i+1;j<_union_group->size()+1; j++)
80 _recv_proc_offsets[j]+=nbrecv[i];
87 _recv_ids.resize(_recv_proc_offsets[_union_group->size()]);
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++)
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];
105 vector<int> offsets = _send_proc_offsets;
106 for (int i=0; i<_sending_ids.size();i++)
108 int iproc = _sending_ids[i].first;
109 isendbuf[offsets[iproc]]=_sending_ids[i].second;
112 comm_interface.allToAllV(isendbuf, sendcounts, senddispls, MPI_INT,
113 irecvbuf, recvcounts, recvdispls, MPI_INT,
116 for (int i=0; i< _recv_proc_offsets[_union_group->size()]; i++)
117 _recv_ids[i]=irecvbuf[i];
119 if (_sending_ids.size()>0)
121 if (_recv_ids.size()>0)
129 /*! Exchanging field data between two groups of processes
131 * \param field MEDCoupling field containing the values to be sent
133 * The ids that were defined by addElementFromSource method
136 void MxN_Mapping::sendRecv(double* sendfield, MEDCouplingFieldDouble& field) const
138 CommInterface comm_interface=_union_group->getCommInterface();
139 const MPIProcessorGroup* group = static_cast<const MPIProcessorGroup*>(_union_group);
141 int nbcomp=field.getArray()->getNumberOfComponents();
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];
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()];
154 for (int i=0; i< _union_group->size(); i++)
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]);
161 //building the buffer of the elements to be sent
162 vector<int> offsets = _send_proc_offsets;
164 for (int i=0; i<_sending_ids.size();i++)
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];
172 //communication phase
173 switch (getAllToAllMethod())
177 const MPI_Comm* comm = group->getComm();
178 comm_interface.allToAllV(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
179 recvbuf, recvcounts, recvdispls, MPI_DOUBLE,
184 _access_DEC->allToAllv(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
185 recvbuf, recvcounts, recvdispls, MPI_DOUBLE);
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++)
194 for (int icomp=0; icomp<nbcomp; icomp++)
196 double temp = fieldArr->getIJ(_recv_ids[i],icomp);
197 fieldArr->setIJ(_recv_ids[i],icomp,temp+*recvptr);
201 if (sendbuf!=0 && getAllToAllMethod()== Native)
212 /*! Exchanging field data between two groups of processes
214 * \param field MEDCoupling field containing the values to be sent
216 * The ids that were defined by addElementFromSource method
219 void MxN_Mapping::reverseSendRecv(double* recvfield, MEDCouplingFieldDouble& field) const
221 CommInterface comm_interface=_union_group->getCommInterface();
222 const MPIProcessorGroup* group = static_cast<const MPIProcessorGroup*>(_union_group);
224 int nbcomp=field.getArray()->getNumberOfComponents();
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];
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()];
237 for (int i=0; i< _union_group->size(); i++)
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]);
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++)
250 for (int icomp=0; icomp<nbcomp; icomp++)
251 sendbuf[i*nbcomp+icomp]=fieldArr->getIJ(_recv_ids[i],icomp);
254 //communication phase
255 switch (getAllToAllMethod())
259 const MPI_Comm* comm = group->getComm();
260 comm_interface.allToAllV(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
261 recvbuf, recvcounts, recvdispls, MPI_DOUBLE,
266 _access_DEC->allToAllv(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
267 recvbuf, recvcounts, recvdispls, MPI_DOUBLE);
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++)
275 for (int icomp=0; icomp<nbcomp; icomp++)
277 recvfield[i*nbcomp+icomp]=*recvptr;
281 if (sendbuf!=0 && getAllToAllMethod() == Native)
292 ostream & operator<< (ostream & f ,const AllToAllMethod & alltoallmethod )
294 switch (alltoallmethod)
300 f << " PointToPoint ";
303 f << " UnknownAllToAllMethod ";