Back to index

salome-med  6.5.0
MEDPARTITIONER_JointFinder.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 "MEDPARTITIONER_JointFinder.hxx"
00021 #include "MEDPARTITIONER_MeshCollection.hxx"
00022 #include "MEDPARTITIONER_Topology.hxx"
00023 #include "MEDPARTITIONER_ParaDomainSelector.hxx"
00024 #include "MEDPARTITIONER_Utils.hxx"
00025 
00026 #include "MEDCouplingUMesh.hxx"
00027 #include "BBTree.txx"
00028 
00032 MEDPARTITIONER::JointFinder::JointFinder(const MeshCollection& mc):_mesh_collection(mc),_domain_selector(mc.getParaDomainSelector()),_topology(mc.getTopology())
00033 {
00034 }
00035 
00036 MEDPARTITIONER::JointFinder::~JointFinder()
00037 {
00038 }
00039 
00040 void MEDPARTITIONER::JointFinder::findCommonDistantNodes()
00041 {
00042   int nbdomain=_topology->nbDomain();
00043   _distant_node_cell.resize(nbdomain);
00044   _node_node.resize(nbdomain);
00045   for (int i=0; i<nbdomain; i++) 
00046     {
00047       _distant_node_cell[i].resize(nbdomain);
00048       _node_node[i].resize(nbdomain);
00049     }
00050   int nbproc=_domain_selector->nbProcs();
00051   std::vector<BBTree<3>* > bbtree(nbdomain,(BBTree<3>*) 0);
00052   std::vector<double* > bbxi(nbdomain,(double*) 0);
00053   std::vector<ParaMEDMEM::DataArrayInt*> rev(nbdomain,(ParaMEDMEM::DataArrayInt*) 0);
00054   std::vector<ParaMEDMEM::DataArrayInt*> revIndx(nbdomain,(ParaMEDMEM::DataArrayInt*) 0);
00055   int meshDim=-1;
00056   int spaceDim=-1;
00057   
00058   //init rev and revIndx and bbtree for my domain (of me:proc n)
00059   for (int mydomain=0; mydomain<nbdomain; mydomain++)
00060     {
00061       if(!_domain_selector->isMyDomain(mydomain))
00062         continue;
00063       const ParaMEDMEM::MEDCouplingUMesh* myMesh=_mesh_collection.getMesh(mydomain);
00064       meshDim = myMesh->getMeshDimension();
00065       spaceDim= myMesh->getSpaceDimension();
00066       rev[mydomain] = ParaMEDMEM::DataArrayInt::New();
00067       revIndx[mydomain] = ParaMEDMEM::DataArrayInt::New();
00068       myMesh->getReverseNodalConnectivity(rev[mydomain],revIndx[mydomain]);
00069       double* bbx=new double[2*spaceDim*myMesh->getNumberOfNodes()];
00070       for (int i=0; i<myMesh->getNumberOfNodes()*spaceDim; i++)
00071         {
00072           const double* coords=myMesh->getCoords()->getConstPointer();
00073           bbx[2*i]=(coords[i])-1e-12;
00074           bbx[2*i+1]=bbx[2*i]+2e-12;
00075         }
00076       bbtree[mydomain]=new BBTree<3> (bbx,0,0,myMesh->getNumberOfNodes(),-1e-12);
00077       //keep bbx because need it in getIntersectingElems
00078       //no delete [] bbx yet
00079       bbxi[mydomain]=bbx;
00080     }
00081   
00082   //send my domains to other proc an receive other domains from other proc
00083   for (int isource=0; isource<nbdomain; isource++)
00084     {
00085       for (int itarget=0; itarget<nbdomain; itarget++)
00086         {
00087           const ParaMEDMEM::MEDCouplingUMesh* sourceMesh=_mesh_collection.getMesh(isource);
00088           if (_domain_selector->isMyDomain(isource)&&_domain_selector->isMyDomain(itarget))
00089             continue;
00090           if (_domain_selector->isMyDomain(isource))
00091             {
00092               //preparing data for treatment on target proc
00093               int targetProc = _domain_selector->getProcessorID(itarget);
00094     
00095               std::vector<double> vec(spaceDim*sourceMesh->getNumberOfNodes());
00096               std::copy(sourceMesh->getCoords()->getConstPointer(),sourceMesh->getCoords()->getConstPointer()+sourceMesh->getNumberOfNodes()*spaceDim,&vec[0]);
00097               SendDoubleVec(vec,targetProc);
00098     
00099               //retrieving target data for storage in commonDistantNodes array
00100               std::vector<int> localCorrespondency;
00101               RecvIntVec(localCorrespondency, targetProc);
00102               for (std::size_t i=0; i<localCorrespondency.size()/2; i++)
00103                 {
00104                   _distant_node_cell[isource][itarget].insert(std::make_pair(localCorrespondency[2*i],localCorrespondency[2*i+1]));
00105                 }
00106     
00107             }
00108 
00109           if (_domain_selector->isMyDomain(itarget))
00110             {
00111               //receiving data from source proc
00112               int sourceProc = isource%nbproc;
00113               std::vector<double> recvVec;
00114               RecvDoubleVec(recvVec,sourceProc);
00115               std::map<int,int> commonNodes; // (local nodes, distant nodes) list
00116               for (int inode=0; inode<(recvVec.size()/spaceDim); inode++)
00117                 {
00118                   double* bbox=new double[2*spaceDim];
00119                   for (int i=0; i<spaceDim; i++)
00120                     {
00121                       bbox[2*i]=recvVec[inode*spaceDim+i]-1e-12;
00122                       bbox[2*i+1]=bbox[2*i]+2e-12;
00123                     }
00124                   std::vector<int> inodes;
00125                   bbtree[itarget]->getIntersectingElems(bbox,inodes);
00126                   delete [] bbox;
00127       
00128                   if (inodes.size()>0) 
00129                     {
00130                       commonNodes.insert(std::make_pair(inodes[0],inode));
00131                     }
00132           
00133                 }
00134               std::vector<int> nodeCellCorrespondency;
00135               for (std::map<int,int>::iterator iter=commonNodes.begin(); iter!=commonNodes.end(); iter++)
00136                 {
00137                   _node_node[itarget][isource].push_back(std::make_pair(iter->first, iter->second));//storing node pairs in a vector
00138                   const int* revIndxPtr=revIndx[itarget]->getConstPointer();
00139                   const int* revPtr=rev[itarget]->getConstPointer();
00140                   for (int icell=revIndxPtr[iter->first]; icell<revIndxPtr[iter->first+1]; icell++)
00141                     {
00142                       nodeCellCorrespondency.push_back(iter->second); //
00143                       int globalCell=_topology->convertCellToGlobal(itarget,revPtr[icell]);
00144                       nodeCellCorrespondency.push_back(globalCell);
00145                     }
00146                 }
00147               SendIntVec(nodeCellCorrespondency, sourceProc); //itarget proc send to other (otherLocalNode-itargetGlobalCell)
00148             }
00149         }
00150     }
00151     
00152   //free  rev(nbdomain) revIndx(nbdomain) bbtree(nbdomain) bbxi(nbdomain)
00153   for (int i=0; i<nbdomain; i++)
00154     {
00155       if (rev[i]!=0)
00156         rev[i]->decrRef();
00157       if (revIndx[i]!=0)
00158         revIndx[i]->decrRef();
00159       if (bbtree[i]!=0)
00160         delete bbtree[i];
00161       if (bbxi[i]!=0)
00162         delete [] bbxi[i];
00163     }
00164 
00165   if (MyGlobals::_Verbose>100) 
00166     std::cout << "proc " << _domain_selector->rank() << " : end JointFinder::findCommonDistantNodes" << std::endl;
00167 }
00168 
00169 std::vector<std::vector<std::multimap<int,int> > >& MEDPARTITIONER::JointFinder::getDistantNodeCell()
00170 {
00171   return _distant_node_cell;
00172 }
00173 
00174 std::vector<std::vector<std::vector<std::pair<int,int> > > >& MEDPARTITIONER::JointFinder::getNodeNode()
00175 {
00176   return _node_node;
00177 }
00178 
00179 void MEDPARTITIONER::JointFinder::print()
00180 //it is for debug on small arrays under mpi 2,3 cpus
00181 {
00182   int nbdomain=_topology->nbDomain();
00183   //MPI_Barrier(MPI_COMM_WORLD);
00184   if (MyGlobals::_Is0verbose>0) 
00185     std::cout << "\nJointFinder print node-node (nn)iproc|itarget|isource|i|inodefirst-inodesecond\n\n" <<
00186       "JointFinder print distantNode=cell (nc)iproc|itarget|isource|inode=icell\n\n";
00187   for (int isource=0; isource<nbdomain; isource++)
00188     {
00189       for (int itarget=0; itarget<nbdomain; itarget++)
00190         {
00191           for (std::size_t i=0; i<_node_node[itarget][isource].size(); i++)
00192             std::cout << " nn" << _domain_selector->rank() << itarget << "|" << isource << "|" << i << "|" <<
00193               _node_node[itarget][isource][i].first << "-" <<
00194               _node_node[itarget][isource][i].second;
00195         }
00196     }
00197   std::cout<<std::endl;
00198   //MPI_Barrier(MPI_COMM_WORLD);
00199   for (int isource=0; isource<nbdomain; isource++)
00200     {
00201       for (int itarget=0; itarget<nbdomain; itarget++)
00202         {
00203           std::multimap<int,int>::iterator it;
00204           for (it=_distant_node_cell[isource][itarget].begin() ; it!=_distant_node_cell[isource][itarget].end(); it++)
00205             {
00206               std::cout << " nc" << _domain_selector->rank() << "|" << itarget << "|" << isource << "|" << (*it).first << "=" << (*it).second;
00207             }
00208         }
00209     }
00210   std::cout << std::endl;
00211   //MPI_Barrier(MPI_COMM_WORLD);
00212 }