Salome HOME
OverlapDEC: bug fix. Bounding box adjustment was negative.
[modules/med.git] / src / ParaMEDMEM / OverlapElementLocator.cxx
index 51560e14579c4738e995336b73315ad8443d8047..134fc400835f5521464e7ac6402d013470f92423 100644 (file)
@@ -39,20 +39,24 @@ using namespace std;
 
 namespace ParaMEDMEM 
 { 
-  OverlapElementLocator::OverlapElementLocator(const ParaFIELD *sourceField, const ParaFIELD *targetField, const ProcessorGroup& group)
+  const int OverlapElementLocator::START_TAG_MESH_XCH = 1140;
+
+  OverlapElementLocator::OverlapElementLocator(const ParaFIELD *sourceField, const ParaFIELD *targetField,
+                                               const ProcessorGroup& group, double epsAbs)
     : _local_source_field(sourceField),
       _local_target_field(targetField),
       _local_source_mesh(0),
       _local_target_mesh(0),
       _domain_bounding_boxes(0),
-      _group(group)
+      _group(group),
+      _epsAbs(epsAbs)
   { 
     if(_local_source_field)
       _local_source_mesh=_local_source_field->getSupport()->getCellMesh();
     if(_local_target_field)
       _local_target_mesh=_local_target_field->getSupport()->getCellMesh();
     _comm=getCommunicator();
-    computeBoundingBoxes();
+    computeBoundingBoxesAndTodoList();
   }
 
   OverlapElementLocator::~OverlapElementLocator()
@@ -66,7 +70,7 @@ namespace ParaMEDMEM
     return group->getComm();
   }
 
-  void OverlapElementLocator::computeBoundingBoxes()
+  void OverlapElementLocator::computeBoundingBoxesAndTodoList()
   {
     CommInterface comm_interface=_group.getCommInterface();
     const MPIProcessorGroup* group=static_cast<const MPIProcessorGroup*> (&_group);
@@ -113,19 +117,21 @@ namespace ParaMEDMEM
       for(int j=0;j<_group.size();j++)
         {
           if(intersectsBoundingBox(i,j))
+            {
             _proc_pairs[i].push_back(j);
+//            std::cout << "("  << _group.myRank() << ") PROC pair: " << i << "," << j << std::endl;
+            }
         }
-
     // OK now let's assigning as balanced as possible, job to each proc of group
-    std::vector< std::vector< std::pair<int,int> > > pairsToBeDonePerProc(_group.size());
+    std::vector< std::vector< ProcCouple > > pairsToBeDonePerProc(_group.size());
     int i=0;
     for(std::vector< std::vector< int > >::const_iterator it1=_proc_pairs.begin();it1!=_proc_pairs.end();it1++,i++)
       for(std::vector< int >::const_iterator it2=(*it1).begin();it2!=(*it1).end();it2++)
         {
           if(pairsToBeDonePerProc[i].size()<=pairsToBeDonePerProc[*it2].size())//it includes the fact that i==*it2
-            pairsToBeDonePerProc[i].push_back(std::pair<int,int>(i,*it2));
+            pairsToBeDonePerProc[i].push_back(ProcCouple(i,*it2));
           else
-            pairsToBeDonePerProc[*it2].push_back(std::pair<int,int>(i,*it2));
+            pairsToBeDonePerProc[*it2].push_back(ProcCouple(i,*it2));
         }
     //Keeping todo list of current proc. _to_do_list contains a set of pair where at least _group.myRank() appears once.
     //This proc will be in charge to perform interpolation of any of element of '_to_do_list'
@@ -135,20 +141,32 @@ namespace ParaMEDMEM
     int myProcId=_group.myRank();
     _to_do_list=pairsToBeDonePerProc[myProcId];
 
-    //Feeding now '_procs_to_send'. A same id can appears twice. The second parameter in pair means what to send true=source, false=target
-    _procs_to_send.clear();
+//    std::stringstream scout;
+//    scout << "(" << myProcId << ") my TODO list is: ";
+//    for (std::vector< ProcCouple >::const_iterator itdbg=_to_do_list.begin(); itdbg!=_to_do_list.end(); itdbg++)
+//      scout << "(" << (*itdbg).first << "," << (*itdbg).second << ")";
+//    std::cout << scout.str() << "\n";
+
+    // Feeding now '_procs_to_send*'. A same id can appears twice. The second parameter in pair means what
+    // to send true=source, false=target
+    _procs_to_send_mesh.clear();
+    _procs_to_send_field.clear();
     for(int i=_group.size()-1;i>=0;i--)
-      if(i!=myProcId)
-        {
-          const std::vector< std::pair<int,int> >& anRemoteProcToDoList=pairsToBeDonePerProc[i];
-          for(std::vector< std::pair<int,int> >::const_iterator it=anRemoteProcToDoList.begin();it!=anRemoteProcToDoList.end();it++)
-            {
-              if((*it).first==myProcId)
-                _procs_to_send.push_back(std::pair<int,bool>(i,true));
-              if((*it).second==myProcId)
-                _procs_to_send.push_back(std::pair<int,bool>(i,false));
-            }
-        }
+      {
+        const std::vector< ProcCouple >& anRemoteProcToDoList=pairsToBeDonePerProc[i];
+        for(std::vector< ProcCouple >::const_iterator it=anRemoteProcToDoList.begin();it!=anRemoteProcToDoList.end();it++)
+          {
+            if((*it).first==myProcId)
+              {
+                if(i!=myProcId)
+                  _procs_to_send_mesh.push_back(Proc_SrcOrTgt(i,true));
+                _procs_to_send_field.push_back((*it).second);
+              }
+            if((*it).second==myProcId)
+              if(i!=myProcId)
+                _procs_to_send_mesh.push_back(Proc_SrcOrTgt(i,false));
+          }
+      }
   }
 
   /*!
@@ -159,39 +177,40 @@ namespace ParaMEDMEM
   {
     int myProcId=_group.myRank();
     //starting to receive every procs whose id is lower than myProcId.
-    std::vector< std::pair<int,int> > toDoListForFetchRemaining;
-    for(std::vector< std::pair<int,int> >::const_iterator it=_to_do_list.begin();it!=_to_do_list.end();it++)
+    std::vector< ProcCouple > toDoListForFetchRemaining;
+    for(std::vector< ProcCouple >::const_iterator it=_to_do_list.begin();it!=_to_do_list.end();it++)
       {
-        if((*it).first!=(*it).second)
+        int first = (*it).first, second = (*it).second;
+        if(first!=second)
           {
-            if((*it).first==myProcId)
+            if(first==myProcId)
               {
-                if((*it).second<myProcId)
-                  receiveRemoteMesh((*it).second,false);
+                if(second<myProcId)
+                  receiveRemoteMeshFrom(second,false);
                 else
-                  toDoListForFetchRemaining.push_back(std::pair<int,int>((*it).first,(*it).second));
+                  toDoListForFetchRemaining.push_back(ProcCouple(first,second));
               }
             else
               {//(*it).second==myProcId
-                if((*it).first<myProcId)
-                  receiveRemoteMesh((*it).first,true);
+                if(first<myProcId)
+                  receiveRemoteMeshFrom(first,true);
                 else
-                  toDoListForFetchRemaining.push_back(std::pair<int,int>((*it).first,(*it).second));
+                  toDoListForFetchRemaining.push_back(ProcCouple(first,second));
               }
           }
       }
     //sending source or target mesh to remote procs
-    for(std::vector< std::pair<int,bool> >::const_iterator it2=_procs_to_send.begin();it2!=_procs_to_send.end();it2++)
+    for(std::vector< Proc_SrcOrTgt >::const_iterator it2=_procs_to_send_mesh.begin();it2!=_procs_to_send_mesh.end();it2++)
       sendLocalMeshTo((*it2).first,(*it2).second,matrix);
     //fetching remaining meshes
-    for(std::vector< std::pair<int,int> >::const_iterator it=toDoListForFetchRemaining.begin();it!=toDoListForFetchRemaining.end();it++)
+    for(std::vector< ProcCouple >::const_iterator it=toDoListForFetchRemaining.begin();it!=toDoListForFetchRemaining.end();it++)
       {
         if((*it).first!=(*it).second)
           {
             if((*it).first==myProcId)
-              receiveRemoteMesh((*it).second,false);
+              receiveRemoteMeshFrom((*it).second,false);
             else//(*it).second==myProcId
-              receiveRemoteMesh((*it).first,true);
+              receiveRemoteMeshFrom((*it).first,true);
           }
       }
   }
@@ -211,8 +230,8 @@ namespace ParaMEDMEM
     int myProcId=_group.myRank();
     if(myProcId==procId)
       return _local_source_mesh;
-    std::pair<int,bool> p(procId,true);
-    std::map<std::pair<int,bool>, MEDCouplingAutoRefCountObjectPtr< MEDCouplingPointSet > >::const_iterator it=_remote_meshes.find(p);
+    Proc_SrcOrTgt p(procId,true);
+    std::map<Proc_SrcOrTgt, AutoMCPointSet >::const_iterator it=_remote_meshes.find(p);
     return (*it).second;
   }
 
@@ -221,8 +240,8 @@ namespace ParaMEDMEM
     int myProcId=_group.myRank();
     if(myProcId==procId)
       return 0;
-    std::pair<int,bool> p(procId,true);
-    std::map<std::pair<int,bool>, MEDCouplingAutoRefCountObjectPtr< DataArrayInt > >::const_iterator it=_remote_elems.find(p);
+    Proc_SrcOrTgt p(procId,true);
+    std::map<Proc_SrcOrTgt, AutoDAInt >::const_iterator it=_remote_elems.find(p);
     return (*it).second;
   }
 
@@ -231,8 +250,8 @@ namespace ParaMEDMEM
     int myProcId=_group.myRank();
     if(myProcId==procId)
       return _local_target_mesh;
-    std::pair<int,bool> p(procId,false);
-    std::map<std::pair<int,bool>, MEDCouplingAutoRefCountObjectPtr< MEDCouplingPointSet > >::const_iterator it=_remote_meshes.find(p);
+    Proc_SrcOrTgt p(procId,false);
+    std::map<Proc_SrcOrTgt, AutoMCPointSet >::const_iterator it=_remote_meshes.find(p);
     return (*it).second;
   }
 
@@ -241,11 +260,12 @@ namespace ParaMEDMEM
     int myProcId=_group.myRank();
     if(myProcId==procId)
       return 0;
-    std::pair<int,bool> p(procId,false);
-    std::map<std::pair<int,bool>, MEDCouplingAutoRefCountObjectPtr< DataArrayInt > >::const_iterator it=_remote_elems.find(p);
+    Proc_SrcOrTgt p(procId,false);
+    std::map<Proc_SrcOrTgt, AutoDAInt >::const_iterator it=_remote_elems.find(p);
     return (*it).second;
   }
 
+
   bool OverlapElementLocator::intersectsBoundingBox(int isource, int itarget) const
   {
     const double *source_bb=_domain_bounding_boxes+isource*2*2*_local_space_dim;
@@ -253,9 +273,8 @@ namespace ParaMEDMEM
 
     for (int idim=0; idim < _local_space_dim; idim++)
       {
-        const double eps = -1e-12;//tony to change
-        bool intersects = (target_bb[idim*2]<source_bb[idim*2+1]+eps)
-          && (source_bb[idim*2]<target_bb[idim*2+1]+eps);
+        bool intersects = (target_bb[idim*2]<source_bb[idim*2+1]+_epsAbs)
+          && (source_bb[idim*2]<target_bb[idim*2+1]+_epsAbs);
         if (!intersects)
           return false; 
       }
@@ -263,8 +282,8 @@ namespace ParaMEDMEM
   }
 
   /*!
-   * This methods sends local source if 'sourceOrTarget'==True to proc 'procId'.
-   * This methods sends local target if 'sourceOrTarget'==False to proc 'procId'.
+   * This methods sends (part of) local source if 'sourceOrTarget'==True to proc 'procId'.
+   * This methods sends (part of) local target if 'sourceOrTarget'==False to proc 'procId'.
    *
    * This method prepares the matrix too, for matrix assembling and future matrix-vector computation.
    */
@@ -274,7 +293,7 @@ namespace ParaMEDMEM
    const double *distant_bb=0;
    MEDCouplingPointSet *local_mesh=0;
    const ParaFIELD *field=0;
-   if(sourceOrTarget)//source for local but target for distant
+   if(sourceOrTarget)//source for local mesh but target for distant mesh
      {
        distant_bb=_domain_bounding_boxes+procId*2*2*_local_space_dim+2*_local_space_dim;
        local_mesh=_local_source_mesh;
@@ -286,35 +305,36 @@ namespace ParaMEDMEM
        local_mesh=_local_target_mesh;
        field=_local_target_field;
      }
-   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=local_mesh->getCellsInBoundingBox(distant_bb,getBoundingBoxAdjustment());
-   DataArrayInt *idsToSend;
-   MEDCouplingPointSet *send_mesh=static_cast<MEDCouplingPointSet *>(field->getField()->buildSubMeshData(elems->begin(),elems->end(),idsToSend));
+   AutoDAInt elems=local_mesh->getCellsInBoundingBox(distant_bb,getBoundingBoxAdjustment());
+   DataArrayInt *old2new_map;
+   MEDCouplingPointSet *send_mesh=static_cast<MEDCouplingPointSet *>(field->getField()->buildSubMeshData(elems->begin(),elems->end(),old2new_map));
    if(sourceOrTarget)
-     matrix.keepTracksOfSourceIds(procId,idsToSend);//Case#1 in Step2 of main algorithm.
+     matrix.keepTracksOfSourceIds(procId,old2new_map);
    else
-     matrix.keepTracksOfTargetIds(procId,idsToSend);//Case#0 in Step2 of main algorithm.
-   sendMesh(procId,send_mesh,idsToSend);
+     matrix.keepTracksOfTargetIds(procId,old2new_map);
+   sendMesh(procId,send_mesh,old2new_map);
    send_mesh->decrRef();
-   idsToSend->decrRef();
+   old2new_map->decrRef();
   }
 
   /*!
    * This method recieves source remote mesh on proc 'procId' if sourceOrTarget==True
    * This method recieves target remote mesh on proc 'procId' if sourceOrTarget==False
    */
-  void OverlapElementLocator::receiveRemoteMesh(int procId, bool sourceOrTarget)
+  void OverlapElementLocator::receiveRemoteMeshFrom(int procId, bool sourceOrTarget)
   {
-    DataArrayInt *da=0;
+    DataArrayInt *old2new_map=0;
     MEDCouplingPointSet *m=0;
-    receiveMesh(procId,m,da);
-    std::pair<int,bool> p(procId,sourceOrTarget);
+    receiveMesh(procId,m,old2new_map);
+    Proc_SrcOrTgt p(procId,sourceOrTarget);
     _remote_meshes[p]=m;
-    _remote_elems[p]=da;
+    _remote_elems[p]=old2new_map;
   }
 
   void OverlapElementLocator::sendMesh(int procId, const MEDCouplingPointSet *mesh, const DataArrayInt *idsToSend) const
   {
     CommInterface comInterface=_group.getCommInterface();
+
     // First stage : exchanging sizes
     vector<double> tinyInfoLocalD;//tinyInfoLocalD not used for the moment
     vector<int> tinyInfoLocal;
@@ -325,16 +345,16 @@ namespace ParaMEDMEM
     int lgth[2];
     lgth[0]=tinyInfoLocal.size();
     lgth[1]=idsToSend->getNbOfElems();
-    comInterface.send(&lgth,2,MPI_INT,procId,1140,*_comm);
-    comInterface.send(&tinyInfoLocal[0],tinyInfoLocal.size(),MPI_INT,procId,1141,*comm);
+    comInterface.send(&lgth,2,MPI_INT,procId,START_TAG_MESH_XCH,*_comm);
+    comInterface.send(&tinyInfoLocal[0],tinyInfoLocal.size(),MPI_INT,procId,START_TAG_MESH_XCH+1,*comm);
     //
     DataArrayInt *v1Local=0;
     DataArrayDouble *v2Local=0;
     mesh->serialize(v1Local,v2Local);
-    comInterface.send(v1Local->getPointer(),v1Local->getNbOfElems(),MPI_INT,procId,1142,*comm);
-    comInterface.send(v2Local->getPointer(),v2Local->getNbOfElems(),MPI_DOUBLE,procId,1143,*comm);
+    comInterface.send(v1Local->getPointer(),v1Local->getNbOfElems(),MPI_INT,procId,START_TAG_MESH_XCH+2,*comm);
+    comInterface.send(v2Local->getPointer(),v2Local->getNbOfElems(),MPI_DOUBLE,procId,START_TAG_MESH_XCH+3,*comm);
     //finished for mesh, ids now
-    comInterface.send(const_cast<int *>(idsToSend->getConstPointer()),lgth[1],MPI_INT,procId,1144,*comm);
+    comInterface.send(const_cast<int *>(idsToSend->getConstPointer()),lgth[1],MPI_INT,procId,START_TAG_MESH_XCH+4,*comm);
     //
     v1Local->decrRef();
     v2Local->decrRef();
@@ -346,19 +366,19 @@ namespace ParaMEDMEM
     MPI_Status status;
     const MPI_Comm *comm=getCommunicator();
     CommInterface comInterface=_group.getCommInterface();
-    comInterface.recv(lgth,2,MPI_INT,procId,1140,*_comm,&status);
+    comInterface.recv(lgth,2,MPI_INT,procId,START_TAG_MESH_XCH,*_comm,&status);
     std::vector<int> tinyInfoDistant(lgth[0]);
     ids=DataArrayInt::New();
     ids->alloc(lgth[1],1);
-    comInterface.recv(&tinyInfoDistant[0],lgth[0],MPI_INT,procId,1141,*comm,&status);
+    comInterface.recv(&tinyInfoDistant[0],lgth[0],MPI_INT,procId,START_TAG_MESH_XCH+1,*comm,&status);
     mesh=MEDCouplingPointSet::BuildInstanceFromMeshType((MEDCouplingMeshType)tinyInfoDistant[0]);
     std::vector<std::string> unusedTinyDistantSts;
     vector<double> tinyInfoDistantD(1);//tinyInfoDistantD not used for the moment
     DataArrayInt *v1Distant=DataArrayInt::New();
     DataArrayDouble *v2Distant=DataArrayDouble::New();
     mesh->resizeForUnserialization(tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
-    comInterface.recv(v1Distant->getPointer(),v1Distant->getNbOfElems(),MPI_INT,procId,1142,*comm,&status);
-    comInterface.recv(v2Distant->getPointer(),v2Distant->getNbOfElems(),MPI_DOUBLE,procId,1143,*comm,&status);
+    comInterface.recv(v1Distant->getPointer(),v1Distant->getNbOfElems(),MPI_INT,procId,START_TAG_MESH_XCH+2,*comm,&status);
+    comInterface.recv(v2Distant->getPointer(),v2Distant->getNbOfElems(),MPI_DOUBLE,procId,START_TAG_MESH_XCH+3,*comm,&status);
     mesh->unserialization(tinyInfoDistantD,tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
     //finished for mesh, ids now
     comInterface.recv(ids->getPointer(),lgth[1],MPI_INT,procId,1144,*comm,&status);