-// Copyright (C) 2007-2008 CEA/DEN, EDF R&D
+// Copyright (C) 2007-2014 CEA/DEN, EDF R&D
//
-// 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 <mpi.h>
#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 "MEDCouplingAutoRefCountObjectPtr.hxx"
+#include "DirectedBoundingBox.hxx"
#include <map>
#include <set>
using namespace std;
+//#define USE_DIRECTED_BB
+
namespace ParaMEDMEM
{
- 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()
delete [] _domain_bounding_boxes;
}
+ const MPI_Comm *ElementLocator::getCommunicator() const
+ {
+ MPIProcessorGroup* group=static_cast<MPIProcessorGroup*> (_union_group);
+ return group->getComm();
+ }
+
+ NatureOfField ElementLocator::getLocalNature() const
+ {
+ return _local_para_field.getField()->getNature();
+ }
+
// ==========================================================================
// Procedure for exchanging mesh between a distant proc and a local processor
// param idistantrank proc id on distant group
// between the distant ids and the ids of the local reconstruction
// ==========================================================================
void ElementLocator::exchangeMesh(int idistantrank,
- MEDCouplingUMesh*& distant_mesh,
+ MEDCouplingPointSet*& distant_mesh,
int*& 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;
- }
+ return;
- set <int> 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() ;
-
- for ( int ielem=0; ielem<_local_cell_mesh->getNumberOfCells() ; ielem++)
- {
- for (int i=0; i<dim; i++)
- {
- elem_bb[i*2]=std::numeric_limits<double>::max();
- elem_bb[i*2+1]=-std::numeric_limits<double>::max();
- }
-
- for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
- {
- int node= conn[inode];
-
- for (int idim=0; idim<dim; idim++)
- {
- if ( coords[node*dim+idim] < elem_bb[idim*2] )
- {
- elem_bb[idim*2] = coords[node*dim+idim] ;
- }
- if ( coords[node*dim+idim] > 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);
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> 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<int>::const_iterator iter = elems.begin(); iter!= elems.end(); iter++)
- {
- distant_ids_send[index]=*iter;
- index++;
- }
- }
+ DataArrayInt *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)
CommInterface comm_interface=_union_group->getCommInterface();
MPIProcessorGroup* group=static_cast<MPIProcessorGroup*> (_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];
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<dim; idim++)
- {
- minmax[idim*2]=std::numeric_limits<double>::max();
- minmax[idim*2+1]=-std::numeric_limits<double>::max();
- }
-
- for (int i=0; i<nbnodes; i++)
- {
- for (int idim=0; idim<dim;idim++)
- {
- if ( minmax[idim*2] > 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<MPIProcessorGroup*> (_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<double> 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<double>::max();
+ minmax[i*2+1]=std::numeric_limits<double>::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
}
// =============================================
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;
+
+ for (int idim=0; idim < _local_cell_mesh_space_dim; idim++)
{
const double eps = 1e-12;
bool intersects = (distant_bb[idim*2]<local_bb[idim*2+1]+eps)
if (!intersects) return false;
}
return true;
+#endif
}
- // =============================================
- // Intersect Bounding Box given 2 Bounding Boxes
- // =============================================
- bool ElementLocator::_intersectsBoundingBox(double* bb1, double* bb2, int dim)
- {
- double bbtemp[2*dim];
- double deltamax=0.0;
- double adjustment_eps=getBoundingBoxAdjustment();
-
- for (int i=0; i< dim; i++)
- {
- double delta = bb1[2*i+1]-bb1[2*i];
- if ( delta > deltamax )
- {
- deltamax = delta ;
- }
- // deltamax = (delta>deltamax)?delta:deltamax;
- }
- for (int i=0; i<dim; i++)
- {
- bbtemp[i*2]=bb1[i*2]-deltamax*adjustment_eps;
- bbtemp[i*2+1]=bb1[i*2+1]+deltamax*adjustment_eps;
- }
-
- for (int idim=0; idim < dim; idim++)
- {
- bool intersects = (bbtemp[idim*2]<bb2[idim*2+1])
- && (bb2[idim*2]<bbtemp[idim*2+1]) ;
- if (!intersects) return false;
- }
- return true;
- }
-
-
// ======================
// Exchanging meshes data
// ======================
- void ElementLocator::_exchangeMesh( MEDCouplingUMesh* local_mesh,
- MEDCouplingUMesh*& distant_mesh,
+ void ElementLocator::_exchangeMesh( MEDCouplingPointSet* local_mesh,
+ MEDCouplingPointSet*& distant_mesh,
int iproc_distant,
- const int* distant_ids_send,
+ const DataArrayInt* distant_ids_send,
int*& distant_ids_recv)
{
CommInterface comm_interface=_union_group->getCommInterface();
// 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<double> tinyInfoLocalD,tinyInfoDistantD(1);//not used for the moment
+ vector<int> tinyInfoLocal,tinyInfoDistant;
+ vector<string> 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<MPIProcessorGroup*> (_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], tinyInfoLocal.size(), MPI_INT, iprocdistant_in_union, 1112,
+ &tinyInfoDistant[0], tinyInfoDistant.size(), MPI_INT,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)
+ DataArrayInt *v1Local=0;
+ DataArrayDouble *v2Local=0;
+ DataArrayInt *v1Distant=DataArrayInt::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<std::string> unusedTinyDistantSts;
+ distant_mesh_tmp->resizeForUnserialization(tinyInfoDistant,v1Distant,v2Distant,unusedTinyDistantSts);
+ int nbLocalElems=0;
+ int nbDistElem=0;
+ int *ptLocal=0;
+ int *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, nbLocalElems, MPI_INT,
iprocdistant_in_union, 1111,
- recv_buffer, nb_recv_integers, MPI_INT,
+ ptDist, nbDistElem, MPI_INT,
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, nbLocalElems, MPI_DOUBLE,
iprocdistant_in_union, 1112,
- myCoords->getPointer(), nb_recv_floats, MPI_DOUBLE,
+ ptDist2, 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 int[tinyInfoDistant.back()];
+ comm_interface.sendRecv(const_cast<void *>(reinterpret_cast<const void *>(distant_ids_send->getConstPointer())),tinyInfoLocal.back(), MPI_INT,
+ iprocdistant_in_union, 1113,
+ distant_ids_recv,tinyInfoDistant.back(), MPI_INT,
+ 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<int>& policy)
+ {
+ policy.resize(_distant_proc_ids.size());
+ int procId=0;
+ CommInterface comm;
+ MPI_Status status;
+ for(vector<int>::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; i<distant_nb_elems; i++)
- {
- distant_ids_recv[i]=*work++;
- }
-
- // Mesh dimension
- meshing->setMeshDimension(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<int> >& distantLocEltIds, const std::vector< std::vector<double> >& partialSumRelToDistantIds)
+ {
+ int procId=0;
+ CommInterface comm;
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ const vector<int>& eltIds=distantLocEltIds[procId];
+ const vector<double>& valued=partialSumRelToDistantIds[procId];
+ int lgth=eltIds.size();
+ comm.send(&lgth,1,MPI_INT,*iter,1114,*_comm);
+ comm.send(const_cast<void *>(reinterpret_cast<const void *>(&eltIds[0])),lgth,MPI_INT,*iter,1115,*_comm);
+ comm.send(const_cast<void *>(reinterpret_cast<const void *>(&valued[0])),lgth,MPI_DOUBLE,*iter,1116,*_comm);
+ }
}
+ /*!
+ * connected with ElementLocator::sendToWorkingSideL
+ */
+ void ElementLocator::recvSumFromLazySideW(std::vector< std::vector<double> >& globalSumRelToDistantIds)
+ {
+ int procId=0;
+ CommInterface comm;
+ MPI_Status status;
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ std::vector<double>& vec=globalSumRelToDistantIds[procId];
+ comm.recv(&vec[0],vec.size(),MPI_DOUBLE,*iter,1117,*_comm,&status);
+ }
+ }
- // ==============
- // _meshFromElems
- // ==============
+ /*!
+ * connected with ElementLocator::recvLocalIdsFromWorkingSideL
+ */
+ void ElementLocator::sendLocalIdsToLazyProcsW(const std::vector< std::vector<int> >& distantLocEltIds)
+ {
+ int procId=0;
+ CommInterface comm;
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ const vector<int>& eltIds=distantLocEltIds[procId];
+ int lgth=eltIds.size();
+ comm.send(&lgth,1,MPI_INT,*iter,1121,*_comm);
+ comm.send(const_cast<void *>(reinterpret_cast<const void *>(&eltIds[0])),lgth,MPI_INT,*iter,1122,*_comm);
+ }
+ }
- MEDCouplingUMesh* ElementLocator::_meshFromElems(set<int>& elems)
+ /*!
+ * connected with ElementLocator::sendGlobalIdsToWorkingSideL
+ */
+ void ElementLocator::recvGlobalIdsFromLazyProcsW(const std::vector< std::vector<int> >& distantLocEltIds, std::vector< std::vector<int> >& globalIds)
{
- //returns null pointer if there are no elems in the mesh
- if ( elems.size()==0 ) return 0;
+ int procId=0;
+ CommInterface comm;
+ MPI_Status status;
+ globalIds.resize(_distant_proc_ids.size());
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ const std::vector<int>& vec=distantLocEltIds[procId];
+ std::vector<int>& global=globalIds[procId];
+ global.resize(vec.size());
+ comm.recv(&global[0],vec.size(),MPI_INT,*iter,1123,*_comm,&status);
+ }
+ }
+
+ /*!
+ * connected with ElementLocator::sendCandidatesGlobalIdsToWorkingSideL
+ */
+ void ElementLocator::recvCandidatesGlobalIdsFromLazyProcsW(std::vector< std::vector<int> >& globalIds)
+ {
+ int procId=0;
+ CommInterface comm;
+ MPI_Status status;
+ globalIds.resize(_distant_proc_ids.size());
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ std::vector<int>& global=globalIds[procId];
+ int lgth;
+ comm.recv(&lgth,1,MPI_INT,*iter,1132,*_comm,&status);
+ global.resize(lgth);
+ comm.recv(&global[0],lgth,MPI_INT,*iter,1133,*_comm,&status);
+ }
+ }
+
+ /*!
+ * connected with ElementLocator::recvSumFromWorkingSideL
+ */
+ void ElementLocator::sendPartialSumToLazyProcsW(const std::vector<int>& distantGlobIds, const std::vector<double>& sum)
+ {
+ int procId=0;
+ CommInterface comm;
+ int lgth=distantGlobIds.size();
+ for(vector<int>::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<void *>(reinterpret_cast<const void *>(&distantGlobIds[0])),lgth,MPI_INT,*iter,1125,*_comm);
+ comm.send(const_cast<void *>(reinterpret_cast<const void *>(&sum[0])),lgth,MPI_DOUBLE,*iter,1126,*_comm);
+ }
+ }
- // Defining pointers
- const int* conn_mesh =
- const_cast<int*> (_local_cell_mesh->getNodalConnectivity()->getPointer());
+ /*!
+ * connected with ElementLocator::recvCandidatesForAddElementsL
+ */
+ void ElementLocator::sendCandidatesForAddElementsW(const std::vector<int>& distantGlobIds)
+ {
+ int procId=0;
+ CommInterface comm;
+ int lgth=distantGlobIds.size();
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ comm.send(const_cast<void *>(reinterpret_cast<const void *>(&lgth)),1,MPI_INT,*iter,1128,*_comm);
+ comm.send(const_cast<void *>(reinterpret_cast<const void *>(&distantGlobIds[0])),lgth,MPI_INT,*iter,1129,*_comm);
+ }
+ }
+
+ /*!
+ * connected with ElementLocator::sendAddElementsToWorkingSideL
+ */
+ void ElementLocator::recvAddElementsFromLazyProcsW(std::vector<std::vector<int> >& elementsToAdd)
+ {
+ int procId=0;
+ CommInterface comm;
+ MPI_Status status;
+ int lgth=_distant_proc_ids.size();
+ elementsToAdd.resize(lgth);
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ int locLgth;
+ std::vector<int>& eltToFeed=elementsToAdd[procId];
+ comm.recv(&locLgth,1,MPI_INT,*iter,1130,*_comm,&status);
+ eltToFeed.resize(locLgth);
+ comm.recv(&eltToFeed[0],locLgth,MPI_INT,*iter,1131,*_comm,&status);
+ }
+ }
- const int* conn_index =
- const_cast<int*> (_local_cell_mesh->getNodalConnectivityIndex()->getPointer());
+ /*!
+ * connected with ElementLocator::recvPolicyFromLazySideW
+ */
+ int ElementLocator::sendPolicyToWorkingSideL()
+ {
+ CommInterface comm;
+ int toSend;
+ DataArrayInt *isCumulative=_local_para_field.returnCumulativeGlobalNumbering();
+ if(isCumulative)
+ {
+ toSend=CUMULATIVE_POLICY;
+ isCumulative->decrRef();
+ }
+ else
+ toSend=NO_POST_TREATMENT_POLICY;
+ for(vector<int>::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<double*> ( _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<int>::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<int>& ids=_ids_per_working_proc[procId];
+ ids.resize(lgth);
+ vector<double> values(lgth);
+ comm.recv(&ids[0],lgth,MPI_INT,*iter,1115,*_comm,&status);
+ comm.recv(&values[0],lgth,MPI_DOUBLE,*iter,1116,*_comm,&status);
+ for(int i=0;i<lgth;i++)
+ _values_added[ids[i]]+=values[i];
+ }
+ }
- set<int> nodes;
- int nbconn=0;
- for (set<int>::const_iterator iter=elems.begin(); iter!=elems.end(); iter++)
+ /*!
+ * connected with ElementLocator::recvSumFromLazySideW
+ */
+ void ElementLocator::sendToWorkingSideL()
+ {
+ int procId=0;
+ CommInterface comm;
+ for(vector<int>::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<conn_index[*iter+1]; inode++)
- {
- nodes.insert(conn_mesh[inode]);
- nbconn++ ;
- }
+ vector<int>& ids=_ids_per_working_proc[procId];
+ vector<double> valsToSend(ids.size());
+ vector<double>::iterator iter3=valsToSend.begin();
+ for(vector<int>::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter3++)
+ *iter3=_values_added[*iter2];
+ comm.send(&valsToSend[0],ids.size(),MPI_DOUBLE,*iter,1117,*_comm);
+ //ids.clear();
}
+ //_ids_per_working_proc.clear();
+ }
- map<int,int> big2small;
- int i=0;
- for (set<int>::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<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
{
- big2small[*iter]=i;
- i++;
+ int lgth;
+ vector<int>& 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_INT,*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;
+ DataArrayInt *globalIds=_local_para_field.returnGlobalNumbering();
+ const int *globalIdsC=globalIds->getConstPointer();
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ const vector<int>& ids=_ids_per_working_proc[procId];
+ vector<int> valsToSend(ids.size());
+ vector<int>::iterator iter1=valsToSend.begin();
+ for(vector<int>::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter1++)
+ *iter1=globalIdsC[*iter2];
+ comm.send(&valsToSend[0],ids.size(),MPI_INT,*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()
+ {
+ int procId=0;
+ int wProcSize=_distant_proc_ids.size();
+ CommInterface comm;
+ _ids_per_working_proc.resize(wProcSize);
+ _values_per_working_proc.resize(wProcSize);
+ MPI_Status status;
+ std::map<int,double> sums;
+ for(vector<int>::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<int>& ids=_ids_per_working_proc[procId];
+ vector<double>& vals=_values_per_working_proc[procId];
+ ids.resize(lgth);
+ vals.resize(lgth);
+ comm.recv(&ids[0],lgth,MPI_INT,*iter,1125,*_comm,&status);
+ comm.recv(&vals[0],lgth,MPI_DOUBLE,*iter,1126,*_comm,&status);
+ vector<int>::const_iterator iter1=ids.begin();
+ vector<double>::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<wProcSize;procId++)
+ {
+ vector<int>& ids=_ids_per_working_proc[procId];
+ vector<double>& vals=_values_per_working_proc[procId];
+ vector<int>::const_iterator iter1=ids.begin();
+ vector<double>::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()
+ {
+ int procId=0;
+ int wProcSize=_distant_proc_ids.size();
+ CommInterface comm;
+ _ids_per_working_proc3.resize(wProcSize);
+ MPI_Status status;
+ std::map<int,double> sums;
+ DataArrayInt *globalIds=_local_para_field.returnGlobalNumbering();
+ const int *globalIdsC=globalIds->getConstPointer();
+ int nbElts=globalIds->getNumberOfTuples();
+ std::set<int> globalIdsS(globalIdsC,globalIdsC+nbElts);
+ for(vector<int>::const_iterator iter=_distant_proc_ids.begin();iter!=_distant_proc_ids.end();iter++,procId++)
+ {
+ const std::vector<int>& ids0=_ids_per_working_proc[procId];
+ int lgth0=ids0.size();
+ std::set<int> elts0;
+ for(int i=0;i<lgth0;i++)
+ elts0.insert(globalIdsC[ids0[i]]);
+ int lgth;
+ comm.recv(&lgth,1,MPI_INT,*iter,1128,*_comm,&status);
+ vector<int> ids(lgth);
+ comm.recv(&ids[0],lgth,MPI_INT,*iter,1129,*_comm,&status);
+ set<int> ids1(ids.begin(),ids.end());
+ ids.clear();
+ set<int> 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<int>& ids2=_ids_per_working_proc3[procId];
+ ids2.resize(tmp6.size());
+ std::copy(tmp6.begin(),tmp6.end(),ids2.begin());
+ //global->local
+ for(std::vector<int>::iterator iter2=ids2.begin();iter2!=ids2.end();iter2++)
+ *iter2=std::find(globalIdsC,globalIdsC+nbElts,*iter2)-globalIdsC;
+ }
+ if(globalIds)
+ globalIds->decrRef();
+ }
- // New connectivity table
- int index=0;
- int mainIndex=0;
- for (set<int>::const_iterator iter=elems.begin(); iter!=elems.end(); iter++,mainIndex++)
+ /*!
+ * connected with ElementLocator::recvAddElementsFromLazyProcsW
+ */
+ void ElementLocator::sendAddElementsToWorkingSideL()
+ {
+ int procId=0;
+ CommInterface comm;
+ for(vector<int>::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<int>& vals=_ids_per_working_proc3[procId];
+ int size=vals.size();
+ comm.send(const_cast<void *>(reinterpret_cast<const void *>(&size)),1,MPI_INT,*iter,1130,*_comm);
+ comm.send(const_cast<void *>(reinterpret_cast<const void *>(&vals[0])),size,MPI_INT,*iter,1131,*_comm);
}
- connIndexPtr[mainIndex]=index;
- // Coordinates
- index=0;
- for (set<int>::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;
+ DataArrayInt *globalIds=_local_para_field.returnGlobalNumbering();
+ const int *globalIdsC=globalIds->getConstPointer();
+ MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=_local_para_field.getSupport()->getCellMesh()->findBoundaryNodes();
+ for(int *iter1=candidates->getPointer();iter1!=candidates->getPointer()+candidates->getNumberOfTuples();iter1++)
+ (*iter1)=globalIdsC[*iter1];
+ std::set<int> candidatesS(candidates->begin(),candidates->end());
+ for(vector<int>::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<dim;i++)
- {
- new_coords_ptr[index]=coords[(*iter)*dim+i];
- index++;
- }
+ const vector<int>& ids=_ids_per_working_proc[procId];
+ vector<int> valsToSend(ids.size());
+ vector<int>::iterator iter1=valsToSend.begin();
+ for(vector<int>::const_iterator iter2=ids.begin();iter2!=ids.end();iter2++,iter1++)
+ *iter1=globalIdsC[*iter2];
+ std::set<int> tmp2(valsToSend.begin(),valsToSend.end());
+ std::vector<int> tmp3;
+ set_intersection(candidatesS.begin(),candidatesS.end(),tmp2.begin(),tmp2.end(),std::back_insert_iterator< std::vector<int> >(tmp3));
+ int lgth=tmp3.size();
+ comm.send(&lgth,1,MPI_INT,*iter,1132,*_comm);
+ comm.send(&tmp3[0],lgth,MPI_INT,*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();
}
}