X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FParaMEDMEM%2FElementLocator.cxx;h=31d7033cdb775fa1fd41b43ddff6d039247e34f8;hb=HEAD;hp=5397b2a67e8bfbe80fec6ad71547d0b100608535;hpb=48782c06022ca2caa36f849cb5a29ea4fe2aaa83;p=tools%2Fmedcoupling.git diff --git a/src/ParaMEDMEM/ElementLocator.cxx b/src/ParaMEDMEM/ElementLocator.cxx index 5397b2a67..31d7033cd 100644 --- a/src/ParaMEDMEM/ElementLocator.cxx +++ b/src/ParaMEDMEM/ElementLocator.cxx @@ -1,29 +1,34 @@ -// Copyright (C) 2007-2008 CEA/DEN, EDF R&D +// Copyright (C) 2007-2024 CEA, EDF // -// This library is free software; you can redistribute it and/or -// modify it under the terms of the GNU Lesser General Public -// License as published by the Free Software Foundation; either -// version 2.1 of the License. +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. // -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// Lesser General Public License for more details. +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. // -// You should have received a copy of the GNU Lesser General Public -// License along with this library; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // -// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // + #include #include "CommInterface.hxx" #include "ElementLocator.hxx" #include "Topology.hxx" #include "BlockTopology.hxx" +#include "ParaFIELD.hxx" #include "ParaMESH.hxx" #include "ProcessorGroup.hxx" #include "MPIProcessorGroup.hxx" +#include "MEDCouplingFieldDouble.hxx" +#include "MCAuto.hxx" +#include "DirectedBoundingBox.hxx" #include #include @@ -31,18 +36,22 @@ using namespace std; -namespace ParaMEDMEM +//#define USE_DIRECTED_BB + +namespace MEDCoupling { - ElementLocator::ElementLocator(const ParaMESH& sourceMesh, - const ProcessorGroup& distant_group) - : _local_para_mesh(sourceMesh), - _local_cell_mesh(sourceMesh.getCellMesh()), - _local_face_mesh(sourceMesh.getFaceMesh()), - _local_group(*sourceMesh.getBlockTopology()->getProcGroup()), - _distant_group(distant_group) + ElementLocator::ElementLocator(const ParaFIELD& sourceField, + const ProcessorGroup& distant_group, + const ProcessorGroup& local_group) + : _local_para_field(sourceField), + _local_cell_mesh(sourceField.getSupport()->getCellMesh()), + _local_face_mesh(sourceField.getSupport()->getFaceMesh()), + _distant_group(distant_group), + _local_group(local_group) { _union_group = _local_group.fuse(distant_group); _computeBoundingBoxes(); + _comm=getCommunicator(); } ElementLocator::~ElementLocator() @@ -51,87 +60,52 @@ namespace ParaMEDMEM delete [] _domain_bounding_boxes; } - // ========================================================================== - // Procedure for exchanging mesh between a distant proc and a local processor - // param idistantrank proc id on distant group - // param distant_mesh on return , points to a local reconstruction of - // the distant mesh - // param distant_ids on return, contains a vector defining a correspondence - // between the distant ids and the ids of the local reconstruction - // ========================================================================== + const MPI_Comm *ElementLocator::getCommunicator() const + { + MPIProcessorGroup* group=static_cast (_union_group); + return group->getComm(); + } + + NatureOfField ElementLocator::getLocalNature() const + { + return _local_para_field.getField()->getNature(); + } + + + /*! Procedure for exchanging a mesh between a distant proc and a local processor + \param idistantrank proc id on distant group + \param distant_mesh on return , points to a local reconstruction of + the distant mesh + \param distant_ids on return, contains a vector defining a correspondence + between the distant ids and the ids of the local reconstruction + */ void ElementLocator::exchangeMesh(int idistantrank, - MEDCouplingUMesh*& distant_mesh, - int*& distant_ids) + MEDCouplingPointSet*& distant_mesh, + mcIdType*& distant_ids) { - int dim = _local_cell_mesh->getSpaceDimension(); int rank = _union_group->translateRank(&_distant_group,idistantrank); if (find(_distant_proc_ids.begin(), _distant_proc_ids.end(),rank)==_distant_proc_ids.end()) - { - return; - } - - set elems; - double* distant_bb = _domain_bounding_boxes+rank*2*dim; - double* elem_bb=new double[2*dim]; - - //defining pointers to med - const int* conn = _local_cell_mesh->getNodalConnectivity()->getPointer() ; - const int* conn_index= _local_cell_mesh->getNodalConnectivityIndex()->getPointer(); - const double* coords = _local_cell_mesh->getCoords()->getPointer() ; + return; - for ( int ielem=0; ielem<_local_cell_mesh->getNumberOfCells() ; ielem++) - { - for (int i=0; i::max(); - elem_bb[i*2+1]=-std::numeric_limits::max(); - } - - for (int inode=conn_index[ielem]+1; inode elem_bb[idim*2+1] ) - { - elem_bb[idim*2+1] = coords[node*dim+idim] ; - } - } - } - if (_intersectsBoundingBox(elem_bb, distant_bb, dim)) - { - elems.insert(ielem); - } - } - //send_mesh contains null pointer if elems is empty - MEDCouplingUMesh* send_mesh = _meshFromElems(elems); + MCAuto elems; +#ifdef USE_DIRECTED_BB + INTERP_KERNEL::DirectedBoundingBox dbb; + double* distant_bb = _domain_bounding_boxes+rank*dbb.dataSize(_local_cell_mesh_space_dim); + dbb.setData(distant_bb); + elems=_local_cell_mesh->getCellsInBoundingBox(dbb,getBoundingBoxAdjustment()); +#else + double* distant_bb = _domain_bounding_boxes+rank*2*_local_cell_mesh_space_dim; + elems=_local_cell_mesh->getCellsInBoundingBox(distant_bb,getBoundingBoxAdjustment()); +#endif - // Constituting an array containing the ids of the elements that are - // going to be sent to the distant subdomain. - // This array enables the correct redistribution of the data when the - // interpolated field is transmitted to the target array - - int* distant_ids_send=0; - if (elems.size()>0) - { - distant_ids_send = new int[elems.size()]; - int index=0; - for (std::set::const_iterator iter = elems.begin(); iter!= elems.end(); iter++) - { - distant_ids_send[index]=*iter; - index++; - } - } + DataArrayIdType *distant_ids_send; + MEDCouplingPointSet *send_mesh = (MEDCouplingPointSet *)_local_para_field.getField()->buildSubMeshData(elems->begin(),elems->end(),distant_ids_send); _exchangeMesh(send_mesh, distant_mesh, idistantrank, distant_ids_send, distant_ids); - delete[] distant_ids_send; - delete[] elem_bb; - send_mesh->decrRef(); + distant_ids_send->decrRef(); + + if(send_mesh) + send_mesh->decrRef(); } void ElementLocator::exchangeMethod(const std::string& sourceMeth, int idistantrank, std::string& targetMeth) @@ -139,7 +113,7 @@ namespace ParaMEDMEM CommInterface comm_interface=_union_group->getCommInterface(); MPIProcessorGroup* group=static_cast (_union_group); const MPI_Comm* comm=(group->getComm()); - MPI_Status status; + MPI_Status status; // it must be converted to union numbering before communication int idistRankInUnion = group->translateRank(&_distant_group,idistantrank); char *recv_buffer=new char[4]; @@ -153,368 +127,594 @@ namespace ParaMEDMEM } - // ====================== - // Compute bounding boxes - // ====================== + /*! + Compute bounding boxes + */ void ElementLocator::_computeBoundingBoxes() { CommInterface comm_interface =_union_group->getCommInterface(); - int dim = _local_cell_mesh->getSpaceDimension(); - _domain_bounding_boxes = new double[2*dim*_union_group->size()]; - const double* coords = _local_cell_mesh->getCoords()->getPointer() ; - - int nbnodes = _local_cell_mesh->getNumberOfNodes(); - double * minmax=new double [2*dim]; - for (int idim=0; idim::max(); - minmax[idim*2+1]=-std::numeric_limits::max(); - } - - for (int i=0; i coords[i*dim+idim] ) - { - minmax[idim*2] = coords[i*dim+idim] ; - } - if ( minmax[idim*2+1] < coords[i*dim+idim] ) - { - minmax[idim*2+1] = coords[i*dim+idim] ; - } - } - } - MPIProcessorGroup* group=static_cast (_union_group); const MPI_Comm* comm = group->getComm(); - comm_interface.allGather(minmax, 2*dim, MPI_DOUBLE, - _domain_bounding_boxes,2*dim, MPI_DOUBLE, + _local_cell_mesh_space_dim = -1; + if(_local_cell_mesh->getMeshDimension() != -1) + _local_cell_mesh_space_dim=_local_cell_mesh->getSpaceDimension(); + int *spaceDimForAll=new int[_union_group->size()]; + comm_interface.allGather(&_local_cell_mesh_space_dim, 1, MPI_INT, + spaceDimForAll,1, MPI_INT, + *comm); + _local_cell_mesh_space_dim=*std::max_element(spaceDimForAll,spaceDimForAll+_union_group->size()); + _is_m1d_corr=((*std::min_element(spaceDimForAll,spaceDimForAll+_union_group->size()))==-1); + for(int i=0;i<_union_group->size();i++) + if(spaceDimForAll[i]!=_local_cell_mesh_space_dim && spaceDimForAll[i]!=-1) + throw INTERP_KERNEL::Exception("Spacedim not matches !"); + delete [] spaceDimForAll; +#ifdef USE_DIRECTED_BB + INTERP_KERNEL::DirectedBoundingBox dbb; + int bbSize = dbb.dataSize(_local_cell_mesh_space_dim); + _domain_bounding_boxes = new double[bbSize*_union_group->size()]; + if(_local_cell_mesh->getMeshDimension() != -1) + dbb = INTERP_KERNEL::DirectedBoundingBox(_local_cell_mesh->getCoords()->getPointer(), + _local_cell_mesh->getNumberOfNodes(), + _local_cell_mesh_space_dim); + std::vector dbbData = dbb.getData(); + if ( dbbData.size() < bbSize ) dbbData.resize(bbSize,0); + double * minmax= &dbbData[0]; +#else + int bbSize = 2*_local_cell_mesh_space_dim; + _domain_bounding_boxes = new double[bbSize*_union_group->size()]; + double * minmax=new double [bbSize]; + if(_local_cell_mesh->getMeshDimension() != -1) + _local_cell_mesh->getBoundingBox(minmax); + else + for(int i=0;i<_local_cell_mesh_space_dim;i++) + { + minmax[i*2]=-std::numeric_limits::max(); + minmax[i*2+1]=std::numeric_limits::max(); + } +#endif + + comm_interface.allGather(minmax, bbSize, MPI_DOUBLE, + _domain_bounding_boxes,bbSize, MPI_DOUBLE, *comm); for (int i=0; i< _distant_group.size(); i++) { - int rank= _union_group->translateRank(&_distant_group,i); + int rank=_union_group->translateRank(&_distant_group,i); if (_intersectsBoundingBox(rank)) { _distant_proc_ids.push_back(rank); } } - delete[] minmax; +#ifdef USE_DIRECTED_BB +#else + delete [] minmax; +#endif } - // ============================================= - // Intersect Bounding Box (with a given "irank") - // ============================================= + + /*! + * Intersect local bounding box with a given distant bounding box on "irank" + */ bool ElementLocator::_intersectsBoundingBox(int irank) { - int dim=_local_cell_mesh->getSpaceDimension(); - double* local_bb = _domain_bounding_boxes+_union_group->myRank()*2*dim; - double* distant_bb = _domain_bounding_boxes+irank*2*dim; - - for (int idim=0; idim < _local_cell_mesh->getSpaceDimension(); idim++) +#ifdef USE_DIRECTED_BB + INTERP_KERNEL::DirectedBoundingBox local_dbb, distant_dbb; + local_dbb.setData( _domain_bounding_boxes+_union_group->myRank()*local_dbb.dataSize( _local_cell_mesh_space_dim )); + distant_dbb.setData( _domain_bounding_boxes+irank*distant_dbb.dataSize( _local_cell_mesh_space_dim )); + return !local_dbb.isDisjointWith( distant_dbb ); +#else + double* local_bb = _domain_bounding_boxes+_union_group->myRank()*2*_local_cell_mesh_space_dim; + double* distant_bb = _domain_bounding_boxes+irank*2*_local_cell_mesh_space_dim; + + const double eps = 1e-12; + for (int idim=0; idim < _local_cell_mesh_space_dim; idim++) { - const double eps = 1e-12; bool intersects = (distant_bb[idim*2] deltamax ) - { - deltamax = delta ; - } - // deltamax = (delta>deltamax)?delta:deltamax; - } - for (int i=0; igetCommInterface(); // First stage : exchanging sizes // ------------------------------ - - int* send_buffer = new int[5]; - int* recv_buffer = new int[5]; - - //treatment for non-empty mesh - int nbconn=0; - int nbelems=0; - - if (local_mesh !=0) - { - nbelems = local_mesh->getNumberOfCells(); - nbconn = local_mesh->getMeshLength(); - send_buffer[0] = local_mesh->getSpaceDimension(); - send_buffer[1] = local_mesh->getMeshDimension(); - send_buffer[2] = local_mesh->getNumberOfNodes(); - send_buffer[3] = nbelems; - send_buffer[4] = nbconn; - } - else - { - for (int i=0; i<5; i++) - { - send_buffer[i]=0; - } - } - + vector tinyInfoLocalD,tinyInfoDistantD(1);//not used for the moment + vector tinyInfoLocal,tinyInfoDistant; + vector tinyInfoLocalS; + //Getting tiny info of local mesh to allow the distant proc to initialize and allocate + //the transmitted mesh. + local_mesh->getTinySerializationInformation(tinyInfoLocalD,tinyInfoLocal,tinyInfoLocalS); + tinyInfoLocal.push_back(distant_ids_send->getNumberOfTuples()); + tinyInfoDistant.resize(tinyInfoLocal.size()); + std::fill(tinyInfoDistant.begin(),tinyInfoDistant.end(),0); MPIProcessorGroup* group=static_cast (_union_group); - const MPI_Comm* comm=(group->getComm()); + const MPI_Comm* comm=group->getComm(); MPI_Status status; - + // iproc_distant is the number of proc in distant group // it must be converted to union numbering before communication int iprocdistant_in_union = group->translateRank(&_distant_group, iproc_distant); - - comm_interface.sendRecv(send_buffer, 5, MPI_INT, iprocdistant_in_union, 1112, - recv_buffer, 5, MPI_INT,iprocdistant_in_union,1112, + + comm_interface.sendRecv(&tinyInfoLocal[0], (int)tinyInfoLocal.size(), MPI_ID_TYPE, iprocdistant_in_union, 1112, + &tinyInfoDistant[0], (int)tinyInfoDistant.size(), MPI_ID_TYPE,iprocdistant_in_union,1112, *comm, &status); - - int distant_space_dim = recv_buffer[0]; - int distant_mesh_dim = recv_buffer[1]; - int distant_nnodes = recv_buffer[2]; - int distant_nb_elems = recv_buffer[3]; - int distant_nb_conn = recv_buffer[4]; - - delete[] send_buffer; - delete[] recv_buffer; - - // Second stage : exchanging connectivity buffers - // ---------------------------------------------- - - int nb_integers = nbconn + 2*nbelems + 1; - send_buffer = new int[nb_integers]; - const int* conn = 0; - const int* global_numbering=0; - int* ptr_buffer = send_buffer; - - if (local_mesh != 0) + DataArrayIdType *v1Local=0; + DataArrayDouble *v2Local=0; + DataArrayIdType *v1Distant=DataArrayIdType::New(); + DataArrayDouble *v2Distant=DataArrayDouble::New(); + //serialization of local mesh to send data to distant proc. + local_mesh->serialize(v1Local,v2Local); + //Building the right instance of copy of distant mesh. + MEDCouplingPointSet *distant_mesh_tmp=MEDCouplingPointSet::BuildInstanceFromMeshType((MEDCouplingMeshType)tinyInfoDistant[0]); + std::vector unusedTinyDistantSts; + distant_mesh_tmp->resizeForUnserialization(tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts); + mcIdType nbLocalElems=0; + mcIdType nbDistElem=0; + mcIdType *ptLocal=0; + mcIdType *ptDist=0; + if(v1Local) { - conn = local_mesh->getNodalConnectivity()->getPointer(); - - global_numbering = local_mesh->getNodalConnectivityIndex()->getPointer() ; - - //copying the data in the integer buffer - - memcpy(ptr_buffer, global_numbering, (nbelems+1)*sizeof(int)); - ptr_buffer += nbelems+1; - memcpy(ptr_buffer,conn, nbconn*sizeof(int)); - ptr_buffer += nbconn; - memcpy(ptr_buffer, distant_ids_send, nbelems*sizeof(int)); + nbLocalElems=v1Local->getNbOfElems(); + ptLocal=v1Local->getPointer(); } - - // Preparing the recv buffers - int nb_recv_integers = distant_nb_conn + 2*distant_nb_elems + 1 ; - recv_buffer=new int[nb_recv_integers]; - - // Exchanging integer buffer - comm_interface.sendRecv(send_buffer, nb_integers, MPI_INT, + if(v1Distant) + { + nbDistElem=v1Distant->getNbOfElems(); + ptDist=v1Distant->getPointer(); + } + comm_interface.sendRecv(ptLocal, (int)nbLocalElems, MPI_ID_TYPE, iprocdistant_in_union, 1111, - recv_buffer, nb_recv_integers, MPI_INT, + ptDist, (int)nbDistElem, MPI_ID_TYPE, iprocdistant_in_union,1111, *comm, &status); - - if ( nb_integers>0 ) + nbLocalElems=0; + double *ptLocal2=0; + double *ptDist2=0; + if(v2Local) { - delete[] send_buffer; + nbLocalElems=v2Local->getNbOfElems(); + ptLocal2=v2Local->getPointer(); } - - // Third stage : exchanging coordinates - // ------------------------------------ - - int nb_recv_floats = distant_space_dim*distant_nnodes; - int nb_send_floats = 0; - double* coords=0; - - if ( local_mesh!=0 ) + nbDistElem=0; + if(v2Distant) { - nb_send_floats = local_mesh->getSpaceDimension() - * local_mesh->getNumberOfNodes(); - coords = local_mesh->getCoords()->getPointer(); + nbDistElem=v2Distant->getNbOfElems(); + ptDist2=v2Distant->getPointer(); } - - DataArrayDouble* myCoords=DataArrayDouble::New(); - myCoords->alloc(distant_nnodes,distant_space_dim); - - comm_interface.sendRecv(coords, nb_send_floats, MPI_DOUBLE, + comm_interface.sendRecv(ptLocal2, (int)nbLocalElems, MPI_DOUBLE, iprocdistant_in_union, 1112, - myCoords->getPointer(), nb_recv_floats, MPI_DOUBLE, + ptDist2, (int)nbDistElem, MPI_DOUBLE, iprocdistant_in_union, 1112, - *group->getComm(), &status); - - - // Reconstructing an image of the distant mesh locally + *comm, &status); + // + distant_mesh=distant_mesh_tmp; + //finish unserialization + distant_mesh->unserialization(tinyInfoDistantD,tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts); + // + distant_ids_recv=new mcIdType[tinyInfoDistant.back()]; + comm_interface.sendRecv(const_cast(reinterpret_cast(distant_ids_send->getConstPointer())),(int)tinyInfoLocal.back(), MPI_ID_TYPE, + iprocdistant_in_union, 1113, + distant_ids_recv,(int)tinyInfoDistant.back(), MPI_ID_TYPE, + iprocdistant_in_union,1113, + *comm, &status); + if(v1Local) + v1Local->decrRef(); + if(v2Local) + v2Local->decrRef(); + if(v1Distant) + v1Distant->decrRef(); + if(v2Distant) + v2Distant->decrRef(); + } - if ( nb_recv_integers>0 && distant_space_dim !=0 ) + /*! + * connected with ElementLocator::sendPolicyToWorkingSideL + */ + void ElementLocator::recvPolicyFromLazySideW(std::vector& policy) + { + policy.resize(_distant_proc_ids.size()); + int procId=0; + CommInterface comm; + MPI_Status status; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) { - MEDCouplingUMesh* meshing = MEDCouplingUMesh::New() ; - - // Coordinates - meshing->setCoords(myCoords) ; - myCoords->decrRef(); - // Connectivity - - int *work=recv_buffer; - DataArrayInt* myConnecIndex=DataArrayInt::New(); - myConnecIndex->alloc(distant_nb_elems+1,1); - memcpy(myConnecIndex->getPointer(), work, (distant_nb_elems+1)*sizeof(int)); - work += distant_nb_elems + 1 ; - - DataArrayInt* myConnec=DataArrayInt::New(); - myConnec->alloc(distant_nb_conn,1); - memcpy(myConnec->getPointer(), work, (distant_nb_conn)*sizeof(int)); - work+=distant_nb_conn; - meshing->setConnectivity(myConnec, myConnecIndex) ; - myConnec->decrRef(); - myConnecIndex->decrRef(); - - // correspondence between the distant ids and the ids of - // the local reconstruction - - distant_ids_recv=new int [distant_nb_elems]; - for (int i=0; isetMeshDimension(distant_mesh_dim); - - distant_mesh=meshing; - delete[] recv_buffer; + int toRecv; + comm.recv((void *)&toRecv,1,MPI_INT,*iter,1120,*_comm,&status); + policy[procId]=toRecv; } + } + /*! + * connected with ElementLocator::recvFromWorkingSideL + */ + void ElementLocator::sendSumToLazySideW(const std::vector< std::vector >& distantLocEltIds, const std::vector< std::vector >& partialSumRelToDistantIds) + { + int procId=0; + CommInterface comm; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + const vector& eltIds=distantLocEltIds[procId]; + const vector& valued=partialSumRelToDistantIds[procId]; + int lgth=(int)eltIds.size(); + comm.send(&lgth,1,MPI_INT,*iter,1114,*_comm); + comm.send(const_cast(reinterpret_cast(&eltIds[0])),lgth,MPI_ID_TYPE,*iter,1115,*_comm); + comm.send(const_cast(reinterpret_cast(&valued[0])),lgth,MPI_DOUBLE,*iter,1116,*_comm); + } } + /*! + * connected with ElementLocator::sendToWorkingSideL + */ + void ElementLocator::recvSumFromLazySideW(std::vector< std::vector >& globalSumRelToDistantIds) + { + int procId=0; + CommInterface comm; + MPI_Status status; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + std::vector& vec=globalSumRelToDistantIds[procId]; + comm.recv(&vec[0],(int)vec.size(),MPI_DOUBLE,*iter,1117,*_comm,&status); + } + } - // ============== - // _meshFromElems - // ============== + /*! + * connected with ElementLocator::recvLocalIdsFromWorkingSideL + */ + void ElementLocator::sendLocalIdsToLazyProcsW(const std::vector< std::vector >& distantLocEltIds) + { + int procId=0; + CommInterface comm; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + const vector& eltIds=distantLocEltIds[procId]; + int lgth=(int)eltIds.size(); + comm.send(&lgth,1,MPI_INT,*iter,1121,*_comm); + comm.send(const_cast(reinterpret_cast(&eltIds[0])),lgth,MPI_ID_TYPE,*iter,1122,*_comm); + } + } - MEDCouplingUMesh* ElementLocator::_meshFromElems(set& elems) + /*! + * connected with ElementLocator::sendGlobalIdsToWorkingSideL + */ + void ElementLocator::recvGlobalIdsFromLazyProcsW(const std::vector< std::vector >& distantLocEltIds, std::vector< std::vector >& globalIds) + { + int procId=0; + CommInterface comm; + MPI_Status status; + globalIds.resize(_distant_proc_ids.size()); + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + const std::vector& vec=distantLocEltIds[procId]; + std::vector& global=globalIds[procId]; + global.resize(vec.size()); + comm.recv(&global[0],(int)vec.size(),MPI_ID_TYPE,*iter,1123,*_comm,&status); + } + } + + /*! + * connected with ElementLocator::sendCandidatesGlobalIdsToWorkingSideL + */ + void ElementLocator::recvCandidatesGlobalIdsFromLazyProcsW(std::vector< std::vector >& globalIds) + { + int procId=0; + CommInterface comm; + MPI_Status status; + globalIds.resize(_distant_proc_ids.size()); + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + std::vector& global=globalIds[procId]; + int lgth; + comm.recv(&lgth,1,MPI_INT,*iter,1132,*_comm,&status); + global.resize(lgth); + comm.recv(&global[0],lgth,MPI_ID_TYPE,*iter,1133,*_comm,&status); + } + } + + /*! + * connected with ElementLocator::recvSumFromWorkingSideL + */ + void ElementLocator::sendPartialSumToLazyProcsW(const std::vector& distantGlobIds, const std::vector& sum) { - //returns null pointer if there are no elems in the mesh - if ( elems.size()==0 ) return 0; + int procId=0; + CommInterface comm; + int lgth=(int)distantGlobIds.size(); + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + comm.send(&lgth,1,MPI_INT,*iter,1124,*_comm); + comm.send(const_cast(reinterpret_cast(&distantGlobIds[0])),lgth,MPI_ID_TYPE,*iter,1125,*_comm); + comm.send(const_cast(reinterpret_cast(&sum[0])),lgth,MPI_DOUBLE,*iter,1126,*_comm); + } + } - // Defining pointers - const int* conn_mesh = - const_cast (_local_cell_mesh->getNodalConnectivity()->getPointer()); + /*! + * connected with ElementLocator::recvCandidatesForAddElementsL + */ + void ElementLocator::sendCandidatesForAddElementsW(const std::vector& distantGlobIds) + { + int procId=0; + CommInterface comm; + int lgth=(int)distantGlobIds.size(); + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + comm.send(const_cast(reinterpret_cast(&lgth)),1,MPI_INT,*iter,1128,*_comm); + comm.send(const_cast(reinterpret_cast(&distantGlobIds[0])),lgth,MPI_ID_TYPE,*iter,1129,*_comm); + } + } + + /*! + * connected with ElementLocator::sendAddElementsToWorkingSideL + */ + void ElementLocator::recvAddElementsFromLazyProcsW(std::vector >& elementsToAdd) + { + int procId=0; + CommInterface comm; + MPI_Status status; + int lgth=(int)_distant_proc_ids.size(); + elementsToAdd.resize(lgth); + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + int locLgth; + std::vector& eltToFeed=elementsToAdd[procId]; + comm.recv(&locLgth,1,MPI_INT,*iter,1130,*_comm,&status); + eltToFeed.resize(locLgth); + comm.recv(&eltToFeed[0],locLgth,MPI_ID_TYPE,*iter,1131,*_comm,&status); + } + } - const int* conn_index = - const_cast (_local_cell_mesh->getNodalConnectivityIndex()->getPointer()); + /*! + * connected with ElementLocator::recvPolicyFromLazySideW + */ + int ElementLocator::sendPolicyToWorkingSideL() + { + CommInterface comm; + int toSend; + DataArrayIdType *isCumulative=_local_para_field.returnCumulativeGlobalNumbering(); + if(isCumulative) + { + toSend=CUMULATIVE_POLICY; + isCumulative->decrRef(); + } + else + toSend=NO_POST_TREATMENT_POLICY; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++) + comm.send(&toSend,1,MPI_INT,*iter,1120,*_comm); + return toSend; + } - const double* coords = - const_cast ( _local_cell_mesh->getCoords()->getPointer()); + /*! + * connected with ElementLocator::sendSumToLazySideW + */ + void ElementLocator::recvFromWorkingSideL() + { + _values_added.resize(_local_para_field.getField()->getNumberOfTuples()); + int procId=0; + CommInterface comm; + _ids_per_working_proc.resize(_distant_proc_ids.size()); + MPI_Status status; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + int lgth; + comm.recv(&lgth,1,MPI_INT,*iter,1114,*_comm,&status); + vector& ids=_ids_per_working_proc[procId]; + ids.resize(lgth); + vector values(lgth); + comm.recv(&ids[0],lgth,MPI_ID_TYPE,*iter,1115,*_comm,&status); + comm.recv(&values[0],lgth,MPI_DOUBLE,*iter,1116,*_comm,&status); + for(mcIdType i=0;i nodes; - int nbconn=0; - for (set::const_iterator iter=elems.begin(); iter!=elems.end(); iter++) + /*! + * connected with ElementLocator::recvSumFromLazySideW + */ + void ElementLocator::sendToWorkingSideL() + { + int procId=0; + CommInterface comm; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) { - // Conn_index : C-like Addresses - for (int inode=conn_index[*iter]+1; inode& ids=_ids_per_working_proc[procId]; + vector valsToSend(ids.size()); + vector::iterator iter3=valsToSend.begin(); + for(vector::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter3++) + *iter3=_values_added[*iter2]; + comm.send(&valsToSend[0],(int)ids.size(),MPI_DOUBLE,*iter,1117,*_comm); + //ids.clear(); } + //_ids_per_working_proc.clear(); + } - map big2small; - int i=0; - for (set::const_iterator iter=nodes.begin(); iter!=nodes.end(); iter++) + /*! + * connected with ElementLocator::sendLocalIdsToLazyProcsW + */ + void ElementLocator::recvLocalIdsFromWorkingSideL() + { + int procId=0; + CommInterface comm; + _ids_per_working_proc.resize(_distant_proc_ids.size()); + MPI_Status status; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) { - big2small[*iter]=i; - i++; + int lgth; + vector& ids=_ids_per_working_proc[procId]; + comm.recv(&lgth,1,MPI_INT,*iter,1121,*_comm,&status); + ids.resize(lgth); + comm.recv(&ids[0],lgth,MPI_ID_TYPE,*iter,1122,*_comm,&status); } + } - // Memory allocate - DataArrayInt *conn = DataArrayInt::New() ; - conn->alloc(nbconn+elems.size(),1) ; - int *connPtr=conn->getPointer(); + /*! + * connected with ElementLocator::recvGlobalIdsFromLazyProcsW + */ + void ElementLocator::sendGlobalIdsToWorkingSideL() + { + int procId=0; + CommInterface comm; + DataArrayIdType *globalIds=_local_para_field.returnGlobalNumbering(); + const mcIdType *globalIdsC=globalIds->getConstPointer(); + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + const vector& ids=_ids_per_working_proc[procId]; + vector valsToSend(ids.size()); + vector::iterator iter1=valsToSend.begin(); + for(vector::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter1++) + *iter1=globalIdsC[*iter2]; + comm.send(&valsToSend[0],(int)ids.size(),MPI_ID_TYPE,*iter,1123,*_comm); + } + if(globalIds) + globalIds->decrRef(); + } - DataArrayInt * connIndex = DataArrayInt::New() ; - connIndex->alloc(elems.size()+1,1) ; - int* connIndexPtr=connIndex->getPointer(); + /*! + * connected with ElementLocator::sendPartialSumToLazyProcsW + */ + void ElementLocator::recvSumFromWorkingSideL() + { + std::size_t procId=0; + std::size_t wProcSize=_distant_proc_ids.size(); + CommInterface comm; + _ids_per_working_proc.resize(wProcSize); + _values_per_working_proc.resize(wProcSize); + MPI_Status status; + std::map sums; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + int lgth; + comm.recv(&lgth,1,MPI_INT,*iter,1124,*_comm,&status); + vector& ids=_ids_per_working_proc[procId]; + vector& vals=_values_per_working_proc[procId]; + ids.resize(lgth); + vals.resize(lgth); + comm.recv(&ids[0],lgth,MPI_ID_TYPE,*iter,1125,*_comm,&status); + comm.recv(&vals[0],lgth,MPI_DOUBLE,*iter,1126,*_comm,&status); + vector::const_iterator iter1=ids.begin(); + vector::const_iterator iter2=vals.begin(); + for(;iter1!=ids.end();iter1++,iter2++) + sums[*iter1]+=*iter2; + } + //assign sum to prepare sending to working side + for(procId=0;procId& ids=_ids_per_working_proc[procId]; + vector& vals=_values_per_working_proc[procId]; + vector::const_iterator iter1=ids.begin(); + vector::iterator iter2=vals.begin(); + for(;iter1!=ids.end();iter1++,iter2++) + *iter2=sums[*iter1]; + ids.clear(); + } + } - DataArrayDouble *new_coords = DataArrayDouble::New() ; - new_coords->alloc(nodes.size(), _local_cell_mesh->getSpaceDimension()) ; - double *new_coords_ptr = new_coords->getPointer(); + /*! + * Foreach working procs Wi compute and push it in _ids_per_working_proc3, + * if it exist, local id of nodes that are in interaction with an another lazy proc than this + * and that exists in this \b but with no interaction with this. + * The computation is performed here. sendAddElementsToWorkingSideL is only in charge to send + * precomputed _ids_per_working_proc3 attribute. + * connected with ElementLocator::sendCandidatesForAddElementsW + */ + void ElementLocator::recvCandidatesForAddElementsL() + { + std::size_t procId=0; + std::size_t wProcSize=_distant_proc_ids.size(); + CommInterface comm; + _ids_per_working_proc3.resize(wProcSize); + MPI_Status status; + std::map sums; + DataArrayIdType *globalIds=_local_para_field.returnGlobalNumbering(); + const mcIdType *globalIdsC=globalIds->getConstPointer(); + mcIdType nbElts=globalIds->getNumberOfTuples(); + std::set globalIdsS(globalIdsC,globalIdsC+nbElts); + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) + { + const std::vector& ids0=_ids_per_working_proc[procId]; + std::size_t lgth0=ids0.size(); + std::set elts0; + for(std::size_t i=0;i ids(lgth); + comm.recv(&ids[0],lgth,MPI_ID_TYPE,*iter,1129,*_comm,&status); + set ids1(ids.begin(),ids.end()); + ids.clear(); + set tmp5,tmp6; + set_intersection(globalIdsS.begin(),globalIdsS.end(),ids1.begin(),ids1.end(),inserter(tmp5,tmp5.begin())); + set_difference(tmp5.begin(),tmp5.end(),elts0.begin(),elts0.end(),inserter(tmp6,tmp6.begin())); + std::vector& ids2=_ids_per_working_proc3[procId]; + ids2.resize(tmp6.size()); + std::copy(tmp6.begin(),tmp6.end(),ids2.begin()); + //global->local + for(std::vector::iterator iter2=ids2.begin();iter2!=ids2.end();iter2++) + *iter2=ToIdType(std::find(globalIdsC,globalIdsC+nbElts,*iter2)-globalIdsC); + } + if(globalIds) + globalIds->decrRef(); + } - // New connectivity table - int index=0; - int mainIndex=0; - for (set::const_iterator iter=elems.begin(); iter!=elems.end(); iter++,mainIndex++) + /*! + * connected with ElementLocator::recvAddElementsFromLazyProcsW + */ + void ElementLocator::sendAddElementsToWorkingSideL() + { + int procId=0; + CommInterface comm; + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) { - connIndexPtr[mainIndex]=index; - connPtr[index++]=conn_mesh[conn_index[*iter]]; - for (int inode = conn_index[*iter]+1; inode < conn_index[*iter+1]; inode++) - { - connPtr[index]=big2small[conn_mesh[inode]] ; // C-like number - index++; - } + const std::vector& vals=_ids_per_working_proc3[procId]; + int size=(int)vals.size(); + comm.send(const_cast(reinterpret_cast(&size)),1,MPI_INT,*iter,1130,*_comm); + comm.send(const_cast(reinterpret_cast(&vals[0])),size,MPI_ID_TYPE,*iter,1131,*_comm); } - connIndexPtr[mainIndex]=index; - // Coordinates - index=0; - for (set::const_iterator iter=nodes.begin(); iter!=nodes.end(); iter++) + } + + /*! + * This method sends to working side Wi only nodes in interaction with Wi \b and located on boundary, to reduce number. + * connected with ElementLocator::recvCandidatesGlobalIdsFromLazyProcsW + */ + void ElementLocator::sendCandidatesGlobalIdsToWorkingSideL() + { + int procId=0; + CommInterface comm; + DataArrayIdType *globalIds=_local_para_field.returnGlobalNumbering(); + const mcIdType *globalIdsC=globalIds->getConstPointer(); + MCAuto candidates=_local_para_field.getSupport()->getCellMesh()->findBoundaryNodes(); + for(mcIdType *iter1=candidates->getPointer();iter1!=candidates->getPointer()+candidates->getNumberOfTuples();iter1++) + (*iter1)=globalIdsC[*iter1]; + std::set candidatesS(candidates->begin(),candidates->end()); + for(vector::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++) { - int dim = _local_cell_mesh->getSpaceDimension(); - for (int i=0; i& ids=_ids_per_working_proc[procId]; + vector valsToSend(ids.size()); + vector::iterator iter1=valsToSend.begin(); + for(vector::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter1++) + *iter1=globalIdsC[*iter2]; + std::set tmp2(valsToSend.begin(),valsToSend.end()); + std::vector tmp3; + set_intersection(candidatesS.begin(),candidatesS.end(),tmp2.begin(),tmp2.end(),std::back_insert_iterator< std::vector >(tmp3)); + int lgth=(int)tmp3.size(); + comm.send(&lgth,1,MPI_INT,*iter,1132,*_comm); + comm.send(&tmp3[0],lgth,MPI_ID_TYPE,*iter,1133,*_comm); } - - // Initialize - MEDCouplingUMesh* meshing = MEDCouplingUMesh::New() ; - meshing->setCoords(new_coords) ; - new_coords->decrRef(); - meshing->setConnectivity(conn, connIndex) ; - conn->decrRef(); - connIndex->decrRef(); - meshing->setMeshDimension(_local_cell_mesh->getMeshDimension()); - - return meshing; + if(globalIds) + globalIds->decrRef(); } }