1 // Copyright (C) 2007-2015 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, or (at your option) any later version.
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 // Author : Anthony Geay (CEA/DEN)
21 #include "OverlapMapping.hxx"
22 #include "MPIProcessorGroup.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
27 #include "InterpKernelAutoPtr.hxx"
32 using namespace ParaMEDMEM;
34 OverlapMapping::OverlapMapping(const ProcessorGroup& group):_group(group)
39 * This method keeps tracks of source ids to know in step 6 of main algorithm, which tuple ids to send away.
40 * This method incarnates item#1 of step2 algorithm.
42 void OverlapMapping::keepTracksOfSourceIds(int procId, DataArrayInt *ids)
45 _src_ids_st2.push_back(ids);
46 _src_proc_st2.push_back(procId);
50 * This method keeps tracks of target ids to know in step 6 of main algorithm.
51 * This method incarnates item#0 of step2 algorithm.
53 void OverlapMapping::keepTracksOfTargetIds(int procId, DataArrayInt *ids)
56 _trg_ids_st2.push_back(ids);
57 _trg_proc_st2.push_back(procId);
61 * This method stores from a matrix in format Target(rows)/Source(cols) for a source procId 'srcProcId' and for a target procId 'trgProcId'.
62 * All ids (source and target) are in format of local ids.
64 void OverlapMapping::addContributionST(const std::vector< std::map<int,double> >& matrixST, const DataArrayInt *srcIds, int srcProcId, const DataArrayInt *trgIds, int trgProcId)
66 _matrixes_st.push_back(matrixST);
67 _source_proc_id_st.push_back(srcProcId);
68 _target_proc_id_st.push_back(trgProcId);
70 {//item#1 of step2 algorithm in proc m. Only to know in advanced nb of recv ids [ (0,1) computed on proc1 and Matrix-Vector on proc1 ]
71 _nb_of_src_ids_proc_st2.push_back(srcIds->getNumberOfTuples());
72 _src_ids_proc_st2.push_back(srcProcId);
75 {//item#0 of step2 algorithm in proc k
77 for(std::vector< std::map<int,double> >::const_iterator it1=matrixST.begin();it1!=matrixST.end();it1++)
78 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
79 s.insert((*it2).first);
80 _src_ids_zip_st2.resize(_src_ids_zip_st2.size()+1);
81 _src_ids_zip_st2.back().insert(_src_ids_zip_st2.back().end(),s.begin(),s.end());
82 _src_ids_zip_proc_st2.push_back(trgProcId);
87 * 'procsInInteraction' gives the global view of interaction between procs.
88 * In 'procsInInteraction' for a proc with id i, is in interaction with procs listed in procsInInteraction[i].
90 * This method is in charge to send matrixes in AlltoAll mode.
91 * After the call of this method 'this' contains the matrixST for all source elements of the current proc
93 void OverlapMapping::prepare(const std::vector< std::vector<int> >& procsInInteraction, int nbOfTrgElems)
95 CommInterface commInterface=_group.getCommInterface();
96 const MPIProcessorGroup *group=static_cast<const MPIProcessorGroup*>(&_group);
97 const MPI_Comm *comm=group->getComm();
98 int grpSize=_group.size();
99 INTERP_KERNEL::AutoPtr<int> nbsend=new int[grpSize];
100 INTERP_KERNEL::AutoPtr<int> nbsend2=new int[grpSize];
101 INTERP_KERNEL::AutoPtr<int> nbsend3=new int[grpSize];
102 std::fill<int *>(nbsend,nbsend+grpSize,0);
103 int myProcId=_group.myRank();
104 _proc_ids_to_recv_vector_st.clear();
106 for(std::vector< std::vector<int> >::const_iterator it1=procsInInteraction.begin();it1!=procsInInteraction.end();it1++,curProc++)
107 if(std::find((*it1).begin(),(*it1).end(),myProcId)!=(*it1).end())
108 _proc_ids_to_recv_vector_st.push_back(curProc);
109 _proc_ids_to_send_vector_st=procsInInteraction[myProcId];
110 for(std::size_t i=0;i<_matrixes_st.size();i++)
111 if(_source_proc_id_st[i]==myProcId)
112 nbsend[_target_proc_id_st[i]]=_matrixes_st[i].size();
113 INTERP_KERNEL::AutoPtr<int> nbrecv=new int[grpSize];
114 commInterface.allToAll(nbsend,1,MPI_INT,nbrecv,1,MPI_INT,*comm);
116 //first exchanging offsets+ids_source
117 INTERP_KERNEL::AutoPtr<int> nbrecv1=new int[grpSize];
118 INTERP_KERNEL::AutoPtr<int> nbrecv2=new int[grpSize];
121 serializeMatrixStep0ST(nbrecv,
124 INTERP_KERNEL::AutoPtr<int> bigArr=tmp;
125 INTERP_KERNEL::AutoPtr<int> bigArrRecv=new int[nbrecv2[grpSize-1]+nbrecv1[grpSize-1]];
126 commInterface.allToAllV(bigArr,nbsend2,nbsend3,MPI_INT,
127 bigArrRecv,nbrecv1,nbrecv2,MPI_INT,
128 *comm);// sending ids of sparse matrix (n+1 elems)
129 //second phase echange target ids
130 std::fill<int *>(nbsend2,nbsend2+grpSize,0);
131 INTERP_KERNEL::AutoPtr<int> nbrecv3=new int[grpSize];
132 INTERP_KERNEL::AutoPtr<int> nbrecv4=new int[grpSize];
134 int lgthOfArr=serializeMatrixStep1ST(nbrecv,bigArrRecv,nbrecv1,nbrecv2,
136 nbsend2,nbsend3,nbrecv3,nbrecv4);
137 INTERP_KERNEL::AutoPtr<int> bigArr2=tmp;
138 INTERP_KERNEL::AutoPtr<double> bigArrD2=tmp2;
139 INTERP_KERNEL::AutoPtr<int> bigArrRecv2=new int[lgthOfArr];
140 INTERP_KERNEL::AutoPtr<double> bigArrDRecv2=new double[lgthOfArr];
141 commInterface.allToAllV(bigArr2,nbsend2,nbsend3,MPI_INT,
142 bigArrRecv2,nbrecv3,nbrecv4,MPI_INT,
144 commInterface.allToAllV(bigArrD2,nbsend2,nbsend3,MPI_DOUBLE,
145 bigArrDRecv2,nbrecv3,nbrecv4,MPI_DOUBLE,
148 unserializationST(nbOfTrgElems,nbrecv,bigArrRecv,nbrecv1,nbrecv2,
149 bigArrRecv2,bigArrDRecv2,nbrecv3,nbrecv4);
150 //updating _src_ids_zip_st2 and _src_ids_zip_st2 with received matrix.
151 updateZipSourceIdsForFuture();
152 //finish to fill _the_matrix_st with already in place matrix in _matrixes_st
153 finishToFillFinalMatrixST();
158 * Compute denominators.
160 void OverlapMapping::computeDenoGlobConstraint()
162 _the_deno_st.clear();
163 std::size_t sz1=_the_matrix_st.size();
164 _the_deno_st.resize(sz1);
165 for(std::size_t i=0;i<sz1;i++)
167 std::size_t sz2=_the_matrix_st[i].size();
168 _the_deno_st[i].resize(sz2);
169 for(std::size_t j=0;j<sz2;j++)
172 std::map<int,double>& mToFill=_the_deno_st[i][j];
173 const std::map<int,double>& m=_the_matrix_st[i][j];
174 for(std::map<int,double>::const_iterator it=m.begin();it!=m.end();it++)
176 for(std::map<int,double>::const_iterator it=m.begin();it!=m.end();it++)
177 mToFill[(*it).first]=sum;
183 * Compute denominators.
185 void OverlapMapping::computeDenoConservativeVolumic(int nbOfTuplesTrg)
187 CommInterface commInterface=_group.getCommInterface();
188 int myProcId=_group.myRank();
190 _the_deno_st.clear();
191 std::size_t sz1=_the_matrix_st.size();
192 _the_deno_st.resize(sz1);
193 std::vector<double> deno(nbOfTuplesTrg);
194 for(std::size_t i=0;i<sz1;i++)
196 const std::vector< std::map<int,double> >& mat=_the_matrix_st[i];
197 int curSrcId=_the_matrix_st_source_proc_id[i];
198 std::vector<int>::iterator isItem1=std::find(_trg_proc_st2.begin(),_trg_proc_st2.end(),curSrcId);
200 if(isItem1==_trg_proc_st2.end() || curSrcId==myProcId)//item1 of step2 main algo. Simple, because rowId of mat are directly target ids.
202 for(std::vector< std::map<int,double> >::const_iterator it1=mat.begin();it1!=mat.end();it1++,rowId++)
203 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
204 deno[rowId]+=(*it2).second;
207 {//item0 of step2 main algo. More complicated.
208 std::vector<int>::iterator fnd=isItem1;//std::find(_trg_proc_st2.begin(),_trg_proc_st2.end(),curSrcId);
209 int locId=std::distance(_trg_proc_st2.begin(),fnd);
210 const DataArrayInt *trgIds=_trg_ids_st2[locId];
211 const int *trgIds2=trgIds->getConstPointer();
212 for(std::vector< std::map<int,double> >::const_iterator it1=mat.begin();it1!=mat.end();it1++,rowId++)
213 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
214 deno[trgIds2[rowId]]+=(*it2).second;
218 for(std::size_t i=0;i<sz1;i++)
221 const std::vector< std::map<int,double> >& mat=_the_matrix_st[i];
222 int curSrcId=_the_matrix_st_source_proc_id[i];
223 std::vector<int>::iterator isItem1=std::find(_trg_proc_st2.begin(),_trg_proc_st2.end(),curSrcId);
224 std::vector< std::map<int,double> >& denoM=_the_deno_st[i];
225 denoM.resize(mat.size());
226 if(isItem1==_trg_proc_st2.end() || curSrcId==myProcId)//item1 of step2 main algo. Simple, because rowId of mat are directly target ids.
229 for(std::vector< std::map<int,double> >::const_iterator it1=mat.begin();it1!=mat.end();it1++,rowId++)
230 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
231 denoM[rowId][(*it2).first]=deno[rowId];
235 std::vector<int>::iterator fnd=isItem1;
236 int locId=std::distance(_trg_proc_st2.begin(),fnd);
237 const DataArrayInt *trgIds=_trg_ids_st2[locId];
238 const int *trgIds2=trgIds->getConstPointer();
239 for(std::vector< std::map<int,double> >::const_iterator it1=mat.begin();it1!=mat.end();it1++,rowId++)
240 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
241 denoM[rowId][(*it2).first]=deno[trgIds2[rowId]];
247 * This method performs step #0/3 in serialization process.
248 * \param count tells specifies nb of elems to send to corresponding proc id. size equal to _group.size().
249 * \param offsets tells for a proc i where to start serialize#0 matrix. size equal to _group.size().
250 * \param nbOfElemsSrc of size _group.size(). Comes from previous all2all call. tells how many srcIds per proc contains matrix for current proc.
252 void OverlapMapping::serializeMatrixStep0ST(const int *nbOfElemsSrc, int *&bigArr, int *count, int *offsets,
253 int *countForRecv, int *offsetsForRecv) const
255 int grpSize=_group.size();
256 std::fill<int *>(count,count+grpSize,0);
258 int myProcId=_group.myRank();
259 for(std::size_t i=0;i<_matrixes_st.size();i++)
261 if(_source_proc_id_st[i]==myProcId)// && _target_proc_id_st[i]!=myProcId
263 count[_target_proc_id_st[i]]=_matrixes_st[i].size()+1;
264 szz+=_matrixes_st[i].size()+1;
269 for(int i=1;i<grpSize;i++)
270 offsets[i]=offsets[i-1]+count[i-1];
271 for(std::size_t i=0;i<_matrixes_st.size();i++)
273 if(_source_proc_id_st[i]==myProcId)
275 int start=offsets[_target_proc_id_st[i]];
276 int *work=bigArr+start;
278 const std::vector< std::map<int,double> >& mat=_matrixes_st[i];
279 for(std::vector< std::map<int,double> >::const_iterator it=mat.begin();it!=mat.end();it++,work++)
280 work[1]=work[0]+(*it).size();
285 for(int i=0;i<grpSize;i++)
287 if(nbOfElemsSrc[i]>0)
288 countForRecv[i]=nbOfElemsSrc[i]+1;
292 offsetsForRecv[i]=offsetsForRecv[i-1]+countForRecv[i-1];
297 * This method performs step#1 and step#2/3. It returns the size of expected array to get allToAllV.
299 int OverlapMapping::serializeMatrixStep1ST(const int *nbOfElemsSrc, const int *recvStep0, const int *countStep0, const int *offsStep0,
300 int *&bigArrI, double *&bigArrD, int *count, int *offsets,
301 int *countForRecv, int *offsForRecv) const
303 int grpSize=_group.size();
304 int myProcId=_group.myRank();
307 for(int i=0;i<grpSize;i++)
309 if(nbOfElemsSrc[i]!=0)
310 countForRecv[i]=recvStep0[offsStep0[i]+nbOfElemsSrc[i]];
313 szz+=countForRecv[i];
315 offsForRecv[i]=offsForRecv[i-1]+countForRecv[i-1];
318 std::fill(count,count+grpSize,0);
321 for(std::size_t i=0;i<_matrixes_st.size();i++)
323 if(_source_proc_id_st[i]==myProcId)
325 const std::vector< std::map<int,double> >& mat=_matrixes_st[i];
327 for(std::vector< std::map<int,double> >::const_iterator it=mat.begin();it!=mat.end();it++)
328 lgthToSend+=(*it).size();
329 count[_target_proc_id_st[i]]=lgthToSend;
330 fullLgth+=lgthToSend;
333 for(int i=1;i<grpSize;i++)
334 offsets[i]=offsets[i-1]+count[i-1];
336 bigArrI=new int[fullLgth];
337 bigArrD=new double[fullLgth];
340 for(std::size_t i=0;i<_matrixes_st.size();i++)
342 if(_source_proc_id_st[i]==myProcId)
344 const std::vector< std::map<int,double> >& mat=_matrixes_st[i];
345 for(std::vector< std::map<int,double> >::const_iterator it1=mat.begin();it1!=mat.end();it1++)
348 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++,j++)
350 bigArrI[fullLgth+j]=(*it2).first;
351 bigArrD[fullLgth+j]=(*it2).second;
353 fullLgth+=(*it1).size();
361 * This is the last step after all2Alls for matrix exchange.
362 * _the_matrix_st is the final matrix :
363 * - The first entry is srcId in current proc.
364 * - The second is the pseudo id of source proc (correspondance with true id is in attribute _the_matrix_st_source_proc_id and _the_matrix_st_source_ids)
365 * - the third is the srcId in the pseudo source proc
367 void OverlapMapping::unserializationST(int nbOfTrgElems,
368 const int *nbOfElemsSrcPerProc,//first all2all
369 const int *bigArrRecv, const int *bigArrRecvCounts, const int *bigArrRecvOffs,//2nd all2all
370 const int *bigArrRecv2, const double *bigArrDRecv2, const int *bigArrRecv2Count, const int *bigArrRecv2Offs)//3rd and 4th all2alls
372 _the_matrix_st.clear();
373 _the_matrix_st_source_proc_id.clear();
375 int grpSize=_group.size();
376 for(int i=0;i<grpSize;i++)
377 if(nbOfElemsSrcPerProc[i]!=0)
378 _the_matrix_st_source_proc_id.push_back(i);
379 int nbOfPseudoProcs=_the_matrix_st_source_proc_id.size();//_the_matrix_st_target_proc_id.size() contains number of matrix fetched remotely whose sourceProcId==myProcId
380 _the_matrix_st.resize(nbOfPseudoProcs);
383 for(int i=0;i<grpSize;i++)
384 if(nbOfElemsSrcPerProc[i]!=0)
386 _the_matrix_st[j].resize(nbOfElemsSrcPerProc[i]);
387 for(int k=0;k<nbOfElemsSrcPerProc[i];k++)
389 int offs=bigArrRecv[bigArrRecvOffs[i]+k];
390 int lgthOfMap=bigArrRecv[bigArrRecvOffs[i]+k+1]-offs;
391 for(int l=0;l<lgthOfMap;l++)
392 _the_matrix_st[j][k][bigArrRecv2[bigArrRecv2Offs[i]+offs+l]]=bigArrDRecv2[bigArrRecv2Offs[i]+offs+l];
399 * This method should be called when all remote matrix with sourceProcId==thisProcId have been retrieved and are in 'this->_the_matrix_st' and 'this->_the_matrix_st_target_proc_id'
400 * and 'this->_the_matrix_st_target_ids'.
401 * This method finish the job of filling 'this->_the_matrix_st' and 'this->_the_matrix_st_target_proc_id' by putting candidates in 'this->_matrixes_st' into them.
403 void OverlapMapping::finishToFillFinalMatrixST()
405 int myProcId=_group.myRank();
406 int sz=_matrixes_st.size();
407 int nbOfEntryToAdd=0;
408 for(int i=0;i<sz;i++)
409 if(_source_proc_id_st[i]!=myProcId)
411 if(nbOfEntryToAdd==0)
413 int oldNbOfEntry=_the_matrix_st.size();
414 int newNbOfEntry=oldNbOfEntry+nbOfEntryToAdd;
415 _the_matrix_st.resize(newNbOfEntry);
417 for(int i=0;i<sz;i++)
418 if(_source_proc_id_st[i]!=myProcId)
420 const std::vector<std::map<int,double> >& mat=_matrixes_st[i];
421 _the_matrix_st[j]=mat;
422 _the_matrix_st_source_proc_id.push_back(_source_proc_id_st[i]);
425 _matrixes_st.clear();
429 * This method performs the operation of target ids broadcasting.
431 void OverlapMapping::prepareIdsToSendST()
433 CommInterface commInterface=_group.getCommInterface();
434 const MPIProcessorGroup *group=static_cast<const MPIProcessorGroup*>(&_group);
435 const MPI_Comm *comm=group->getComm();
436 int grpSize=_group.size();
437 _source_ids_to_send_st.clear();
438 _source_ids_to_send_st.resize(grpSize);
439 INTERP_KERNEL::AutoPtr<int> nbsend=new int[grpSize];
440 std::fill<int *>(nbsend,nbsend+grpSize,0);
441 for(std::size_t i=0;i<_the_matrix_st_source_proc_id.size();i++)
442 nbsend[_the_matrix_st_source_proc_id[i]]=_the_matrix_st_source_ids[i].size();
443 INTERP_KERNEL::AutoPtr<int> nbrecv=new int[grpSize];
444 commInterface.allToAll(nbsend,1,MPI_INT,nbrecv,1,MPI_INT,*comm);
446 INTERP_KERNEL::AutoPtr<int> nbsend2=new int[grpSize];
447 std::copy((int *)nbsend,((int *)nbsend)+grpSize,(int *)nbsend2);
448 INTERP_KERNEL::AutoPtr<int> nbsend3=new int[grpSize];
450 for(int i=1;i<grpSize;i++)
451 nbsend3[i]=nbsend3[i-1]+nbsend2[i-1];
452 int sendSz=nbsend3[grpSize-1]+nbsend2[grpSize-1];
453 INTERP_KERNEL::AutoPtr<int> bigDataSend=new int[sendSz];
454 for(std::size_t i=0;i<_the_matrix_st_source_proc_id.size();i++)
456 int offset=nbsend3[_the_matrix_st_source_proc_id[i]];
457 std::copy(_the_matrix_st_source_ids[i].begin(),_the_matrix_st_source_ids[i].end(),((int *)nbsend3)+offset);
459 INTERP_KERNEL::AutoPtr<int> nbrecv2=new int[grpSize];
460 INTERP_KERNEL::AutoPtr<int> nbrecv3=new int[grpSize];
461 std::copy((int *)nbrecv,((int *)nbrecv)+grpSize,(int *)nbrecv2);
463 for(int i=1;i<grpSize;i++)
464 nbrecv3[i]=nbrecv3[i-1]+nbrecv2[i-1];
465 int recvSz=nbrecv3[grpSize-1]+nbrecv2[grpSize-1];
466 INTERP_KERNEL::AutoPtr<int> bigDataRecv=new int[recvSz];
468 commInterface.allToAllV(bigDataSend,nbsend2,nbsend3,MPI_INT,
469 bigDataRecv,nbrecv2,nbrecv3,MPI_INT,
471 for(int i=0;i<grpSize;i++)
475 _source_ids_to_send_st[i].insert(_source_ids_to_send_st[i].end(),((int *)bigDataRecv)+nbrecv3[i],((int *)bigDataRecv)+nbrecv3[i]+nbrecv2[i]);
481 * This method performs a transpose multiply of 'fieldInput' and put the result into 'fieldOutput'.
482 * 'fieldInput' is expected to be the sourcefield and 'fieldOutput' the targetfield.
484 void OverlapMapping::multiply(const MEDCouplingFieldDouble *fieldInput, MEDCouplingFieldDouble *fieldOutput) const
486 int nbOfCompo=fieldInput->getNumberOfComponents();//to improve same number of components to test
487 CommInterface commInterface=_group.getCommInterface();
488 const MPIProcessorGroup *group=static_cast<const MPIProcessorGroup*>(&_group);
489 const MPI_Comm *comm=group->getComm();
490 int grpSize=_group.size();
491 int myProcId=_group.myRank();
493 INTERP_KERNEL::AutoPtr<int> nbsend=new int[grpSize];
494 INTERP_KERNEL::AutoPtr<int> nbsend2=new int[grpSize];
495 INTERP_KERNEL::AutoPtr<int> nbrecv=new int[grpSize];
496 INTERP_KERNEL::AutoPtr<int> nbrecv2=new int[grpSize];
497 std::fill<int *>(nbsend,nbsend+grpSize,0);
498 std::fill<int *>(nbrecv,nbrecv+grpSize,0);
501 std::vector<double> valsToSend;
502 for(int i=0;i<grpSize;i++)
504 if(std::find(_proc_ids_to_send_vector_st.begin(),_proc_ids_to_send_vector_st.end(),i)!=_proc_ids_to_send_vector_st.end())
506 std::vector<int>::const_iterator isItem1=std::find(_src_proc_st2.begin(),_src_proc_st2.end(),i);
507 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> vals;
508 if(isItem1!=_src_proc_st2.end())//item1 of step2 main algo
510 int id=std::distance(_src_proc_st2.begin(),isItem1);
511 vals=fieldInput->getArray()->selectByTupleId(_src_ids_st2[id]->getConstPointer(),_src_ids_st2[id]->getConstPointer()+_src_ids_st2[id]->getNumberOfTuples());
514 {//item0 of step2 main algo
515 int id=std::distance(_src_ids_zip_proc_st2.begin(),std::find(_src_ids_zip_proc_st2.begin(),_src_ids_zip_proc_st2.end(),i));
516 vals=fieldInput->getArray()->selectByTupleId(&(_src_ids_zip_st2[id])[0],&(_src_ids_zip_st2[id])[0]+_src_ids_zip_st2[id].size());
518 nbsend[i]=vals->getNbOfElems();
519 valsToSend.insert(valsToSend.end(),vals->getConstPointer(),vals->getConstPointer()+nbsend[i]);
521 if(std::find(_proc_ids_to_recv_vector_st.begin(),_proc_ids_to_recv_vector_st.end(),i)!=_proc_ids_to_recv_vector_st.end())
523 std::vector<int>::const_iterator isItem0=std::find(_trg_proc_st2.begin(),_trg_proc_st2.end(),i);
524 if(isItem0==_trg_proc_st2.end())//item1 of step2 main algo [ (0,1) computed on proc1 and Matrix-Vector on proc1 ]
526 std::vector<int>::const_iterator it1=std::find(_src_ids_proc_st2.begin(),_src_ids_proc_st2.end(),i);
527 if(it1!=_src_ids_proc_st2.end())
529 int id=std::distance(_src_ids_proc_st2.begin(),it1);
530 nbrecv[i]=_nb_of_src_ids_proc_st2[id]*nbOfCompo;
534 nbrecv[i]=fieldInput->getNumberOfTuplesExpected()*nbOfCompo;
537 throw INTERP_KERNEL::Exception("Plouff ! send email to anthony.geay@cea.fr ! ");
540 {//item0 of step2 main algo [ (2,1) computed on proc2 but Matrix-Vector on proc1 ] [(1,0) computed on proc1 but Matrix-Vector on proc0]
541 int id=std::distance(_src_ids_zip_proc_st2.begin(),std::find(_src_ids_zip_proc_st2.begin(),_src_ids_zip_proc_st2.end(),i));
542 nbrecv[i]=_src_ids_zip_st2[id].size()*nbOfCompo;
546 for(int i=1;i<grpSize;i++)
548 nbsend2[i]=nbsend2[i-1]+nbsend[i-1];
549 nbrecv2[i]=nbrecv2[i-1]+nbrecv[i-1];
551 INTERP_KERNEL::AutoPtr<double> bigArr=new double[nbrecv2[grpSize-1]+nbrecv[grpSize-1]];
552 commInterface.allToAllV(&valsToSend[0],nbsend,nbsend2,MPI_DOUBLE,
553 bigArr,nbrecv,nbrecv2,MPI_DOUBLE,*comm);
554 fieldOutput->getArray()->fillWithZero();
555 INTERP_KERNEL::AutoPtr<double> tmp=new double[nbOfCompo];
556 for(int i=0;i<grpSize;i++)
560 double *pt=fieldOutput->getArray()->getPointer();
561 std::vector<int>::const_iterator it=std::find(_the_matrix_st_source_proc_id.begin(),_the_matrix_st_source_proc_id.end(),i);
562 if(it==_the_matrix_st_source_proc_id.end())
563 throw INTERP_KERNEL::Exception("Big problem !");
564 int id=std::distance(_the_matrix_st_source_proc_id.begin(),it);
565 const std::vector< std::map<int,double> >& mat=_the_matrix_st[id];
566 const std::vector< std::map<int,double> >& deno=_the_deno_st[id];
567 std::vector<int>::const_iterator isItem0=std::find(_trg_proc_st2.begin(),_trg_proc_st2.end(),i);
568 if(isItem0==_trg_proc_st2.end())//item1 of step2 main algo [ (0,1) computed on proc1 and Matrix-Vector on proc1 ]
570 int nbOfTrgTuples=mat.size();
571 for(int j=0;j<nbOfTrgTuples;j++,pt+=nbOfCompo)
573 const std::map<int,double>& mat1=mat[j];
574 const std::map<int,double>& deno1=deno[j];
575 std::map<int,double>::const_iterator it4=deno1.begin();
576 for(std::map<int,double>::const_iterator it3=mat1.begin();it3!=mat1.end();it3++,it4++)
578 std::transform(bigArr+nbrecv2[i]+((*it3).first)*nbOfCompo,bigArr+nbrecv2[i]+((*it3).first+1)*(nbOfCompo),(double *)tmp,std::bind2nd(std::multiplies<double>(),(*it3).second/(*it4).second));
579 std::transform((double *)tmp,(double *)tmp+nbOfCompo,pt,pt,std::plus<double>());
584 {//item0 of step2 main algo [ (2,1) computed on proc2 but Matrix-Vector on proc1 ]
585 double *pt=fieldOutput->getArray()->getPointer();
586 std::map<int,int> zipCor;
587 int id=std::distance(_src_ids_zip_proc_st2.begin(),std::find(_src_ids_zip_proc_st2.begin(),_src_ids_zip_proc_st2.end(),i));
588 const std::vector<int> zipIds=_src_ids_zip_st2[id];
590 for(std::vector<int>::const_iterator it=zipIds.begin();it!=zipIds.end();it++,newId++)
592 int id2=std::distance(_trg_proc_st2.begin(),std::find(_trg_proc_st2.begin(),_trg_proc_st2.end(),i));
593 const DataArrayInt *tgrIds=_trg_ids_st2[id2];
594 const int *tgrIds2=tgrIds->getConstPointer();
595 int nbOfTrgTuples=mat.size();
596 for(int j=0;j<nbOfTrgTuples;j++)
598 const std::map<int,double>& mat1=mat[j];
599 const std::map<int,double>& deno1=deno[j];
600 std::map<int,double>::const_iterator it5=deno1.begin();
601 for(std::map<int,double>::const_iterator it3=mat1.begin();it3!=mat1.end();it3++,it5++)
603 std::map<int,int>::const_iterator it4=zipCor.find((*it3).first);
604 if(it4==zipCor.end())
605 throw INTERP_KERNEL::Exception("Hmmmmm send e mail to anthony.geay@cea.fr !");
606 std::transform(bigArr+nbrecv2[i]+((*it4).second)*nbOfCompo,bigArr+nbrecv2[i]+((*it4).second+1)*(nbOfCompo),(double *)tmp,std::bind2nd(std::multiplies<double>(),(*it3).second/(*it5).second));
607 std::transform((double *)tmp,(double *)tmp+nbOfCompo,pt+tgrIds2[j]*nbOfCompo,pt+tgrIds2[j]*nbOfCompo,std::plus<double>());
616 * This method performs a transpose multiply of 'fieldInput' and put the result into 'fieldOutput'.
617 * 'fieldInput' is expected to be the targetfield and 'fieldOutput' the sourcefield.
619 void OverlapMapping::transposeMultiply(const MEDCouplingFieldDouble *fieldInput, MEDCouplingFieldDouble *fieldOutput)
624 * This method should be called immediately after _the_matrix_st has been filled with remote computed matrix put in this proc for Matrix-Vector.
625 * This method computes for these matrix the minimal set of source ids corresponding to the source proc id.
627 void OverlapMapping::updateZipSourceIdsForFuture()
629 CommInterface commInterface=_group.getCommInterface();
630 int myProcId=_group.myRank();
631 int nbOfMatrixRecveived=_the_matrix_st_source_proc_id.size();
632 for(int i=0;i<nbOfMatrixRecveived;i++)
634 int curSrcProcId=_the_matrix_st_source_proc_id[i];
635 if(curSrcProcId!=myProcId)
637 const std::vector< std::map<int,double> >& mat=_the_matrix_st[i];
638 _src_ids_zip_proc_st2.push_back(curSrcProcId);
639 _src_ids_zip_st2.resize(_src_ids_zip_st2.size()+1);
641 for(std::vector< std::map<int,double> >::const_iterator it1=mat.begin();it1!=mat.end();it1++)
642 for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
643 s.insert((*it2).first);
644 _src_ids_zip_st2.back().insert(_src_ids_zip_st2.back().end(),s.begin(),s.end());
649 // #include <iostream>
651 // void OverlapMapping::printTheMatrix() const
653 // CommInterface commInterface=_group.getCommInterface();
654 // const MPIProcessorGroup *group=static_cast<const MPIProcessorGroup*>(&_group);
655 // const MPI_Comm *comm=group->getComm();
656 // int grpSize=_group.size();
657 // int myProcId=_group.myRank();
658 // std::cerr << "I am proc #" << myProcId << std::endl;
659 // int nbOfMat=_the_matrix_st.size();
660 // std::cerr << "I do manage " << nbOfMat << "matrix : "<< std::endl;
661 // for(int i=0;i<nbOfMat;i++)
663 // std::cerr << " - Matrix #" << i << " on source proc #" << _the_matrix_st_source_proc_id[i];
664 // const std::vector< std::map<int,double> >& locMat=_the_matrix_st[i];
665 // for(std::vector< std::map<int,double> >::const_iterator it1=locMat.begin();it1!=locMat.end();it1++)
667 // for(std::map<int,double>::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
668 // std::cerr << "(" << (*it2).first << "," << (*it2).second << "), ";
669 // std::cerr << std::endl;
672 // std::cerr << "*********" << std::endl;