Back to index

salome-med  6.5.0
MxN_Mapping.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "CommInterface.hxx" 
00021 #include "ProcessorGroup.hxx"
00022 #include "MPIProcessorGroup.hxx"
00023 #include "MPIAccessDEC.hxx"
00024 #include "MxN_Mapping.hxx"
00025 
00026 using namespace std;
00027 
00028 namespace ParaMEDMEM
00029 {
00030   MxN_Mapping::MxN_Mapping()
00031   {
00032   }
00033 
00034 
00035   MxN_Mapping::MxN_Mapping(const ProcessorGroup& source_group, const ProcessorGroup& target_group,const DECOptions& dec_options)
00036     : DECOptions(dec_options),_union_group(source_group.fuse(target_group))
00037   {
00038     _access_DEC = new MPIAccessDEC(source_group,target_group,getAsynchronous());
00039     _access_DEC->setTimeInterpolator(getTimeInterpolationMethod());
00040     _send_proc_offsets.resize(_union_group->size()+1,0);
00041     _recv_proc_offsets.resize(_union_group->size()+1,0);
00042   
00043   }
00044 
00045   MxN_Mapping::~MxN_Mapping()
00046   {
00047     delete _union_group;
00048     delete _access_DEC;
00049   }
00050 
00051 
00057   void MxN_Mapping::addElementFromSource(int distant_proc, int distant_element)
00058   {
00059     _sending_ids.push_back(make_pair(distant_proc,distant_element));
00060     for (int i=distant_proc; i<_union_group->size(); i++)
00061       _send_proc_offsets[i+1]++;
00062   }
00063 
00064   void MxN_Mapping::initialize()
00065   {
00066     _sending_ids.clear();
00067     std::fill(_send_proc_offsets.begin(),_send_proc_offsets.end(),0);
00068   }
00069 
00070   void MxN_Mapping::prepareSendRecv()
00071   {
00072     CommInterface comm_interface=_union_group->getCommInterface();
00073     // sending count pattern
00074     int* nbsend=new int[_union_group->size()];
00075     int* nbrecv=new int[_union_group->size()];
00076     for (int i=0; i<_union_group->size(); i++)
00077       {
00078         nbsend[i]=_send_proc_offsets[i+1]-_send_proc_offsets[i];
00079       }
00080   
00081     MPIProcessorGroup* group = static_cast<MPIProcessorGroup*>(_union_group);
00082     const MPI_Comm* comm=group->getComm();
00083     comm_interface.allToAll(nbsend, 1, MPI_INT,
00084                             nbrecv, 1, MPI_INT,
00085                             *comm);
00086          
00087     for (int i=0; i<_union_group->size(); i++)
00088       {
00089         for (int j=i+1;j<_union_group->size()+1; j++)
00090           _recv_proc_offsets[j]+=nbrecv[i];
00091     
00092       } 
00093 
00094     delete[] nbsend;
00095     delete[] nbrecv;
00096 
00097     _recv_ids.resize(_recv_proc_offsets[_union_group->size()]);
00098     int* isendbuf=0;
00099     int* irecvbuf=0;
00100     if (_sending_ids.size()>0)
00101       isendbuf = new int[_sending_ids.size()];
00102     if (_recv_ids.size()>0)  
00103       irecvbuf = new int[_recv_ids.size()];
00104     int* sendcounts = new int[_union_group->size()];
00105     int* senddispls=new int[_union_group->size()];
00106     int* recvcounts=new int[_union_group->size()];
00107     int* recvdispls=new int[_union_group->size()];
00108     for (int i=0; i< _union_group->size(); i++)
00109       {
00110         sendcounts[i]=_send_proc_offsets[i+1]-_send_proc_offsets[i];
00111         senddispls[i]=_send_proc_offsets[i];
00112         recvcounts[i]=_recv_proc_offsets[i+1]-_recv_proc_offsets[i];
00113         recvdispls[i]=_recv_proc_offsets[i];
00114       }
00115     vector<int> offsets = _send_proc_offsets;
00116     for (int i=0; i<(int)_sending_ids.size();i++)
00117       {
00118         int iproc = _sending_ids[i].first;
00119         isendbuf[offsets[iproc]]=_sending_ids[i].second;
00120         offsets[iproc]++;
00121       }
00122     comm_interface.allToAllV(isendbuf, sendcounts, senddispls, MPI_INT,
00123                              irecvbuf, recvcounts, recvdispls, MPI_INT,
00124                              *comm);
00125                            
00126     for (int i=0; i< _recv_proc_offsets[_union_group->size()]; i++)
00127       _recv_ids[i]=irecvbuf[i];                           
00128  
00129     if (_sending_ids.size()>0)
00130       delete[] isendbuf;
00131     if (_recv_ids.size()>0)  
00132       delete[] irecvbuf;
00133     delete[] sendcounts;
00134     delete[]recvcounts;
00135     delete[]senddispls;
00136     delete[] recvdispls;
00137   }
00138 
00146   void MxN_Mapping::sendRecv(double* sendfield, MEDCouplingFieldDouble& field) const 
00147   {
00148     CommInterface comm_interface=_union_group->getCommInterface();
00149     const MPIProcessorGroup* group = static_cast<const MPIProcessorGroup*>(_union_group);
00150  
00151     int nbcomp=field.getArray()->getNumberOfComponents();
00152     double* sendbuf=0;
00153     double* recvbuf=0;
00154     if (_sending_ids.size() >0)
00155       sendbuf = new double[_sending_ids.size()*nbcomp];
00156     if (_recv_ids.size()>0)
00157       recvbuf = new double[_recv_ids.size()*nbcomp];
00158     
00159     int* sendcounts = new int[_union_group->size()];
00160     int* senddispls=new int[_union_group->size()];
00161     int* recvcounts=new int[_union_group->size()];
00162     int* recvdispls=new int[_union_group->size()];
00163   
00164     for (int i=0; i< _union_group->size(); i++)
00165       {
00166         sendcounts[i]=nbcomp*(_send_proc_offsets[i+1]-_send_proc_offsets[i]);
00167         senddispls[i]=nbcomp*(_send_proc_offsets[i]);
00168         recvcounts[i]=nbcomp*(_recv_proc_offsets[i+1]-_recv_proc_offsets[i]);
00169         recvdispls[i]=nbcomp*(_recv_proc_offsets[i]);
00170       }
00171     //building the buffer of the elements to be sent
00172     vector<int> offsets = _send_proc_offsets;
00173 
00174     for (int i=0; i<(int)_sending_ids.size();i++)
00175       { 
00176         int iproc = _sending_ids[i].first;
00177         for (int icomp=0; icomp<nbcomp; icomp++)
00178           sendbuf[offsets[iproc]*nbcomp+icomp]=sendfield[i*nbcomp+icomp];
00179         offsets[iproc]++;
00180       }
00181   
00182     //communication phase
00183     switch (getAllToAllMethod())
00184       {
00185       case Native:
00186         {
00187           const MPI_Comm* comm = group->getComm();
00188           comm_interface.allToAllV(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
00189                                    recvbuf, recvcounts, recvdispls, MPI_DOUBLE,
00190                                    *comm);
00191         }
00192         break;
00193       case PointToPoint:
00194         _access_DEC->allToAllv(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
00195                               recvbuf, recvcounts, recvdispls, MPI_DOUBLE);
00196         break;
00197       }
00198   
00199     //setting the received values in the field
00200     DataArrayDouble *fieldArr=field.getArray();
00201     double* recvptr=recvbuf;                         
00202     for (int i=0; i< _recv_proc_offsets[_union_group->size()]; i++)
00203       {
00204         for (int icomp=0; icomp<nbcomp; icomp++)
00205           {
00206             double temp = fieldArr->getIJ(_recv_ids[i],icomp);
00207             fieldArr->setIJ(_recv_ids[i],icomp,temp+*recvptr);
00208             recvptr++;
00209           }
00210       }   
00211     if (sendbuf!=0 && getAllToAllMethod()== Native)
00212       delete[] sendbuf;
00213     if (recvbuf !=0)
00214       delete[] recvbuf;
00215     delete[] sendcounts;
00216     delete[] recvcounts;
00217     delete[] senddispls; 
00218     delete[] recvdispls;
00219   
00220   }
00221 
00229   void MxN_Mapping::reverseSendRecv(double* recvfield, MEDCouplingFieldDouble& field) const 
00230   {
00231     CommInterface comm_interface=_union_group->getCommInterface();
00232     const MPIProcessorGroup* group = static_cast<const MPIProcessorGroup*>(_union_group);
00233 
00234     int nbcomp=field.getArray()->getNumberOfComponents();
00235     double* sendbuf=0;
00236     double* recvbuf=0;
00237     if (_recv_ids.size() >0)
00238       sendbuf = new double[_recv_ids.size()*nbcomp];
00239     if (_sending_ids.size()>0)
00240       recvbuf = new double[_sending_ids.size()*nbcomp];
00241 
00242     int* sendcounts = new int[_union_group->size()];
00243     int* senddispls=new int[_union_group->size()];
00244     int* recvcounts=new int[_union_group->size()];
00245     int* recvdispls=new int[_union_group->size()];
00246 
00247     for (int i=0; i< _union_group->size(); i++)
00248       {
00249         sendcounts[i]=nbcomp*(_recv_proc_offsets[i+1]-_recv_proc_offsets[i]);
00250         senddispls[i]=nbcomp*(_recv_proc_offsets[i]);
00251         recvcounts[i]=nbcomp*(_send_proc_offsets[i+1]-_send_proc_offsets[i]);
00252         recvdispls[i]=nbcomp*(_send_proc_offsets[i]);
00253       }
00254     //building the buffer of the elements to be sent
00255     vector<int> offsets = _recv_proc_offsets;
00256     DataArrayDouble *fieldArr=field.getArray();
00257     for (int iproc=0; iproc<_union_group->size();iproc++)
00258       for (int i=_recv_proc_offsets[iproc]; i<_recv_proc_offsets[iproc+1]; i++)
00259         {
00260           for (int icomp=0; icomp<nbcomp; icomp++)
00261             sendbuf[i*nbcomp+icomp]=fieldArr->getIJ(_recv_ids[i],icomp);
00262         }
00263 
00264     //communication phase
00265     switch (getAllToAllMethod())
00266       {
00267       case Native:
00268         {
00269           const MPI_Comm* comm = group->getComm();
00270           comm_interface.allToAllV(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
00271                                    recvbuf, recvcounts, recvdispls, MPI_DOUBLE,
00272                                    *comm);
00273         }
00274         break;
00275       case PointToPoint:
00276         _access_DEC->allToAllv(sendbuf, sendcounts, senddispls, MPI_DOUBLE,
00277                                recvbuf, recvcounts, recvdispls, MPI_DOUBLE);
00278         break;
00279       }
00280 
00281     //setting the received values in the field
00282     double* recvptr=recvbuf;                         
00283     for (int i=0; i< _send_proc_offsets[_union_group->size()]; i++)
00284       {
00285         for (int icomp=0; icomp<nbcomp; icomp++)
00286           {
00287             recvfield[i*nbcomp+icomp]=*recvptr;
00288             recvptr++;
00289           }
00290       }
00291     if (sendbuf!=0 && getAllToAllMethod() == Native)
00292       delete[] sendbuf;
00293     if (recvbuf!=0)
00294       delete[] recvbuf;
00295     delete[] sendcounts;
00296     delete[] recvcounts;
00297     delete[] senddispls; 
00298     delete[] recvdispls;
00299   }
00300 
00301   ostream & operator<< (ostream & f ,const AllToAllMethod & alltoallmethod )
00302   {
00303     switch (alltoallmethod)
00304       {
00305       case Native :
00306         f << " Native ";
00307         break;
00308       case PointToPoint :
00309         f << " PointToPoint ";
00310         break;
00311       default :
00312         f << " UnknownAllToAllMethod ";
00313         break;
00314       }
00315     return f;
00316   }
00317 }